OSDN Git Service

CodeSign tool updated to version 1.0.1 (2022-06-27).
[lamexp/LameXP.git] / src / Dialog_WorkingBanner.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2022 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; always including the non-optional
9 // LAMEXP GNU GENERAL PUBLIC LICENSE ADDENDUM. See "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
29 //MUtils
30 #include <MUtils/Global.h>
31 #include <MUtils/GUI.h>
32 #include <MUtils/Taskbar7.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()),
88         m_iconHourglass(new QIcon(":/icons/hourglass.png")),
89         m_taskbar(new MUtils::Taskbar7(parent)),
90         m_metrics(NULL), m_working(NULL), m_style(NULL)
91 {
92         //Init the dialog, from the .ui file
93         ui->setupUi(this);
94         setModal(true);
95
96         //Enable the "sheet of glass" effect
97         if(MUtils::GUI::sheet_of_glass(this))
98         {
99                 m_style.reset(new QWindowsVistaStyle());
100                 this->setStyle(m_style.data());
101                 ui->progressBar->setStyle(m_style.data());
102                 ui->labelStatus->setStyle(m_style.data());
103                 ui->labelStatus->setStyleSheet("background-color: #FFFFFF;");
104         }
105         else
106         {
107                 UPDATE_MARGINS(this, 5);
108                 m_working.reset(new QMovie(":/images/Busy.gif"));
109                 m_working->setCacheMode(QMovie::CacheAll);
110                 ui->labelWorking->setMovie(m_working.data());
111         }
112         
113         //Set Opacity
114         this->setWindowOpacity(0.9);
115
116         //Set wait cursor
117         setCursor(Qt::WaitCursor);
118
119         //Clear label
120         ui->labelStatus->clear();
121 }
122
123 ////////////////////////////////////////////////////////////
124 // Destructor
125 ////////////////////////////////////////////////////////////
126
127 WorkingBanner::~WorkingBanner(void)
128 {
129         if(!m_working.isNull())
130         {
131                 m_working->stop();
132         }
133
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         m_taskbar->setOverlayIcon(m_iconHourglass.data());
167         m_taskbar->setTaskbarState(MUtils::Taskbar7::TASKBAR_STATE_INTERMEDIATE);
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         m_taskbar->setTaskbarState(MUtils::Taskbar7::TASKBAR_STATE_NONE);
186         m_taskbar->setOverlayIcon(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         m_taskbar->setOverlayIcon(m_iconHourglass.data());
202         m_taskbar->setTaskbarState(MUtils::Taskbar7::TASKBAR_STATE_INTERMEDIATE);
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         m_taskbar->setTaskbarState(MUtils::Taskbar7::TASKBAR_STATE_NONE);
215         m_taskbar->setOverlayIcon(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 void WorkingBanner::showEvent(QShowEvent *event)
258 {
259         QDialog::showEvent(event);
260         if(!event->spontaneous())
261         {
262                 if(m_working)
263                 {
264                         m_working->start();
265                 }
266         }
267         QTimer::singleShot(25, this, SLOT(windowShown()));
268 }
269
270 void WorkingBanner::hideEvent(QHideEvent *event)
271 {
272         QDialog::hideEvent(event);
273         if(!event->spontaneous())
274         {
275                 if(m_working)
276                 {
277                         m_working->stop();
278                 }
279         }
280 }
281
282 ////////////////////////////////////////////////////////////
283 // SLOTS
284 ////////////////////////////////////////////////////////////
285
286 void WorkingBanner::windowShown(void)
287 {
288         MUtils::GUI::bring_to_front(this);
289 }
290
291 void WorkingBanner::setText(const QString &text)
292 {
293         if(m_metrics.isNull())
294         {
295                  m_metrics.reset(new QFontMetrics(ui->labelStatus->font()));
296         }
297
298         if(m_metrics->width(text) <= ui->labelStatus->width() - 16)
299         {
300                 ui->labelStatus->setText(text);
301         }
302         else
303         {
304                 QString choppedText = text.simplified().append("...");
305                 while((m_metrics->width(choppedText) > ui->labelStatus->width() - 16) && (choppedText.length() > 8))
306                 {
307                         choppedText.chop(4);
308                         choppedText = choppedText.trimmed();
309                         choppedText.append("...");
310                 }
311                 ui->labelStatus->setText(choppedText);
312         }
313 }
314
315 void WorkingBanner::setProgressMax(unsigned int max)
316 {
317         ui->progressBar->setMaximum(max);
318         if(ui->progressBar->maximum() > ui->progressBar->minimum())
319         {
320                 m_taskbar->setTaskbarState(MUtils::Taskbar7::TASKBAR_STATE_NONE);
321                 m_taskbar->setTaskbarProgress(ui->progressBar->value(), ui->progressBar->maximum());
322         }
323         else
324         {
325                 m_taskbar->setTaskbarState(MUtils::Taskbar7::TASKBAR_STATE_INTERMEDIATE);
326         }
327 }
328
329 void WorkingBanner::setProgressVal(unsigned int val)
330 {
331         ui->progressBar->setValue(val);
332         if(ui->progressBar->maximum() > ui->progressBar->minimum())
333         {
334                 m_taskbar->setTaskbarProgress(ui->progressBar->value(), ui->progressBar->maximum());
335         }
336 }
337
338 ////////////////////////////////////////////////////////////
339 // Private
340 ////////////////////////////////////////////////////////////
341
342 /*
343 void WorkingBanner::updateProgress(void)
344 {
345         if(m_progressMax > 0)
346         {
347                 int newProgress = qRound(qBound(0.0, static_cast<double>(m_progressVal) / static_cast<double>(m_progressMax), 1.0) * 100.0);
348                 if(m_progressInt != newProgress)
349                 {
350                         m_progressInt = newProgress;
351                         m_progress->setText(QString::number(m_progressInt));
352                         if(this->isVisible())
353                         {
354                                 labelStatus->repaint();
355                         }
356                 }
357         }
358 }
359 */