OSDN Git Service

Happy new year 2019!
[lamexp/LameXP.git] / src / Dialog_SplashScreen.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2019 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 //UIC includes
26 #include "UIC_SplashScreen.h"
27
28 //Internal
29 #include "Global.h"
30
31 //MUtils
32 #include <MUtils/Global.h>
33 #include <MUtils/GUI.h>
34 #include <MUtils/Taskbar7.h>
35
36 //Qt
37 #include <QThread>
38 #include <QMovie>
39 #include <QKeyEvent>
40 #include <QTimer>
41
42 #define FADE_DELAY 16
43 #define OPACITY_DELTA 0.04
44
45 //Setup taskbar indicator
46 #define SET_TASKBAR_STATE(WIDGET,FLAG) do \
47 { \
48         const int _oldFlag = (WIDGET)->m_taskBarFlag.fetchAndStoreOrdered((FLAG) ? 1 : 0); \
49         if(_oldFlag != ((FLAG) ? 1 : 0)) \
50         { \
51                 (WIDGET)->m_taskbar->setTaskbarState((FLAG) ? MUtils::Taskbar7::TASKBAR_STATE_INTERMEDIATE : MUtils::Taskbar7::TASKBAR_STATE_NONE); \
52         } \
53 } \
54 while(0)
55
56 ////////////////////////////////////////////////////////////
57 // Constructor
58 ////////////////////////////////////////////////////////////
59
60 SplashScreen::SplashScreen(QWidget *parent)
61 :
62         QFrame(parent, Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint),
63         ui(new Ui::SplashScreen),
64         m_opacitySteps(qRound(1.0 / OPACITY_DELTA)),
65         m_taskbar(new MUtils::Taskbar7(this))
66 {
67         //Init the dialog, from the .ui file
68         ui->setupUi(this);
69
70         //Make size fixed
71         setFixedSize(this->size());
72         
73         //Create event loop
74         m_loop.reset(new QEventLoop(this));
75
76         //Create timer
77         m_timer.reset(new QTimer(this));
78         m_timer->setInterval(FADE_DELAY);
79         m_timer->setSingleShot(false);
80
81         //Connect timer to slot
82         connect(m_timer.data(), SIGNAL(timeout()), this, SLOT(updateHandler()));
83
84         //Enable "sheet of glass" effect on splash screen
85         if(!MUtils::GUI::sheet_of_glass(this))
86         {
87                 setStyleSheet("background-image: url(:/images/Background.jpg)");
88         }
89
90         //Start animation
91         m_working.reset(new QMovie(":/images/Loading4.gif"));
92         m_working->setCacheMode(QMovie::CacheAll);
93         ui->labelLoading->setMovie(m_working.data());
94         m_working->start();
95
96         //Init status
97         m_status = STATUS_FADE_IN;
98         m_fadeValue = 0;
99 }
100
101 ////////////////////////////////////////////////////////////
102 // Destructor
103 ////////////////////////////////////////////////////////////
104
105 SplashScreen::~SplashScreen(void)
106 {
107         if(m_working)
108         {
109                 m_working->stop();
110         }
111
112         delete ui;
113 }
114
115 ////////////////////////////////////////////////////////////
116 // PUBLIC FUNCTIONS
117 ////////////////////////////////////////////////////////////
118
119 void SplashScreen::showSplash(QThread *thread)
120 {
121         QScopedPointer<SplashScreen> splashScreen(new SplashScreen());
122
123         //Show splash
124         splashScreen->setWindowOpacity(OPACITY_DELTA);
125         splashScreen->show();
126
127         //Set wait cursor
128         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
129
130         //Wait for window to show
131         QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
132         splashScreen->repaint(); MUtils::GUI::bring_to_front(splashScreen.data());
133         QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
134
135         //Connect thread signals
136         connect(thread, SIGNAL(terminated()), splashScreen.data(), SLOT(threadComplete()), Qt::QueuedConnection);
137         connect(thread, SIGNAL(finished()),   splashScreen.data(), SLOT(threadComplete()), Qt::QueuedConnection);
138
139         //Init taskbar
140         SET_TASKBAR_STATE(splashScreen, true);
141
142         //Start the thread
143         splashScreen->m_timer->start(FADE_DELAY);
144         QTimer::singleShot(8*60*1000, splashScreen->m_loop.data(), SLOT(quit()));
145         QTimer::singleShot(333, thread, SLOT(start()));
146
147         //Start event handling!
148         const int ret = splashScreen->m_loop->exec(QEventLoop::ExcludeUserInputEvents);
149
150         //Check for timeout
151         if(ret != 42)
152         {
153                 thread->terminate();
154                 qFatal("Deadlock in initialization thread encountered!");
155         }
156
157         //Restore taskbar
158         SET_TASKBAR_STATE(splashScreen, false);
159
160         //Restore cursor
161         QApplication::restoreOverrideCursor();
162
163         //Hide splash
164         splashScreen->m_canClose.ref();
165         splashScreen->close();
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, true);
180                 }
181                 else
182                 {
183                         setWindowOpacity(1.0);
184                         MUtils::GUI::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, 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         MUtils::GUI::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 }