1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquicklabsplatformsystemtrayicon_p.h"
5#include "qquicklabsplatformmenu_p.h"
6#include "qquicklabsplatformiconloader_p.h"
7
8#include <QtCore/qloggingcategory.h>
9#include <QtGui/qpa/qplatformtheme.h>
10#include <QtGui/private/qguiapplication_p.h>
11
12#include "widgets/qwidgetplatform_p.h"
13
14QT_BEGIN_NAMESPACE
15
16/*!
17 \qmltype SystemTrayIcon
18 \inherits QtObject
19//! \nativetype QQuickLabsPlatformSystemTrayIcon
20 \inqmlmodule Qt.labs.platform
21 \since 5.8
22 \brief A system tray icon.
23
24 The SystemTrayIcon type provides an icon for an application in the system tray.
25
26 Many desktop platforms provide a special system tray or notification area,
27 where applications can display icons and notification messages.
28
29 \image qtlabsplatform-systemtrayicon.png
30
31 The following example shows how to create a system tray icon, and how to make
32 use of the \l activated() signal:
33
34 \code
35 SystemTrayIcon {
36 visible: true
37 icon.source: "qrc:/images/tray-icon.png"
38
39 onActivated: {
40 window.show()
41 window.raise()
42 window.requestActivate()
43 }
44 }
45 \endcode
46
47 \section2 Tray menu
48
49 SystemTrayIcon can have a menu that opens when the icon is activated.
50
51 \image qtlabsplatform-systemtrayicon-menu.png
52
53 The following example illustrates how to assign a \l Menu to a system tray icon:
54
55 \code
56 SystemTrayIcon {
57 visible: true
58 icon.source: "qrc:/images/tray-icon.png"
59
60 menu: Menu {
61 MenuItem {
62 text: qsTr("Quit")
63 onTriggered: Qt.quit()
64 }
65 }
66 }
67 \endcode
68
69 \section2 Notification messages
70
71 SystemTrayIcon can display notification messages.
72
73 \image qtlabsplatform-systemtrayicon-message.png
74
75 The following example presents how to show a notification message using
76 \l showMessage(), and how to make use of the \l messageClicked() signal:
77
78 \code
79 SystemTrayIcon {
80 visible: true
81 icon.source: "qrc:/images/tray-icon.png"
82
83 onMessageClicked: console.log("Message clicked")
84 Component.onCompleted: showMessage("Message title", "Something important came up. Click this to know more.")
85 }
86 \endcode
87
88 \section2 Availability
89
90 A native system tray icon is currently \l available on the following platforms:
91
92 \list
93 \li All window managers and independent tray implementations for X11 that implement the
94 \l{http://standards.freedesktop.org/systemtray-spec/systemtray-spec-0.2.html}
95 {freedesktop.org XEmbed system tray specification}.
96 \li All desktop environments that implement the
97 \l{http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierItem}
98 {freedesktop.org D-Bus StatusNotifierItem specification}, including recent versions of KDE and Unity.
99 \li All supported versions of macOS. Note that the Growl notification system must be installed
100 for showMessage() to display messages on OS X prior to 10.8 (Mountain Lion).
101 \endlist
102
103 \input includes/widgets.qdocinc 1
104
105 \labs
106
107 \sa Menu
108*/
109
110/*!
111 \qmlsignal Qt.labs.platform::SystemTrayIcon::activated(ActivationReason reason)
112
113 This signal is emitted when the system tray icon is activated by the user. The
114 \a reason argument specifies how the system tray icon was activated.
115
116 Available reasons:
117
118 \value SystemTrayIcon.Unknown Unknown reason
119 \value SystemTrayIcon.Context The context menu for the system tray icon was requested
120 \value SystemTrayIcon.DoubleClick The system tray icon was double clicked
121 \value SystemTrayIcon.Trigger The system tray icon was clicked
122 \value SystemTrayIcon.MiddleClick The system tray icon was clicked with the middle mouse button
123*/
124
125/*!
126 \qmlsignal Qt.labs.platform::SystemTrayIcon::messageClicked()
127
128 This signal is emitted when a notification message is clicked by the user.
129
130 \sa showMessage()
131*/
132
133Q_LOGGING_CATEGORY(qtLabsPlatformTray, "qt.labs.platform.tray")
134
135QQuickLabsPlatformSystemTrayIcon::QQuickLabsPlatformSystemTrayIcon(QObject *parent)
136 : QObject(parent),
137 m_complete(false),
138 m_visible(false),
139 m_menu(nullptr),
140 m_iconLoader(nullptr),
141 m_handle(nullptr)
142{
143 m_handle = QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon();
144 if (!m_handle)
145 m_handle = QWidgetPlatform::createSystemTrayIcon(parent: this);
146 qCDebug(qtLabsPlatformTray) << "SystemTrayIcon ->" << m_handle;
147
148 if (m_handle) {
149 connect(sender: m_handle, signal: &QPlatformSystemTrayIcon::activated, context: this, slot: &QQuickLabsPlatformSystemTrayIcon::activated);
150 connect(sender: m_handle, signal: &QPlatformSystemTrayIcon::messageClicked, context: this, slot: &QQuickLabsPlatformSystemTrayIcon::messageClicked);
151 }
152}
153
154QQuickLabsPlatformSystemTrayIcon::~QQuickLabsPlatformSystemTrayIcon()
155{
156 if (m_menu)
157 m_menu->setSystemTrayIcon(nullptr);
158 cleanup();
159 delete m_iconLoader;
160 m_iconLoader = nullptr;
161 delete m_handle;
162 m_handle = nullptr;
163}
164
165QPlatformSystemTrayIcon *QQuickLabsPlatformSystemTrayIcon::handle() const
166{
167 return m_handle;
168}
169
170/*!
171 \readonly
172 \qmlproperty bool Qt.labs.platform::SystemTrayIcon::available
173
174 This property holds whether the system tray is available.
175*/
176bool QQuickLabsPlatformSystemTrayIcon::isAvailable() const
177{
178 return m_handle && m_handle->isSystemTrayAvailable();
179}
180
181/*!
182 \readonly
183 \qmlproperty bool Qt.labs.platform::SystemTrayIcon::supportsMessages
184
185 This property holds whether the system tray icon supports notification messages.
186
187 \sa showMessage()
188*/
189bool QQuickLabsPlatformSystemTrayIcon::supportsMessages() const
190{
191 return m_handle && m_handle->supportsMessages();
192}
193
194/*!
195 \qmlproperty bool Qt.labs.platform::SystemTrayIcon::visible
196
197 This property holds whether the system tray icon is visible.
198
199 The default value is \c false.
200*/
201bool QQuickLabsPlatformSystemTrayIcon::isVisible() const
202{
203 return m_visible;
204}
205
206void QQuickLabsPlatformSystemTrayIcon::setVisible(bool visible)
207{
208 if (m_visible == visible)
209 return;
210
211 if (m_handle && m_complete) {
212 if (visible)
213 init();
214 else
215 cleanup();
216 }
217
218 m_visible = visible;
219 emit visibleChanged();
220}
221
222/*!
223 \qmlproperty string Qt.labs.platform::SystemTrayIcon::tooltip
224
225 This property holds the tooltip of the system tray icon.
226*/
227QString QQuickLabsPlatformSystemTrayIcon::tooltip() const
228{
229 return m_tooltip;
230}
231
232void QQuickLabsPlatformSystemTrayIcon::setTooltip(const QString &tooltip)
233{
234 if (m_tooltip == tooltip)
235 return;
236
237 if (m_handle && m_complete)
238 m_handle->updateToolTip(tooltip);
239
240 m_tooltip = tooltip;
241 emit tooltipChanged();
242}
243
244/*!
245 \qmlproperty Menu Qt.labs.platform::SystemTrayIcon::menu
246
247 This property holds a menu for the system tray icon.
248*/
249QQuickLabsPlatformMenu *QQuickLabsPlatformSystemTrayIcon::menu() const
250{
251 return m_menu;
252}
253
254void QQuickLabsPlatformSystemTrayIcon::setMenu(QQuickLabsPlatformMenu *menu)
255{
256 if (m_menu == menu)
257 return;
258
259 if (m_menu)
260 m_menu->setSystemTrayIcon(nullptr);
261
262 if (menu)
263 menu->setSystemTrayIcon(this);
264
265 if (m_handle && m_complete) {
266 if (menu && menu->create())
267 m_handle->updateMenu(menu: menu->handle());
268 else
269 m_handle->updateMenu(menu: nullptr);
270 }
271
272 m_menu = menu;
273 emit menuChanged();
274}
275
276/*!
277 \since Qt.labs.platform 1.1 (Qt 5.12)
278 \qmlproperty rect Qt.labs.platform::SystemTrayIcon::geometry
279
280 This property holds the geometry of the system tray icon.
281*/
282QRect QQuickLabsPlatformSystemTrayIcon::geometry() const
283{
284 return m_handle ? m_handle->geometry() : QRect();
285}
286
287/*!
288 \since Qt.labs.platform 1.1 (Qt 5.12)
289 \qmlproperty url Qt.labs.platform::SystemTrayIcon::icon.source
290 \qmlproperty string Qt.labs.platform::SystemTrayIcon::icon.name
291 \qmlproperty bool Qt.labs.platform::SystemTrayIcon::icon.mask
292
293 This property holds the system tray icon.
294
295 \code
296 SystemTrayIcon {
297 icon.mask: true
298 icon.source: "qrc:/images/tray-icon.png"
299 }
300 \endcode
301*/
302QQuickLabsPlatformIcon QQuickLabsPlatformSystemTrayIcon::icon() const
303{
304 if (!m_iconLoader)
305 return QQuickLabsPlatformIcon();
306
307 return m_iconLoader->icon();
308}
309
310void QQuickLabsPlatformSystemTrayIcon::setIcon(const QQuickLabsPlatformIcon &icon)
311{
312 if (iconLoader()->icon() == icon)
313 return;
314
315 iconLoader()->setIcon(icon);
316 emit iconChanged();
317}
318
319/*!
320 \qmlmethod void Qt.labs.platform::SystemTrayIcon::show()
321
322 Shows the system tray icon.
323*/
324void QQuickLabsPlatformSystemTrayIcon::show()
325{
326 setVisible(true);
327}
328
329/*!
330 \qmlmethod void Qt.labs.platform::SystemTrayIcon::hide()
331
332 Hides the system tray icon.
333*/
334void QQuickLabsPlatformSystemTrayIcon::hide()
335{
336 setVisible(false);
337}
338
339/*!
340 \qmlmethod void Qt.labs.platform::SystemTrayIcon::showMessage(string title, string message, MessageIcon icon, int msecs)
341
342 Shows a system tray message with the given \a title, \a message and \a icon
343 for the time specified in \a msecs.
344
345 \note System tray messages are dependent on the system configuration and user preferences,
346 and may not appear at all. Therefore, it should not be relied upon as the sole means for providing
347 critical information.
348
349 \sa supportsMessages, messageClicked()
350*/
351void QQuickLabsPlatformSystemTrayIcon::showMessage(const QString &title, const QString &msg, QPlatformSystemTrayIcon::MessageIcon icon, int msecs)
352{
353 if (m_handle)
354 m_handle->showMessage(title, msg, icon: QIcon(), iconType: icon, msecs);
355}
356
357void QQuickLabsPlatformSystemTrayIcon::init()
358{
359 if (!m_handle)
360 return;
361
362 m_handle->init();
363 if (m_menu && m_menu->create())
364 m_handle->updateMenu(menu: m_menu->handle());
365 m_handle->updateToolTip(tooltip: m_tooltip);
366 if (m_iconLoader)
367 m_iconLoader->setEnabled(true);
368}
369
370void QQuickLabsPlatformSystemTrayIcon::cleanup()
371{
372 if (m_handle)
373 m_handle->cleanup();
374 if (m_iconLoader)
375 m_iconLoader->setEnabled(false);
376}
377
378void QQuickLabsPlatformSystemTrayIcon::classBegin()
379{
380}
381
382void QQuickLabsPlatformSystemTrayIcon::componentComplete()
383{
384 m_complete = true;
385 if (m_visible)
386 init();
387}
388
389QQuickLabsPlatformIconLoader *QQuickLabsPlatformSystemTrayIcon::iconLoader() const
390{
391 if (!m_iconLoader) {
392 QQuickLabsPlatformSystemTrayIcon *that = const_cast<QQuickLabsPlatformSystemTrayIcon *>(this);
393 static int slot = staticMetaObject.indexOfSlot(slot: "updateIcon()");
394 m_iconLoader = new QQuickLabsPlatformIconLoader(slot, that);
395 m_iconLoader->setEnabled(m_complete);
396 }
397 return m_iconLoader;
398}
399
400void QQuickLabsPlatformSystemTrayIcon::updateIcon()
401{
402 if (!m_handle || !m_iconLoader)
403 return;
404
405 const QRect oldGeometry = m_handle->geometry();
406
407 m_handle->updateIcon(icon: m_iconLoader->toQIcon());
408
409 if (oldGeometry != m_handle->geometry())
410 emit geometryChanged();
411}
412
413QT_END_NAMESPACE
414
415#include "moc_qquicklabsplatformsystemtrayicon_p.cpp"
416

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtdeclarative/src/labs/platform/qquicklabsplatformsystemtrayicon.cpp