diff --git a/res/localization/LameXP_UK.qm b/res/localization/LameXP_UK.qm index 96408eef..5bc114a9 100644 Binary files a/res/localization/LameXP_UK.qm and b/res/localization/LameXP_UK.qm differ diff --git a/src/Config.h b/src/Config.h index a0b30a99..9219abc9 100644 --- a/src/Config.h +++ b/src/Config.h @@ -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 /////////////////////////////////////////////////////////////////////////////// diff --git a/src/Dialog_SplashScreen.cpp b/src/Dialog_SplashScreen.cpp index ab824a5b..901577be 100644 --- a/src/Dialog_SplashScreen.cpp +++ b/src/Dialog_SplashScreen.cpp @@ -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(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(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(++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(--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 //////////////////////////////////////////////////////////// diff --git a/src/Dialog_SplashScreen.h b/src/Dialog_SplashScreen.h index 3cabdd55..ddabb485 100644 --- a/src/Dialog_SplashScreen.h +++ b/src/Dialog_SplashScreen.h @@ -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);