1/* This file is part of the KDE libraries
2 Copyright 2009 by Marco Martin <notmart@gmail.com>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License (LGPL) as published by the Free Software Foundation;
7 either version 2 of the License, or (at your option) any later
8 version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#ifndef KSTATUSNOTIFIERITEM_H
22#define KSTATUSNOTIFIERITEM_H
23
24#include <QtCore/QObject>
25#include <QtCore/QString>
26#include <QtDBus/QDBusArgument>
27#include <QtCore/QPoint>
28
29#include "kdeui_export.h"
30
31class KActionCollection;
32class KMenu;
33class QMovie;
34
35
36class KStatusNotifierItemPrivate;
37
38/**
39 * \brief %KDE Status notifier Item protocol implementation
40 *
41 * This class implements the Status notifier Item Dbus specification.
42 * It provides an icon similar to the classical systemtray icons,
43 * with some key differences:
44 *
45 * - the actual representation is done by the systemtray (or the app behaving
46 * like it) itself, not by this app. Since 4.5 this also includes the menu,
47 * which means you cannot use embed widgets in the menu.
48 *
49 * - there is communication between the systemtray and the icon owner, so the
50 * system tray can know if the application is in a normal or in a requesting
51 * attention state.
52 *
53 * - icons are divided in categories, so the systemtray can represent in a
54 * different way the icons from normal applications and for instance the ones
55 * about hardware status.
56 *
57 * Whenever possible you should prefer passing icon by name rather than by
58 * pixmap because:
59 *
60 * - it is much lighter on Dbus (no need to pass all image pixels).
61 *
62 * - it makes it possible for the systemtray to load an icon of the appropriate
63 * size or to replace your icon with a systemtray specific icon which matches
64 * with the desktop theme.
65 *
66 * - some implementations of the system tray do not support passing icons by
67 * pixmap and will show a blank icon instead.
68 *
69 * @author Marco Martin <notmart@gmail.com>
70 * @since 4.4
71 */
72class KDEUI_EXPORT KStatusNotifierItem : public QObject
73{
74 Q_OBJECT
75
76 Q_ENUMS(ItemStatus)
77 Q_ENUMS(ItemCategory)
78 Q_PROPERTY( ItemCategory category READ category WRITE setCategory )
79 Q_PROPERTY( QString title READ title WRITE setTitle )
80 Q_PROPERTY( ItemStatus status READ status WRITE setStatus )
81 Q_PROPERTY( QString iconName READ iconName WRITE setIconByName )
82 Q_PROPERTY( QString overlayIconName READ overlayIconName WRITE setOverlayIconByName )
83 Q_PROPERTY( QString attentionIconName READ attentionIconName WRITE setAttentionIconByName )
84 Q_PROPERTY( QString toolTipIconName READ toolTipIconName WRITE setToolTipIconByName )
85 Q_PROPERTY( QString toolTipTitle READ toolTipTitle WRITE setToolTipTitle )
86 Q_PROPERTY( QString toolTipSubTitle READ toolTipSubTitle WRITE setToolTipSubTitle )
87
88 friend class KStatusNotifierItemDBus;
89 friend class KStatusNotifierItemPrivate;
90public:
91 /**
92 * All the possible status this icon can have, depending on the
93 * importance of the events that happens in the parent application
94 */
95 enum ItemStatus {
96 /// Nothing is happening in the application, so showing this icon is not required
97 Passive = 1,
98 /// The application is doing something, or it is important that the
99 /// icon is always reachable from the user
100 Active = 2,
101 /// The application requests the attention of the user, for instance
102 /// battery running out or a new IM message was received
103 NeedsAttention = 3
104 };
105
106 /**
107 * Different kinds of applications announce their type to the systemtray,
108 * so can be drawn in a different way or in a different place
109 */
110 enum ItemCategory {
111 /// An icon for a normal application, can be seen as its taskbar entry
112 ApplicationStatus = 1,
113 /// This is a communication oriented application; this icon will be used
114 /// for things such as the notification of a new message
115 Communications = 2,
116 /// This is a system service, it can show itself in the system tray if
117 /// it requires interaction from the user or wants to inform him about
118 /// something
119 SystemServices = 3,
120 /// This application shows hardware status or a means to control it
121 Hardware = 4,
122 Reserved = 129
123 };
124
125 /**
126 * Construct a new status notifier item
127 *
128 * @param parent the parent object for this object. If the object passed in as
129 * a parent is also a QWidget, it will be used as the main application window
130 * represented by this icon and will be shown/hidden when an activation is requested.
131 * @see associatedWidget
132 **/
133 explicit KStatusNotifierItem(QObject *parent = 0);
134
135 /**
136 * Construct a new status notifier item with a unique identifier.
137 * If your application has more than one status notifier item and the user
138 * should be able to manipulate them separately (e.g. mark them for hiding
139 * in a user interface), the id can be used to differentiate between them.
140 *
141 * The id should remain consistent even between application restarts.
142 * Status notifier items without ids default to the application's name for the id.
143 * This id may be used, for instance, by hosts displaying status notifier items to
144 * associate configuration information with this item in a way that can persist
145 * between sessions or application restarts.
146 *
147 * @param id the unique id for this icon
148 * @param parent the parent object for this object. If the object passed in as
149 * a parent is also a QWidget, it will be used as the main application window
150 * represented by this icon and will be shown/hidden when an activation is requested.
151 * @see associatedWidget
152 **/
153 explicit KStatusNotifierItem(const QString &id, QObject *parent = 0);
154
155 ~KStatusNotifierItem();
156
157 /**
158 * @return The id which was specified in the constructor. This should be
159 * guaranteed to be consistent between application starts and
160 * untranslated, as host applications displaying items may use it for
161 * storing configuration related to this item.
162 */
163 QString id() const;
164
165 /**
166 * Sets the category for this icon, usually it's needed to call this function only once
167 *
168 * @param category the new category for this icon
169 */
170 void setCategory(const ItemCategory category);
171
172 /**
173 * @return the application category
174 */
175 ItemCategory category() const;
176
177 /**
178 * Sets a title for this icon
179 */
180 void setTitle(const QString &title);
181
182 /**
183 * @return the title of this icon
184 */
185 QString title() const;
186
187 /**
188 * Sets a new status for this icon.
189 */
190 void setStatus(const ItemStatus status);
191
192 /**
193 * @return the current application status
194 */
195 ItemStatus status() const;
196
197 //Main icon related functions
198 /**
199 * Sets a new main icon for the system tray
200 *
201 * @param name it must be a KIconLoader compatible name, this is
202 * the preferred way to set an icon
203 */
204 void setIconByName(const QString &name);
205
206 /**
207 * @return the name of the main icon to be displayed
208 * if image() is not empty this will always return an empty string
209 */
210 QString iconName() const;
211
212 /**
213 * Sets a new main icon for the system tray
214 *
215 * @param pixmap our icon, use setIcon(const QString) when possible
216 */
217 void setIconByPixmap(const QIcon &icon);
218
219 /**
220 * @return a pixmap of the icon
221 */
222 QIcon iconPixmap() const;
223
224 /**
225 * Sets an icon to be used as overlay for the main one
226 * @param icon name, if name is and empty QString()
227 * (and overlayIconPixmap() is empty too) the icon will be removed
228 */
229 void setOverlayIconByName(const QString &name);
230
231 /**
232 * @return the name of the icon to be used as overlay fr the main one
233 */
234 QString overlayIconName() const;
235
236 /**
237 * Sets an icon to be used as overlay for the main one
238 * setOverlayIconByPixmap(QIcon()) will remove the overlay when
239 * overlayIconName() is empty too.
240 *
241 * @param pixmap our overlay icon, use setOverlayIcon(const QString) when possible.
242 */
243 void setOverlayIconByPixmap(const QIcon &icon);
244
245 /**
246 * @return a pixmap of the icon
247 */
248 QIcon overlayIconPixmap() const;
249
250 //Requesting attention icon
251
252 /**
253 * Sets a new icon that should be used when the application
254 * wants to request attention (usually the systemtray
255 * will blink between this icon and the main one)
256 *
257 * @param name KIconLoader-compatible name of icon to use
258 */
259 void setAttentionIconByName(const QString &name);
260
261 /**
262 * @return the name of the icon to be displayed when the application
263 * is requesting the user's attention
264 * if attentionImage() is not empty this will always return an empty string
265 */
266 QString attentionIconName() const;
267
268 /**
269 * Sets the pixmap of the requesting attention icon.
270 * Use setAttentionIcon(const QString) instead when possible.
271 *
272 * @param icon QIcon to use for requesting attention.
273 */
274 void setAttentionIconByPixmap(const QIcon &icon);
275
276 /**
277 * @return a pixmap of the requesting attention icon
278 */
279 QIcon attentionIconPixmap() const;
280
281 /**
282 * Sets a movie as the requesting attention icon.
283 * This overrides anything set in setAttentionIcon()
284 */
285 void setAttentionMovieByName(const QString &name);
286
287 /**
288 * @return the name of the movie to be displayed when the application is
289 * requesting the user attention
290 */
291 QString attentionMovieName() const;
292
293
294 //ToolTip handling
295 /**
296 * Sets a new toolTip or this icon, a toolTip is composed of an icon,
297 * a title ad a text, all fields are optional.
298 *
299 * @param iconName a KIconLoader compatible name for the tootip icon
300 * @param title tootip title
301 * @param subTitle subtitle for the toolTip
302 */
303 void setToolTip(const QString &iconName, const QString &title, const QString &subTitle);
304
305 /**
306 * Sets a new toolTip or this status notifier item.
307 * This is an overloaded member provided for convenience
308 */
309 void setToolTip(const QIcon &icon, const QString &title, const QString &subTitle);
310
311 /**
312 * Set a new icon for the toolTip
313 *
314 * @param name the name for the icon
315 */
316 void setToolTipIconByName(const QString &name);
317
318 /**
319 * @return the name of the toolTip icon
320 * if toolTipImage() is not empty this will always return an empty string
321 */
322 QString toolTipIconName() const;
323
324 /**
325 * Set a new icon for the toolTip.
326 *
327 * Use setToolTipIconByName(QString) if possible.
328 * @param pixmap representing the icon
329 */
330 void setToolTipIconByPixmap(const QIcon &icon);
331
332 /**
333 * @return a serialization of the toolTip icon data
334 */
335 QIcon toolTipIconPixmap() const;
336
337 /**
338 * Sets a new title for the toolTip
339 */
340 void setToolTipTitle(const QString &title);
341
342 /**
343 * @return the title of the main icon toolTip
344 */
345 QString toolTipTitle() const;
346
347 /**
348 * Sets a new subtitle for the toolTip
349 */
350 void setToolTipSubTitle(const QString &subTitle);
351
352 /**
353 * @return the subtitle of the main icon toolTip
354 */
355 QString toolTipSubTitle() const;
356
357 /**
358 * Sets a new context menu for this StatusNotifierItem.
359 * the menu will be shown with a contextMenu(int,int)
360 * call by the systemtray over dbus
361 * usually you don't need to call this unless you want to use
362 * a custom KMenu subclass as context menu
363 */
364 void setContextMenu(KMenu *menu);
365
366 /**
367 * Access the context menu associated to this status notifier item
368 */
369 KMenu *contextMenu() const;
370
371 /**
372 * Sets the main widget associated with this StatusNotifierItem
373 *
374 * If you pass contextMenu() as a parent then the menu will be displayed
375 * when the user activate the icon. In this case the activate() method will
376 * not be called and the activateRequested() signal will not be emitted
377 *
378 * @param parent the new main widget: must be a top level window,
379 * if it's not parent->window() will be used instead.
380 */
381 void setAssociatedWidget(QWidget *parent);
382
383 /**
384 * Access the main widget associated with this StatusNotifierItem
385 */
386 QWidget *associatedWidget() const;
387
388 /**
389 * All the actions present in the menu
390 */
391 KActionCollection *actionCollection() const;
392
393 /**
394 * Sets whether to show the standard items in the menu, such as Quit
395 */
396 void setStandardActionsEnabled(bool enabled);
397
398 /**
399 * @return if the standard items in the menu, such as Quit
400 */
401 bool standardActionsEnabled() const;
402
403 /**
404 * Shows the user a notification. If possible use KNotify instead
405 *
406 * @param title message title
407 * @param message the actual text shown to the user
408 * @param icon icon to be shown to the user
409 * @param timeout how much time will elaps before hiding the message
410 */
411 void showMessage(const QString &title, const QString &message, const QString &icon, int timeout = 10000);
412
413
414public Q_SLOTS:
415
416 /**
417 * Shows the main widget and try to position it on top
418 * of the other windows, if the widget is already visible, hide it.
419 *
420 * @param pos if it's a valid position it represents the mouse coordinates when the event was triggered
421 */
422 virtual void activate(const QPoint &pos = QPoint());
423
424Q_SIGNALS:
425 /**
426 * Inform the host application that the mouse wheel
427 * (or another mean of scrolling that the visualization provides) has been used
428 *
429 * @param delta the amount of scrolling, can be either positive or negative
430 * @param orientation direction of the scrolling, can be either horizontal or vertical
431 */
432 void scrollRequested(int delta, Qt::Orientation orientation);
433
434 /**
435 * Inform the host application that an activation has been requested,
436 * for instance left mouse click, but this is not guaranteed since
437 * it's dependent from the visualization
438 * @param active if it's true the application asked for the activatin
439 * of the main window, if it's false it asked for hiding
440 * @param pos the position in the screen where the user clicked to
441 * trigger this signal, QPoint() if it's not the consequence of a mouse click.
442 */
443 void activateRequested(bool active, const QPoint &pos);
444
445 /**
446 * Alternate activate action,
447 * for instance right mouse click, but this is not guaranteed since
448 * it's dependent from the visualization
449 *
450 * @param pos the position in the screen where the user clicked to
451 * trigger this signal, QPoint() if it's not the consequence of a mouse click.
452 */
453 void secondaryActivateRequested(const QPoint &pos);
454
455protected:
456 bool eventFilter(QObject *watched, QEvent *event);
457
458private:
459 KStatusNotifierItemPrivate *const d;
460
461 Q_PRIVATE_SLOT(d, void serviceChange(const QString& name,
462 const QString& oldOwner,
463 const QString& newOwner))
464 Q_PRIVATE_SLOT(d, void checkForRegisteredHosts())
465 Q_PRIVATE_SLOT(d, void registerToDaemon())
466 Q_PRIVATE_SLOT(d, void contextMenuAboutToShow())
467 Q_PRIVATE_SLOT(d, void maybeQuit())
468 Q_PRIVATE_SLOT(d, void minimizeRestore())
469 Q_PRIVATE_SLOT(d, void hideMenu())
470 Q_PRIVATE_SLOT(d, void legacyWheelEvent(int))
471 Q_PRIVATE_SLOT(d, void legacyActivated(QSystemTrayIcon::ActivationReason))
472};
473
474#endif
475