OSDN Git Service

Make sure the Taskbar state is set properly in the Splash screen.
[lamexp/LameXP.git] / src / Dialog_SplashScreen.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2013 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
21
22 #include "Dialog_SplashScreen.h"
23
24 #include "Global.h"
25
26 #include <QThread>
27 #include <QMovie>
28 #include <QKeyEvent>
29 #include <QTimer>
30
31 #include "WinSevenTaskbar.h"
32
33 #define FADE_DELAY 16
34 #define OPACITY_DELTA 0.02
35
36 /* 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. */
37 /* For this reason the macro will first check the 'isRunning' flag. If (and only if) the flag still returns TRUE, then we will wait() for at most 50 ms. */
38 /* If, after 50 ms, the wait() function returns with FALSE, then the thread probably is still running and we return TRUE. Otherwise we can return FALSE. */
39 #define THREAD_RUNNING(THRD) (((THRD)->isRunning()) ? (!((THRD)->wait(50))) : false)
40
41 #define SET_TASKBAR_STATE(FLAG) do \
42 { \
43         if(FLAG) \
44         { \
45                 if(!bTaskBar) bTaskBar = WinSevenTaskbar::setTaskbarState(splashScreen, WinSevenTaskbar::WinSevenTaskbarIndeterminateState); \
46         } \
47         else \
48         { \
49                 if(bTaskBar) bTaskBar = (!WinSevenTaskbar::setTaskbarState(splashScreen, WinSevenTaskbar::WinSevenTaskbarNoState)); \
50         } \
51 } \
52 while(0)
53
54 ////////////////////////////////////////////////////////////
55 // Constructor
56 ////////////////////////////////////////////////////////////
57
58 SplashScreen::SplashScreen(QWidget *parent)
59 :
60         QFrame(parent, Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)
61 {
62         //Init the dialog, from the .ui file
63         setupUi(this);
64
65         //Start animation
66         m_working = new QMovie(":/images/Loading.gif");
67         labelLoading->setMovie(m_working);
68         m_working->start();
69
70         //Set wait cursor
71         setCursor(Qt::WaitCursor);
72
73         //Prevent close
74         m_canClose = false;
75 }
76
77 ////////////////////////////////////////////////////////////
78 // Destructor
79 ////////////////////////////////////////////////////////////
80
81 SplashScreen::~SplashScreen(void)
82 {
83         if(m_working)
84         {
85                 m_working->stop();
86                 delete m_working;
87                 m_working = NULL;
88         }
89 }
90
91 ////////////////////////////////////////////////////////////
92 // PUBLIC FUNCTIONS
93 ////////////////////////////////////////////////////////////
94
95 void SplashScreen::showSplash(QThread *thread)
96 {
97         double opacity = OPACITY_DELTA;
98         const int opacitySteps = qRound(1.0 / OPACITY_DELTA);
99         SplashScreen *splashScreen = new SplashScreen();
100         bool bTaskBar = false;
101         
102         //Show splash
103         splashScreen->m_canClose = false;
104         splashScreen->setWindowOpacity(opacity);
105         splashScreen->setFixedSize(splashScreen->size());
106         splashScreen->show();
107
108         //Wait for window to show
109         QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
110         splashScreen->repaint();
111         QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
112
113         //Setup the event loop
114         QEventLoop *loop = new QEventLoop(splashScreen);
115         connect(thread, SIGNAL(terminated()), loop, SLOT(quit()), Qt::QueuedConnection);
116         connect(thread, SIGNAL(finished()), loop, SLOT(quit()), Qt::QueuedConnection);
117
118         //Create timer
119         QTimer *timer = new QTimer();
120         connect(timer, SIGNAL(timeout()), loop, SLOT(quit()));
121
122         //Start thread
123         QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
124         thread->start();
125         QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
126
127         //Init taskbar
128         SET_TASKBAR_STATE(true);
129
130         //Fade in
131         for(int i = 1; i <= opacitySteps; i++)
132         {
133                 opacity = (i < opacitySteps) ? (OPACITY_DELTA * static_cast<double>(i)) : 1.0;
134                 splashScreen->setWindowOpacity(opacity);
135                 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, FADE_DELAY);
136                 SET_TASKBAR_STATE(true);
137                 Sleep(FADE_DELAY);
138         }
139
140         //Start the timer
141         timer->start(30720);
142
143         //Loop while thread is still running
144         if(bool bIsRunning = THREAD_RUNNING(thread))
145         {
146                 while(bIsRunning)
147                 {
148                         loop->exec();
149                         if(bIsRunning = THREAD_RUNNING(thread))
150                         {
151                                 qWarning("Potential deadlock in initialization thread!");
152                         }
153                 }
154         }
155
156         //Stop the timer
157         timer->stop();
158
159         //Fade out
160         for(int i = opacitySteps; i >= 0; i--)
161         {
162                 opacity = OPACITY_DELTA * static_cast<double>(i);
163                 splashScreen->setWindowOpacity(opacity);
164                 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, FADE_DELAY);
165                 Sleep(FADE_DELAY);
166         }
167
168         //Restore taskbar
169         SET_TASKBAR_STATE(false);
170
171         //Hide splash
172         splashScreen->m_canClose = true;
173         splashScreen->close();
174
175         //Free
176         LAMEXP_DELETE(loop);
177         LAMEXP_DELETE(timer);
178         LAMEXP_DELETE(splashScreen);
179 }
180
181 ////////////////////////////////////////////////////////////
182 // EVENTS
183 ////////////////////////////////////////////////////////////
184
185 void SplashScreen::keyPressEvent(QKeyEvent *event)
186 {
187         event->ignore();
188 }
189
190 void SplashScreen::keyReleaseEvent(QKeyEvent *event)
191 {
192         event->ignore();
193 }
194
195 void SplashScreen::closeEvent(QCloseEvent *event)
196 {
197         if(!m_canClose) event->ignore();
198 }
199
200 bool SplashScreen::winEvent(MSG *message, long *result)
201 {
202         return WinSevenTaskbar::handleWinEvent(message, result);
203 }