X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fstatusbarmessagelabel.cpp;h=1cb0a0647041f70f67fd819e48a1d79a64727413;hb=56aee6aedeeed3efd10ada8fe3c229eddc01ef05;hp=e7e87b48868e090d8e40ed245c2e8ae2378b1194;hpb=a67e3b0ffffda4c6c6098cd7cb1b889a29f15d3d;p=kdenlive diff --git a/src/statusbarmessagelabel.cpp b/src/statusbarmessagelabel.cpp index e7e87b48..1cb0a064 100644 --- a/src/statusbarmessagelabel.cpp +++ b/src/statusbarmessagelabel.cpp @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (C) 2006 by Peter Penz * + * 2012 Simon A. Eugster * * peter.penz@gmx.at * * Code borrowed from Dolphin, adapted (2008) to Kdenlive by * * Jean-Baptiste Mardelle, jb@kdenlive.org * @@ -21,75 +22,133 @@ ***************************************************************************/ #include "statusbarmessagelabel.h" +#include "kdenlivesettings.h" #include #include #include #include +#include #include #include #include #include #include -#include + StatusBarMessageLabel::StatusBarMessageLabel(QWidget* parent) : - QWidget(parent), - m_type(DefaultMessage), - m_state(Default), - m_illumination(0), - 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() { +StatusBarMessageLabel::~StatusBarMessageLabel() +{ } void StatusBarMessageLabel::setMessage(const QString& text, - MessageType type) { - if ((text == m_text) && (type == m_type)) { - return; + MessageType type, int timeoutMS) +{ + StatusBarMessageItem item(text, type, timeoutMS); + + if (item.type == ErrorMessage || item.type == MltError) { + KNotification::event("ErrorMessage", item.text); + } + + 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); + } + + } } - /*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.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.isEmpty()) { + + 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.isEmpty() && 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.isEmpty()) { + + 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_timer->stop(); - m_illumination = 0; + m_illumination = -64; m_state = Default; + 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; @@ -100,11 +159,17 @@ void StatusBarMessageLabel::setMessage(const QString& text, case ErrorMessage: iconName = "dialog-warning"; - m_timer->start(100); + m_timer.start(100); m_state = Illuminate; + m_closeButton->hide(); + break; - //updateCloseButtonPosition(); - //m_closeButton->show(); + case MltError: + iconName = "dialog-close"; + m_timer.start(100); + m_state = Illuminate; + updateCloseButtonPosition(); + m_closeButton->show(); break; case DefaultMessage: @@ -114,42 +179,44 @@ void StatusBarMessageLabel::setMessage(const QString& text, } m_pixmap = (iconName == 0) ? QPixmap() : SmallIcon(iconName); - //QTimer::singleShot(GeometryTimeout, this, SLOT(assureVisibleText())); - show(); //update(); + + m_queueSemaphore.release(); + + update(); + return newMessage; } -void StatusBarMessageLabel::setMinimumTextHeight(int min) { +void StatusBarMessageLabel::confirmErrorMessage() +{ + m_currentMessage.confirmed = true; + m_queueTimer.start(0); +} + +void StatusBarMessageLabel::setMinimumTextHeight(int min) +{ if (min != m_minTextHeight) { m_minTextHeight = min; setMinimumHeight(min); - /*if (m_closeButton->height() > min) { + if (m_closeButton->height() > min) { m_closeButton->setFixedHeight(min); - }*/ + } } } -int StatusBarMessageLabel::widthGap() const { - QFontMetrics fontMetrics(font()); - const int defaultGap = 10; - return fontMetrics.width(m_text) - availableTextWidth() + defaultGap; -} - -void StatusBarMessageLabel::paintEvent(QPaintEvent* /* event */) { +void StatusBarMessageLabel::paintEvent(QPaintEvent*) +{ QPainter painter(this); // draw background - QColor backgroundColor = palette().window().color(); - if (m_illumination > 0) { - // at this point, a: we are a second label being drawn over the already - // painted status area, so we can be translucent, and b: our palette's - // window color (bg only) seems to be wrong (always black) - KColorScheme scheme(palette().currentColorGroup(), KColorScheme::Window); - backgroundColor = scheme.background(KColorScheme::NegativeBackground).color(); - backgroundColor.setAlpha(qMin(255, m_illumination*2)); + QColor backgroundColor; + if (m_state == Default || m_illumination < 0) backgroundColor = palette().window().color(); + else { + backgroundColor = KStatefulBrush(KColorScheme::Window, KColorScheme::NegativeBackground, KSharedConfig::openConfig(KdenliveSettings::colortheme())).brush(this).color(); } - painter.setBrush(backgroundColor); - painter.setPen(Qt::NoPen); - painter.drawRect(0, 0, width(), height()); + if (m_state == Desaturate && m_illumination > 0) { + backgroundColor.setAlpha(m_illumination * 2); + } + painter.fillRect(0, 0, width(), height(), backgroundColor); // draw pixmap int x = BorderGap; @@ -163,20 +230,21 @@ void StatusBarMessageLabel::paintEvent(QPaintEvent* /* event */) { // draw text painter.setPen(palette().windowText().color()); int flags = Qt::AlignVCenter; - /*if (height() > m_minTextHeight) { + 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(); } -void StatusBarMessageLabel::resizeEvent(QResizeEvent* event) { +void StatusBarMessageLabel::resizeEvent(QResizeEvent* event) +{ QWidget::resizeEvent(event); - //updateCloseButtonPosition(); - //QTimer::singleShot(GeometryTimeout, this, SLOT(assureVisibleText())); + updateCloseButtonPosition(); } -void StatusBarMessageLabel::timerDone() { +void StatusBarMessageLabel::timerDone() +{ switch (m_state) { case Illuminate: { // increase the illumination @@ -189,27 +257,30 @@ void StatusBarMessageLabel::timerDone() { update(); } else { m_state = Illuminated; - m_timer->start(5000); + m_timer.start(1500); } break; } case Illuminated: { // start desaturation - m_state = Desaturate; - m_timer->start(100); + if (m_currentMessage.type != MltError) { + m_state = Desaturate; + m_timer.start(80); + } break; } case Desaturate: { // desaturate - if (m_illumination > 0) { + if (m_illumination < -128) { + m_illumination = 0; + m_state = Default; + m_timer.stop(); + setMessage(QString(), DefaultMessage); + } else { m_illumination -= 5; update(); - } else { - m_state = Default; - m_timer->stop(); - reset(); } break; } @@ -219,85 +290,19 @@ void StatusBarMessageLabel::timerDone() { } } -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 { +int StatusBarMessageLabel::availableTextWidth() const +{ const int buttonWidth = 0; /*(m_type == ErrorMessage) ? m_closeButton->width() + BorderGap : 0;*/ return width() - m_pixmap.width() - (BorderGap * 4) - buttonWidth; } -void StatusBarMessageLabel::updateCloseButtonPosition() { +void StatusBarMessageLabel::updateCloseButtonPosition() +{ const int x = width() - m_closeButton->width() - BorderGap; const int y = (height() - m_closeButton->height()) / 2; m_closeButton->move(x, y); } -void StatusBarMessageLabel::closeErrorMessage() { - if (!showPendingMessage()) { - reset(); - setMessage(m_defaultText, DefaultMessage); - } -} - -bool StatusBarMessageLabel::showPendingMessage() { - if (!m_pendingMessages.isEmpty()) { - reset(); - setMessage(m_pendingMessages.takeFirst(), ErrorMessage); - return true; - } - return false; -} - -void StatusBarMessageLabel::reset() { - m_text.clear(); - m_pixmap = QPixmap(); - m_type = DefaultMessage; - update(); -} #include "statusbarmessagelabel.moc"