]> git.sesse.net Git - kdenlive/blob - src/statusbarmessagelabel.cpp
const'ify
[kdenlive] / src / statusbarmessagelabel.cpp
1 /***************************************************************************
2  *   Copyright (C) 2006 by Peter Penz                                      *
3  *                 2012    Simon A. Eugster <simon.eu@gmail.com>           *
4  *   peter.penz@gmx.at                                                     *
5  *   Code borrowed from Dolphin, adapted (2008) to Kdenlive by             *
6  *   Jean-Baptiste Mardelle, jb@kdenlive.org                               *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  *   This program is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with this program; if not, write to the                         *
20  *   Free Software Foundation, Inc.,                                       *
21  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
22  ***************************************************************************/
23
24 #include "statusbarmessagelabel.h"
25 #include "kdenlivesettings.h"
26
27 #include <kcolorscheme.h>
28 #include <kiconloader.h>
29 #include <kicon.h>
30 #include <klocale.h>
31 #include <KNotification>
32
33 #include <QFontMetrics>
34 #include <QPainter>
35 #include <QKeyEvent>
36 #include <QPushButton>
37 #include <QPixmap>
38
39
40 StatusBarMessageLabel::StatusBarMessageLabel(QWidget* parent) :
41     QWidget(parent),
42     m_state(Default),
43     m_illumination(-64),
44     m_minTextHeight(-1),
45     m_queueSemaphore(1),
46     m_closeButton(0)
47 {
48     setMinimumHeight(KIconLoader::SizeSmall);
49     QPalette palette;
50     palette.setColor(QPalette::Background, Qt::transparent);
51     setPalette(palette);
52
53     m_closeButton = new QPushButton(i18nc("@action:button", "Confirm"), this);
54     m_closeButton->hide();
55
56     m_queueTimer.setSingleShot(true);
57
58     bool b = true;
59     b &= connect(&m_queueTimer, SIGNAL(timeout()), this, SLOT(slotMessageTimeout()));
60
61     b &= connect(m_closeButton, SIGNAL(clicked()), this, SLOT(confirmErrorMessage()));
62     b &= connect(&m_timer, SIGNAL(timeout()), this, SLOT(timerDone()));
63     Q_ASSERT(b);
64 }
65
66 StatusBarMessageLabel::~StatusBarMessageLabel()
67 {
68 }
69
70 void StatusBarMessageLabel::setMessage(const QString& text,
71                                        MessageType type, int timeoutMS)
72 {
73     StatusBarMessageItem item(text, type, timeoutMS);
74
75     if (item.type == ErrorMessage || item.type == MltError) {
76         KNotification::event("ErrorMessage", item.text);
77     }
78
79     m_queueSemaphore.acquire();
80     if (!m_messageQueue.contains(item)) {
81         if (item.type == ErrorMessage || item.type == MltError) {
82             qDebug() << item.text;
83
84             // Put the new errror message at first place and immediately show it
85             if (item.timeoutMillis < 2000) {
86                 item.timeoutMillis = 2000;
87             }
88             m_messageQueue.push_front(item);
89
90             // In case we are already displaying an error message, add a little delay
91             int delay = 800 * (m_currentMessage.type == ErrorMessage || m_currentMessage.type == MltError);
92             m_queueTimer.start(delay);
93
94         } else {
95
96             // Message with normal priority
97             m_messageQueue.push_back(item);
98             if (!m_queueTimer.elapsed() >= m_currentMessage.timeoutMillis) {
99                 m_queueTimer.start(0);
100             }
101
102         }
103     }
104
105     m_queueSemaphore.release();
106 }
107
108 bool StatusBarMessageLabel::slotMessageTimeout()
109 {
110     m_queueSemaphore.acquire();
111
112     bool newMessage = false;
113
114     // Get the next message from the queue, unless the current one needs to be confirmed
115     if (!m_messageQueue.isEmpty()) {
116
117         if (!m_currentMessage.needsConfirmation()) {
118
119             m_currentMessage = m_messageQueue.at(0);
120             m_messageQueue.removeFirst();
121             newMessage = true;
122
123         }
124     }
125
126     // If the queue is empty, add a default (empty) message
127     if (m_messageQueue.isEmpty() && m_currentMessage.type != DefaultMessage) {
128         m_messageQueue.push_back(StatusBarMessageItem());
129     }
130
131     // Start a new timer, unless the current message still needs to be confirmed
132     if (!m_messageQueue.isEmpty()) {
133
134         if (!m_currentMessage.needsConfirmation()) {
135
136             // If we only have the default message left to show in the queue,
137             // keep the current one for a little longer.
138             m_queueTimer.start(m_currentMessage.timeoutMillis + 4000*(m_messageQueue.at(0).type == DefaultMessage));
139
140         }
141     }
142
143
144     m_illumination = -64;
145     m_state = Default;
146     m_timer.stop();
147
148     const char* iconName = 0;
149     switch (m_currentMessage.type) {
150     case OperationCompletedMessage:
151         iconName = "dialog-ok";
152         m_closeButton->hide();
153         break;
154
155     case InformationMessage:
156         iconName = "dialog-information";
157         m_closeButton->hide();
158         break;
159
160     case ErrorMessage:
161         iconName = "dialog-warning";
162         m_timer.start(100);
163         m_state = Illuminate;
164         m_closeButton->hide();
165         break;
166
167     case MltError:
168         iconName = "dialog-close";
169         m_timer.start(100);
170         m_state = Illuminate;
171         updateCloseButtonPosition();
172         m_closeButton->show();
173         break;
174
175     case DefaultMessage:
176     default:
177         m_closeButton->hide();
178         break;
179     }
180
181     m_pixmap = (iconName == 0) ? QPixmap() : SmallIcon(iconName);
182
183     m_queueSemaphore.release();
184
185     update();
186     return newMessage;
187 }
188
189 void StatusBarMessageLabel::confirmErrorMessage()
190 {
191     m_currentMessage.confirmed = true;
192     m_queueTimer.start(0);
193 }
194
195 void StatusBarMessageLabel::setMinimumTextHeight(int min)
196 {
197     if (min != m_minTextHeight) {
198         m_minTextHeight = min;
199         setMinimumHeight(min);
200         if (m_closeButton->height() > min) {
201             m_closeButton->setFixedHeight(min);
202         }
203     }
204 }
205
206 void StatusBarMessageLabel::paintEvent(QPaintEvent*)
207 {
208     QPainter painter(this);
209
210     // draw background
211     QColor backgroundColor;
212     if (m_state == Default || m_illumination < 0) backgroundColor = palette().window().color();
213     else {
214         backgroundColor = KStatefulBrush(KColorScheme::Window, KColorScheme::NegativeBackground, KSharedConfig::openConfig(KdenliveSettings::colortheme())).brush(this).color();
215     }
216     if (m_state == Desaturate && m_illumination > 0) {
217         backgroundColor.setAlpha(m_illumination * 2);
218     }
219     painter.fillRect(0, 0, width(), height(), backgroundColor);
220
221     // draw pixmap
222     int x = BorderGap;
223     int y = (height() - m_pixmap.height()) / 2;
224
225     if (!m_pixmap.isNull()) {
226         painter.drawPixmap(x, y, m_pixmap);
227         x += m_pixmap.width() + BorderGap * 2;
228     }
229
230     // draw text
231     painter.setPen(palette().windowText().color());
232     int flags = Qt::AlignVCenter;
233     if (height() > m_minTextHeight) {
234         flags = flags | Qt::TextWordWrap;
235     }
236     painter.drawText(QRect(x, 0, availableTextWidth(), height()), flags, m_currentMessage.text);
237     painter.end();
238 }
239
240 void StatusBarMessageLabel::resizeEvent(QResizeEvent* event)
241 {
242     QWidget::resizeEvent(event);
243     updateCloseButtonPosition();
244 }
245
246 void StatusBarMessageLabel::timerDone()
247 {
248     switch (m_state) {
249     case Illuminate: {
250         // increase the illumination
251         const int illumination_max = 128;
252         if (m_illumination < illumination_max) {
253             m_illumination += 32;
254             if (m_illumination > illumination_max) {
255                 m_illumination = illumination_max;
256             }
257             update();
258         } else {
259             m_state = Illuminated;
260             m_timer.start(1500);
261         }
262         break;
263     }
264
265     case Illuminated: {
266         // start desaturation
267         if (m_currentMessage.type != MltError) {
268             m_state = Desaturate;
269             m_timer.start(80);
270         }
271         break;
272     }
273
274     case Desaturate: {
275         // desaturate
276         if (m_illumination < -128) {
277             m_illumination = 0;
278             m_state = Default;
279             m_timer.stop();
280             setMessage(QString(), DefaultMessage);
281         } else {
282             m_illumination -= 5;
283             update();
284         }
285         break;
286     }
287
288     default:
289         break;
290     }
291 }
292
293 int StatusBarMessageLabel::availableTextWidth() const
294 {
295     const int buttonWidth = 0; /*(m_type == ErrorMessage) ?
296                             m_closeButton->width() + BorderGap : 0;*/
297     return width() - m_pixmap.width() - (BorderGap * 4) - buttonWidth;
298 }
299
300 void StatusBarMessageLabel::updateCloseButtonPosition()
301 {
302     const int x = width() - m_closeButton->width() - BorderGap;
303     const int y = (height() - m_closeButton->height()) / 2;
304     m_closeButton->move(x, y);
305 }
306
307
308 #include "statusbarmessagelabel.moc"