File indexing completed on 2024-04-28 03:59:08

0001 /*
0002     This file is part of the KDE libraries
0003 
0004     SPDX-FileCopyrightText: 2011 Aurélien Gâteau <agateau@kde.org>
0005     SPDX-FileCopyrightText: 2014 Dominik Haumann <dhaumann@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.1-or-later
0008 */
0009 #ifndef KMESSAGEWIDGET_H
0010 #define KMESSAGEWIDGET_H
0011 
0012 #include <kwidgetsaddons_export.h>
0013 
0014 #include <QFrame>
0015 #include <memory>
0016 
0017 /**
0018  * @class KMessageWidget kmessagewidget.h KMessageWidget
0019  *
0020  * @short A widget to provide feedback or propose opportunistic interactions.
0021  *
0022  * KMessageWidget can be used to provide inline positive or negative
0023  * feedback, or to implement opportunistic interactions.
0024  *
0025  * As a feedback widget, KMessageWidget provides a less intrusive alternative
0026  * to "OK Only" message boxes. If you want to avoid a modal KMessageBox,
0027  * consider using KMessageWidget instead.
0028  *
0029  * Examples of KMessageWidget look as follows, all of them having an icon set
0030  * with setIcon(), and the first three show a close button:
0031  *
0032  * \image html kmessagewidget.png "KMessageWidget with different message types"
0033  *
0034  * <b>Negative feedback</b>
0035  *
0036  * The KMessageWidget can be used as a secondary indicator of failure: the
0037  * first indicator is usually the fact the action the user expected to happen
0038  * did not happen.
0039  *
0040  * Example: User fills a form, clicks "Submit".
0041  *
0042  * @li Expected feedback: form closes
0043  * @li First indicator of failure: form stays there
0044  * @li Second indicator of failure: a KMessageWidget appears on top of the
0045  * form, explaining the error condition
0046  *
0047  * When used to provide negative feedback, KMessageWidget should be placed
0048  * close to its context. In the case of a form, it should appear on top of the
0049  * form entries.
0050  *
0051  * KMessageWidget should get inserted in the existing layout. Space should not
0052  * be reserved for it, otherwise it becomes "dead space", ignored by the user.
0053  * KMessageWidget should also not appear as an overlay to prevent blocking
0054  * access to elements the user needs to interact with to fix the failure.
0055  *
0056  * <b>Positive feedback</b>
0057  *
0058  * KMessageWidget can be used for positive feedback but it shouldn't be
0059  * overused. It is often enough to provide feedback by simply showing the
0060  * results of an action.
0061  *
0062  * Examples of acceptable uses:
0063  *
0064  * @li Confirm success of "critical" transactions
0065  * @li Indicate completion of background tasks
0066  *
0067  * Example of unadapted uses:
0068  *
0069  * @li Indicate successful saving of a file
0070  * @li Indicate a file has been successfully removed
0071  *
0072  * <b>Opportunistic interaction</b>
0073  *
0074  * Opportunistic interaction is the situation where the application suggests to
0075  * the user an action he could be interested in perform, either based on an
0076  * action the user just triggered or an event which the application noticed.
0077  *
0078  * Example of acceptable uses:
0079  *
0080  * @li A browser can propose remembering a recently entered password
0081  * @li A music collection can propose ripping a CD which just got inserted
0082  * @li A chat application may notify the user a "special friend" just connected
0083  *
0084  * @author Aurélien Gâteau <agateau@kde.org>
0085  * @since 4.7
0086  */
0087 class KWIDGETSADDONS_EXPORT KMessageWidget : public QFrame
0088 {
0089     Q_OBJECT
0090 
0091     Q_PROPERTY(QString text READ text WRITE setText)
0092     Q_PROPERTY(Qt::TextFormat textFormat READ textFormat WRITE setTextFormat)
0093     Q_PROPERTY(bool wordWrap READ wordWrap WRITE setWordWrap)
0094     Q_PROPERTY(bool closeButtonVisible READ isCloseButtonVisible WRITE setCloseButtonVisible)
0095     Q_PROPERTY(MessageType messageType READ messageType WRITE setMessageType)
0096     Q_PROPERTY(QIcon icon READ icon WRITE setIcon)
0097     Q_PROPERTY(Position position READ position WRITE setPosition)
0098 public:
0099     /**
0100      * Available message types.
0101      * The background colors are chosen depending on the message type.
0102      */
0103     enum MessageType {
0104         Positive, ///< Positive message type
0105         Information, ///< Information message type
0106         Warning, ///< Warning message type
0107         Error, ///< Error message type
0108     };
0109     Q_ENUM(MessageType)
0110 
0111     /**
0112      * Position of the KMessageWidget
0113      *
0114      * This will update the look of the KMessageWidget to be appropriate to the position.
0115      * @since 6.0
0116      */
0117     enum Position {
0118         Inline, ///< The message widget is display inside the content.
0119         Header, ///< The message widget is displayed as header.
0120         Footer, ///< The message widget is displayed as footer.
0121     };
0122     Q_ENUM(Position);
0123 
0124     /**
0125      * Constructs a KMessageWidget with the specified @p parent.
0126      */
0127     explicit KMessageWidget(QWidget *parent = nullptr);
0128 
0129     /**
0130      * Constructs a KMessageWidget with the specified @p parent and
0131      * contents @p text.
0132      */
0133     explicit KMessageWidget(const QString &text, QWidget *parent = nullptr);
0134 
0135     /**
0136      * Destructor.
0137      */
0138     ~KMessageWidget() override;
0139 
0140     /**
0141      * Get the position of this message. By default this is KMessageWidget::Inline.
0142      * @see setPosition()
0143      * @since 6.0
0144      */
0145     Position position() const;
0146 
0147     /**
0148      * Get the text of this message widget.
0149      * @see setText()
0150      */
0151     QString text() const;
0152 
0153     /**
0154      * Get the text format of the message widget's label.
0155      * @see QLabel::textFormat()
0156      * @since 6.0
0157      */
0158     Qt::TextFormat textFormat() const;
0159 
0160     /**
0161      * Set the text format of the message widget's label.
0162      * @see QLabel::setTextFormat()
0163      * @since 6.0
0164      */
0165     void setTextFormat(Qt::TextFormat textFormat);
0166 
0167     /**
0168      * Check whether word wrap is enabled.
0169      *
0170      * If word wrap is enabled, the message widget wraps the displayed text
0171      * as required to the available width of the widget. This is useful to
0172      * avoid breaking widget layouts.
0173      *
0174      * @see setWordWrap()
0175      */
0176     bool wordWrap() const;
0177 
0178     /**
0179      * Check whether the close button is visible.
0180      *
0181      * @see setCloseButtonVisible()
0182      */
0183     bool isCloseButtonVisible() const;
0184 
0185     /**
0186      * Get the type of this message.
0187      * By default, the type is set to KMessageWidget::Information.
0188      *
0189      * @see KMessageWidget::MessageType, setMessageType()
0190      */
0191     MessageType messageType() const;
0192 
0193     /**
0194      * Add @p action to the message widget.
0195      * For each action a button is added to the message widget in the
0196      * order the actions were added.
0197      *
0198      * @param action the action to add
0199      * @see removeAction(), QWidget::actions()
0200      */
0201     void addAction(QAction *action);
0202 
0203     /**
0204      * Remove @p action from the message widget.
0205      *
0206      * @param action the action to remove
0207      * @see KMessageWidget::MessageType, addAction(), setMessageType()
0208      */
0209     void removeAction(QAction *action);
0210 
0211     /**
0212      * Clears all actions from the message widget.
0213      * @see KMessageWidget::MessageType, addAction() and removeAction()
0214      * @since 5.100
0215      */
0216     void clearActions();
0217 
0218     /**
0219      * Returns the preferred size of the message widget.
0220      */
0221     QSize sizeHint() const override;
0222 
0223     /**
0224      * Returns the minimum size of the message widget.
0225      */
0226     QSize minimumSizeHint() const override;
0227 
0228     /**
0229      * Returns the required height for @p width.
0230      * @param width the width in pixels
0231      */
0232     int heightForWidth(int width) const override;
0233 
0234     /**
0235      * The icon shown on the left of the text. By default, no icon is shown.
0236      * @since 4.11
0237      */
0238     QIcon icon() const;
0239 
0240     /**
0241      * Check whether the hide animation started by calling animatedHide()
0242      * is still running. If animations are disabled, this function always
0243      * returns @e false.
0244      *
0245      * @see animatedHide(), hideAnimationFinished()
0246      * @since 5.0
0247      */
0248     bool isHideAnimationRunning() const;
0249 
0250     /**
0251      * Check whether the show animation started by calling animatedShow()
0252      * is still running. If animations are disabled, this function always
0253      * returns @e false.
0254      *
0255      * @see animatedShow(), showAnimationFinished()
0256      * @since 5.0
0257      */
0258     bool isShowAnimationRunning() const;
0259 
0260 public Q_SLOTS:
0261     /**
0262      * Set the text of the message widget to @p text.
0263      * If the message widget is already visible, the text changes on the fly.
0264      *
0265      * @param text the text to display, rich text is allowed
0266      * @see text()
0267      */
0268     void setText(const QString &text);
0269 
0270     /**
0271      * Set the position of this message
0272      * @see position()
0273      * @since 6.0
0274      */
0275     void setPosition(Position position);
0276 
0277     /**
0278      * Set word wrap to @p wordWrap. If word wrap is enabled, the text()
0279      * of the message widget is wrapped to fit the available width.
0280      * If word wrap is disabled, the message widget's minimum size is
0281      * such that the entire text fits.
0282      *
0283      * By default word wrap is disabled.
0284      *
0285      * @param wordWrap disable/enable word wrap
0286      * @see wordWrap()
0287      */
0288     void setWordWrap(bool wordWrap);
0289 
0290     /**
0291      * Set the visibility of the close button. If @p visible is @e true,
0292      * a close button is shown that calls animatedHide() if clicked.
0293      *
0294      * By default the close button is set to be visible.
0295      *
0296      * @see closeButtonVisible(), animatedHide()
0297      */
0298     void setCloseButtonVisible(bool visible);
0299 
0300     /**
0301      * Set the message type to @p type.
0302      * By default, the message type is set to KMessageWidget::Information.
0303      * Appropriate colors are chosen to mimic the appearance of Kirigami's
0304      * InlineMessage.
0305      *
0306      * @see messageType(), KMessageWidget::MessageType
0307      */
0308     void setMessageType(KMessageWidget::MessageType type);
0309 
0310     /**
0311      * Show the widget using an animation.
0312      */
0313     void animatedShow();
0314 
0315     /**
0316      * Hide the widget using an animation.
0317      */
0318     void animatedHide();
0319 
0320     /**
0321      * Define an icon to be shown on the left of the text
0322      * @since 4.11
0323      */
0324     void setIcon(const QIcon &icon);
0325 
0326 Q_SIGNALS:
0327     /**
0328      * This signal is emitted when the user clicks a link in the text label.
0329      * The URL referred to by the href anchor is passed in contents.
0330      * @param contents text of the href anchor
0331      * @see QLabel::linkActivated()
0332      * @since 4.10
0333      */
0334     void linkActivated(const QString &contents);
0335 
0336     /**
0337      * This signal is emitted when the user hovers over a link in the text label.
0338      * The URL referred to by the href anchor is passed in contents.
0339      * @param contents text of the href anchor
0340      * @see QLabel::linkHovered()
0341      * @since 4.11
0342      */
0343     void linkHovered(const QString &contents);
0344 
0345     /**
0346      * This signal is emitted when the hide animation is finished, started by
0347      * calling animatedHide(). If animations are disabled, this signal is
0348      * emitted immediately after the message widget got hidden.
0349      *
0350      * @note This signal is @e not emitted if the widget was hidden by
0351      *       calling hide(), so this signal is only useful in conjunction
0352      *       with animatedHide().
0353      *
0354      * @see animatedHide()
0355      * @since 5.0
0356      */
0357     void hideAnimationFinished();
0358 
0359     /**
0360      * This signal is emitted when the show animation is finished, started by
0361      * calling animatedShow(). If animations are disabled, this signal is
0362      * emitted immediately after the message widget got shown.
0363      *
0364      * @note This signal is @e not emitted if the widget was shown by
0365      *       calling show(), so this signal is only useful in conjunction
0366      *       with animatedShow().
0367      *
0368      * @see animatedShow()
0369      * @since 5.0
0370      */
0371     void showAnimationFinished();
0372 
0373 protected:
0374     void paintEvent(QPaintEvent *event) override;
0375 
0376     bool event(QEvent *event) override;
0377 
0378     void resizeEvent(QResizeEvent *event) override;
0379 
0380 private:
0381     friend class KMessageWidgetPrivate;
0382     std::unique_ptr<class KMessageWidgetPrivate> const d;
0383 };
0384 
0385 #endif /* KMESSAGEWIDGET_H */