1/*
2 This file is part of the KDE libraries
3
4 SPDX-FileCopyrightText: 2011 Aurélien Gâteau <agateau@kde.org>
5 SPDX-FileCopyrightText: 2014 Dominik Haumann <dhaumann@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.1-or-later
8*/
9#ifndef KMESSAGEWIDGET_H
10#define KMESSAGEWIDGET_H
11
12#include <kwidgetsaddons_export.h>
13
14#include <QFrame>
15#include <memory>
16
17/*!
18 * \class KMessageWidget
19 * \inmodule KWidgetsAddons
20 *
21 * \brief A widget to provide feedback or propose opportunistic interactions.
22 *
23 * KMessageWidget can be used to provide inline positive or negative
24 * feedback, or to implement opportunistic interactions.
25 *
26 * As a feedback widget, KMessageWidget provides a less intrusive alternative
27 * to "OK Only" message boxes. If you want to avoid a modal KMessageBox,
28 * consider using KMessageWidget instead.
29 *
30 * Examples of KMessageWidget look as follows, all of them having an icon set
31 * with setIcon(), and the first three show a close button:
32 *
33 * \image kmessagewidget.png "KMessageWidget with different message types"
34 *
35 * \section1 Negative feedback
36 *
37 * The KMessageWidget can be used as a secondary indicator of failure: the
38 * first indicator is usually the fact the action the user expected to happen
39 * did not happen.
40 *
41 * Example: User fills a form, clicks "Submit".
42 * \list
43 * \li Expected feedback: form closes
44 * \li First indicator of failure: form stays there
45 * \li Second indicator of failure: a KMessageWidget appears on top of the
46 * form, explaining the error condition
47 * \endlist
48 *
49 * When used to provide negative feedback, KMessageWidget should be placed
50 * close to its context. In the case of a form, it should appear on top of the
51 * form entries.
52 *
53 * KMessageWidget should get inserted in the existing layout. Space should not
54 * be reserved for it, otherwise it becomes "dead space", ignored by the user.
55 * KMessageWidget should also not appear as an overlay to prevent blocking
56 * access to elements the user needs to interact with to fix the failure.
57 *
58 * \section1 Positive feedback
59 *
60 * KMessageWidget can be used for positive feedback but it shouldn't be
61 * overused. It is often enough to provide feedback by simply showing the
62 * results of an action.
63 *
64 * Examples of acceptable uses:
65 * \list
66 * \li Confirm success of "critical" transactions
67 * \li Indicate completion of background tasks
68 * \endlist
69 *
70 * Example of unadapted uses:
71 * \list
72 * \li Indicate successful saving of a file
73 * \li Indicate a file has been successfully removed
74 * \endlist
75 *
76 * \section1 Opportunistic interaction
77 *
78 * Opportunistic interaction is the situation where the application suggests to
79 * the user an action he could be interested in perform, either based on an
80 * action the user just triggered or an event which the application noticed.
81 *
82 * Example of acceptable uses:
83 * \list
84 * \li A browser can propose remembering a recently entered password
85 * \li A music collection can propose ripping a CD which just got inserted
86 * \li A chat application may notify the user a "special friend" just connected
87 * \endlist
88 *
89 * \since 4.7
90 */
91class KWIDGETSADDONS_EXPORT KMessageWidget : public QFrame
92{
93 Q_OBJECT
94
95 /*!
96 * \property KMessageWidget::text
97 */
98 Q_PROPERTY(QString text READ text WRITE setText)
99
100 /*!
101 * \property KMessageWidget::textFormat
102 */
103 Q_PROPERTY(Qt::TextFormat textFormat READ textFormat WRITE setTextFormat)
104
105 /*!
106 * \property KMessageWidget::wordWrap
107 */
108 Q_PROPERTY(bool wordWrap READ wordWrap WRITE setWordWrap)
109
110 /*!
111 * \property KMessageWidget::closeButtonVisible
112 */
113 Q_PROPERTY(bool closeButtonVisible READ isCloseButtonVisible WRITE setCloseButtonVisible)
114
115 /*!
116 * \property KMessageWidget::messageType
117 */
118 Q_PROPERTY(MessageType messageType READ messageType WRITE setMessageType)
119
120 /*!
121 * \property KMessageWidget::icon
122 */
123 Q_PROPERTY(QIcon icon READ icon WRITE setIcon)
124
125 /*!
126 * \property KMessageWidget::position
127 */
128 Q_PROPERTY(Position position READ position WRITE setPosition)
129public:
130 /*!
131 * Available message types.
132 * The background colors are chosen depending on the message type.
133 *
134 * \value Positive Positive message type
135 * \value Information Information message type
136 * \value Warning Warning message type
137 * \value Error Error message type
138 */
139 enum MessageType {
140 Positive,
141 Information,
142 Warning,
143 Error,
144 };
145 Q_ENUM(MessageType)
146
147 /*!
148 * Position of the KMessageWidget
149 *
150 * This will update the look of the KMessageWidget to be appropriate to the position.
151 *
152 * \value Inline The message widget is display inside the content.
153 * \value Header The message widget is displayed as header.
154 * \value Footer The message widget is displayed as footer.
155 *
156 * \since 6.0
157 */
158 enum Position {
159 Inline,
160 Header,
161 Footer,
162 };
163 Q_ENUM(Position);
164
165 /*!
166 * Constructs a KMessageWidget with the specified \a parent.
167 */
168 explicit KMessageWidget(QWidget *parent = nullptr);
169
170 /*!
171 * Constructs a KMessageWidget with the specified \a parent and
172 * contents \a text.
173 */
174 explicit KMessageWidget(const QString &text, QWidget *parent = nullptr);
175
176 /*!
177 * Destructor.
178 */
179 ~KMessageWidget() override;
180
181 /*!
182 * Get the position of this message. By default this is KMessageWidget::Inline.
183 * \sa setPosition()
184 * \since 6.0
185 */
186 Position position() const;
187
188 /*!
189 * Get the text of this message widget.
190 * \sa setText()
191 */
192 QString text() const;
193
194 /*!
195 * Get the text format of the message widget's label.
196 * \sa QLabel::textFormat()
197 * \since 6.0
198 */
199 Qt::TextFormat textFormat() const;
200
201 /*!
202 * Set the text format of the message widget's label.
203 * \sa QLabel::setTextFormat()
204 * \since 6.0
205 */
206 void setTextFormat(Qt::TextFormat textFormat);
207
208 /*!
209 * Check whether word wrap is enabled.
210 *
211 * If word wrap is enabled, the message widget wraps the displayed text
212 * as required to the available width of the widget. This is useful to
213 * avoid breaking widget layouts.
214 *
215 * \sa setWordWrap()
216 */
217 bool wordWrap() const;
218
219 /*!
220 * Check whether the close button is visible.
221 *
222 * \sa setCloseButtonVisible()
223 */
224 bool isCloseButtonVisible() const;
225
226 /*!
227 * Get the type of this message.
228 * By default, the type is set to KMessageWidget::Information.
229 *
230 * \sa KMessageWidget::MessageType, setMessageType()
231 */
232 MessageType messageType() const;
233
234 /*!
235 * Add \a action to the message widget.
236 *
237 * For each action a button is added to the message widget in the
238 * order the actions were added.
239 *
240 * \a action the action to add
241 * \sa removeAction(), QWidget::actions()
242 */
243 void addAction(QAction *action);
244
245 /*!
246 * Remove \a action from the message widget.
247 *
248 * \a action the action to remove
249 *
250 * \sa KMessageWidget::MessageType, addAction(), setMessageType()
251 */
252 void removeAction(QAction *action);
253
254 /*!
255 * Clears all actions from the message widget.
256 *
257 * \sa KMessageWidget::MessageType, addAction() and removeAction()
258 * \since 5.100
259 */
260 void clearActions();
261
262 QSize sizeHint() const override;
263
264 QSize minimumSizeHint() const override;
265
266 int heightForWidth(int width) const override;
267
268 /*!
269 * The icon shown on the left of the text. By default, no icon is shown.
270 * \since 4.11
271 */
272 QIcon icon() const;
273
274 /*!
275 * Check whether the hide animation started by calling animatedHide()
276 * is still running. If animations are disabled, this function always
277 * returns \c false.
278 *
279 * \sa animatedHide(), hideAnimationFinished()
280 * \since 5.0
281 */
282 bool isHideAnimationRunning() const;
283
284 /*!
285 * Check whether the show animation started by calling animatedShow()
286 * is still running. If animations are disabled, this function always
287 * returns \c false.
288 *
289 * \sa animatedShow(), showAnimationFinished()
290 * \since 5.0
291 */
292 bool isShowAnimationRunning() const;
293
294public Q_SLOTS:
295 /*!
296 * Set the text of the message widget to \a text.
297 * If the message widget is already visible, the text changes on the fly.
298 *
299 * \a text the text to display, rich text is allowed
300 *
301 * \sa text()
302 */
303 void setText(const QString &text);
304
305 /*!
306 * Set the position of this message
307 * \sa position()
308 * \since 6.0
309 */
310 void setPosition(Position position);
311
312 /*!
313 * Set word wrap to \a wordWrap. If word wrap is enabled, the text()
314 * of the message widget is wrapped to fit the available width.
315 * If word wrap is disabled, the message widget's minimum size is
316 * such that the entire text fits.
317 *
318 * By default word wrap is disabled.
319 *
320 * \a wordWrap disable/enable word wrap
321 * \sa wordWrap()
322 */
323 void setWordWrap(bool wordWrap);
324
325 /*!
326 * Set the visibility of the close button. If \a visible is \c true,
327 * a close button is shown that calls animatedHide() if clicked.
328 *
329 * By default the close button is set to be visible.
330 *
331 * \sa closeButtonVisible(), animatedHide()
332 */
333 void setCloseButtonVisible(bool visible);
334
335 /*!
336 * Set the message type to \a type.
337 * By default, the message type is set to KMessageWidget::Information.
338 * Appropriate colors are chosen to mimic the appearance of Kirigami's
339 * InlineMessage.
340 *
341 * \sa messageType(), KMessageWidget::MessageType
342 */
343 void setMessageType(KMessageWidget::MessageType type);
344
345 /*!
346 * Show the widget using an animation.
347 */
348 void animatedShow();
349
350 /*!
351 * Hide the widget using an animation.
352 */
353 void animatedHide();
354
355 /*!
356 * Define an icon to be shown on the left of the text
357 * \since 4.11
358 */
359 void setIcon(const QIcon &icon);
360
361Q_SIGNALS:
362 /*!
363 * This signal is emitted when the user clicks a link in the text label.
364 *
365 * The URL referred to by the href anchor is passed in contents.
366 *
367 * \a contents text of the href anchor
368 *
369 * \sa QLabel::linkActivated()
370 * \since 4.10
371 */
372 void linkActivated(const QString &contents);
373
374 /*!
375 * This signal is emitted when the user hovers over a link in the text label.
376 *
377 * The URL referred to by the href anchor is passed in contents.
378 *
379 * \a contents text of the href anchor
380 *
381 * \sa QLabel::linkHovered()
382 * \since 4.11
383 */
384 void linkHovered(const QString &contents);
385
386 /*!
387 * This signal is emitted when the hide animation is finished, started by
388 * calling animatedHide(). If animations are disabled, this signal is
389 * emitted immediately after the message widget got hidden.
390 *
391 * \note This signal is not emitted if the widget was hidden by
392 * calling hide(), so this signal is only useful in conjunction
393 * with animatedHide().
394 *
395 * \sa animatedHide()
396 * \since 5.0
397 */
398 void hideAnimationFinished();
399
400 /*!
401 * This signal is emitted when the show animation is finished, started by
402 * calling animatedShow(). If animations are disabled, this signal is
403 * emitted immediately after the message widget got shown.
404 *
405 * \note This signal is not emitted if the widget was shown by
406 * calling show(), so this signal is only useful in conjunction
407 * with animatedShow().
408 *
409 * \sa animatedShow()
410 * \since 5.0
411 */
412 void showAnimationFinished();
413
414protected:
415 void paintEvent(QPaintEvent *event) override;
416
417 bool event(QEvent *event) override;
418
419 void resizeEvent(QResizeEvent *event) override;
420
421private:
422 friend class KMessageWidgetPrivate;
423 std::unique_ptr<class KMessageWidgetPrivate> const d;
424};
425
426#endif /* KMESSAGEWIDGET_H */
427

source code of kwidgetsaddons/src/kmessagewidget.h