mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-06-07 06:22:44 -04:00
Update KMessageWidget
This commit is contained in:
parent
84222e8078
commit
b6ea06ba24
2 changed files with 579 additions and 421 deletions
|
@ -1,6 +1,7 @@
|
||||||
/* This file is part of the KDE libraries
|
/* This file is part of the KDE libraries
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011 Aurélien Gâteau <agateau@kde.org>
|
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -19,16 +20,46 @@
|
||||||
*/
|
*/
|
||||||
#include "kmessagewidget.h"
|
#include "kmessagewidget.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QDialogButtonBox>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QShowEvent>
|
#include <QShowEvent>
|
||||||
#include <QTimeLine>
|
#include <QTimeLine>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QStyle>
|
#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)
|
void KMessageWidgetPrivate::init(KMessageWidget *q_ptr)
|
||||||
{
|
{
|
||||||
|
@ -52,16 +83,20 @@ void KMessageWidgetPrivate::init(KMessageWidget *q_ptr)
|
||||||
textLabel = new QLabel(content);
|
textLabel = new QLabel(content);
|
||||||
textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||||
QObject::connect(textLabel, SIGNAL(linkActivated(const QString &)), q, SIGNAL(linkActivated(const QString &)));
|
QObject::connect(textLabel, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString)));
|
||||||
QObject::connect(textLabel, SIGNAL(linkHovered(const QString &)), q, SIGNAL(linkHovered(const QString &)));
|
QObject::connect(textLabel, SIGNAL(linkHovered(QString)), q, SIGNAL(linkHovered(QString)));
|
||||||
|
|
||||||
QAction *closeAction = new QAction(QObject::tr("Close"), q);
|
QAction *closeAction = new QAction(q);
|
||||||
q->connect(closeAction, SIGNAL(triggered(bool)), q, SLOT(animatedHide()));
|
closeAction->setText(KMessageWidget::tr("&Close"));
|
||||||
|
closeAction->setToolTip(KMessageWidget::tr("Close message"));
|
||||||
|
closeAction->setIcon(q->style()->standardIcon(QStyle::SP_DialogCloseButton));
|
||||||
|
|
||||||
|
QObject::connect(closeAction, SIGNAL(triggered(bool)), q, SLOT(animatedHide()));
|
||||||
|
|
||||||
closeButton = new QToolButton(content);
|
closeButton = new QToolButton(content);
|
||||||
closeButton->setAutoRaise(true);
|
closeButton->setAutoRaise(true);
|
||||||
closeButton->setDefaultAction(closeAction);
|
closeButton->setDefaultAction(closeAction);
|
||||||
closeButton->setVisible(true);
|
|
||||||
q->setMessageType(KMessageWidget::Information);
|
q->setMessageType(KMessageWidget::Information);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,38 +127,32 @@ void KMessageWidgetPrivate::createLayout()
|
||||||
layout->addWidget(iconLabel, 0, 0, 1, 1, Qt::AlignHCenter | Qt::AlignTop);
|
layout->addWidget(iconLabel, 0, 0, 1, 1, Qt::AlignHCenter | Qt::AlignTop);
|
||||||
layout->addWidget(textLabel, 0, 1);
|
layout->addWidget(textLabel, 0, 1);
|
||||||
|
|
||||||
QDialogButtonBox *buttonLayout = new QDialogButtonBox();
|
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||||
//buttonLayout->addStretch();
|
buttonLayout->addStretch();
|
||||||
Q_FOREACH (QToolButton *button, buttons) {
|
Q_FOREACH (QToolButton *button, buttons) {
|
||||||
// For some reason, calling show() is necessary if wordwrap is true,
|
// For some reason, calling show() is necessary if wordwrap is true,
|
||||||
// otherwise the buttons do not show up. It is not needed if
|
// otherwise the buttons do not show up. It is not needed if
|
||||||
// wordwrap is false.
|
// wordwrap is false.
|
||||||
button->show();
|
button->show();
|
||||||
buttonLayout->addButton(button, QDialogButtonBox::QDialogButtonBox::AcceptRole);
|
buttonLayout->addWidget(button);
|
||||||
}
|
}
|
||||||
buttonLayout->addButton(closeButton, QDialogButtonBox::RejectRole);
|
buttonLayout->addWidget(closeButton);
|
||||||
layout->addWidget(buttonLayout, 1, 0, 1, 2, Qt::AlignHCenter | Qt::AlignTop);
|
layout->addItem(buttonLayout, 1, 0, 1, 2);
|
||||||
} else {
|
} else {
|
||||||
bool closeButtonVisible = closeButton->isVisible();
|
|
||||||
QHBoxLayout *layout = new QHBoxLayout(content);
|
QHBoxLayout *layout = new QHBoxLayout(content);
|
||||||
layout->addWidget(iconLabel);
|
layout->addWidget(iconLabel);
|
||||||
layout->addWidget(textLabel);
|
layout->addWidget(textLabel);
|
||||||
|
|
||||||
QDialogButtonBox *buttonLayout = new QDialogButtonBox();
|
|
||||||
Q_FOREACH (QToolButton *button, buttons) {
|
Q_FOREACH (QToolButton *button, buttons) {
|
||||||
buttonLayout->addButton(button, QDialogButtonBox::QDialogButtonBox::AcceptRole);
|
layout->addWidget(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonLayout->addButton(closeButton, QDialogButtonBox::RejectRole);
|
layout->addWidget(closeButton);
|
||||||
// Something gets changed when added to the buttonLayout
|
|
||||||
closeButton->setVisible(closeButtonVisible);
|
|
||||||
layout->addWidget(buttonLayout);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (q->isVisible()) {
|
if (q->isVisible()) {
|
||||||
q->setFixedHeight(content->sizeHint().height());
|
q->setFixedHeight(content->sizeHint().height());
|
||||||
}
|
}
|
||||||
|
|
||||||
q->updateGeometry();
|
q->updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +169,8 @@ void KMessageWidgetPrivate::updateSnapShot()
|
||||||
// window layouts to be activated. Calling this method from resizeEvent()
|
// window layouts to be activated. Calling this method from resizeEvent()
|
||||||
// can lead to infinite recursion, see:
|
// can lead to infinite recursion, see:
|
||||||
// https://bugs.kde.org/show_bug.cgi?id=311336
|
// https://bugs.kde.org/show_bug.cgi?id=311336
|
||||||
contentSnapShot = QPixmap(content->size());
|
contentSnapShot = QPixmap(content->size() * q->devicePixelRatio());
|
||||||
|
contentSnapShot.setDevicePixelRatio(q->devicePixelRatio());
|
||||||
contentSnapShot.fill(Qt::transparent);
|
contentSnapShot.fill(Qt::transparent);
|
||||||
content->render(&contentSnapShot, QPoint(), QRegion(), QWidget::DrawChildren);
|
content->render(&contentSnapShot, QPoint(), QRegion(), QWidget::DrawChildren);
|
||||||
}
|
}
|
||||||
|
@ -158,33 +188,38 @@ void KMessageWidgetPrivate::slotTimeLineFinished()
|
||||||
// We set the whole geometry here, because it may be wrong if a
|
// We set the whole geometry here, because it may be wrong if a
|
||||||
// KMessageWidget is shown right when the toplevel window is created.
|
// KMessageWidget is shown right when the toplevel window is created.
|
||||||
content->setGeometry(0, 0, q->width(), bestContentHeight());
|
content->setGeometry(0, 0, q->width(), bestContentHeight());
|
||||||
|
|
||||||
|
// notify about finished animation
|
||||||
|
emit q->showAnimationFinished();
|
||||||
} else {
|
} else {
|
||||||
// Hide
|
// hide and notify about finished animation
|
||||||
q->hide();
|
q->hide();
|
||||||
|
emit q->hideAnimationFinished();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int KMessageWidgetPrivate::bestContentHeight() const
|
int KMessageWidgetPrivate::bestContentHeight() const
|
||||||
{
|
{
|
||||||
int height = content->heightForWidth(q->width());
|
int height = content->heightForWidth(q->width());
|
||||||
|
|
||||||
if (height == -1) {
|
if (height == -1) {
|
||||||
height = content->sizeHint().height();
|
height = content->sizeHint().height();
|
||||||
}
|
}
|
||||||
|
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// KMessageWidget
|
// 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);
|
d->init(this);
|
||||||
setText(text);
|
setText(text);
|
||||||
|
@ -206,50 +241,57 @@ void KMessageWidget::setText(const QString &text)
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
int KMessageWidget::bestContentHeight() const
|
|
||||||
{
|
|
||||||
return d->bestContentHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KMessageWidget::MessageType KMessageWidget::messageType() const
|
KMessageWidget::MessageType KMessageWidget::messageType() const
|
||||||
{
|
{
|
||||||
return d->messageType;
|
return d->messageType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QColor darkShade(QColor c)
|
||||||
|
{
|
||||||
|
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)
|
void KMessageWidget::setMessageType(KMessageWidget::MessageType type)
|
||||||
{
|
{
|
||||||
d->messageType = type;
|
d->messageType = type;
|
||||||
QColor bg0, bg1, bg2, border, fg;
|
QColor bg0, bg1, bg2, border, fg;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Positive:
|
case Positive:
|
||||||
bg1 = QColor("#72D594"); // nice green
|
bg1.setRgb(0, 110, 40); // values taken from kcolorscheme.cpp (Positive)
|
||||||
fg = QColor(Qt::white);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Information:
|
case Information:
|
||||||
bg1 = QColor("#41A8E3"); // nice blue
|
bg1 = palette().highlight().color();
|
||||||
fg = QColor(Qt::black);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Warning:
|
case Warning:
|
||||||
bg1 = QColor("#FFCD0F"); // nice yellow
|
bg1.setRgb(176, 128, 0); // values taken from kcolorscheme.cpp (Neutral)
|
||||||
fg = QColor(Qt::black);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Error:
|
case Error:
|
||||||
bg1 = QColor("#FF7D7D"); // nice red.
|
bg1.setRgb(191, 3, 3); // values taken from kcolorscheme.cpp (Negative)
|
||||||
fg = QColor(Qt::black);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Colors
|
// Colors
|
||||||
|
fg = palette().highlightedText().color();
|
||||||
bg0 = bg1.lighter(110);
|
bg0 = bg1.lighter(110);
|
||||||
bg2 = bg1.darker(110);
|
bg2 = bg1.darker(110);
|
||||||
border = bg2.darker(110);
|
border = darkShade(bg1);
|
||||||
|
|
||||||
d->content->setStyleSheet(
|
d->content->setStyleSheet(
|
||||||
QString(".QFrame {"
|
QString(QLatin1String(".QFrame {"
|
||||||
"background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
|
"background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
|
||||||
" stop: 0 %1,"
|
" stop: 0 %1,"
|
||||||
" stop: 0.1 %2,"
|
" stop: 0.1 %2,"
|
||||||
|
@ -258,17 +300,16 @@ void KMessageWidget::setMessageType(KMessageWidget::MessageType type)
|
||||||
"border: 1px solid %4;"
|
"border: 1px solid %4;"
|
||||||
"margin: %5px;"
|
"margin: %5px;"
|
||||||
"}"
|
"}"
|
||||||
".QLabel { color: %6; }").arg(bg0.name())
|
".QLabel { color: %6; }"
|
||||||
|
))
|
||||||
|
.arg(bg0.name())
|
||||||
.arg(bg1.name())
|
.arg(bg1.name())
|
||||||
.arg(bg2.name())
|
.arg(bg2.name())
|
||||||
.arg(border.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
|
||||||
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(style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this) - 1)
|
||||||
.arg(fg.name()));
|
.arg(fg.name())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize KMessageWidget::sizeHint() const
|
QSize KMessageWidget::sizeHint() const
|
||||||
|
@ -288,7 +329,6 @@ bool KMessageWidget::event(QEvent *event)
|
||||||
if (event->type() == QEvent::Polish && !d->content->layout()) {
|
if (event->type() == QEvent::Polish && !d->content->layout()) {
|
||||||
d->createLayout();
|
d->createLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
return QFrame::event(event);
|
return QFrame::event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +350,6 @@ int KMessageWidget::heightForWidth(int width) const
|
||||||
void KMessageWidget::paintEvent(QPaintEvent *event)
|
void KMessageWidget::paintEvent(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
QFrame::paintEvent(event);
|
QFrame::paintEvent(event);
|
||||||
|
|
||||||
if (d->timeLine->state() == QTimeLine::Running) {
|
if (d->timeLine->state() == QTimeLine::Running) {
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
painter.setOpacity(d->timeLine->currentValue() * d->timeLine->currentValue());
|
painter.setOpacity(d->timeLine->currentValue() * d->timeLine->currentValue());
|
||||||
|
@ -318,13 +357,6 @@ void KMessageWidget::paintEvent(QPaintEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KMessageWidget::showEvent(QShowEvent *event)
|
|
||||||
{
|
|
||||||
// Keep this method here to avoid breaking binary compatibility:
|
|
||||||
// QFrame::showEvent() used to be reimplemented.
|
|
||||||
QFrame::showEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KMessageWidget::wordWrap() const
|
bool KMessageWidget::wordWrap() const
|
||||||
{
|
{
|
||||||
return d->wordWrap;
|
return d->wordWrap;
|
||||||
|
@ -338,7 +370,6 @@ void KMessageWidget::setWordWrap(bool wordWrap)
|
||||||
policy.setHeightForWidth(wordWrap);
|
policy.setHeightForWidth(wordWrap);
|
||||||
setSizePolicy(policy);
|
setSizePolicy(policy);
|
||||||
d->updateLayout();
|
d->updateLayout();
|
||||||
|
|
||||||
// Without this, when user does wordWrap -> !wordWrap -> wordWrap, a minimum
|
// Without this, when user does wordWrap -> !wordWrap -> wordWrap, a minimum
|
||||||
// height is set, causing the widget to be too high.
|
// height is set, causing the widget to be too high.
|
||||||
// Mostly visible in test programs.
|
// Mostly visible in test programs.
|
||||||
|
@ -372,6 +403,12 @@ void KMessageWidget::removeAction(QAction *action)
|
||||||
|
|
||||||
void KMessageWidget::animatedShow()
|
void KMessageWidget::animatedShow()
|
||||||
{
|
{
|
||||||
|
if (!style()->styleHint(QStyle::SH_Widget_Animate, 0, this)) {
|
||||||
|
show();
|
||||||
|
emit showAnimationFinished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isVisible()) {
|
if (isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -384,7 +421,6 @@ void KMessageWidget::animatedShow()
|
||||||
d->updateSnapShot();
|
d->updateSnapShot();
|
||||||
|
|
||||||
d->timeLine->setDirection(QTimeLine::Forward);
|
d->timeLine->setDirection(QTimeLine::Forward);
|
||||||
|
|
||||||
if (d->timeLine->state() == QTimeLine::NotRunning) {
|
if (d->timeLine->state() == QTimeLine::NotRunning) {
|
||||||
d->timeLine->start();
|
d->timeLine->start();
|
||||||
}
|
}
|
||||||
|
@ -392,6 +428,12 @@ void KMessageWidget::animatedShow()
|
||||||
|
|
||||||
void KMessageWidget::animatedHide()
|
void KMessageWidget::animatedHide()
|
||||||
{
|
{
|
||||||
|
if (!style()->styleHint(QStyle::SH_Widget_Animate, 0, this)) {
|
||||||
|
hide();
|
||||||
|
emit hideAnimationFinished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isVisible()) {
|
if (!isVisible()) {
|
||||||
hide();
|
hide();
|
||||||
return;
|
return;
|
||||||
|
@ -401,12 +443,23 @@ void KMessageWidget::animatedHide()
|
||||||
d->updateSnapShot();
|
d->updateSnapShot();
|
||||||
|
|
||||||
d->timeLine->setDirection(QTimeLine::Backward);
|
d->timeLine->setDirection(QTimeLine::Backward);
|
||||||
|
|
||||||
if (d->timeLine->state() == QTimeLine::NotRunning) {
|
if (d->timeLine->state() == QTimeLine::NotRunning) {
|
||||||
d->timeLine->start();
|
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
|
QIcon KMessageWidget::icon() const
|
||||||
{
|
{
|
||||||
return d->icon;
|
return d->icon;
|
||||||
|
@ -415,11 +468,13 @@ QIcon KMessageWidget::icon() const
|
||||||
void KMessageWidget::setIcon(const QIcon &icon)
|
void KMessageWidget::setIcon(const QIcon &icon)
|
||||||
{
|
{
|
||||||
d->icon = icon;
|
d->icon = icon;
|
||||||
|
|
||||||
if (d->icon.isNull()) {
|
if (d->icon.isNull()) {
|
||||||
d->iconLabel->hide();
|
d->iconLabel->hide();
|
||||||
} else {
|
} else {
|
||||||
d->iconLabel->setPixmap(d->icon.pixmap(QSize(16, 16)));
|
const int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
|
||||||
|
d->iconLabel->setPixmap(d->icon.pixmap(size));
|
||||||
d->iconLabel->show();
|
d->iconLabel->show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "moc_kmessagewidget.cpp"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* This file is part of the KDE libraries
|
/* This file is part of the KDE libraries
|
||||||
*
|
*
|
||||||
* Copyright (c) 2011 Aurélien Gâteau <agateau@kde.org>
|
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -31,9 +32,14 @@ class KMessageWidgetPrivate;
|
||||||
* feedback, or to implement opportunistic interactions.
|
* feedback, or to implement opportunistic interactions.
|
||||||
*
|
*
|
||||||
* As a feedback widget, KMessageWidget provides a less intrusive alternative
|
* 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.
|
* 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>
|
* <b>Negative feedback</b>
|
||||||
*
|
*
|
||||||
* The KMessageWidget can be used as a secondary indicator of failure: the
|
* 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 Confirm success of "critical" transactions
|
||||||
* @li Indicate completion of background tasks
|
* @li Indicate completion of background tasks
|
||||||
*
|
*
|
||||||
* Example of inadapted uses:
|
* Example of unadapted uses:
|
||||||
*
|
*
|
||||||
* @li Indicate successful saving of a file
|
* @li Indicate successful saving of a file
|
||||||
* @li Indicate a file has been successfully removed
|
* @li Indicate a file has been successfully removed
|
||||||
|
@ -87,7 +93,8 @@ class KMessageWidgetPrivate;
|
||||||
* @author Aurélien Gâteau <agateau@kde.org>
|
* @author Aurélien Gâteau <agateau@kde.org>
|
||||||
* @since 4.7
|
* @since 4.7
|
||||||
*/
|
*/
|
||||||
class KMessageWidget : public QFrame {
|
class KMessageWidget : public QFrame
|
||||||
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_ENUMS(MessageType)
|
Q_ENUMS(MessageType)
|
||||||
|
|
||||||
|
@ -97,6 +104,11 @@ class KMessageWidget : public QFrame {
|
||||||
Q_PROPERTY(MessageType messageType READ messageType WRITE setMessageType)
|
Q_PROPERTY(MessageType messageType READ messageType WRITE setMessageType)
|
||||||
Q_PROPERTY(QIcon icon READ icon WRITE setIcon)
|
Q_PROPERTY(QIcon icon READ icon WRITE setIcon)
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Available message types.
|
||||||
|
* The background colors are chosen depending on the message type.
|
||||||
|
*/
|
||||||
enum MessageType {
|
enum MessageType {
|
||||||
Positive,
|
Positive,
|
||||||
Information,
|
Information,
|
||||||
|
@ -105,31 +117,86 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a KMessageWidget with the specified parent.
|
* Constructs a KMessageWidget with the specified @p parent.
|
||||||
*/
|
*/
|
||||||
explicit KMessageWidget(QWidget *parent = 0);
|
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);
|
explicit KMessageWidget(const QString &text, QWidget *parent = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
~KMessageWidget();
|
~KMessageWidget();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the text of this message widget.
|
||||||
|
* @see setText()
|
||||||
|
*/
|
||||||
QString text() const;
|
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;
|
bool wordWrap() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the close button is visible.
|
||||||
|
*
|
||||||
|
* @see setCloseButtonVisible()
|
||||||
|
*/
|
||||||
bool isCloseButtonVisible() const;
|
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;
|
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);
|
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);
|
void removeAction(QAction *action);
|
||||||
|
|
||||||
QSize sizeHint() const;
|
/**
|
||||||
|
* Returns the preferred size of the message widget.
|
||||||
|
*/
|
||||||
|
QSize sizeHint() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
QSize minimumSizeHint() const;
|
/**
|
||||||
|
* Returns the minimum size of the message widget.
|
||||||
|
*/
|
||||||
|
QSize minimumSizeHint() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
int heightForWidth(int width) const;
|
/**
|
||||||
|
* 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.
|
* The icon shown on the left of the text. By default, no icon is shown.
|
||||||
|
@ -137,25 +204,70 @@ public:
|
||||||
*/
|
*/
|
||||||
QIcon icon() const;
|
QIcon icon() const;
|
||||||
|
|
||||||
public
|
/**
|
||||||
Q_SLOTS:
|
* 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);
|
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);
|
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);
|
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);
|
void setMessageType(KMessageWidget::MessageType type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the widget using an animation, unless
|
* Show the widget using an animation.
|
||||||
* KGlobalSettings::graphicsEffectLevel() does not allow simple effects.
|
|
||||||
*/
|
*/
|
||||||
void animatedShow();
|
void animatedShow();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hide the widget using an animation, unless
|
* Hide the widget using an animation.
|
||||||
* KGlobalSettings::graphicsEffectLevel() does not allow simple effects.
|
|
||||||
*/
|
*/
|
||||||
void animatedHide();
|
void animatedHide();
|
||||||
|
|
||||||
|
@ -165,7 +277,6 @@ Q_SLOTS:
|
||||||
*/
|
*/
|
||||||
void setIcon(const QIcon &icon);
|
void setIcon(const QIcon &icon);
|
||||||
|
|
||||||
int bestContentHeight() const;
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
/**
|
/**
|
||||||
* This signal is emitted when the user clicks a link in the text label.
|
* This signal is emitted when the user clicks a link in the text label.
|
||||||
|
@ -185,14 +296,40 @@ Q_SIGNALS:
|
||||||
*/
|
*/
|
||||||
void linkHovered(const QString &contents);
|
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:
|
protected:
|
||||||
void paintEvent(QPaintEvent *event);
|
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
bool event(QEvent *event);
|
bool event(QEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent *event);
|
void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
void showEvent(QShowEvent *event);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KMessageWidgetPrivate *const d;
|
KMessageWidgetPrivate *const d;
|
||||||
|
@ -202,38 +339,4 @@ private:
|
||||||
Q_PRIVATE_SLOT(d, void slotTimeLineFinished())
|
Q_PRIVATE_SLOT(d, void slotTimeLineFinished())
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
#endif /* KMESSAGEWIDGET_H */
|
||||||
// KMessageWidgetPrivate
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
class QLabel;
|
|
||||||
class QToolButton;
|
|
||||||
class QTimeLine;
|
|
||||||
#include <QIcon>
|
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // KMESSAGEWIDGET_H
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue