diff options
author | Tomaz Canabrava <tomaz.canabrava@gmail.com> | 2015-06-03 22:08:57 -0300 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2015-06-03 21:26:31 -0700 |
commit | ef10490e037c435cac8b1089cb9130d260351ad2 (patch) | |
tree | 49602dc027bb4912b8eb73f53a6b8f5c7fed025f /qt-ui | |
parent | be0a708db0b05f2b8a42f81d49020ca2e656b714 (diff) | |
download | subsurface-ef10490e037c435cac8b1089cb9130d260351ad2.tar.gz |
Update KMessageWidget to KF5
The KMessageWidget that we used was from an ancient version of KDE4, KF5
is out for quite a while, so it's good that we also update our software
that uses parts of KDE.
Signed-off-by: Tomaz Canabrava <tomaz.canabrava@gmail.com>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'qt-ui')
-rw-r--r-- | qt-ui/kmessagewidget.cpp | 569 | ||||
-rw-r--r-- | qt-ui/kmessagewidget.h | 381 | ||||
-rw-r--r-- | qt-ui/maintab.cpp | 14 |
3 files changed, 564 insertions, 400 deletions
diff --git a/qt-ui/kmessagewidget.cpp b/qt-ui/kmessagewidget.cpp index bfa8c2745..04fb6c2b0 100644 --- a/qt-ui/kmessagewidget.cpp +++ b/qt-ui/kmessagewidget.cpp @@ -1,6 +1,7 @@ /* This file is part of the KDE libraries * * Copyright (c) 2011 Aurélien Gâteau <agateau@kde.org> + * Copyright (c) 2014 Dominik Haumann <dhaumann@kde.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,406 +20,460 @@ */ #include "kmessagewidget.h" +#include <QAction> +#include <QEvent> #include <QGridLayout> -#include <QDialogButtonBox> +#include <QHBoxLayout> #include <QLabel> #include <QPainter> #include <QShowEvent> #include <QTimeLine> #include <QToolButton> #include <QStyle> -#include <QAction> + +//--------------------------------------------------------------------- +// KMessageWidgetPrivate +//--------------------------------------------------------------------- +class KMessageWidgetPrivate +{ +public: + void init(KMessageWidget *); + + KMessageWidget *q; + QFrame *content; + QLabel *iconLabel; + QLabel *textLabel; + QToolButton *closeButton; + QTimeLine *timeLine; + QIcon icon; + + KMessageWidget::MessageType messageType; + bool wordWrap; + QList<QToolButton *> buttons; + QPixmap contentSnapShot; + + void createLayout(); + void updateSnapShot(); + void updateLayout(); + void slotTimeLineChanged(qreal); + void slotTimeLineFinished(); + + int bestContentHeight() const; +}; void KMessageWidgetPrivate::init(KMessageWidget *q_ptr) { - q = q_ptr; + q = q_ptr; + + q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + + timeLine = new QTimeLine(500, q); + QObject::connect(timeLine, SIGNAL(valueChanged(qreal)), q, SLOT(slotTimeLineChanged(qreal))); + QObject::connect(timeLine, SIGNAL(finished()), q, SLOT(slotTimeLineFinished())); - q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + content = new QFrame(q); + content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - timeLine = new QTimeLine(500, q); - QObject::connect(timeLine, SIGNAL(valueChanged(qreal)), q, SLOT(slotTimeLineChanged(qreal))); - QObject::connect(timeLine, SIGNAL(finished()), q, SLOT(slotTimeLineFinished())); + wordWrap = false; - content = new QFrame(q); - content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + iconLabel = new QLabel(content); + iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + iconLabel->hide(); - wordWrap = false; + textLabel = new QLabel(content); + textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); + QObject::connect(textLabel, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString))); + QObject::connect(textLabel, SIGNAL(linkHovered(QString)), q, SIGNAL(linkHovered(QString))); - iconLabel = new QLabel(content); - iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - iconLabel->hide(); + QAction *closeAction = new QAction(q); + closeAction->setText(KMessageWidget::tr("&Close")); + closeAction->setToolTip(KMessageWidget::tr("Close message")); + closeAction->setIcon(q->style()->standardIcon(QStyle::SP_DialogCloseButton)); - textLabel = new QLabel(content); - textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); - QObject::connect(textLabel, SIGNAL(linkActivated(const QString &)), q, SIGNAL(linkActivated(const QString &))); - QObject::connect(textLabel, SIGNAL(linkHovered(const QString &)), q, SIGNAL(linkHovered(const QString &))); + QObject::connect(closeAction, SIGNAL(triggered(bool)), q, SLOT(animatedHide())); - QAction *closeAction = new QAction(QObject::tr("Close"), q); - q->connect(closeAction, SIGNAL(triggered(bool)), q, SLOT(animatedHide())); + closeButton = new QToolButton(content); + closeButton->setAutoRaise(true); + closeButton->setDefaultAction(closeAction); - closeButton = new QToolButton(content); - closeButton->setAutoRaise(true); - closeButton->setDefaultAction(closeAction); - closeButton->setVisible(false); - q->setMessageType(KMessageWidget::Information); + q->setMessageType(KMessageWidget::Information); } void KMessageWidgetPrivate::createLayout() { - delete content->layout(); - - content->resize(q->size()); - - qDeleteAll(buttons); - buttons.clear(); - - Q_FOREACH (QAction *action, q->actions()) { - QToolButton *button = new QToolButton(content); - button->setDefaultAction(action); - button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - buttons.append(button); - } - - // AutoRaise reduces visual clutter, but we don't want to turn it on if - // there are other buttons, otherwise the close button will look different - // from the others. - closeButton->setAutoRaise(buttons.isEmpty()); - - if (wordWrap) { - QGridLayout *layout = new QGridLayout(content); - // Set alignment to make sure icon does not move down if text wraps - layout->addWidget(iconLabel, 0, 0, 1, 1, Qt::AlignHCenter | Qt::AlignTop); - layout->addWidget(textLabel, 0, 1); - - QDialogButtonBox *buttonLayout = new QDialogButtonBox(); - //buttonLayout->addStretch(); - Q_FOREACH (QToolButton *button, buttons) { - // For some reason, calling show() is necessary if wordwrap is true, - // otherwise the buttons do not show up. It is not needed if - // wordwrap is false. - button->show(); - buttonLayout->addButton(button, QDialogButtonBox::QDialogButtonBox::AcceptRole); - } - buttonLayout->addButton(closeButton, QDialogButtonBox::RejectRole); - layout->addWidget(buttonLayout, 1, 0, 1, 2, Qt::AlignHCenter | Qt::AlignTop); - } else { - bool closeButtonVisible = closeButton->isVisible(); - QHBoxLayout *layout = new QHBoxLayout(content); - layout->addWidget(iconLabel); - layout->addWidget(textLabel); - - QDialogButtonBox *buttonLayout = new QDialogButtonBox(); - Q_FOREACH (QToolButton *button, buttons) { - buttonLayout->addButton(button, QDialogButtonBox::QDialogButtonBox::AcceptRole); - } - - buttonLayout->addButton(closeButton, QDialogButtonBox::RejectRole); - // Something gets changed when added to the buttonLayout - closeButton->setVisible(closeButtonVisible); - layout->addWidget(buttonLayout); - }; - - if (q->isVisible()) { - q->setFixedHeight(content->sizeHint().height()); - } - - q->updateGeometry(); + delete content->layout(); + + content->resize(q->size()); + + qDeleteAll(buttons); + buttons.clear(); + + Q_FOREACH (QAction *action, q->actions()) { + QToolButton *button = new QToolButton(content); + button->setDefaultAction(action); + button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + buttons.append(button); + } + + // AutoRaise reduces visual clutter, but we don't want to turn it on if + // there are other buttons, otherwise the close button will look different + // from the others. + closeButton->setAutoRaise(buttons.isEmpty()); + + if (wordWrap) { + QGridLayout *layout = new QGridLayout(content); + // Set alignment to make sure icon does not move down if text wraps + layout->addWidget(iconLabel, 0, 0, 1, 1, Qt::AlignHCenter | Qt::AlignTop); + layout->addWidget(textLabel, 0, 1); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addStretch(); + Q_FOREACH (QToolButton *button, buttons) { + // For some reason, calling show() is necessary if wordwrap is true, + // otherwise the buttons do not show up. It is not needed if + // wordwrap is false. + button->show(); + buttonLayout->addWidget(button); + } + buttonLayout->addWidget(closeButton); + layout->addItem(buttonLayout, 1, 0, 1, 2); + } else { + QHBoxLayout *layout = new QHBoxLayout(content); + layout->addWidget(iconLabel); + layout->addWidget(textLabel); + + Q_FOREACH (QToolButton *button, buttons) { + layout->addWidget(button); + } + + layout->addWidget(closeButton); + }; + + if (q->isVisible()) { + q->setFixedHeight(content->sizeHint().height()); + } + q->updateGeometry(); } void KMessageWidgetPrivate::updateLayout() { - if (content->layout()) { - createLayout(); - } + if (content->layout()) { + createLayout(); + } } void KMessageWidgetPrivate::updateSnapShot() { - // Attention: updateSnapShot calls QWidget::render(), which causes the whole - // window layouts to be activated. Calling this method from resizeEvent() - // can lead to infinite recursion, see: - // https://bugs.kde.org/show_bug.cgi?id=311336 - contentSnapShot = QPixmap(content->size()); - contentSnapShot.fill(Qt::transparent); - content->render(&contentSnapShot, QPoint(), QRegion(), QWidget::DrawChildren); + // Attention: updateSnapShot calls QWidget::render(), which causes the whole + // window layouts to be activated. Calling this method from resizeEvent() + // can lead to infinite recursion, see: + // https://bugs.kde.org/show_bug.cgi?id=311336 + contentSnapShot = QPixmap(content->size() * q->devicePixelRatio()); + contentSnapShot.setDevicePixelRatio(q->devicePixelRatio()); + contentSnapShot.fill(Qt::transparent); + content->render(&contentSnapShot, QPoint(), QRegion(), QWidget::DrawChildren); } void KMessageWidgetPrivate::slotTimeLineChanged(qreal value) { - q->setFixedHeight(qMin(value * 2, qreal(1.0)) * content->height()); - q->update(); + q->setFixedHeight(qMin(value * 2, qreal(1.0)) * content->height()); + q->update(); } void KMessageWidgetPrivate::slotTimeLineFinished() { - if (timeLine->direction() == QTimeLine::Forward) { - // Show - // We set the whole geometry here, because it may be wrong if a - // KMessageWidget is shown right when the toplevel window is created. - content->setGeometry(0, 0, q->width(), bestContentHeight()); - } else { - // Hide - q->hide(); - } + if (timeLine->direction() == QTimeLine::Forward) { + // Show + // We set the whole geometry here, because it may be wrong if a + // KMessageWidget is shown right when the toplevel window is created. + content->setGeometry(0, 0, q->width(), bestContentHeight()); + + // notify about finished animation + emit q->showAnimationFinished(); + } else { + // hide and notify about finished animation + q->hide(); + emit q->hideAnimationFinished(); + } } int KMessageWidgetPrivate::bestContentHeight() const { - int height = content->heightForWidth(q->width()); - - if (height == -1) { - height = content->sizeHint().height(); - } - - return height; + int height = content->heightForWidth(q->width()); + if (height == -1) { + height = content->sizeHint().height(); + } + return height; } - //--------------------------------------------------------------------- // KMessageWidget //--------------------------------------------------------------------- -KMessageWidget::KMessageWidget(QWidget *parent) : QFrame(parent), d(new KMessageWidgetPrivate) +KMessageWidget::KMessageWidget(QWidget *parent) + : QFrame(parent) + , d(new KMessageWidgetPrivate) { - d->init(this); + d->init(this); } -KMessageWidget::KMessageWidget(const QString &text, QWidget *parent) : QFrame(parent), d(new KMessageWidgetPrivate) +KMessageWidget::KMessageWidget(const QString &text, QWidget *parent) + : QFrame(parent) + , d(new KMessageWidgetPrivate) { - d->init(this); - setText(text); + d->init(this); + setText(text); } KMessageWidget::~KMessageWidget() { - delete d; + delete d; } QString KMessageWidget::text() const { - return d->textLabel->text(); + return d->textLabel->text(); } void KMessageWidget::setText(const QString &text) { - d->textLabel->setText(text); - updateGeometry(); + d->textLabel->setText(text); + updateGeometry(); } -int KMessageWidget::bestContentHeight() const +KMessageWidget::MessageType KMessageWidget::messageType() const { - return d->bestContentHeight(); + return d->messageType; } - -KMessageWidget::MessageType KMessageWidget::messageType() const +static QColor darkShade(QColor c) { - return d->messageType; + qreal contrast = 0.7; // taken from kcolorscheme for the dark shade + + qreal darkAmount; + if (c.lightnessF() < 0.006) { /* too dark */ + darkAmount = 0.02 + 0.40 * contrast; + } else if (c.lightnessF() > 0.93) { /* too bright */ + darkAmount = -0.06 - 0.60 * contrast; + } else { + darkAmount = (-c.lightnessF()) * (0.55 + contrast * 0.35); + } + + qreal v = c.lightnessF() + darkAmount; + v = v > 0.0 ? (v < 1.0 ? v : 1.0) : 0.0; + c.setHsvF(c.hslHueF(), c.hslSaturationF(), v); + return c; } void KMessageWidget::setMessageType(KMessageWidget::MessageType type) { - d->messageType = type; - QColor bg0, bg1, bg2, border, fg; - - switch (type) { - case Positive: - bg1 = QColor("#72D594"); // nice green - fg = QColor(Qt::white); - break; - - case Information: - bg1 = QColor("#41A8E3"); // nice blue - fg = QColor(Qt::black); - break; - - case Warning: - bg1 = QColor("#72D594"); // nice yellow - fg = QColor(Qt::black); - break; - - case Error: - bg1 = QColor("#E4B7B7"); // nice red. - fg = QColor(Qt::black); - break; - } - - // Colors - bg0 = bg1.lighter(110); - bg2 = bg1.darker(110); - border = bg2.darker(110); - d->content->setStyleSheet( - QString(".QFrame {" - "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," - " stop: 0 %1," - " stop: 0.1 %2," - " stop: 1.0 %3);" - "border-radius: 5px;" - "border: 1px solid %4;" - "margin: %5px;" - "}" - ".QLabel { color: %6; }").arg(bg0.name()) - .arg(bg1.name()) - .arg(bg2.name()) - .arg(border.name()) - /* - DefaultFrameWidth returns the size of the external margin + border width. - We know our border is 1px, so we subtract this from the frame - normal QStyle FrameWidth to get our margin - */ - .arg(style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this) - 1) - .arg(fg.name())); + d->messageType = type; + QColor bg0, bg1, bg2, border, fg; + switch (type) { + case Positive: + bg1.setRgb(0, 110, 40); // values taken from kcolorscheme.cpp (Positive) + break; + case Information: + bg1 = palette().highlight().color(); + break; + case Warning: + bg1.setRgb(176, 128, 0); // values taken from kcolorscheme.cpp (Neutral) + break; + case Error: + bg1.setRgb(191, 3, 3); // values taken from kcolorscheme.cpp (Negative) + break; + } + + // Colors + fg = palette().highlightedText().color(); + bg0 = bg1.lighter(110); + bg2 = bg1.darker(110); + border = darkShade(bg1); + + d->content->setStyleSheet( + QString(QLatin1String(".QFrame {" + "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," + " stop: 0 %1," + " stop: 0.1 %2," + " stop: 1.0 %3);" + "border-radius: 5px;" + "border: 1px solid %4;" + "margin: %5px;" + "}" + ".QLabel { color: %6; }" + )) + .arg(bg0.name()) + .arg(bg1.name()) + .arg(bg2.name()) + .arg(border.name()) + // DefaultFrameWidth returns the size of the external margin + border width. We know our border is 1px, so we subtract this from the frame normal QStyle FrameWidth to get our margin + .arg(style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this) - 1) + .arg(fg.name()) + ); } QSize KMessageWidget::sizeHint() const { - ensurePolished(); - return d->content->sizeHint(); + ensurePolished(); + return d->content->sizeHint(); } QSize KMessageWidget::minimumSizeHint() const { - ensurePolished(); - return d->content->minimumSizeHint(); + ensurePolished(); + return d->content->minimumSizeHint(); } bool KMessageWidget::event(QEvent *event) { - if (event->type() == QEvent::Polish && !d->content->layout()) { - d->createLayout(); - } - - return QFrame::event(event); + if (event->type() == QEvent::Polish && !d->content->layout()) { + d->createLayout(); + } + return QFrame::event(event); } void KMessageWidget::resizeEvent(QResizeEvent *event) { - QFrame::resizeEvent(event); + QFrame::resizeEvent(event); - if (d->timeLine->state() == QTimeLine::NotRunning) { - d->content->resize(width(), d->bestContentHeight()); - } + if (d->timeLine->state() == QTimeLine::NotRunning) { + d->content->resize(width(), d->bestContentHeight()); + } } int KMessageWidget::heightForWidth(int width) const { - ensurePolished(); - return d->content->heightForWidth(width); + ensurePolished(); + return d->content->heightForWidth(width); } void KMessageWidget::paintEvent(QPaintEvent *event) { - QFrame::paintEvent(event); - - if (d->timeLine->state() == QTimeLine::Running) { - QPainter painter(this); - painter.setOpacity(d->timeLine->currentValue() * d->timeLine->currentValue()); - painter.drawPixmap(0, 0, d->contentSnapShot); - } -} - -void KMessageWidget::showEvent(QShowEvent *event) -{ - // Keep this method here to avoid breaking binary compatibility: - // QFrame::showEvent() used to be reimplemented. - QFrame::showEvent(event); + QFrame::paintEvent(event); + if (d->timeLine->state() == QTimeLine::Running) { + QPainter painter(this); + painter.setOpacity(d->timeLine->currentValue() * d->timeLine->currentValue()); + painter.drawPixmap(0, 0, d->contentSnapShot); + } } bool KMessageWidget::wordWrap() const { - return d->wordWrap; + return d->wordWrap; } void KMessageWidget::setWordWrap(bool wordWrap) { - d->wordWrap = wordWrap; - d->textLabel->setWordWrap(wordWrap); - QSizePolicy policy = sizePolicy(); - policy.setHeightForWidth(wordWrap); - setSizePolicy(policy); - d->updateLayout(); - - // Without this, when user does wordWrap -> !wordWrap -> wordWrap, a minimum - // height is set, causing the widget to be too high. - // Mostly visible in test programs. - if (wordWrap) { - setMinimumHeight(0); - } + d->wordWrap = wordWrap; + d->textLabel->setWordWrap(wordWrap); + QSizePolicy policy = sizePolicy(); + policy.setHeightForWidth(wordWrap); + setSizePolicy(policy); + d->updateLayout(); + // Without this, when user does wordWrap -> !wordWrap -> wordWrap, a minimum + // height is set, causing the widget to be too high. + // Mostly visible in test programs. + if (wordWrap) { + setMinimumHeight(0); + } } bool KMessageWidget::isCloseButtonVisible() const { - return d->closeButton->isVisible(); + return d->closeButton->isVisible(); } void KMessageWidget::setCloseButtonVisible(bool show) { - d->closeButton->setVisible(show); - updateGeometry(); + d->closeButton->setVisible(show); + updateGeometry(); } void KMessageWidget::addAction(QAction *action) { - QFrame::addAction(action); - d->updateLayout(); + QFrame::addAction(action); + d->updateLayout(); } void KMessageWidget::removeAction(QAction *action) { - QFrame::removeAction(action); - d->updateLayout(); + QFrame::removeAction(action); + d->updateLayout(); } void KMessageWidget::animatedShow() { - if (isVisible()) { - return; - } + if (!style()->styleHint(QStyle::SH_Widget_Animate, 0, this)) { + show(); + emit showAnimationFinished(); + return; + } - QFrame::show(); - setFixedHeight(0); - int wantedHeight = d->bestContentHeight(); - d->content->setGeometry(0, -wantedHeight, width(), wantedHeight); + if (isVisible()) { + return; + } - d->updateSnapShot(); + QFrame::show(); + setFixedHeight(0); + int wantedHeight = d->bestContentHeight(); + d->content->setGeometry(0, -wantedHeight, width(), wantedHeight); - d->timeLine->setDirection(QTimeLine::Forward); + d->updateSnapShot(); - if (d->timeLine->state() == QTimeLine::NotRunning) { - d->timeLine->start(); - } + d->timeLine->setDirection(QTimeLine::Forward); + if (d->timeLine->state() == QTimeLine::NotRunning) { + d->timeLine->start(); + } } void KMessageWidget::animatedHide() { - if (!isVisible()) { - hide(); - return; - } + if (!style()->styleHint(QStyle::SH_Widget_Animate, 0, this)) { + hide(); + emit hideAnimationFinished(); + return; + } - d->content->move(0, -d->content->height()); - d->updateSnapShot(); + if (!isVisible()) { + return; + } - d->timeLine->setDirection(QTimeLine::Backward); + d->content->move(0, -d->content->height()); + d->updateSnapShot(); - if (d->timeLine->state() == QTimeLine::NotRunning) { - d->timeLine->start(); - } + d->timeLine->setDirection(QTimeLine::Backward); + if (d->timeLine->state() == QTimeLine::NotRunning) { + d->timeLine->start(); + } +} + +bool KMessageWidget::isHideAnimationRunning() const +{ + return (d->timeLine->direction() == QTimeLine::Backward) + && (d->timeLine->state() == QTimeLine::Running); +} + +bool KMessageWidget::isShowAnimationRunning() const +{ + return (d->timeLine->direction() == QTimeLine::Forward) + && (d->timeLine->state() == QTimeLine::Running); } QIcon KMessageWidget::icon() const { - return d->icon; + return d->icon; } void KMessageWidget::setIcon(const QIcon &icon) { - d->icon = icon; - - if (d->icon.isNull()) { - d->iconLabel->hide(); - } else { - d->iconLabel->setPixmap(d->icon.pixmap(QSize(16, 16))); - d->iconLabel->show(); - } + d->icon = icon; + if (d->icon.isNull()) { + d->iconLabel->hide(); + } else { + const int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize); + d->iconLabel->setPixmap(d->icon.pixmap(size)); + d->iconLabel->show(); + } } + +#include "moc_kmessagewidget.cpp" diff --git a/qt-ui/kmessagewidget.h b/qt-ui/kmessagewidget.h index dbc694afa..885d2a78f 100644 --- a/qt-ui/kmessagewidget.h +++ b/qt-ui/kmessagewidget.h @@ -1,6 +1,7 @@ /* This file is part of the KDE libraries * * Copyright (c) 2011 Aurélien Gâteau <agateau@kde.org> + * Copyright (c) 2014 Dominik Haumann <dhaumann@kde.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,9 +32,14 @@ class KMessageWidgetPrivate; * feedback, or to implement opportunistic interactions. * * As a feedback widget, KMessageWidget provides a less intrusive alternative - * to "OK Only" message boxes. If you do not need the modalness of KMessageBox, + * to "OK Only" message boxes. If you want to avoid a modal KMessageBox, * consider using KMessageWidget instead. * + * Examples of KMessageWidget look as follows, all of them having an icon set + * with setIcon(), and the first three show a close button: + * + * \image html kmessagewidget.png "KMessageWidget with different message types" + * * <b>Negative feedback</b> * * The KMessageWidget can be used as a secondary indicator of failure: the @@ -67,7 +73,7 @@ class KMessageWidgetPrivate; * @li Confirm success of "critical" transactions * @li Indicate completion of background tasks * - * Example of inadapted uses: + * Example of unadapted uses: * * @li Indicate successful saving of a file * @li Indicate a file has been successfully removed @@ -87,153 +93,250 @@ class KMessageWidgetPrivate; * @author Aurélien Gâteau <agateau@kde.org> * @since 4.7 */ -class KMessageWidget : public QFrame { - Q_OBJECT - Q_ENUMS(MessageType) - - Q_PROPERTY(QString text READ text WRITE setText) - Q_PROPERTY(bool wordWrap READ wordWrap WRITE setWordWrap) - Q_PROPERTY(bool closeButtonVisible READ isCloseButtonVisible WRITE setCloseButtonVisible) - Q_PROPERTY(MessageType messageType READ messageType WRITE setMessageType) - Q_PROPERTY(QIcon icon READ icon WRITE setIcon) +class KMessageWidget : public QFrame +{ + Q_OBJECT + Q_ENUMS(MessageType) + + Q_PROPERTY(QString text READ text WRITE setText) + Q_PROPERTY(bool wordWrap READ wordWrap WRITE setWordWrap) + Q_PROPERTY(bool closeButtonVisible READ isCloseButtonVisible WRITE setCloseButtonVisible) + Q_PROPERTY(MessageType messageType READ messageType WRITE setMessageType) + Q_PROPERTY(QIcon icon READ icon WRITE setIcon) public: - enum MessageType { - Positive, - Information, - Warning, - Error - }; - - /** - * Constructs a KMessageWidget with the specified parent. - */ - explicit KMessageWidget(QWidget *parent = 0); - - explicit KMessageWidget(const QString &text, QWidget *parent = 0); - - ~KMessageWidget(); - - QString text() const; - - bool wordWrap() const; - - bool isCloseButtonVisible() const; - - MessageType messageType() const; - - void addAction(QAction *action); - - void removeAction(QAction *action); - - QSize sizeHint() const; - - QSize minimumSizeHint() const; - int heightForWidth(int width) const; + /** + * Available message types. + * The background colors are chosen depending on the message type. + */ + enum MessageType { + Positive, + Information, + Warning, + Error + }; + + /** + * Constructs a KMessageWidget with the specified @p parent. + */ + explicit KMessageWidget(QWidget *parent = 0); + + /** + * Constructs a KMessageWidget with the specified @p parent and + * contents @p text. + */ + explicit KMessageWidget(const QString &text, QWidget *parent = 0); + + /** + * Destructor. + */ + ~KMessageWidget(); + + /** + * Get the text of this message widget. + * @see setText() + */ + QString text() const; + + /** + * Check whether word wrap is enabled. + * + * If word wrap is enabled, the message widget wraps the displayed text + * as required to the available width of the widget. This is useful to + * avoid breaking widget layouts. + * + * @see setWordWrap() + */ + bool wordWrap() const; + + /** + * Check whether the close button is visible. + * + * @see setCloseButtonVisible() + */ + bool isCloseButtonVisible() const; + + /** + * Get the type of this message. + * By default, the type is set to KMessageWidget::Information. + * + * @see KMessageWidget::MessageType, setMessageType() + */ + MessageType messageType() const; + + /** + * Add @p action to the message widget. + * For each action a button is added to the message widget in the + * order the actions were added. + * + * @param action the action to add + * @see removeAction(), QWidget::actions() + */ + void addAction(QAction *action); + + /** + * Remove @p action from the message widget. + * + * @param action the action to remove + * @see KMessageWidget::MessageType, addAction(), setMessageType() + */ + void removeAction(QAction *action); + + /** + * Returns the preferred size of the message widget. + */ + QSize sizeHint() const Q_DECL_OVERRIDE; + + /** + * Returns the minimum size of the message widget. + */ + QSize minimumSizeHint() const Q_DECL_OVERRIDE; + + /** + * Returns the required height for @p width. + * @param width the width in pixels + */ + int heightForWidth(int width) const Q_DECL_OVERRIDE; + + /** + * The icon shown on the left of the text. By default, no icon is shown. + * @since 4.11 + */ + QIcon icon() const; + + /** + * Check whether the hide animation started by calling animatedHide() + * is still running. If animations are disabled, this function always + * returns @e false. + * + * @see animatedHide(), hideAnimationFinished() + * @since 5.0 + */ + bool isHideAnimationRunning() const; + + /** + * Check whether the show animation started by calling animatedShow() + * is still running. If animations are disabled, this function always + * returns @e false. + * + * @see animatedShow(), showAnimationFinished() + * @since 5.0 + */ + bool isShowAnimationRunning() const; + +public Q_SLOTS: + /** + * Set the text of the message widget to @p text. + * If the message widget is already visible, the text changes on the fly. + * + * @param text the text to display, rich text is allowed + * @see text() + */ + void setText(const QString &text); + + /** + * Set word wrap to @p wordWrap. If word wrap is enabled, the text() + * of the message widget is wrapped to fit the available width. + * If word wrap is disabled, the message widget's minimum size is + * such that the entire text fits. + * + * @param wordWrap disable/enable word wrap + * @see wordWrap() + */ + void setWordWrap(bool wordWrap); + + /** + * Set the visibility of the close button. If @p visible is @e true, + * a close button is shown that calls animatedHide() if clicked. + * + * @see closeButtonVisible(), animatedHide() + */ + void setCloseButtonVisible(bool visible); + + /** + * Set the message type to @p type. + * By default, the message type is set to KMessageWidget::Information. + * + * @see messageType(), KMessageWidget::MessageType + */ + void setMessageType(KMessageWidget::MessageType type); + + /** + * Show the widget using an animation. + */ + void animatedShow(); + + /** + * Hide the widget using an animation. + */ + void animatedHide(); + + /** + * Define an icon to be shown on the left of the text + * @since 4.11 + */ + void setIcon(const QIcon &icon); - /** - * The icon shown on the left of the text. By default, no icon is shown. - * @since 4.11 - */ - QIcon icon() const; - -public -Q_SLOTS: - void setText(const QString &text); - - void setWordWrap(bool wordWrap); - - void setCloseButtonVisible(bool visible); - - void setMessageType(KMessageWidget::MessageType type); - - /** - * Show the widget using an animation, unless - * KGlobalSettings::graphicsEffectLevel() does not allow simple effects. - */ - void animatedShow(); - - /** - * Hide the widget using an animation, unless - * KGlobalSettings::graphicsEffectLevel() does not allow simple effects. - */ - void animatedHide(); - - /** - * Define an icon to be shown on the left of the text - * @since 4.11 - */ - void setIcon(const QIcon &icon); - - int bestContentHeight() const; Q_SIGNALS: - /** - * This signal is emitted when the user clicks a link in the text label. - * The URL referred to by the href anchor is passed in contents. - * @param contents text of the href anchor - * @see QLabel::linkActivated() - * @since 4.10 - */ - void linkActivated(const QString &contents); - - /** - * This signal is emitted when the user hovers over a link in the text label. - * The URL referred to by the href anchor is passed in contents. - * @param contents text of the href anchor - * @see QLabel::linkHovered() - * @since 4.11 - */ - void linkHovered(const QString &contents); + /** + * This signal is emitted when the user clicks a link in the text label. + * The URL referred to by the href anchor is passed in contents. + * @param contents text of the href anchor + * @see QLabel::linkActivated() + * @since 4.10 + */ + void linkActivated(const QString &contents); + + /** + * This signal is emitted when the user hovers over a link in the text label. + * The URL referred to by the href anchor is passed in contents. + * @param contents text of the href anchor + * @see QLabel::linkHovered() + * @since 4.11 + */ + void linkHovered(const QString &contents); + + /** + * This signal is emitted when the hide animation is finished, started by + * calling animatedHide(). If animations are disabled, this signal is + * emitted immediately after the message widget got hidden. + * + * @note This signal is @e not emitted if the widget was hidden by + * calling hide(), so this signal is only useful in conjunction + * with animatedHide(). + * + * @see animatedHide() + * @since 5.0 + */ + void hideAnimationFinished(); + + /** + * This signal is emitted when the show animation is finished, started by + * calling animatedShow(). If animations are disabled, this signal is + * emitted immediately after the message widget got shown. + * + * @note This signal is @e not emitted if the widget was shown by + * calling show(), so this signal is only useful in conjunction + * with animatedShow(). + * + * @see animatedShow() + * @since 5.0 + */ + void showAnimationFinished(); protected: - void paintEvent(QPaintEvent *event); - - bool event(QEvent *event); + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; - void resizeEvent(QResizeEvent *event); + bool event(QEvent *event) Q_DECL_OVERRIDE; - void showEvent(QShowEvent *event); + void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; private: - KMessageWidgetPrivate *const d; - friend class KMessageWidgetPrivate; - - Q_PRIVATE_SLOT(d, void slotTimeLineChanged(qreal)) - Q_PRIVATE_SLOT(d, void slotTimeLineFinished()) -}; - -//--------------------------------------------------------------------- -// KMessageWidgetPrivate -//--------------------------------------------------------------------- -class QLabel; -class QToolButton; -class QTimeLine; -#include <QIcon> + KMessageWidgetPrivate *const d; + friend class KMessageWidgetPrivate; -class KMessageWidgetPrivate { -public: - void init(KMessageWidget *); - - KMessageWidget *q; - QFrame *content; - QLabel *iconLabel; - QLabel *textLabel; - QToolButton *closeButton; - QTimeLine *timeLine; - QIcon icon; - - KMessageWidget::MessageType messageType; - bool wordWrap; - QList<QToolButton *> buttons; - QPixmap contentSnapShot; - - void createLayout(); - void updateSnapShot(); - void updateLayout(); - void slotTimeLineChanged(qreal); - void slotTimeLineFinished(); - - int bestContentHeight() const; + Q_PRIVATE_SLOT(d, void slotTimeLineChanged(qreal)) + Q_PRIVATE_SLOT(d, void slotTimeLineFinished()) }; -#endif // KMESSAGEWIDGET_H +#endif /* KMESSAGEWIDGET_H */ diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index 85d45b357..f4c0d3af3 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -116,7 +116,10 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent), ui.divemaster->setCompleter(completers.divemaster); ui.suit->setCompleter(completers.suit); ui.tagWidget->setCompleter(completers.tags); - + ui.diveNotesMessage->hide(); + ui.diveEquipmentMessage->hide(); + ui.diveInfoMessage->hide(); + ui.diveStatisticsMessage->hide(); setMinimumHeight(0); setMinimumWidth(0); @@ -312,9 +315,12 @@ void MainTab::displayMessage(QString str) ui.diveStatisticsMessage->setText(str); ui.diveStatisticsMessage->animatedShow(); updateTextLabels(); - ui.tagWidget->fixPopupPosition(ui.diveNotesMessage->bestContentHeight()); - ui.buddy->fixPopupPosition(ui.diveNotesMessage->bestContentHeight()); - ui.divemaster->fixPopupPosition(ui.diveNotesMessage->bestContentHeight()); + +// TODO: this doesn't exists anymore. Find out why it was removed from +// the KMessageWidget and try to see if this is still needed. +// ui.tagWidget->fixPopupPosition(ui.diveNotesMessage->bestContentHeight()); +// ui.buddy->fixPopupPosition(ui.diveNotesMessage->bestContentHeight()); +// ui.divemaster->fixPopupPosition(ui.diveNotesMessage->bestContentHeight()); } void MainTab::updateTextLabels(bool showUnits) |