More improvements in Splash Screen (application initialization) code. It's now completely event-driven.
This commit is contained in:
parent
758906b4c8
commit
3b0577c733
Binary file not shown.
@ -35,7 +35,7 @@
|
||||
#define VER_LAMEXP_MINOR_LO 9
|
||||
#define VER_LAMEXP_TYPE Alpha
|
||||
#define VER_LAMEXP_PATCH 4
|
||||
#define VER_LAMEXP_BUILD 1427
|
||||
#define VER_LAMEXP_BUILD 1430
|
||||
#define VER_LAMEXP_CONFG 1348
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -34,41 +34,46 @@
|
||||
#define FADE_DELAY 16
|
||||
#define OPACITY_DELTA 0.02
|
||||
|
||||
/* It can happen that the QThread has just terminated and already emitted the 'terminated' signal, but did NOT change the 'isRunning' flag to FALSE yet. */
|
||||
/* For this reason the macro will first check the 'isRunning' flag. If (and only if) the flag still returns TRUE, we will call the wait() on the thread. */
|
||||
#define THREAD_RUNNING(THRD) (((THRD)->isRunning()) ? (!((THRD)->wait(1))) : false)
|
||||
|
||||
#define SET_TASKBAR_STATE(FLAG) do \
|
||||
//Setup taskbar indicator
|
||||
#define SET_TASKBAR_STATE(WIDGET,VAR,FLAG) do \
|
||||
{ \
|
||||
if(FLAG) \
|
||||
{ \
|
||||
if(!bTaskBar) bTaskBar = WinSevenTaskbar::setTaskbarState(splashScreen, WinSevenTaskbar::WinSevenTaskbarIndeterminateState); \
|
||||
if(!(VAR)) (VAR) = WinSevenTaskbar::setTaskbarState((WIDGET), WinSevenTaskbar::WinSevenTaskbarIndeterminateState); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if(bTaskBar) bTaskBar = (!WinSevenTaskbar::setTaskbarState(splashScreen, WinSevenTaskbar::WinSevenTaskbarNoState)); \
|
||||
if((VAR)) (VAR) = (!WinSevenTaskbar::setTaskbarState((WIDGET), WinSevenTaskbar::WinSevenTaskbarNoState)); \
|
||||
} \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define ASYNC_WAIT(LOOP, DELAY) do \
|
||||
{ \
|
||||
QTimer::singleShot((DELAY), (LOOP), SLOT(quit())); \
|
||||
(LOOP)->exec(QEventLoop::ExcludeUserInputEvents); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
SplashScreen::SplashScreen(QWidget *parent)
|
||||
:
|
||||
m_opacitySteps(qRound(1.0 / OPACITY_DELTA)),
|
||||
QFrame(parent, Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)
|
||||
{
|
||||
//Init the dialog, from the .ui file
|
||||
setupUi(this);
|
||||
|
||||
//Make size fixed
|
||||
setFixedSize(this->size());
|
||||
|
||||
//Create event loop
|
||||
m_loop = new QEventLoop(this);
|
||||
|
||||
//Create timer
|
||||
m_timer = new QTimer(this);
|
||||
m_timer->setInterval(FADE_DELAY);
|
||||
m_timer->setSingleShot(false);
|
||||
|
||||
//Connect timer to slot
|
||||
connect(m_timer, SIGNAL(timeout()), this, SLOT(updateHandler()));
|
||||
|
||||
//Start animation
|
||||
m_working = new QMovie(":/images/Loading.gif");
|
||||
labelLoading->setMovie(m_working);
|
||||
@ -77,8 +82,11 @@ SplashScreen::SplashScreen(QWidget *parent)
|
||||
//Set wait cursor
|
||||
setCursor(Qt::WaitCursor);
|
||||
|
||||
//Prevent close
|
||||
//Init status
|
||||
m_canClose = false;
|
||||
m_status = STATUS_FADE_IN;
|
||||
m_fadeValue = 0;
|
||||
m_taskBarInit = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -90,9 +98,11 @@ SplashScreen::~SplashScreen(void)
|
||||
if(m_working)
|
||||
{
|
||||
m_working->stop();
|
||||
delete m_working;
|
||||
m_working = NULL;
|
||||
}
|
||||
|
||||
LAMEXP_DELETE(m_working);
|
||||
LAMEXP_DELETE(m_loop);
|
||||
LAMEXP_DELETE(m_timer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -101,15 +111,10 @@ SplashScreen::~SplashScreen(void)
|
||||
|
||||
void SplashScreen::showSplash(QThread *thread)
|
||||
{
|
||||
const int opacitySteps = qRound(1.0 / OPACITY_DELTA);
|
||||
bool bTaskBar = false;
|
||||
unsigned int deadlockCounter = 0;
|
||||
SplashScreen *splashScreen = new SplashScreen();
|
||||
|
||||
//Show splash
|
||||
splashScreen->m_canClose = false;
|
||||
splashScreen->setWindowOpacity(OPACITY_DELTA);
|
||||
splashScreen->setFixedSize(splashScreen->size());
|
||||
splashScreen->show();
|
||||
|
||||
//Wait for window to show
|
||||
@ -117,67 +122,85 @@ void SplashScreen::showSplash(QThread *thread)
|
||||
splashScreen->repaint();
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
//Setup the event loop
|
||||
QEventLoop *loop = new QEventLoop(splashScreen);
|
||||
connect(thread, SIGNAL(terminated()), loop, SLOT(quit()), Qt::QueuedConnection);
|
||||
connect(thread, SIGNAL(finished()), loop, SLOT(quit()), Qt::QueuedConnection);
|
||||
|
||||
//Create timer
|
||||
QTimer *timer = new QTimer();
|
||||
connect(timer, SIGNAL(timeout()), loop, SLOT(quit()));
|
||||
|
||||
//Start the thread
|
||||
thread->start();
|
||||
//Connect thread signals
|
||||
connect(thread, SIGNAL(terminated()), splashScreen, SLOT(threadComplete()), Qt::QueuedConnection);
|
||||
connect(thread, SIGNAL(finished()), splashScreen, SLOT(threadComplete()), Qt::QueuedConnection);
|
||||
|
||||
//Init taskbar
|
||||
SET_TASKBAR_STATE(true);
|
||||
SET_TASKBAR_STATE(splashScreen, splashScreen->m_taskBarInit, true);
|
||||
|
||||
//Fade in
|
||||
for(int i = 1; i <= opacitySteps; i++)
|
||||
//Start the thread
|
||||
splashScreen->m_timer->start(FADE_DELAY);
|
||||
QTimer::singleShot(3*60*1000, splashScreen->m_loop, SLOT(quit()));
|
||||
QTimer::singleShot(0, thread, SLOT(start()));
|
||||
|
||||
//Start event handling!
|
||||
const int ret = splashScreen->m_loop->exec(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
//Check for timeout
|
||||
if(ret != 42)
|
||||
{
|
||||
const double opacity = (i < opacitySteps) ? (OPACITY_DELTA * static_cast<double>(i)) : 1.0;
|
||||
splashScreen->setWindowOpacity(opacity); //splashScreen->update();
|
||||
ASYNC_WAIT(loop, FADE_DELAY);
|
||||
SET_TASKBAR_STATE(true);
|
||||
}
|
||||
|
||||
//Start the timer
|
||||
timer->start(30720);
|
||||
|
||||
//Loop while thread is still running
|
||||
while(THREAD_RUNNING(thread))
|
||||
{
|
||||
if((++deadlockCounter) > 60)
|
||||
{
|
||||
qFatal("Deadlock in initialization thread detected!");
|
||||
}
|
||||
ASYNC_WAIT(loop, 5000);
|
||||
}
|
||||
|
||||
//Stop the timer
|
||||
timer->stop();
|
||||
|
||||
//Fade out
|
||||
for(int i = opacitySteps; i >= 0; i--)
|
||||
{
|
||||
const double opacity = OPACITY_DELTA * static_cast<double>(i);
|
||||
splashScreen->setWindowOpacity(opacity); //splashScreen->update();
|
||||
ASYNC_WAIT(loop, FADE_DELAY);
|
||||
thread->terminate();
|
||||
qFatal("Deadlock in initialization thread encountered!");
|
||||
}
|
||||
|
||||
//Restore taskbar
|
||||
SET_TASKBAR_STATE(false);
|
||||
SET_TASKBAR_STATE(splashScreen, splashScreen->m_taskBarInit, false);
|
||||
|
||||
//Hide splash
|
||||
splashScreen->m_canClose = true;
|
||||
splashScreen->close();
|
||||
|
||||
//Free
|
||||
LAMEXP_DELETE(loop);
|
||||
LAMEXP_DELETE(timer);
|
||||
LAMEXP_DELETE(splashScreen);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// SLOTS
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void SplashScreen::updateHandler(void)
|
||||
{
|
||||
if(m_status == STATUS_FADE_IN)
|
||||
{
|
||||
if(m_fadeValue < m_opacitySteps)
|
||||
{
|
||||
setWindowOpacity(OPACITY_DELTA * static_cast<double>(++m_fadeValue));
|
||||
SET_TASKBAR_STATE(this, m_taskBarInit, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
setWindowOpacity(1.0);
|
||||
m_timer->stop();
|
||||
m_status = STATUS_WAIT;
|
||||
}
|
||||
}
|
||||
else if(m_status == STATUS_FADE_OUT)
|
||||
{
|
||||
if(m_fadeValue > 0)
|
||||
{
|
||||
setWindowOpacity(OPACITY_DELTA * static_cast<double>(--m_fadeValue));
|
||||
SET_TASKBAR_STATE(this, m_taskBarInit, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
setWindowOpacity(0.0);
|
||||
m_timer->stop();
|
||||
m_status = STATUS_DONE;
|
||||
m_loop->exit(42);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SplashScreen::threadComplete(void)
|
||||
{
|
||||
m_status = STATUS_FADE_OUT;
|
||||
if(!m_timer->isActive())
|
||||
{
|
||||
m_timer->start(FADE_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// EVENTS
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -33,14 +33,36 @@ class SplashScreen: public QFrame, private Ui::SplashScreen
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SplashScreen(QWidget *parent = 0);
|
||||
~SplashScreen(void);
|
||||
|
||||
static void showSplash(QThread *thread);
|
||||
|
||||
private:
|
||||
SplashScreen(QWidget *parent = 0);
|
||||
~SplashScreen(void);
|
||||
|
||||
enum
|
||||
{
|
||||
STATUS_FADE_IN = 0,
|
||||
STATUS_WAIT = 1,
|
||||
STATUS_FADE_OUT = 2,
|
||||
STATUS_DONE = 3
|
||||
}
|
||||
status_t;
|
||||
|
||||
QMovie *m_working;
|
||||
bool m_canClose;
|
||||
QEventLoop *m_loop;
|
||||
QTimer *m_timer;
|
||||
|
||||
const unsigned int m_opacitySteps;
|
||||
|
||||
unsigned int m_status;
|
||||
unsigned int m_fadeValue;
|
||||
|
||||
volatile bool m_canClose;
|
||||
volatile bool m_taskBarInit;
|
||||
|
||||
private slots:
|
||||
void updateHandler(void);
|
||||
void threadComplete(void);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
|
Loading…
Reference in New Issue
Block a user