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

source code of qtquickcontrols2/src/imports/platform/qquickplatformsystemtrayicon.cpp