File indexing completed on 2024-04-28 15:29:11
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 0015 #include <knotifications_export.h> 0016 0017 #include <memory> 0018 0019 class QAction; 0020 class QMenu; 0021 0022 class KStatusNotifierItemPrivate; 0023 0024 /** 0025 * @class KStatusNotifierItem kstatusnotifieritem.h KStatusNotifierItem 0026 * 0027 * \brief %KDE Status notifier Item protocol implementation 0028 * 0029 * This class implements the Status notifier Item D-Bus specification. 0030 * It provides an icon similar to the classical systemtray icons, 0031 * with some key differences: 0032 * 0033 * - the actual representation is done by the systemtray (or the app behaving 0034 * like it) itself, not by this app. Since 4.5 this also includes the menu, 0035 * which means you cannot use embed widgets in the menu. 0036 * 0037 * - there is communication between the systemtray and the icon owner, so the 0038 * system tray can know if the application is in a normal or in a requesting 0039 * attention state. 0040 * 0041 * - icons are divided in categories, so the systemtray can represent in a 0042 * different way the icons from normal applications and for instance the ones 0043 * about hardware status. 0044 * 0045 * Whenever possible you should prefer passing icon by name rather than by 0046 * pixmap because: 0047 * 0048 * - it is much lighter on D-Bus (no need to pass all image pixels). 0049 * 0050 * - it makes it possible for the systemtray to load an icon of the appropriate 0051 * size or to replace your icon with a systemtray specific icon which matches 0052 * with the desktop theme. 0053 * 0054 * - some implementations of the system tray do not support passing icons by 0055 * pixmap and will show a blank icon instead. 0056 * 0057 * @author Marco Martin <notmart@gmail.com> 0058 * @since 4.4 0059 */ 0060 class KNOTIFICATIONS_EXPORT KStatusNotifierItem : public QObject 0061 { 0062 Q_OBJECT 0063 0064 Q_PROPERTY(ItemCategory category READ category WRITE setCategory) 0065 Q_PROPERTY(QString title READ title WRITE setTitle) 0066 Q_PROPERTY(ItemStatus status READ status WRITE setStatus) 0067 Q_PROPERTY(QString iconName READ iconName WRITE setIconByName) 0068 Q_PROPERTY(QString overlayIconName READ overlayIconName WRITE setOverlayIconByName) 0069 Q_PROPERTY(QString attentionIconName READ attentionIconName WRITE setAttentionIconByName) 0070 Q_PROPERTY(QString toolTipIconName READ toolTipIconName WRITE setToolTipIconByName) 0071 Q_PROPERTY(QString toolTipTitle READ toolTipTitle WRITE setToolTipTitle) 0072 Q_PROPERTY(QString toolTipSubTitle READ toolTipSubTitle WRITE setToolTipSubTitle) 0073 0074 friend class KStatusNotifierItemDBus; 0075 friend class KStatusNotifierItemPrivate; 0076 0077 public: 0078 /** 0079 * All the possible status this icon can have, depending on the 0080 * importance of the events that happens in the parent application 0081 */ 0082 enum ItemStatus { 0083 /// Nothing is happening in the application, so showing this icon is not required. This is the default value 0084 Passive = 1, 0085 /// The application is doing something, or it is important that the 0086 /// icon is always reachable from the user 0087 Active = 2, 0088 /// The application requests the attention of the user, for instance 0089 /// battery running out or a new IM message was received 0090 NeedsAttention = 3, 0091 }; 0092 Q_ENUM(ItemStatus) 0093 0094 /** 0095 * Different kinds of applications announce their type to the systemtray, 0096 * so can be drawn in a different way or in a different place 0097 */ 0098 enum ItemCategory { 0099 /// An icon for a normal application, can be seen as its taskbar entry. This is the default value 0100 ApplicationStatus = 1, 0101 /// This is a communication oriented application; this icon will be used 0102 /// for things such as the notification of a new message 0103 Communications = 2, 0104 /// This is a system service, it can show itself in the system tray if 0105 /// it requires interaction from the user or wants to inform him about 0106 /// something 0107 SystemServices = 3, 0108 /// This application shows hardware status or a means to control it 0109 Hardware = 4, 0110 Reserved = 129, 0111 }; 0112 Q_ENUM(ItemCategory) 0113 0114 /** 0115 * Construct a new status notifier item 0116 * 0117 * @param parent the parent object for this object. If the object passed in as 0118 * a parent is also a QWidget, it will be used as the main application window 0119 * represented by this icon and will be shown/hidden when an activation is requested. 0120 * @see associatedWidget 0121 **/ 0122 explicit KStatusNotifierItem(QObject *parent = nullptr); 0123 0124 /** 0125 * Construct a new status notifier item with a unique identifier. 0126 * If your application has more than one status notifier item and the user 0127 * should be able to manipulate them separately (e.g. mark them for hiding 0128 * in a user interface), the id can be used to differentiate between them. 0129 * 0130 * The id should remain consistent even between application restarts. 0131 * Status notifier items without ids default to the application's name for the id. 0132 * This id may be used, for instance, by hosts displaying status notifier items to 0133 * associate configuration information with this item in a way that can persist 0134 * between sessions or application restarts. 0135 * 0136 * @param id the unique id for this icon 0137 * @param parent the parent object for this object. If the object passed in as 0138 * a parent is also a QWidget, it will be used as the main application window 0139 * represented by this icon and will be shown/hidden when an activation is requested. 0140 * @see associatedWidget 0141 **/ 0142 explicit KStatusNotifierItem(const QString &id, QObject *parent = nullptr); 0143 0144 ~KStatusNotifierItem() override; 0145 0146 /** 0147 * @return The id which was specified in the constructor. This should be 0148 * guaranteed to be consistent between application starts and 0149 * untranslated, as host applications displaying items may use it for 0150 * storing configuration related to this item. 0151 */ 0152 QString id() const; 0153 0154 /** 0155 * Sets the category for this icon, usually it's needed to call this function only once 0156 * 0157 * @param category the new category for this icon 0158 */ 0159 void setCategory(const ItemCategory category); 0160 0161 /** 0162 * @return the application category 0163 */ 0164 ItemCategory category() const; 0165 0166 /** 0167 * Sets a title for this icon 0168 */ 0169 void setTitle(const QString &title); 0170 0171 /** 0172 * @return the title of this icon 0173 */ 0174 QString title() const; 0175 0176 /** 0177 * Sets a new status for this icon. 0178 */ 0179 void setStatus(const ItemStatus status); 0180 0181 /** 0182 * @return the current application status 0183 */ 0184 ItemStatus status() const; 0185 0186 // Main icon related functions 0187 /** 0188 * Sets a new main icon for the system tray 0189 * 0190 * @param name it must be a QIcon::fromTheme compatible name, this is 0191 * the preferred way to set an icon 0192 */ 0193 void setIconByName(const QString &name); 0194 0195 /** 0196 * @return the name of the main icon to be displayed 0197 * if image() is not empty this will always return an empty string 0198 */ 0199 QString iconName() const; 0200 0201 /** 0202 * Sets a new main icon for the system tray 0203 * 0204 * @param pixmap our icon, use setIcon(const QString) when possible 0205 */ 0206 void setIconByPixmap(const QIcon &icon); 0207 0208 /** 0209 * @return a pixmap of the icon 0210 */ 0211 QIcon iconPixmap() const; 0212 0213 /** 0214 * Sets an icon to be used as overlay for the main one 0215 * @param icon name, if name is and empty QString() 0216 * (and overlayIconPixmap() is empty too) the icon will be removed 0217 */ 0218 void setOverlayIconByName(const QString &name); 0219 0220 /** 0221 * @return the name of the icon to be used as overlay fr the main one 0222 */ 0223 QString overlayIconName() const; 0224 0225 /** 0226 * Sets an icon to be used as overlay for the main one 0227 * setOverlayIconByPixmap(QIcon()) will remove the overlay when 0228 * overlayIconName() is empty too. 0229 * 0230 * @param pixmap our overlay icon, use setOverlayIcon(const QString) when possible. 0231 */ 0232 void setOverlayIconByPixmap(const QIcon &icon); 0233 0234 /** 0235 * @return a pixmap of the icon 0236 */ 0237 QIcon overlayIconPixmap() const; 0238 0239 // Requesting attention icon 0240 0241 /** 0242 * Sets a new icon that should be used when the application 0243 * wants to request attention (usually the systemtray 0244 * will blink between this icon and the main one) 0245 * 0246 * @param name QIcon::fromTheme compatible name of icon to use 0247 */ 0248 void setAttentionIconByName(const QString &name); 0249 0250 /** 0251 * @return the name of the icon to be displayed when the application 0252 * is requesting the user's attention 0253 * if attentionImage() is not empty this will always return an empty string 0254 */ 0255 QString attentionIconName() const; 0256 0257 /** 0258 * Sets the pixmap of the requesting attention icon. 0259 * Use setAttentionIcon(const QString) instead when possible. 0260 * 0261 * @param icon QIcon to use for requesting attention. 0262 */ 0263 void setAttentionIconByPixmap(const QIcon &icon); 0264 0265 /** 0266 * @return a pixmap of the requesting attention icon 0267 */ 0268 QIcon attentionIconPixmap() const; 0269 0270 /** 0271 * Sets a movie as the requesting attention icon. 0272 * This overrides anything set in setAttentionIcon() 0273 */ 0274 void setAttentionMovieByName(const QString &name); 0275 0276 /** 0277 * @return the name of the movie to be displayed when the application is 0278 * requesting the user attention 0279 */ 0280 QString attentionMovieName() const; 0281 0282 // ToolTip handling 0283 /** 0284 * Sets a new toolTip or this icon, a toolTip is composed of an icon, 0285 * a title and a text, all fields are optional. 0286 * 0287 * @param iconName a QIcon::fromTheme compatible name for the tootip icon 0288 * @param title tootip title 0289 * @param subTitle subtitle for the toolTip 0290 */ 0291 void setToolTip(const QString &iconName, const QString &title, const QString &subTitle); 0292 0293 /** 0294 * Sets a new toolTip or this status notifier item. 0295 * This is an overloaded member provided for convenience 0296 */ 0297 void setToolTip(const QIcon &icon, const QString &title, const QString &subTitle); 0298 0299 /** 0300 * Set a new icon for the toolTip 0301 * 0302 * @param name the name for the icon 0303 */ 0304 void setToolTipIconByName(const QString &name); 0305 0306 /** 0307 * @return the name of the toolTip icon 0308 * if toolTipImage() is not empty this will always return an empty string 0309 */ 0310 QString toolTipIconName() const; 0311 0312 /** 0313 * Set a new icon for the toolTip. 0314 * 0315 * Use setToolTipIconByName(QString) if possible. 0316 * @param pixmap representing the icon 0317 */ 0318 void setToolTipIconByPixmap(const QIcon &icon); 0319 0320 /** 0321 * @return a serialization of the toolTip icon data 0322 */ 0323 QIcon toolTipIconPixmap() const; 0324 0325 /** 0326 * Sets a new title for the toolTip 0327 */ 0328 void setToolTipTitle(const QString &title); 0329 0330 /** 0331 * @return the title of the main icon toolTip 0332 */ 0333 QString toolTipTitle() const; 0334 0335 /** 0336 * Sets a new subtitle for the toolTip 0337 */ 0338 void setToolTipSubTitle(const QString &subTitle); 0339 0340 /** 0341 * @return the subtitle of the main icon toolTip 0342 */ 0343 QString toolTipSubTitle() const; 0344 0345 /** 0346 * Sets a new context menu for this StatusNotifierItem. 0347 * the menu will be shown with a contextMenu(int,int) 0348 * call by the systemtray over D-Bus 0349 * usually you don't need to call this unless you want to use 0350 * a custom QMenu subclass as context menu. 0351 * 0352 * The KStatusNotifierItem instance takes ownership of the menu, 0353 * and will delete it upon its destruction. 0354 */ 0355 void setContextMenu(QMenu *menu); 0356 0357 /** 0358 * Access the context menu associated to this status notifier item 0359 */ 0360 QMenu *contextMenu() const; 0361 0362 /** 0363 * Sets the main widget associated with this StatusNotifierItem 0364 * 0365 * If you pass contextMenu() as a parent then the menu will be displayed 0366 * when the user activate the icon. In this case the activate() method will 0367 * not be called and the activateRequested() signal will not be emitted 0368 * 0369 * @param parent the new main widget: must be a top level window, 0370 * if it's not parent->window() will be used instead. 0371 */ 0372 void setAssociatedWidget(QWidget *parent); 0373 0374 /** 0375 * Access the main widget associated with this StatusNotifierItem 0376 */ 0377 QWidget *associatedWidget() 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 widget and try to position it on top 0437 * of the other windows, if the widget 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 widget, 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 widget via activate(const QPoint &) 0448 * is not wanted, but instead the hidden state should be reached in any case. 0449 * 0450 * @since 5.91 0451 */ 0452 void hideAssociatedWidget(); 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