/***************************************************************************
* Copyright (C) 2006 by Peter Penz *
+ * 2012 Simon A. Eugster <simon.eu@gmail.com> *
* peter.penz@gmx.at *
* Code borrowed from Dolphin, adapted (2008) to Kdenlive by *
* Jean-Baptiste Mardelle, jb@kdenlive.org *
***************************************************************************/
#include "statusbarmessagelabel.h"
+#include "kdenlivesettings.h"
#include <kcolorscheme.h>
#include <kiconloader.h>
#include <kicon.h>
#include <klocale.h>
+#include <KNotification>
#include <QFontMetrics>
#include <QPainter>
#include <QKeyEvent>
#include <QPushButton>
#include <QPixmap>
-#include <QTimer>
+
StatusBarMessageLabel::StatusBarMessageLabel(QWidget* parent) :
- QWidget(parent),
- m_type(DefaultMessage),
- m_state(Default),
- m_illumination(-64),
- m_minTextHeight(-1),
- m_timer(0),
- m_closeButton(0)
+ QWidget(parent),
+ m_state(Default),
+ m_illumination(-64),
+ m_minTextHeight(-1),
+ m_queueSemaphore(1),
+ m_closeButton(0)
{
setMinimumHeight(KIconLoader::SizeSmall);
-
QPalette palette;
palette.setColor(QPalette::Background, Qt::transparent);
setPalette(palette);
- m_timer = new QTimer(this);
- connect(m_timer, SIGNAL(timeout()), this, SLOT(timerDone()));
-
- m_closeButton = new QPushButton(i18nc("@action:button", "Close"), this);
+ m_closeButton = new QPushButton(i18nc("@action:button", "Confirm"), this);
m_closeButton->hide();
- connect(m_closeButton, SIGNAL(clicked()), this, SLOT(closeErrorMessage()));
+
+ m_queueTimer.setSingleShot(true);
+
+ bool b = true;
+ b &= connect(&m_queueTimer, SIGNAL(timeout()), this, SLOT(slotMessageTimeout()));
+
+ b &= connect(m_closeButton, SIGNAL(clicked()), this, SLOT(confirmErrorMessage()));
+ b &= connect(&m_timer, SIGNAL(timeout()), this, SLOT(timerDone()));
+ Q_ASSERT(b);
}
StatusBarMessageLabel::~StatusBarMessageLabel()
}
void StatusBarMessageLabel::setMessage(const QString& text,
- MessageType type)
+ MessageType type, int timeoutMS)
{
- if ((text == m_text) && (type == m_type)) {
- return;
+ StatusBarMessageItem item(text, type, timeoutMS);
+
+ if (item.type == ErrorMessage || item.type == MltError) {
+ KNotification::event("ErrorMessage", item.text);
}
- /*if (m_type == ErrorMessage) {
- if (type == ErrorMessage) {
- m_pendingMessages.insert(0, m_text);
- } else if ((m_state != Default) || !m_pendingMessages.isEmpty()) {
- // a non-error message should not be shown, as there
- // are other pending error messages in the queue
- return;
+ m_queueSemaphore.acquire();
+ if (!m_messageQueue.contains(item)) {
+ if (item.type == ErrorMessage || item.type == MltError) {
+ qDebug() << item.text;
+
+ // Put the new errror message at first place and immediately show it
+ if (item.timeoutMillis < 2000) {
+ item.timeoutMillis = 2000;
+ }
+ m_messageQueue.push_front(item);
+
+ // In case we are already displaying an error message, add a little delay
+ int delay = 800 * (m_currentMessage.type == ErrorMessage || m_currentMessage.type == MltError);
+ m_queueTimer.start(delay);
+
+ } else {
+
+ // Message with normal priority
+ m_messageQueue.push_back(item);
+ if (!m_queueTimer.elapsed() >= m_currentMessage.timeoutMillis) {
+ m_queueTimer.start(0);
+ }
+
}
- }*/
+ }
+
+ m_queueSemaphore.release();
+}
+
+bool StatusBarMessageLabel::slotMessageTimeout()
+{
+ m_queueSemaphore.acquire();
+
+ bool newMessage = false;
+
+ // Get the next message from the queue, unless the current one needs to be confirmed
+ if (m_messageQueue.size() > 0) {
+
+ if (!m_currentMessage.needsConfirmation()) {
+
+ m_currentMessage = m_messageQueue.at(0);
+ m_messageQueue.removeFirst();
+ newMessage = true;
+
+ }
+ }
+
+ // If the queue is empty, add a default (empty) message
+ if (m_messageQueue.size() == 0 && m_currentMessage.type != DefaultMessage) {
+ m_messageQueue.push_back(StatusBarMessageItem());
+ }
+
+ // Start a new timer, unless the current message still needs to be confirmed
+ if (m_messageQueue.size() > 0) {
+
+ if (!m_currentMessage.needsConfirmation()) {
+
+ // If we only have the default message left to show in the queue,
+ // keep the current one for a little longer.
+ m_queueTimer.start(m_currentMessage.timeoutMillis + 4000*(m_messageQueue.at(0).type == DefaultMessage));
+
+ }
+ }
- m_text = text;
- m_type = type;
m_illumination = -64;
m_state = Default;
- m_timer->stop();
+ m_timer.stop();
const char* iconName = 0;
- QPixmap pixmap;
- switch (type) {
+ switch (m_currentMessage.type) {
case OperationCompletedMessage:
iconName = "dialog-ok";
- // "ok" icon should probably be "dialog-success", but we don't have that icon in KDE 4.0
m_closeButton->hide();
break;
case ErrorMessage:
iconName = "dialog-warning";
- m_timer->start(100);
+ m_timer.start(100);
m_state = Illuminate;
m_closeButton->hide();
break;
case MltError:
iconName = "dialog-close";
- m_timer->start(100);
+ m_timer.start(100);
m_state = Illuminate;
updateCloseButtonPosition();
m_closeButton->show();
}
m_pixmap = (iconName == 0) ? QPixmap() : SmallIcon(iconName);
- QTimer::singleShot(GeometryTimeout, this, SLOT(assureVisibleText()));
+
+ m_queueSemaphore.release();
+
update();
+ return newMessage;
+}
+
+void StatusBarMessageLabel::confirmErrorMessage()
+{
+ m_currentMessage.confirmed = true;
+ m_queueTimer.start(0);
}
void StatusBarMessageLabel::setMinimumTextHeight(int min)
}
}
-void StatusBarMessageLabel::paintEvent(QPaintEvent* /* event */)
+void StatusBarMessageLabel::paintEvent(QPaintEvent*)
{
QPainter painter(this);
QColor backgroundColor;
if (m_state == Default || m_illumination < 0) backgroundColor = palette().window().color();
else {
- KColorScheme scheme(palette().currentColorGroup(), KColorScheme::Window);
- backgroundColor = scheme.background(KColorScheme::NegativeBackground).color();
+ backgroundColor = KStatefulBrush(KColorScheme::Window, KColorScheme::NegativeBackground, KSharedConfig::openConfig(KdenliveSettings::colortheme())).brush(this).color();
}
if (m_state == Desaturate && m_illumination > 0) {
backgroundColor.setAlpha(m_illumination * 2);
if (height() > m_minTextHeight) {
flags = flags | Qt::TextWordWrap;
}
- painter.drawText(QRect(x, 0, availableTextWidth(), height()), flags, m_text);
+ painter.drawText(QRect(x, 0, availableTextWidth(), height()), flags, m_currentMessage.text);
painter.end();
}
{
QWidget::resizeEvent(event);
updateCloseButtonPosition();
- QTimer::singleShot(GeometryTimeout, this, SLOT(assureVisibleText()));
}
void StatusBarMessageLabel::timerDone()
update();
} else {
m_state = Illuminated;
- m_timer->start(1500);
+ m_timer.start(1500);
}
break;
}
case Illuminated: {
// start desaturation
- if (m_type != MltError) {
+ if (m_currentMessage.type != MltError) {
m_state = Desaturate;
- m_timer->start(80);
+ m_timer.start(80);
}
break;
}
if (m_illumination < -128) {
m_illumination = 0;
m_state = Default;
- m_timer->stop();
+ m_timer.stop();
setMessage(QString(), DefaultMessage);
} else {
m_illumination -= 5;
}
}
-void StatusBarMessageLabel::assureVisibleText()
-{
- if (m_text.isEmpty()) {
- return;
- }
-
- int requiredHeight = m_minTextHeight;
- if (m_type != DefaultMessage) {
- // Calculate the required height of the widget thats
- // needed for having a fully visible text. Note that for the default
- // statusbar type (e. g. hover information) increasing the text height
- // is not wanted, as this might rearrange the layout of items.
-
- QFontMetrics fontMetrics(font());
- const QRect bounds(fontMetrics.boundingRect(0, 0, availableTextWidth(), height(),
- Qt::AlignVCenter | Qt::TextWordWrap, m_text));
- requiredHeight = bounds.height();
- if (requiredHeight < m_minTextHeight) {
- requiredHeight = m_minTextHeight;
- }
- }
-
- // Increase/decrease the current height of the widget to the
- // required height. The increasing/decreasing is done in several
- // steps to have an animation if the height is modified
- // (see StatusBarMessageLabel::resizeEvent())
- const int gap = m_minTextHeight / 2;
- int minHeight = minimumHeight();
- if (minHeight < requiredHeight) {
- minHeight += gap;
- if (minHeight > requiredHeight) {
- minHeight = requiredHeight;
- }
- setMinimumHeight(minHeight);
- updateGeometry();
- } else if (minHeight > requiredHeight) {
- minHeight -= gap;
- if (minHeight < requiredHeight) {
- minHeight = requiredHeight;
- }
- setMinimumHeight(minHeight);
- updateGeometry();
- }
-
- updateCloseButtonPosition();
-}
-
int StatusBarMessageLabel::availableTextWidth() const
{
const int buttonWidth = 0; /*(m_type == ErrorMessage) ?
m_closeButton->move(x, y);
}
-void StatusBarMessageLabel::closeErrorMessage()
-{
- if (!showPendingMessage()) {
- setMessage(QString(), DefaultMessage);
- }
-}
-
-bool StatusBarMessageLabel::showPendingMessage()
-{
- if (!m_pendingMessages.isEmpty()) {
- setMessage(m_pendingMessages.takeFirst(), ErrorMessage);
- return true;
- }
- return false;
-}
-
#include "statusbarmessagelabel.moc"