OSDN Git Service

Make sure splash screen gets focus. Also better key press/release handling in working...
[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, but always including the *additional*
9 // restrictions defined in the "License.txt" file.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 //
20 // http://www.gnu.org/licenses/gpl-2.0.txt
21 ///////////////////////////////////////////////////////////////////////////////
22
23 #include "Dialog_SplashScreen.h"
24
25 #include "Global.h"
26
27 #include <QThread>
28 #include <QMovie>
29 #include <QKeyEvent>
30 #include <QTimer>
31
32 #include "WinSevenTaskbar.h"
33
34 #define FADE_DELAY 16
35 #define OPACITY_DELTA 0.04
36
37 //Setup taskbar indicator
38 #define SET_TASKBAR_STATE(WIDGET,VAR,FLAG) do \
39 { \
40         if(FLAG) \
41         { \
42                 if(!(VAR)) (VAR) = WinSevenTaskbar::setTaskbarState((WIDGET), WinSevenTaskbar::WinSevenTaskbarIndeterminateState); \
43         } \
44         else \
45         { \
46                 if((VAR)) (VAR) = (!WinSevenTaskbar::setTaskbarState((WIDGET), WinSevenTaskbar::WinSevenTaskbarNoState)); \
47         } \
48 } \
49 while(0)
50
51 ////////////////////////////////////////////////////////////
52 // Constructor
53 ////////////////////////////////////////////////////////////
54
55 SplashScreen::SplashScreen(QWidget *parent)
56 :
57         m_opacitySteps(qRound(1.0 / OPACITY_DELTA)),
58         QFrame(parent, Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)
59 {
60         //Init the dialog, from the .ui file
61         setupUi(this);
62
63         //Make size fixed
64         setFixedSize(this->size());
65         
66         //Create event loop
67         m_loop = new QEventLoop(this);
68
69         //Create timer
70         m_timer = new QTimer(this);
71         m_timer->setInterval(FADE_DELAY);
72         m_timer->setSingleShot(false);
73
74         //Connect timer to slot
75         connect(m_timer, SIGNAL(timeout()), this, SLOT(updateHandler()));
76
77         //Enable "sheet of glass" effect on splash screen
78         if(!lamexp_sheet_of_glass(this))
79         {
80                 setStyleSheet("background-image: url(:/images/Background.jpg)");
81         }
82
83         //Start animation
84         m_working = new QMovie(":/images/Loading4.gif");
85         m_working->setCacheMode(QMovie::CacheAll);
86         labelLoading->setMovie(m_working);
87         m_working->start();
88
89         //Init status
90         m_canClose = false;
91         m_status = STATUS_FADE_IN;
92         m_fadeValue = 0;
93         m_taskBarInit = false;
94 }
95
96 ////////////////////////////////////////////////////////////
97 // Destructor
98 ////////////////////////////////////////////////////////////
99
100 SplashScreen::~SplashScreen(void)
101 {
102         if(m_working)
103         {
104                 m_working->stop();
105         }
106
107         LAMEXP_DELETE(m_working);
108         LAMEXP_DELETE(m_loop);
109         LAMEXP_DELETE(m_timer);
110 }
111
112 ////////////////////////////////////////////////////////////
113 // PUBLIC FUNCTIONS
114 ////////////////////////////////////////////////////////////
115
116 void SplashScreen::showSplash(QThread *thread)
117 {
118         SplashScreen *splashScreen = new SplashScreen();
119
120         //Show splash
121         splashScreen->setWindowOpacity(OPACITY_DELTA);
122         splashScreen->show();
123
124         //Set wait cursor
125         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
126
127         //Wait for window to show
128         QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
129         splashScreen->repaint(); lamexp_bring_to_front(splashScreen);
130         QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
131
132         //Connect thread signals
133         connect(thread, SIGNAL(terminated()), splashScreen, SLOT(threadComplete()), Qt::QueuedConnection);
134         connect(thread, SIGNAL(finished()),   splashScreen, SLOT(threadComplete()), Qt::QueuedConnection);
135
136         //Init taskbar
137         SET_TASKBAR_STATE(splashScreen, splashScreen->m_taskBarInit, true);
138
139         //Start the thread
140         splashScreen->m_timer->start(FADE_DELAY);
141         QTimer::singleShot(8*60*1000, splashScreen->m_loop, SLOT(quit()));
142         QTimer::singleShot(333, thread, SLOT(start()));
143
144         //Start event handling!
145         const int ret = splashScreen->m_loop->exec(QEventLoop::ExcludeUserInputEvents);
146
147         //Check for timeout
148         if(ret != 42)
149         {
150                 thread->terminate();
151                 qFatal("Deadlock in initialization thread encountered!");
152         }
153
154         //Restore taskbar
155         SET_TASKBAR_STATE(splashScreen, splashScreen->m_taskBarInit, false);
156
157         //Restore cursor
158         QApplication::restoreOverrideCursor();
159
160         //Hide splash
161         splashScreen->m_canClose = true;
162         splashScreen->close();
163
164         //Free
165         LAMEXP_DELETE(splashScreen);
166 }
167
168 ////////////////////////////////////////////////////////////
169 // SLOTS
170 ////////////////////////////////////////////////////////////
171
172 void SplashScreen::updateHandler(void)
173 {
174         if(m_status == STATUS_FADE_IN)
175         {
176                 if(m_fadeValue < m_opacitySteps)
177                 {
178                         setWindowOpacity(OPACITY_DELTA * static_cast<double>(++m_fadeValue));
179                         SET_TASKBAR_STATE(this, m_taskBarInit, true);
180                 }
181                 else
182                 {
183                         setWindowOpacity(1.0);
184                         lamexp_bring_to_front(this);
185                         m_timer->stop();
186                         m_status = STATUS_WAIT;
187                 }
188         }
189         else if(m_status == STATUS_FADE_OUT)
190         {
191                 if(m_fadeValue > 0)
192                 {
193                         setWindowOpacity(OPACITY_DELTA * static_cast<double>(--m_fadeValue));
194                         SET_TASKBAR_STATE(this, m_taskBarInit, true);
195                 }
196                 else
197                 {
198                         setWindowOpacity(0.0);
199                         m_timer->stop();
200                         m_status = STATUS_DONE;
201                         m_loop->exit(42);
202                 }
203         }
204 }
205
206 void SplashScreen::threadComplete(void)
207 {
208         m_status = STATUS_FADE_OUT;
209         if(!m_timer->isActive())
210         {
211                 m_timer->start(FADE_DELAY);
212         }
213         lamexp_bring_to_front(this);
214 }
215
216 ////////////////////////////////////////////////////////////
217 // EVENTS
218 ////////////////////////////////////////////////////////////
219
220 void SplashScreen::keyPressEvent(QKeyEvent *event)
221 {
222         event->ignore();
223 }
224
225 void SplashScreen::keyReleaseEvent(QKeyEvent *event)
226 {
227         event->ignore();
228 }
229
230 void SplashScreen::closeEvent(QCloseEvent *event)
231 {
232         if(!m_canClose) event->ignore();
233 }
234
235 bool SplashScreen::winEvent(MSG *message, long *result)
236 {
237         return WinSevenTaskbar::handleWinEvent(message, result);
238 }