KWidgetsAddons

ktitlewidget.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2007 Urs Wolfer <uwolfer@kde.org>
4 SPDX-FileCopyrightText: 2007 Michaƫl Larouche <larouche@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "ktitlewidget.h"
10
11#include <QApplication>
12#include <QFrame>
13#include <QIcon>
14#include <QLabel>
15#include <QLayout>
16#include <QMouseEvent>
17#include <QStyle>
18#include <QTextDocument>
19#include <QTimer>
20
21class KTitleWidgetPrivate
22{
23public:
24 KTitleWidgetPrivate(KTitleWidget *parent)
25 : q(parent)
26 // use Left so updateIconAlignment(ImageRight) as called by constructor triggers the default layout
27 , iconAlignment(KTitleWidget::ImageLeft)
28 , autoHideTimeout(0)
29 , messageType(KTitleWidget::InfoMessage)
30 {
31 }
32
33 QString textStyleSheet() const
34 {
35 qreal factor;
36 switch (level) {
37 case 1:
38 factor = 1.35;
39 break;
40 case 2:
41 factor = 1.20;
42 break;
43 case 3:
44 factor = 1.15;
45 break;
46 case 4:
47 factor = 1.10;
48 break;
49 default:
50 factor = 1;
51 }
52 const double fontSize = QApplication::font().pointSize() * factor;
53 return QStringLiteral("QLabel { font-size: %1pt; color: %2 }").arg(QString::number(fontSize), q->palette().color(QPalette::WindowText).name());
54 }
55
56 QString commentStyleSheet() const
57 {
58 QString styleSheet;
59 switch (messageType) {
60 // FIXME: we need the usability color styles to implement different
61 // yet palette appropriate colours for the different use cases!
62 // also .. should we include an icon here,
63 // perhaps using the imageLabel?
67 styleSheet = QStringLiteral("QLabel { color: palette(%1); background: palette(%2); }")
68 .arg(q->palette().color(QPalette::HighlightedText).name(), q->palette().color(QPalette::Highlight).name());
69 break;
71 default:
72 break;
73 }
74 return styleSheet;
75 }
76
77 void updateIconAlignment(KTitleWidget::ImageAlignment newIconAlignment)
78 {
79 if (iconAlignment == newIconAlignment) {
80 return;
81 }
82
83 iconAlignment = newIconAlignment;
84
85 headerLayout->removeWidget(textLabel);
86 headerLayout->removeWidget(commentLabel);
87 headerLayout->removeWidget(imageLabel);
88
89 if (iconAlignment == KTitleWidget::ImageLeft) {
90 // swap the text and image labels around
91 headerLayout->addWidget(imageLabel, 0, 0, 2, 1);
92 headerLayout->addWidget(textLabel, 0, 1);
93 headerLayout->addWidget(commentLabel, 1, 1);
94 headerLayout->setColumnStretch(0, 0);
95 headerLayout->setColumnStretch(1, 1);
96 } else {
97 headerLayout->addWidget(textLabel, 0, 0);
98 headerLayout->addWidget(commentLabel, 1, 0);
99 headerLayout->addWidget(imageLabel, 0, 1, 2, 1);
100 headerLayout->setColumnStretch(1, 0);
101 headerLayout->setColumnStretch(0, 1);
102 }
103 }
104
105 void updatePixmap()
106 {
107 const QPixmap pixmap = icon.pixmap(q->iconSize());
108 imageLabel->setPixmap(pixmap);
109 }
110
111 int level = 1;
112 KTitleWidget *const q;
113 QGridLayout *headerLayout;
114 QLabel *imageLabel;
115 QLabel *textLabel;
116 QLabel *commentLabel;
117 QIcon icon;
118 QSize iconSize;
119 KTitleWidget::ImageAlignment iconAlignment;
120 int autoHideTimeout;
121 KTitleWidget::MessageType messageType;
122
123 /**
124 * @brief Get the icon name from the icon type
125 * @param type icon type from the enum
126 * @return named icon as QString
127 */
128 QString iconTypeToIconName(KTitleWidget::MessageType type);
129
130 void timeoutFinished()
131 {
132 q->setVisible(false);
133 }
134};
135
136QString KTitleWidgetPrivate::iconTypeToIconName(KTitleWidget::MessageType type)
137{
138 switch (type) {
140 return QStringLiteral("dialog-information");
142 return QStringLiteral("dialog-error");
144 return QStringLiteral("dialog-warning");
146 break;
147 }
148
149 return QString();
150}
151
153 : QWidget(parent)
154 , d(new KTitleWidgetPrivate(this))
155{
156 QFrame *titleFrame = new QFrame(this);
157 titleFrame->setAutoFillBackground(true);
158 titleFrame->setFrameShape(QFrame::StyledPanel);
159 titleFrame->setFrameShadow(QFrame::Plain);
160 titleFrame->setBackgroundRole(QPalette::Window);
161 titleFrame->setContentsMargins(0, 0, 0, 0);
162
163 // default image / text part start
164 d->headerLayout = new QGridLayout(titleFrame);
165 d->headerLayout->setContentsMargins(0, 0, 0, 0);
166 d->headerLayout->setSizeConstraint(QLayout::SetFixedSize);
167
168 d->textLabel = new QLabel(titleFrame);
169 d->textLabel->setVisible(false);
170 d->textLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
171
172 d->imageLabel = new QLabel(titleFrame);
173 d->imageLabel->setVisible(false);
174
175 d->commentLabel = new QLabel(titleFrame);
176 d->commentLabel->setVisible(false);
177 d->commentLabel->setOpenExternalLinks(true);
178 d->commentLabel->setWordWrap(true);
179 d->commentLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
180
181 d->updateIconAlignment(ImageRight); // make sure d->iconAlignment is left, to trigger initial layout
182 // default image / text part end
183
184 QVBoxLayout *mainLayout = new QVBoxLayout(this);
185 mainLayout->addWidget(titleFrame);
186 mainLayout->setContentsMargins(0, 0, 0, 0);
187}
188
189KTitleWidget::~KTitleWidget() = default;
190
191bool KTitleWidget::eventFilter(QObject *object, QEvent *event)
192{
193 // Hide message label on click
194 if (d->autoHideTimeout > 0 && event->type() == QEvent::MouseButtonPress) {
195 QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
196 if (mouseEvent && mouseEvent->button() == Qt::LeftButton) {
197 setVisible(false);
198 return true;
199 }
200 }
201
202 return QWidget::eventFilter(object, event);
203}
204
206{
207 d->headerLayout->addWidget(widget, 2, 0, 1, 2);
208}
209
210QString KTitleWidget::text() const
211{
212 return d->textLabel->text();
213}
214
215QString KTitleWidget::comment() const
216{
217 return d->commentLabel->text();
218}
219
221{
222 return d->icon;
223}
224
226{
227 if (d->iconSize.isValid()) {
228 return d->iconSize;
229 }
232}
233
235{
236 d->textLabel->setBuddy(buddy);
237}
238
239void KTitleWidget::changeEvent(QEvent *e)
240{
243 d->textLabel->setStyleSheet(d->textStyleSheet());
244 d->commentLabel->setStyleSheet(d->commentStyleSheet());
245 d->updatePixmap();
246 } else if (e->type() == QEvent::StyleChange) {
247 if (!d->iconSize.isValid()) {
248 // relies on style's PM_MessageBoxIconSize
249 d->updatePixmap();
250 }
251 }
252}
253
254void KTitleWidget::setText(const QString &text, Qt::Alignment alignment)
255{
256 d->textLabel->setVisible(!text.isNull());
257
258 if (!Qt::mightBeRichText(text)) {
259 d->textLabel->setStyleSheet(d->textStyleSheet());
260 }
261
262 d->textLabel->setText(text);
263 d->textLabel->setAlignment(alignment);
264 show();
265}
266
268{
269 if (d->level == level) {
270 return;
271 }
272
273 d->level = level;
274
275 d->textLabel->setStyleSheet(d->textStyleSheet());
276}
277
279{
280 return d->level;
281}
282
284{
285 setIcon(type);
286 setText(text);
287}
288
290{
291 d->commentLabel->setVisible(!comment.isNull());
292
293 // TODO: should we override the current icon with the corresponding MessageType icon?
294 d->messageType = type;
295 d->commentLabel->setStyleSheet(d->commentStyleSheet());
296 d->commentLabel->setText(comment);
297 show();
298}
299
301{
302 d->icon = icon;
303
304 d->imageLabel->setVisible(!icon.isNull());
305
306 d->updateIconAlignment(alignment);
307
308 d->updatePixmap();
309}
310
311void KTitleWidget::setIconSize(const QSize &iconSize)
312{
313 if (d->iconSize == iconSize) {
314 return;
315 }
316
317 const QSize oldEffectiveIconSize = this->iconSize();
318
319 d->iconSize = iconSize;
320
321 if (oldEffectiveIconSize != this->iconSize()) {
322 d->updatePixmap();
323 }
324}
325
327{
328 setIcon(QIcon::fromTheme(d->iconTypeToIconName(type)), alignment);
329}
330
331int KTitleWidget::autoHideTimeout() const
332{
333 return d->autoHideTimeout;
334}
335
337{
338 d->autoHideTimeout = msecs;
339
340 if (msecs > 0) {
341 installEventFilter(this);
342 } else {
343 removeEventFilter(this);
344 }
345}
346
347void KTitleWidget::showEvent(QShowEvent *event)
348{
350 if (d->autoHideTimeout > 0) {
351 QTimer::singleShot(d->autoHideTimeout, this, [this] {
352 d->timeoutFinished();
353 });
354 }
355}
356
357#include "moc_ktitlewidget.cpp"
Standard title widget.
void setIcon(const QIcon &icon, ImageAlignment alignment=ImageRight)
Set the icon to display in the header.
void setIconSize(const QSize &iconSize)
Set the size of the icon to display in the header.
KTitleWidget(QWidget *parent=nullptr)
Constructs a title widget.
ImageAlignment
Possible title pixmap alignments.
@ ImageLeft
Display the pixmap on the left.
@ ImageRight
Display the pixmap on the right.
void setWidget(QWidget *widget)
void setBuddy(QWidget *buddy)
Sets this label's buddy to buddy.
void setText(const QString &text, Qt::Alignment alignment=Qt::AlignLeft|Qt::AlignVCenter)
void setLevel(int level)
Sets the level of this title, similar to HTML's h1 h2 h3... Follows the KDE HIG.
MessageType
Comment message types.
@ ErrorMessage
An error message.
@ InfoMessage
Information the user should be alerted to.
@ PlainMessage
Normal comment.
@ WarningMessage
A warning the user should be alerted to.
void setAutoHideTimeout(int msecs)
Set the autohide timeout of the label Set value to 0 to disable autohide, which is the default.
void setComment(const QString &comment, MessageType type=PlainMessage)
QFont font()
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
MouseButtonPress
QEvent::Type type() const const
int pointSize() const const
void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
void setColumnStretch(int column, int stretch)
QIcon fromTheme(const QString &name)
bool isNull() const const
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) const const
void setPixmap(const QPixmap &)
void removeWidget(QWidget *widget)
void setContentsMargins(int left, int top, int right, int bottom)
virtual bool eventFilter(QObject *watched, QEvent *event)
void installEventFilter(QObject *filterObj)
T qobject_cast(QObject *object)
void removeEventFilter(QObject *obj)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
bool isNull() const const
QString number(int n, int base)
PM_MessageBoxIconSize
virtual int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const const=0
bool mightBeRichText(const QString &text)
typedef Alignment
LeftButton
TextSelectableByMouse
virtual void changeEvent(QEvent *event)
virtual bool event(QEvent *event) override
void show()
QStyle * style() const const
virtual void setVisible(bool visible)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sun Feb 25 2024 18:40:26 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.