OSDN Git Service

abfff8fb8de3e410e765a7376b1e6c2f80281b61
[lamexp/LameXP.git] / src / Dialog_WorkingBanner.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2014 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_WorkingBanner.h"
24 #include "UIC_WorkingBanner.h"
25
26 //Internal
27 #include "Global.h"
28 #include "WinSevenTaskbar.h"
29
30 //MUtils
31 #include <MUtils/Global.h>
32 #include <MUtils/GUI.h>
33
34 //Qt
35 #include <QThread>
36 #include <QMovie>
37 #include <QKeyEvent>
38 #include <QFontMetrics>
39 #include <QPainter>
40 #include <QWindowsVistaStyle>
41 #include <QTimer>
42
43 #define EPS (1.0E-5)
44
45 /* 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. */
46 /* 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. */
47 /* 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. */
48 #define THREAD_RUNNING(THRD) (((THRD)->isRunning()) ? (!((THRD)->wait(1))) : false)
49
50 /*Update text color*/
51 static inline void SET_TEXT_COLOR(QWidget *control, const QColor &color)
52 {
53         QPalette pal = control->palette();
54         pal.setColor(QPalette::WindowText, color);
55         pal.setColor(QPalette::Text, color);
56         control->setPalette(pal);
57 }
58
59 /*Make widget translucent*/
60 static inline void MAKE_TRANSLUCENT(QWidget *control)
61 {
62         control->setAttribute(Qt::WA_TranslucentBackground);
63         control->setAttribute(Qt::WA_NoSystemBackground);
64 }
65
66 /*Update widget margins*/
67 static inline void UPDATE_MARGINS(QWidget *control, int l = 0, int r = 0, int t = 0, int b = 0)
68 {
69         if(QLayout *layout = control->layout())
70         {
71                 QMargins margins = layout->contentsMargins();
72                 margins.setLeft(margins.left() + l);
73                 margins.setRight(margins.right() + r);
74                 margins.setTop(margins.top() + t);
75                 margins.setBottom(margins.bottom() + b);
76                 layout->setContentsMargins(margins);
77         }
78 }
79
80 ////////////////////////////////////////////////////////////
81 // Constructor
82 ////////////////////////////////////////////////////////////
83
84 WorkingBanner::WorkingBanner(QWidget *parent)
85 :
86         QDialog(parent, Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint),
87         ui(new Ui::WorkingBanner()), m_metrics(NULL), m_working(NULL), m_style(NULL)
88 {
89         //Init the dialog, from the .ui file
90         ui->setupUi(this);
91         setModal(true);
92
93         //Enable the "sheet of glass" effect
94         if(MUtils::GUI::sheet_of_glass(this))
95         {
96                 m_style = new QWindowsVistaStyle();
97                 this->setStyle(m_style);
98                 ui->progressBar->setStyle(m_style);
99                 ui->labelStatus->setStyle(m_style);
100                 ui->labelStatus->setStyleSheet("background-color: #FFFFFF;");
101         }
102         else
103         {
104                 UPDATE_MARGINS(this, 5);
105                 m_working = new QMovie(":/images/Busy.gif");
106                 m_working->setCacheMode(QMovie::CacheAll);
107                 ui->labelWorking->setMovie(m_working);
108         }
109         
110         //Set Opacity
111         this->setWindowOpacity(0.9);
112
113         //Set wait cursor
114         setCursor(Qt::WaitCursor);
115
116         //Clear label
117         ui->labelStatus->clear();
118 }
119
120 ////////////////////////////////////////////////////////////
121 // Destructor
122 ////////////////////////////////////////////////////////////
123
124 WorkingBanner::~WorkingBanner(void)
125 {
126         if(m_working)
127         {
128                 m_working->stop();
129                 MUTILS_DELETE(m_working);
130         }
131
132         MUTILS_DELETE(m_style);
133         MUTILS_DELETE(m_metrics);
134         delete ui;
135 }
136
137 ////////////////////////////////////////////////////////////
138 // PUBLIC FUNCTIONS
139 ////////////////////////////////////////////////////////////
140
141 void WorkingBanner::show(const QString &text)
142 {
143         m_canClose = false;
144
145         QDialog::show();
146         setFixedSize(size());
147         setText(text);
148
149         //Reset progress
150         ui->progressBar->setMinimum(0);
151         ui->progressBar->setMaximum(0);
152         ui->progressBar->setValue(-1);
153 }
154
155 void WorkingBanner::show(const QString &text, QThread *thread)
156 {
157         //Show splash
158         this->show(text);
159
160         //Create event loop
161         QEventLoop *loop = new QEventLoop(this);
162         connect(thread, SIGNAL(finished()), loop, SLOT(quit()));
163         connect(thread, SIGNAL(terminated()), loop, SLOT(quit()));
164
165         //Set taskbar state
166         WinSevenTaskbar::setOverlayIcon(dynamic_cast<QWidget*>(this->parent()), &QIcon(":/icons/hourglass.png"));
167         WinSevenTaskbar::setTaskbarState(dynamic_cast<QWidget*>(this->parent()), WinSevenTaskbar::WinSevenTaskbarIndeterminateState);
168
169         //Start the thread
170         thread->start();
171
172         //Update cursor
173         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
174
175         //Loop while thread is still running
176         while(THREAD_RUNNING(thread))
177         {
178                 loop->exec();
179         }
180
181         //Restore cursor
182         QApplication::restoreOverrideCursor();
183
184         //Set taskbar state
185         WinSevenTaskbar::setTaskbarState(dynamic_cast<QWidget*>(this->parent()), WinSevenTaskbar::WinSevenTaskbarNoState);
186         WinSevenTaskbar::setOverlayIcon(dynamic_cast<QWidget*>(this->parent()), NULL);
187
188         //Free memory
189         MUTILS_DELETE(loop);
190
191         //Hide splash
192         this->close();
193 }
194
195 void WorkingBanner::show(const QString &text, QEventLoop *loop)
196 {
197         //Show splash
198         this->show(text);
199
200         //Set taskbar state
201         WinSevenTaskbar::setOverlayIcon(dynamic_cast<QWidget*>(this->parent()), &QIcon(":/icons/hourglass.png"));
202         WinSevenTaskbar::setTaskbarState(dynamic_cast<QWidget*>(this->parent()), WinSevenTaskbar::WinSevenTaskbarIndeterminateState);
203
204         //Update cursor
205         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
206
207         //Loop while thread is running
208         loop->exec(QEventLoop::ExcludeUserInputEvents);
209
210         //Restore cursor
211         QApplication::restoreOverrideCursor();
212
213         //Set taskbar state
214         WinSevenTaskbar::setTaskbarState(dynamic_cast<QWidget*>(this->parent()), WinSevenTaskbar::WinSevenTaskbarNoState);
215         WinSevenTaskbar::setOverlayIcon(dynamic_cast<QWidget*>(this->parent()), NULL);
216
217         //Hide splash
218         this->close();
219 }
220
221 bool WorkingBanner::close(void)
222 {
223         m_canClose = true;
224         emit userAbort();
225         return QDialog::close();
226 }
227
228 ////////////////////////////////////////////////////////////
229 // EVENTS
230 ////////////////////////////////////////////////////////////
231
232 void WorkingBanner::keyPressEvent(QKeyEvent *event)
233 {
234         if(event->key() == Qt::Key_Escape)
235         {
236                 qDebug("QT::KEY_ESCAPE pressed!");
237                 emit userAbort();
238         }
239         else if(event->key() == Qt::Key_M)
240         {
241                 QTimer::singleShot(0, parent(), SLOT(showMinimized()));
242         }
243         
244         QDialog::keyPressEvent(event);
245 }
246
247 void WorkingBanner::keyReleaseEvent(QKeyEvent *event)
248 {
249         QDialog::keyReleaseEvent(event);
250 }
251
252 void WorkingBanner::closeEvent(QCloseEvent *event)
253 {
254         if(!m_canClose) event->ignore();
255 }
256
257 bool WorkingBanner::winEvent(MSG *message, long *result)
258 {
259         return WinSevenTaskbar::handleWinEvent(message, result);
260 }
261
262 void WorkingBanner::showEvent(QShowEvent *event)
263 {
264         QDialog::showEvent(event);
265         if(!event->spontaneous())
266         {
267                 if(m_working)
268                 {
269                         m_working->start();
270                 }
271         }
272         QTimer::singleShot(25, this, SLOT(windowShown()));
273 }
274
275 void WorkingBanner::hideEvent(QHideEvent *event)
276 {
277         QDialog::hideEvent(event);
278         if(!event->spontaneous())
279         {
280                 if(m_working)
281                 {
282                         m_working->stop();
283                 }
284         }
285 }
286
287 ////////////////////////////////////////////////////////////
288 // SLOTS
289 ////////////////////////////////////////////////////////////
290
291 void WorkingBanner::windowShown(void)
292 {
293         MUtils::GUI::bring_to_front(this);
294 }
295
296 void WorkingBanner::setText(const QString &text)
297 {
298         if(!m_metrics)
299         {
300                  m_metrics = new QFontMetrics(ui->labelStatus->font());
301         }
302
303         if(m_metrics->width(text) <= ui->labelStatus->width() - 16)
304         {
305                 ui->labelStatus->setText(text);
306         }
307         else
308         {
309                 QString choppedText = text.simplified().append("...");
310                 while((m_metrics->width(choppedText) > ui->labelStatus->width() - 16) && (choppedText.length() > 8))
311                 {
312                         choppedText.chop(4);
313                         choppedText = choppedText.trimmed();
314                         choppedText.append("...");
315                 }
316                 ui->labelStatus->setText(choppedText);
317         }
318 }
319
320 void WorkingBanner::setProgressMax(unsigned int max)
321 {
322         ui->progressBar->setMaximum(max);
323         if(ui->progressBar->maximum() > ui->progressBar->minimum())
324         {
325                 WinSevenTaskbar::setTaskbarState(dynamic_cast<QWidget*>(this->parent()), WinSevenTaskbar::WinSevenTaskbarNoState);
326                 WinSevenTaskbar::setTaskbarProgress(dynamic_cast<QWidget*>(this->parent()), ui->progressBar->value(), ui->progressBar->maximum());
327         }
328         else
329         {
330                 WinSevenTaskbar::setTaskbarState(dynamic_cast<QWidget*>(this->parent()), WinSevenTaskbar::WinSevenTaskbarIndeterminateState);
331         }
332 }
333
334 void WorkingBanner::setProgressVal(unsigned int val)
335 {
336         ui->progressBar->setValue(val);
337         if(ui->progressBar->maximum() > ui->progressBar->minimum())
338         {
339                 WinSevenTaskbar::setTaskbarProgress(dynamic_cast<QWidget*>(this->parent()), ui->progressBar->value(), ui->progressBar->maximum());
340         }
341 }
342
343 ////////////////////////////////////////////////////////////
344 // Private
345 ////////////////////////////////////////////////////////////
346
347 /*
348 void WorkingBanner::updateProgress(void)
349 {
350         if(m_progressMax > 0)
351         {
352                 int newProgress = qRound(qBound(0.0, static_cast<double>(m_progressVal) / static_cast<double>(m_progressMax), 1.0) * 100.0);
353                 if(m_progressInt != newProgress)
354                 {
355                         m_progressInt = newProgress;
356                         m_progress->setText(QString::number(m_progressInt));
357                         if(this->isVisible())
358                         {
359                                 labelStatus->repaint();
360                         }
361                 }
362         }
363 }
364 */