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_MINOR_LO 9
|
||||||
#define VER_LAMEXP_TYPE Alpha
|
#define VER_LAMEXP_TYPE Alpha
|
||||||
#define VER_LAMEXP_PATCH 4
|
#define VER_LAMEXP_PATCH 4
|
||||||
#define VER_LAMEXP_BUILD 1427
|
#define VER_LAMEXP_BUILD 1430
|
||||||
#define VER_LAMEXP_CONFG 1348
|
#define VER_LAMEXP_CONFG 1348
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -34,41 +34,46 @@
|
|||||||
#define FADE_DELAY 16
|
#define FADE_DELAY 16
|
||||||
#define OPACITY_DELTA 0.02
|
#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. */
|
//Setup taskbar indicator
|
||||||
/* 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 SET_TASKBAR_STATE(WIDGET,VAR,FLAG) do \
|
||||||
#define THREAD_RUNNING(THRD) (((THRD)->isRunning()) ? (!((THRD)->wait(1))) : false)
|
|
||||||
|
|
||||||
#define SET_TASKBAR_STATE(FLAG) do \
|
|
||||||
{ \
|
{ \
|
||||||
if(FLAG) \
|
if(FLAG) \
|
||||||
{ \
|
{ \
|
||||||
if(!bTaskBar) bTaskBar = WinSevenTaskbar::setTaskbarState(splashScreen, WinSevenTaskbar::WinSevenTaskbarIndeterminateState); \
|
if(!(VAR)) (VAR) = WinSevenTaskbar::setTaskbarState((WIDGET), WinSevenTaskbar::WinSevenTaskbarIndeterminateState); \
|
||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
if(bTaskBar) bTaskBar = (!WinSevenTaskbar::setTaskbarState(splashScreen, WinSevenTaskbar::WinSevenTaskbarNoState)); \
|
if((VAR)) (VAR) = (!WinSevenTaskbar::setTaskbarState((WIDGET), WinSevenTaskbar::WinSevenTaskbarNoState)); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
while(0)
|
while(0)
|
||||||
|
|
||||||
#define ASYNC_WAIT(LOOP, DELAY) do \
|
|
||||||
{ \
|
|
||||||
QTimer::singleShot((DELAY), (LOOP), SLOT(quit())); \
|
|
||||||
(LOOP)->exec(QEventLoop::ExcludeUserInputEvents); \
|
|
||||||
} \
|
|
||||||
while(0)
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Constructor
|
// Constructor
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SplashScreen::SplashScreen(QWidget *parent)
|
SplashScreen::SplashScreen(QWidget *parent)
|
||||||
:
|
:
|
||||||
|
m_opacitySteps(qRound(1.0 / OPACITY_DELTA)),
|
||||||
QFrame(parent, Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)
|
QFrame(parent, Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)
|
||||||
{
|
{
|
||||||
//Init the dialog, from the .ui file
|
//Init the dialog, from the .ui file
|
||||||
setupUi(this);
|
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
|
//Start animation
|
||||||
m_working = new QMovie(":/images/Loading.gif");
|
m_working = new QMovie(":/images/Loading.gif");
|
||||||
labelLoading->setMovie(m_working);
|
labelLoading->setMovie(m_working);
|
||||||
@ -77,8 +82,11 @@ SplashScreen::SplashScreen(QWidget *parent)
|
|||||||
//Set wait cursor
|
//Set wait cursor
|
||||||
setCursor(Qt::WaitCursor);
|
setCursor(Qt::WaitCursor);
|
||||||
|
|
||||||
//Prevent close
|
//Init status
|
||||||
m_canClose = false;
|
m_canClose = false;
|
||||||
|
m_status = STATUS_FADE_IN;
|
||||||
|
m_fadeValue = 0;
|
||||||
|
m_taskBarInit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -90,9 +98,11 @@ SplashScreen::~SplashScreen(void)
|
|||||||
if(m_working)
|
if(m_working)
|
||||||
{
|
{
|
||||||
m_working->stop();
|
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)
|
void SplashScreen::showSplash(QThread *thread)
|
||||||
{
|
{
|
||||||
const int opacitySteps = qRound(1.0 / OPACITY_DELTA);
|
|
||||||
bool bTaskBar = false;
|
|
||||||
unsigned int deadlockCounter = 0;
|
|
||||||
SplashScreen *splashScreen = new SplashScreen();
|
SplashScreen *splashScreen = new SplashScreen();
|
||||||
|
|
||||||
//Show splash
|
//Show splash
|
||||||
splashScreen->m_canClose = false;
|
|
||||||
splashScreen->setWindowOpacity(OPACITY_DELTA);
|
splashScreen->setWindowOpacity(OPACITY_DELTA);
|
||||||
splashScreen->setFixedSize(splashScreen->size());
|
|
||||||
splashScreen->show();
|
splashScreen->show();
|
||||||
|
|
||||||
//Wait for window to show
|
//Wait for window to show
|
||||||
@ -117,67 +122,85 @@ void SplashScreen::showSplash(QThread *thread)
|
|||||||
splashScreen->repaint();
|
splashScreen->repaint();
|
||||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||||
|
|
||||||
//Setup the event loop
|
//Connect thread signals
|
||||||
QEventLoop *loop = new QEventLoop(splashScreen);
|
connect(thread, SIGNAL(terminated()), splashScreen, SLOT(threadComplete()), Qt::QueuedConnection);
|
||||||
connect(thread, SIGNAL(terminated()), loop, SLOT(quit()), Qt::QueuedConnection);
|
connect(thread, SIGNAL(finished()), splashScreen, SLOT(threadComplete()), 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();
|
|
||||||
|
|
||||||
//Init taskbar
|
//Init taskbar
|
||||||
SET_TASKBAR_STATE(true);
|
SET_TASKBAR_STATE(splashScreen, splashScreen->m_taskBarInit, true);
|
||||||
|
|
||||||
//Fade in
|
//Start the thread
|
||||||
for(int i = 1; i <= opacitySteps; i++)
|
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;
|
thread->terminate();
|
||||||
splashScreen->setWindowOpacity(opacity); //splashScreen->update();
|
qFatal("Deadlock in initialization thread encountered!");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Restore taskbar
|
//Restore taskbar
|
||||||
SET_TASKBAR_STATE(false);
|
SET_TASKBAR_STATE(splashScreen, splashScreen->m_taskBarInit, false);
|
||||||
|
|
||||||
//Hide splash
|
//Hide splash
|
||||||
splashScreen->m_canClose = true;
|
splashScreen->m_canClose = true;
|
||||||
splashScreen->close();
|
splashScreen->close();
|
||||||
|
|
||||||
//Free
|
//Free
|
||||||
LAMEXP_DELETE(loop);
|
|
||||||
LAMEXP_DELETE(timer);
|
|
||||||
LAMEXP_DELETE(splashScreen);
|
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
|
// EVENTS
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -33,14 +33,36 @@ class SplashScreen: public QFrame, private Ui::SplashScreen
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SplashScreen(QWidget *parent = 0);
|
|
||||||
~SplashScreen(void);
|
|
||||||
|
|
||||||
static void showSplash(QThread *thread);
|
static void showSplash(QThread *thread);
|
||||||
|
|
||||||
private:
|
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;
|
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:
|
protected:
|
||||||
void keyPressEvent(QKeyEvent *event);
|
void keyPressEvent(QKeyEvent *event);
|
||||||
|
Loading…
Reference in New Issue
Block a user