File indexing completed on 2024-06-23 03:56:33

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2009 Marco Martin <notmart@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KSTATUSNOTIFIERITEM_H
0009 #define KSTATUSNOTIFIERITEM_H
0010 
0011 #include <QObject>
0012 #include <QPoint>
0013 #include <QString>
0014 #include <QWindow>
0015 
0016 #include <kstatusnotifieritem_export.h>
0017 
0018 #include <memory>
0019 
0020 class QAction;
0021 class QMenu;
0022 
0023 class KStatusNotifierItemPrivate;
0024 
0025 /**
0026  * @class KStatusNotifierItem kstatusnotifieritem.h KStatusNotifierItem
0027  *
0028  * \brief %KDE Status notifier Item protocol implementation
0029  *
0030  * This class implements the Status notifier Item D-Bus specification.
0031  * It provides an icon similar to the classical systemtray icons,
0032  * with some key differences:
0033  *
0034  * - the actual representation is done by the systemtray (or the app behaving
0035  *   like it) itself, not by this app.  Since 4.5 this also includes the menu,
0036  *   which means you cannot use embed widgets in the menu.
0037  *
0038  * - there is communication between the systemtray and the icon owner, so the
0039  *   system tray can know if the application is in a normal or in a requesting
0040  *   attention state.
0041  *
0042  * - icons are divided in categories, so the systemtray can represent in a
0043  *   different way the icons from normal applications and for instance the ones
0044  *   about hardware status.
0045  *
0046  * Whenever possible you should prefer passing icon by name rather than by
0047  * pixmap because:
0048  *
0049  * - it is much lighter on D-Bus (no need to pass all image pixels).
0050  *
0051  * - it makes it possible for the systemtray to load an icon of the appropriate
0052  *   size or to replace your icon with a systemtray specific icon which matches
0053  *   with the desktop theme.
0054  *
0055  * - some implementations of the system tray do not support passing icons by
0056  *   pixmap and will show a blank icon instead.
0057  *
0058  * @author Marco Martin <notmart@gmail.com>
0059  * @since 4.4
0060  */
0061 class KSTATUSNOTIFIERITEM_EXPORT KStatusNotifierItem : public QObject
0062 {
0063     Q_OBJECT
0064 
0065     Q_PROPERTY(ItemCategory category READ category WRITE setCategory)
0066     Q_PROPERTY(QString title READ title WRITE setTitle)
0067     Q_PROPERTY(ItemStatus status READ status WRITE setStatus)
0068     Q_PROPERTY(QString iconName READ iconName WRITE setIconByName)
0069     Q_PROPERTY(QString overlayIconName READ overlayIconName WRITE setOverlayIconByName)
0070     Q_PROPERTY(QString attentionIconName READ attentionIconName WRITE setAttentionIconByName)
0071     Q_PROPERTY(QString toolTipIconName READ toolTipIconName WRITE setToolTipIconByName)
0072     Q_PROPERTY(QString toolTipTitle READ toolTipTitle WRITE setToolTipTitle)
0073     Q_PROPERTY(QString toolTipSubTitle READ toolTipSubTitle WRITE setToolTipSubTitle)
0074 
0075     friend class KStatusNotifierItemDBus;
0076     friend class KStatusNotifierItemPrivate;
0077 
0078 public:
0079     /**
0080      * All the possible status this icon can have, depending on the
0081      * importance of the events that happens in the parent application
0082      */
0083     enum ItemStatus {
0084         /// Nothing is happening in the application, so showing this icon is not required. This is the default value
0085         Passive = 1,
0086         /// The application is doing something, or it is important that the
0087         /// icon is always reachable from the user
0088         Active = 2,
0089         /// The application requests the attention of the user, for instance
0090         /// battery running out or a new IM message was received
0091         NeedsAttention = 3,
0092     };
0093     Q_ENUM(ItemStatus)
0094 
0095     /**
0096      * Different kinds of applications announce their type to the systemtray,
0097      * so can be drawn in a different way or in a different place
0098      */
0099     enum ItemCategory {
0100         /// An icon for a normal application, can be seen as its taskbar entry. This is the default value
0101         ApplicationStatus = 1,
0102         /// This is a communication oriented application; this icon will be used
0103         /// for things such as the notification of a new message
0104         Communications = 2,
0105         /// This is a system service, it can show itself in the system tray if
0106         /// it requires interaction from the user or wants to inform him about
0107         /// something
0108         SystemServices = 3,
0109         /// This application shows hardware status or a means to control it
0110         Hardware = 4,
0111         Reserved = 129,
0112     };
0113     Q_ENUM(ItemCategory)
0114 
0115     /**
0116      * Construct a new status notifier item
0117      *
0118      * @param parent the parent object for this object. If the object passed in as
0119      * a parent is also a QWidget, it will  be used as the main application window
0120      * represented by this icon and will be shown/hidden when an activation is requested.
0121      * @see associatedWindow
0122      **/
0123     explicit KStatusNotifierItem(QObject *parent = nullptr);
0124 
0125     /**
0126      * Construct a new status notifier item with a unique identifier.
0127      * If your application has more than one status notifier item and the user
0128      * should be able to manipulate them separately (e.g. mark them for hiding
0129      * in a user interface), the id can be used to differentiate between them.
0130      *
0131      * The id should remain consistent even between application restarts.
0132      * Status notifier items without ids default to the application's name for the id.
0133      * This id may be used, for instance, by hosts displaying status notifier items to
0134      * associate configuration information with this item in a way that can persist
0135      * between sessions or application restarts.
0136      *
0137      * @param id the unique id for this icon
0138      * @param parent the parent object for this object. If the object passed in as
0139      * a parent is also a QWidget, it will  be used as the main application window
0140      * represented by this icon and will be shown/hidden when an activation is requested.
0141      * @see associatedWindow
0142      **/
0143     explicit KStatusNotifierItem(const QString &id, QObject *parent = nullptr);
0144 
0145     ~KStatusNotifierItem() override;
0146 
0147     /**
0148      * @return The id which was specified in the constructor. This should be
0149      * guaranteed to be consistent between application starts and
0150      * untranslated, as host applications displaying items may use it for
0151      * storing configuration related to this item.
0152      */
0153     QString id() const;
0154 
0155     /**
0156      * Sets the category for this icon, usually it's needed to call this function only once
0157      *
0158      * @param category the new category for this icon
0159      */
0160     void setCategory(const ItemCategory category);
0161 
0162     /**
0163      * @return the application category
0164      */
0165     ItemCategory category() const;
0166 
0167     /**
0168      * Sets a title for this icon
0169      */
0170     void setTitle(const QString &title);
0171 
0172     /**
0173      * @return the title of this icon
0174      */
0175     QString title() const;
0176 
0177     /**
0178      * Sets a new status for this icon.
0179      */
0180     void setStatus(const ItemStatus status);
0181 
0182     /**
0183      * @return the current application status
0184      */
0185     ItemStatus status() const;
0186 
0187     // Main icon related functions
0188     /**
0189      * Sets a new main icon for the system tray
0190      *
0191      * @param name it must be a QIcon::fromTheme compatible name, this is
0192      * the preferred way to set an icon
0193      */
0194     void setIconByName(const QString &name);
0195 
0196     /**
0197      * @return the name of the main icon to be displayed
0198      * if image() is not empty this will always return an empty string
0199      */
0200     QString iconName() const;
0201 
0202     /**
0203      * Sets a new main icon for the system tray
0204      *
0205      * @param pixmap our icon, use setIcon(const QString) when possible
0206      */
0207     void setIconByPixmap(const QIcon &icon);
0208 
0209     /**
0210      * @return a pixmap of the icon
0211      */
0212     QIcon iconPixmap() const;
0213 
0214     /**
0215      * Sets an icon to be used as overlay for the main one
0216      * @param icon name, if name is and empty QString()
0217      *     (and overlayIconPixmap() is empty too) the icon will be removed
0218      */
0219     void setOverlayIconByName(const QString &name);
0220 
0221     /**
0222      * @return the name of the icon to be used as overlay fr the main one
0223      */
0224     QString overlayIconName() const;
0225 
0226     /**
0227      * Sets an icon to be used as overlay for the main one
0228      *   setOverlayIconByPixmap(QIcon()) will remove the overlay when
0229      *   overlayIconName() is empty too.
0230      *
0231      * @param pixmap our overlay icon, use setOverlayIcon(const QString) when possible.
0232      */
0233     void setOverlayIconByPixmap(const QIcon &icon);
0234 
0235     /**
0236      * @return a pixmap of the icon
0237      */
0238     QIcon overlayIconPixmap() const;
0239 
0240     // Requesting attention icon
0241 
0242     /**
0243      * Sets a new icon that should be used when the application
0244      * wants to request attention (usually the systemtray
0245      * will blink between this icon and the main one)
0246      *
0247      * @param name QIcon::fromTheme compatible name of icon to use
0248      */
0249     void setAttentionIconByName(const QString &name);
0250 
0251     /**
0252      * @return the name of the icon to be displayed when the application
0253      * is requesting the user's attention
0254      * if attentionImage() is not empty this will always return an empty string
0255      */
0256     QString attentionIconName() const;
0257 
0258     /**
0259      * Sets the pixmap of the requesting attention icon.
0260      * Use setAttentionIcon(const QString) instead when possible.
0261      *
0262      * @param icon QIcon to use for requesting attention.
0263      */
0264     void setAttentionIconByPixmap(const QIcon &icon);
0265 
0266     /**
0267      * @return a pixmap of the requesting attention icon
0268      */
0269     QIcon attentionIconPixmap() const;
0270 
0271     /**
0272      * Sets a movie as the requesting attention icon.
0273      * This overrides anything set in setAttentionIcon()
0274      */
0275     void setAttentionMovieByName(const QString &name);
0276 
0277     /**
0278      * @return the name of the movie to be displayed when the application is
0279      * requesting the user attention
0280      */
0281     QString attentionMovieName() const;
0282 
0283     // ToolTip handling
0284     /**
0285      * Sets a new toolTip or this icon, a toolTip is composed of an icon,
0286      * a title and a text, all fields are optional.
0287      *
0288      * @param iconName a QIcon::fromTheme compatible name for the tootip icon
0289      * @param title tootip title
0290      * @param subTitle subtitle for the toolTip
0291      */
0292     void setToolTip(const QString &iconName, const QString &title, const QString &subTitle);
0293 
0294     /**
0295      * Sets a new toolTip or this status notifier item.
0296      * This is an overloaded member provided for convenience
0297      */
0298     void setToolTip(const QIcon &icon, const QString &title, const QString &subTitle);
0299 
0300     /**
0301      * Set a new icon for the toolTip
0302      *
0303      * @param name the name for the icon
0304      */
0305     void setToolTipIconByName(const QString &name);
0306 
0307     /**
0308      * @return the name of the toolTip icon
0309      * if toolTipImage() is not empty this will always return an empty string
0310      */
0311     QString toolTipIconName() const;
0312 
0313     /**
0314      * Set a new icon for the toolTip.
0315      *
0316      * Use setToolTipIconByName(QString) if possible.
0317      * @param pixmap representing the icon
0318      */
0319     void setToolTipIconByPixmap(const QIcon &icon);
0320 
0321     /**
0322      * @return a serialization of the toolTip icon data
0323      */
0324     QIcon toolTipIconPixmap() const;
0325 
0326     /**
0327      * Sets a new title for the toolTip
0328      */
0329     void setToolTipTitle(const QString &title);
0330 
0331     /**
0332      * @return the title of the main icon toolTip
0333      */
0334     QString toolTipTitle() const;
0335 
0336     /**
0337      * Sets a new subtitle for the toolTip
0338      */
0339     void setToolTipSubTitle(const QString &subTitle);
0340 
0341     /**
0342      * @return the subtitle of the main icon toolTip
0343      */
0344     QString toolTipSubTitle() const;
0345 
0346     /**
0347      * Sets a new context menu for this StatusNotifierItem.
0348      * the menu will be shown with a contextMenu(int,int)
0349      * call by the systemtray over D-Bus
0350      * usually you don't need to call this unless you want to use
0351      * a custom QMenu subclass as context menu.
0352      *
0353      * The KStatusNotifierItem instance takes ownership of the menu,
0354      * and will delete it upon its destruction.
0355      */
0356     void setContextMenu(QMenu *menu);
0357 
0358     /**
0359      * Access the context menu associated to this status notifier item
0360      */
0361     QMenu *contextMenu() const;
0362 
0363     /**
0364      * Sets the main window associated with this StatusNotifierItem
0365      *
0366      * @param window The window to be used.
0367      *
0368      * @since 6.0
0369      */
0370     void setAssociatedWindow(QWindow *window);
0371 
0372     /**
0373      * Access the main window associated with this StatusNotifierItem
0374      *
0375      * @since 6.0
0376      */
0377     QWindow *associatedWindow() const;
0378 
0379     /**
0380      * All the actions present in the menu
0381      */
0382     QList<QAction *> actionCollection() const;
0383 
0384     /**
0385      * Adds an action to the actionCollection()
0386      *
0387      * @param name the name of the action
0388      * @param action the action we want to add
0389      */
0390     void addAction(const QString &name, QAction *action);
0391 
0392     /**
0393      * Removes an action from the collection
0394      *
0395      * @param name the name of the action
0396      */
0397     void removeAction(const QString &name);
0398 
0399     /**
0400      * Retrieves an action from the action collection
0401      * by the action name
0402      *
0403      * @param name the name of the action to retrieve
0404      * @since 5.12
0405      */
0406     QAction *action(const QString &name) const;
0407 
0408     /**
0409      * Sets whether to show the standard items in the menu, such as Quit
0410      */
0411     void setStandardActionsEnabled(bool enabled);
0412 
0413     /**
0414      * @return if the standard items in the menu, such as Quit
0415      */
0416     bool standardActionsEnabled() const;
0417 
0418     /**
0419      * Shows the user a notification. If possible use KNotify instead
0420      *
0421      * @param title message title
0422      * @param message the actual text shown to the user
0423      * @param icon icon to be shown to the user
0424      * @param timeout how much time will elaps before hiding the message
0425      */
0426     void showMessage(const QString &title, const QString &message, const QString &icon, int timeout = 10000);
0427 
0428     /**
0429      * @return the last provided token to be used with Wayland's xdg_activation_v1
0430      */
0431     QString providedToken() const;
0432 
0433 public Q_SLOTS:
0434 
0435     /**
0436      * Shows the main window and try to position it on top
0437      * of the other windows, if the window is already visible, hide it.
0438      *
0439      * @param pos if it's a valid position it represents the mouse coordinates when the event was triggered
0440      */
0441     virtual void activate(const QPoint &pos = QPoint());
0442 
0443     /**
0444      * Hides the main window, if not already hidden.
0445      *
0446      * Stores some information about the window which otherwise would be lost due to unmapping
0447      * from the window system. Use when toggling the main window via activate(const QPoint &)
0448      * is not wanted, but instead the hidden state should be reached in any case.
0449      *
0450      * @since 6.0
0451      */
0452     void hideAssociatedWindow();
0453 
0454 Q_SIGNALS:
0455     /**
0456      * Inform the host application that the mouse wheel
0457      * (or another mean of scrolling that the visualization provides) has been used
0458      *
0459      * @param delta the amount of scrolling, can be either positive or negative
0460      * @param orientation direction of the scrolling, can be either horizontal or vertical
0461      */
0462     void scrollRequested(int delta, Qt::Orientation orientation);
0463 
0464     /**
0465      * Inform the host application that an activation has been requested,
0466      *           for instance left mouse click, but this is not guaranteed since
0467      *           it's dependent from the visualization
0468      * @param active if it's true the application asked for the activation
0469      *              of the main window, if it's false it asked for hiding
0470      * @param pos the position in the screen where the user clicked to
0471      *  trigger this signal, QPoint() if it's not the consequence of a mouse click.
0472      */
0473     void activateRequested(bool active, const QPoint &pos);
0474 
0475     /**
0476      * Alternate activate action,
0477      * for instance right mouse click, but this is not guaranteed since
0478      * it's dependent from the visualization
0479      *
0480      * @param pos the position in the screen where the user clicked to
0481      *  trigger this signal, QPoint() if it's not the consequence of a mouse click.
0482      */
0483     void secondaryActivateRequested(const QPoint &pos);
0484 
0485 protected:
0486     bool eventFilter(QObject *watched, QEvent *event) override;
0487 
0488 private:
0489     std::unique_ptr<KStatusNotifierItemPrivate> const d;
0490 
0491     Q_PRIVATE_SLOT(d, void serviceChange(const QString &name, const QString &oldOwner, const QString &newOwner))
0492     Q_PRIVATE_SLOT(d, void contextMenuAboutToShow())
0493     Q_PRIVATE_SLOT(d, void maybeQuit())
0494     Q_PRIVATE_SLOT(d, void minimizeRestore())
0495     Q_PRIVATE_SLOT(d, void legacyWheelEvent(int))
0496     Q_PRIVATE_SLOT(d, void legacyActivated(QSystemTrayIcon::ActivationReason))
0497 };
0498 
0499 #endif