1// Copyright (C) 2016 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 "qsystemtrayicon.h"
5#include "qsystemtrayicon_p.h"
6
7#ifndef QT_NO_SYSTEMTRAYICON
8
9#if QT_CONFIG(menu)
10#include "qmenu.h"
11#endif
12#include "qlist.h"
13#include "qevent.h"
14#include "qpoint.h"
15#if QT_CONFIG(label)
16#include "qlabel.h"
17#include "private/qlabel_p.h"
18#endif
19#if QT_CONFIG(pushbutton)
20#include "qpushbutton.h"
21#endif
22#include "qpainterpath.h"
23#include "qpainter.h"
24#include "qstyle.h"
25#include "qgridlayout.h"
26#include "qapplication.h"
27#include "qbitmap.h"
28
29#include <private/qhighdpiscaling_p.h>
30#include <qpa/qplatformscreen.h>
31
32QT_BEGIN_NAMESPACE
33
34static QIcon messageIcon2qIcon(QSystemTrayIcon::MessageIcon icon)
35{
36 QStyle::StandardPixmap stdIcon = QStyle::SP_CustomBase; // silence gcc 4.9.0 about uninited variable
37 switch (icon) {
38 case QSystemTrayIcon::Information:
39 stdIcon = QStyle::SP_MessageBoxInformation;
40 break;
41 case QSystemTrayIcon::Warning:
42 stdIcon = QStyle::SP_MessageBoxWarning;
43 break;
44 case QSystemTrayIcon::Critical:
45 stdIcon = QStyle::SP_MessageBoxCritical;
46 break;
47 case QSystemTrayIcon::NoIcon:
48 return QIcon();
49 }
50 return QApplication::style()->standardIcon(standardIcon: stdIcon);
51}
52
53/*!
54 \class QSystemTrayIcon
55 \brief The QSystemTrayIcon class provides an icon for an application in the system tray.
56 \since 4.2
57 \ingroup desktop
58 \inmodule QtWidgets
59
60 Modern operating systems usually provide a special area on the desktop,
61 called the \e{system tray} or \e{notification area}, where long-running
62 applications can display icons and short messages.
63
64 \image system-tray.webp The system tray on Windows 10.
65
66 The QSystemTrayIcon class can be used on the following platforms:
67
68 \list
69 \li All supported versions of Windows.
70 \li All Linux desktop environments that implement the D-Bus
71 \l{http://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierItem}
72 {StatusNotifierItem specification}, including KDE, Gnome, Xfce, LXQt, and DDE.
73 \li All window managers and independent tray implementations for X11 that implement the
74 \l{http://standards.freedesktop.org/systemtray-spec/systemtray-spec-0.2.html}
75 {freedesktop.org XEmbed system tray specification}.
76 \li All supported versions of \macos.
77 \endlist
78
79 To check whether a system tray is present on the user's desktop,
80 call the QSystemTrayIcon::isSystemTrayAvailable() static function.
81
82 To add a system tray entry, create a QSystemTrayIcon object, call setContextMenu()
83 to provide a context menu for the icon, and call show() to make it visible in the
84 system tray. Status notification messages ("balloon messages") can be displayed at
85 any time using showMessage().
86
87 If the system tray is unavailable when a system tray icon is constructed, but
88 becomes available later, QSystemTrayIcon will automatically add an entry for the
89 application in the system tray if the icon is \l visible.
90
91 The activated() signal is emitted when the user activates the icon.
92
93 Only on X11, when a tooltip is requested, the QSystemTrayIcon receives a QHelpEvent
94 of type QEvent::ToolTip. Additionally, the QSystemTrayIcon receives wheel events of
95 type QEvent::Wheel. These are not supported on any other platform. Note: Since GNOME
96 Shell version 3.26, not all QSystemTrayIcon::ActivationReason are supported by the
97 system without shell extensions installed.
98
99 \sa QDesktopServices, {Desktop Integration}, {System Tray Icon Example}
100*/
101
102/*!
103 \enum QSystemTrayIcon::MessageIcon
104
105 This enum describes the icon that is shown when a balloon message is displayed.
106
107 \value NoIcon No icon is shown.
108 \value Information An information icon is shown.
109 \value Warning A standard warning icon is shown.
110 \value Critical A critical warning icon is shown.
111
112 \sa QMessageBox
113*/
114
115/*!
116 Constructs a QSystemTrayIcon object with the given \a parent.
117
118 The icon is initially invisible.
119
120 \sa visible
121*/
122QSystemTrayIcon::QSystemTrayIcon(QObject *parent)
123: QObject(*new QSystemTrayIconPrivate(), parent)
124{
125}
126
127/*!
128 Constructs a QSystemTrayIcon object with the given \a icon and \a parent.
129
130 The icon is initially invisible.
131
132 \sa visible
133*/
134QSystemTrayIcon::QSystemTrayIcon(const QIcon &icon, QObject *parent)
135 : QSystemTrayIcon(parent)
136{
137 setIcon(icon);
138}
139
140/*!
141 Removes the icon from the system tray and frees all allocated resources.
142*/
143QSystemTrayIcon::~QSystemTrayIcon()
144{
145 Q_D(QSystemTrayIcon);
146 d->remove_sys();
147}
148
149#if QT_CONFIG(menu)
150
151/*!
152 Sets the specified \a menu to be the context menu for the system tray icon.
153
154 The menu will pop up when the user requests the context menu for the system
155 tray icon by clicking the mouse button.
156
157 \note The system tray icon does not take ownership of the menu. You must
158 ensure that it is deleted at the appropriate time by, for example, creating
159 the menu with a suitable parent object.
160*/
161void QSystemTrayIcon::setContextMenu(QMenu *menu)
162{
163 Q_D(QSystemTrayIcon);
164 QMenu *oldMenu = d->menu.data();
165 if (oldMenu == menu)
166 return;
167
168 d->menu = menu;
169 d->updateMenu_sys();
170
171 if (d->qpa_sys) {
172 // Show the QMenu-based menu for QPA plugins that do not provide native menus
173 if (oldMenu && !oldMenu->platformMenu())
174 QObject::disconnect(sender: d->qpa_sys, signal: &QPlatformSystemTrayIcon::contextMenuRequested, receiver: oldMenu, zero: nullptr);
175 if (menu && !menu->platformMenu()) {
176 QObject::connect(sender: d->qpa_sys, signal: &QPlatformSystemTrayIcon::contextMenuRequested,
177 context: menu,
178 slot: [menu](QPoint globalNativePos, const QPlatformScreen *platformScreen)
179 {
180 QScreen *screen = platformScreen ? platformScreen->screen() : nullptr;
181 menu->popup(pos: QHighDpi::fromNativePixels(value: globalNativePos, context: screen), at: nullptr);
182 });
183 }
184 }
185}
186
187/*!
188 Returns the current context menu for the system tray entry.
189*/
190QMenu* QSystemTrayIcon::contextMenu() const
191{
192 Q_D(const QSystemTrayIcon);
193 return d->menu;
194}
195
196#endif // QT_CONFIG(menu)
197
198/*!
199 \property QSystemTrayIcon::icon
200 \brief the system tray icon
201
202 On Windows, the system tray icon size is 16x16; on X11, the preferred size is
203 22x22. The icon will be scaled to the appropriate size as necessary.
204*/
205void QSystemTrayIcon::setIcon(const QIcon &icon)
206{
207 Q_D(QSystemTrayIcon);
208 d->icon = icon;
209 d->updateIcon_sys();
210}
211
212QIcon QSystemTrayIcon::icon() const
213{
214 Q_D(const QSystemTrayIcon);
215 return d->icon;
216}
217
218/*!
219 \property QSystemTrayIcon::toolTip
220 \brief the tooltip for the system tray entry
221
222 On some systems, the tooltip's length is limited. The tooltip will be truncated
223 if necessary.
224*/
225void QSystemTrayIcon::setToolTip(const QString &tooltip)
226{
227 Q_D(QSystemTrayIcon);
228 d->toolTip = tooltip;
229 d->updateToolTip_sys();
230}
231
232QString QSystemTrayIcon::toolTip() const
233{
234 Q_D(const QSystemTrayIcon);
235 return d->toolTip;
236}
237
238/*!
239 \fn void QSystemTrayIcon::show()
240
241 Shows the icon in the system tray.
242
243 \sa hide(), visible
244*/
245
246/*!
247 \fn void QSystemTrayIcon::hide()
248
249 Hides the system tray entry.
250
251 \sa show(), visible
252*/
253
254/*!
255 \since 4.3
256 Returns the geometry of the system tray icon in screen coordinates.
257
258 \sa visible
259*/
260QRect QSystemTrayIcon::geometry() const
261{
262 Q_D(const QSystemTrayIcon);
263 if (!d->visible)
264 return QRect();
265 return d->geometry_sys();
266}
267
268/*!
269 \property QSystemTrayIcon::visible
270 \brief whether the system tray entry is visible
271
272 Setting this property to true or calling show() makes the system tray icon
273 visible; setting this property to false or calling hide() hides it.
274*/
275void QSystemTrayIcon::setVisible(bool visible)
276{
277 Q_D(QSystemTrayIcon);
278 if (visible == d->visible)
279 return;
280 if (Q_UNLIKELY(visible && d->icon.isNull()))
281 qWarning(msg: "QSystemTrayIcon::setVisible: No Icon set");
282 d->visible = visible;
283 if (d->visible)
284 d->install_sys();
285 else
286 d->remove_sys();
287}
288
289bool QSystemTrayIcon::isVisible() const
290{
291 Q_D(const QSystemTrayIcon);
292 return d->visible;
293}
294
295/*!
296 \reimp
297*/
298bool QSystemTrayIcon::event(QEvent *e)
299{
300 return QObject::event(event: e);
301}
302
303/*!
304 \enum QSystemTrayIcon::ActivationReason
305
306 This enum describes the reason the system tray was activated.
307
308 \value Unknown Unknown reason
309 \value Context The context menu for the system tray entry was requested
310 \value DoubleClick The system tray entry was double clicked. \note On macOS, a
311 double click will only be emitted if no context menu is set, since the menu
312 opens on mouse press
313 \value Trigger The system tray entry was clicked
314 \value MiddleClick The system tray entry was clicked with the middle mouse button
315
316 \sa activated()
317*/
318
319/*!
320 \fn void QSystemTrayIcon::activated(QSystemTrayIcon::ActivationReason reason)
321
322 This signal is emitted when the user activates the system tray icon. \a reason
323 specifies the reason for activation. QSystemTrayIcon::ActivationReason enumerates
324 the various reasons.
325
326 \sa QSystemTrayIcon::ActivationReason
327*/
328
329/*!
330 \fn void QSystemTrayIcon::messageClicked()
331
332 This signal is emitted when the message displayed using showMessage()
333 was clicked by the user.
334
335 \note We follow Microsoft Windows behavior, so the
336 signal is also emitted when the user clicks on a tray icon with
337 a balloon message displayed.
338
339 \sa activated()
340*/
341
342
343/*!
344 Returns \c true if the system tray is available; otherwise returns \c false.
345
346 If the system tray is currently unavailable but becomes available later,
347 QSystemTrayIcon will automatically add an entry in the system tray if it
348 is \l visible.
349*/
350
351bool QSystemTrayIcon::isSystemTrayAvailable()
352{
353 return QSystemTrayIconPrivate::isSystemTrayAvailable_sys();
354}
355
356/*!
357 Returns \c true if the system tray supports balloon messages; otherwise returns \c false.
358
359 \sa showMessage()
360*/
361bool QSystemTrayIcon::supportsMessages()
362{
363 return QSystemTrayIconPrivate::supportsMessages_sys();
364}
365
366/*!
367 \fn void QSystemTrayIcon::showMessage(const QString &title, const QString &message, MessageIcon icon, int millisecondsTimeoutHint)
368 \since 4.3
369
370 Shows a balloon message for the entry with the given \a title, \a message and
371 \a icon for the time specified in \a millisecondsTimeoutHint. \a title and \a message
372 must be plain text strings.
373
374 Message can be clicked by the user; the messageClicked() signal will emitted when
375 this occurs.
376
377 Note that display of messages are dependent on the system configuration and user
378 preferences, and that messages may not appear at all. Hence, it should not be
379 relied upon as the sole means for providing critical information.
380
381 On Windows, the \a millisecondsTimeoutHint is usually ignored by the system
382 when the application has focus.
383
384 Has been turned into a slot in Qt 5.2.
385
386 \sa show(), supportsMessages()
387 */
388void QSystemTrayIcon::showMessage(const QString& title, const QString& msg,
389 QSystemTrayIcon::MessageIcon msgIcon, int msecs)
390{
391 Q_D(QSystemTrayIcon);
392 if (d->visible)
393 d->showMessage_sys(title, msg, icon: messageIcon2qIcon(icon: msgIcon), msgIcon, msecs);
394}
395
396/*!
397 \fn void QSystemTrayIcon::showMessage(const QString &title, const QString &message, const QIcon &icon, int millisecondsTimeoutHint)
398
399 \overload showMessage()
400
401 Shows a balloon message for the entry with the given \a title, \a message,
402 and custom icon \a icon for the time specified in \a millisecondsTimeoutHint.
403
404 \since 5.9
405*/
406void QSystemTrayIcon::showMessage(const QString &title, const QString &msg,
407 const QIcon &icon, int msecs)
408{
409 Q_D(QSystemTrayIcon);
410 if (d->visible)
411 d->showMessage_sys(title, msg, icon, msgIcon: QSystemTrayIcon::NoIcon, msecs);
412}
413
414void QSystemTrayIconPrivate::_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason reason)
415{
416 Q_Q(QSystemTrayIcon);
417 emit q->activated(reason: static_cast<QSystemTrayIcon::ActivationReason>(reason));
418}
419
420//////////////////////////////////////////////////////////////////////
421static QBalloonTip *theSolitaryBalloonTip = nullptr;
422
423void QBalloonTip::showBalloon(const QIcon &icon, const QString &title,
424 const QString &message, QSystemTrayIcon *trayIcon,
425 const QPoint &pos, int timeout, bool showArrow)
426{
427 hideBalloon();
428 if (message.isEmpty() && title.isEmpty())
429 return;
430
431 theSolitaryBalloonTip = new QBalloonTip(icon, title, message, trayIcon);
432 if (timeout < 0)
433 timeout = 10000; //10 s default
434 theSolitaryBalloonTip->balloon(pos, timeout, showArrow);
435}
436
437void QBalloonTip::hideBalloon()
438{
439 if (!theSolitaryBalloonTip)
440 return;
441 theSolitaryBalloonTip->hide();
442 delete theSolitaryBalloonTip;
443 theSolitaryBalloonTip = nullptr;
444}
445
446void QBalloonTip::updateBalloonPosition(const QPoint& pos)
447{
448 if (!theSolitaryBalloonTip)
449 return;
450 theSolitaryBalloonTip->hide();
451 theSolitaryBalloonTip->balloon(pos, 0, theSolitaryBalloonTip->showArrow);
452}
453
454bool QBalloonTip::isBalloonVisible()
455{
456 return theSolitaryBalloonTip;
457}
458
459QBalloonTip::QBalloonTip(const QIcon &icon, const QString &title,
460 const QString &message, QSystemTrayIcon *ti)
461 : QWidget(nullptr, Qt::ToolTip),
462 trayIcon(ti),
463 timerId(-1),
464 showArrow(true)
465{
466 setAttribute(Qt::WA_DeleteOnClose);
467 QObject::connect(sender: ti, SIGNAL(destroyed()), receiver: this, SLOT(close()));
468
469#if QT_CONFIG(label)
470 QLabel *titleLabel = new QLabel;
471 titleLabel->installEventFilter(filterObj: this);
472 titleLabel->setText(title);
473 QFont f = titleLabel->font();
474 f.setBold(true);
475 titleLabel->setFont(f);
476 titleLabel->setTextFormat(Qt::PlainText); // to maintain compat with windows
477#endif
478
479 const int iconSize = 18;
480 const int closeButtonSize = 15;
481
482#if QT_CONFIG(pushbutton)
483 QPushButton *closeButton = new QPushButton;
484 closeButton->setIcon(style()->standardIcon(standardIcon: QStyle::SP_TitleBarCloseButton));
485 closeButton->setIconSize(QSize(closeButtonSize, closeButtonSize));
486 closeButton->setSizePolicy(hor: QSizePolicy::Fixed, ver: QSizePolicy::Fixed);
487 closeButton->setFixedSize(w: closeButtonSize, h: closeButtonSize);
488 QObject::connect(sender: closeButton, SIGNAL(clicked()), receiver: this, SLOT(close()));
489#else
490 Q_UNUSED(closeButtonSize);
491#endif
492
493#if QT_CONFIG(label)
494 QLabel *msgLabel = new QLabel;
495 msgLabel->installEventFilter(filterObj: this);
496 msgLabel->setText(message);
497 msgLabel->setTextFormat(Qt::PlainText);
498 msgLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
499
500 // smart size for the message label
501 int limit = QWidgetPrivate::availableScreenGeometry(widget: msgLabel).width() / 3;
502 if (msgLabel->sizeHint().width() > limit) {
503 msgLabel->setWordWrap(true);
504 if (msgLabel->sizeHint().width() > limit) {
505 msgLabel->d_func()->ensureTextControl();
506 if (QWidgetTextControl *control = msgLabel->d_func()->control) {
507 QTextOption opt = control->document()->defaultTextOption();
508 opt.setWrapMode(QTextOption::WrapAnywhere);
509 control->document()->setDefaultTextOption(opt);
510 }
511 }
512 // Here we allow the text being much smaller than the balloon widget
513 // to emulate the weird standard windows behavior.
514 msgLabel->setFixedSize(w: limit, h: msgLabel->heightForWidth(limit));
515 }
516#endif
517
518 QGridLayout *layout = new QGridLayout;
519#if QT_CONFIG(label)
520 if (!icon.isNull()) {
521 QLabel *iconLabel = new QLabel;
522 iconLabel->setPixmap(icon.pixmap(w: iconSize, h: iconSize));
523 iconLabel->setSizePolicy(hor: QSizePolicy::Fixed, ver: QSizePolicy::Fixed);
524 iconLabel->setMargin(2);
525 layout->addWidget(iconLabel, row: 0, column: 0);
526 layout->addWidget(titleLabel, row: 0, column: 1);
527 } else {
528 layout->addWidget(titleLabel, row: 0, column: 0, rowSpan: 1, columnSpan: 2);
529 }
530#endif
531
532#if QT_CONFIG(pushbutton)
533 layout->addWidget(closeButton, row: 0, column: 2);
534#endif
535
536#if QT_CONFIG(label)
537 layout->addWidget(msgLabel, row: 1, column: 0, rowSpan: 1, columnSpan: 3);
538#endif
539 layout->setSizeConstraint(QLayout::SetFixedSize);
540 layout->setContentsMargins(left: 3, top: 3, right: 3, bottom: 3);
541 setLayout(layout);
542
543 QPalette pal = palette();
544 pal.setColor(acr: QPalette::Window, acolor: QColor(0xff, 0xff, 0xe1));
545 pal.setColor(acr: QPalette::WindowText, acolor: Qt::black);
546 setPalette(pal);
547}
548
549QBalloonTip::~QBalloonTip()
550{
551 theSolitaryBalloonTip = nullptr;
552}
553
554void QBalloonTip::paintEvent(QPaintEvent *)
555{
556 QPainter painter(this);
557 painter.drawPixmap(r: rect(), pm: pixmap);
558}
559
560void QBalloonTip::resizeEvent(QResizeEvent *ev)
561{
562 QWidget::resizeEvent(event: ev);
563}
564
565void QBalloonTip::balloon(const QPoint& pos, int msecs, bool showArrow)
566{
567 this->showArrow = showArrow;
568 QScreen *screen = QGuiApplication::screenAt(point: pos);
569 if (!screen)
570 screen = QGuiApplication::primaryScreen();
571 QRect screenRect = screen->geometry();
572 QSize sh = sizeHint();
573 const int border = 1;
574 const int ah = 18, ao = 18, aw = 18, rc = 7;
575 bool arrowAtTop = (pos.y() + sh.height() + ah < screenRect.height());
576 bool arrowAtLeft = (pos.x() + sh.width() - ao < screenRect.width());
577 setContentsMargins(left: border + 3, top: border + (arrowAtTop ? ah : 0) + 2, right: border + 3, bottom: border + (arrowAtTop ? 0 : ah) + 2);
578 updateGeometry();
579 sh = sizeHint();
580
581 int ml, mr, mt, mb;
582 QSize sz = sizeHint();
583 if (!arrowAtTop) {
584 ml = mt = 0;
585 mr = sz.width() - 1;
586 mb = sz.height() - ah - 1;
587 } else {
588 ml = 0;
589 mt = ah;
590 mr = sz.width() - 1;
591 mb = sz.height() - 1;
592 }
593
594 QPainterPath path;
595 path.moveTo(x: ml + rc, y: mt);
596 if (arrowAtTop && arrowAtLeft) {
597 if (showArrow) {
598 path.lineTo(x: ml + ao, y: mt);
599 path.lineTo(x: ml + ao, y: mt - ah);
600 path.lineTo(x: ml + ao + aw, y: mt);
601 }
602 move(ax: qMax(a: pos.x() - ao, b: screenRect.left() + 2), ay: pos.y());
603 } else if (arrowAtTop && !arrowAtLeft) {
604 if (showArrow) {
605 path.lineTo(x: mr - ao - aw, y: mt);
606 path.lineTo(x: mr - ao, y: mt - ah);
607 path.lineTo(x: mr - ao, y: mt);
608 }
609 move(ax: qMin(a: pos.x() - sh.width() + ao, b: screenRect.right() - sh.width() - 2), ay: pos.y());
610 }
611 path.lineTo(x: mr - rc, y: mt);
612 path.arcTo(rect: QRect(mr - rc*2, mt, rc*2, rc*2), startAngle: 90, arcLength: -90);
613 path.lineTo(x: mr, y: mb - rc);
614 path.arcTo(rect: QRect(mr - rc*2, mb - rc*2, rc*2, rc*2), startAngle: 0, arcLength: -90);
615 if (!arrowAtTop && !arrowAtLeft) {
616 if (showArrow) {
617 path.lineTo(x: mr - ao, y: mb);
618 path.lineTo(x: mr - ao, y: mb + ah);
619 path.lineTo(x: mr - ao - aw, y: mb);
620 }
621 move(ax: qMin(a: pos.x() - sh.width() + ao, b: screenRect.right() - sh.width() - 2),
622 ay: pos.y() - sh.height());
623 } else if (!arrowAtTop && arrowAtLeft) {
624 if (showArrow) {
625 path.lineTo(x: ao + aw, y: mb);
626 path.lineTo(x: ao, y: mb + ah);
627 path.lineTo(x: ao, y: mb);
628 }
629 move(ax: qMax(a: pos.x() - ao, b: screenRect.x() + 2), ay: pos.y() - sh.height());
630 }
631 path.lineTo(x: ml + rc, y: mb);
632 path.arcTo(rect: QRect(ml, mb - rc*2, rc*2, rc*2), startAngle: -90, arcLength: -90);
633 path.lineTo(x: ml, y: mt + rc);
634 path.arcTo(rect: QRect(ml, mt, rc*2, rc*2), startAngle: 180, arcLength: -90);
635
636 // Set the mask
637 QBitmap bitmap = QBitmap(sizeHint());
638 bitmap.fill(fillColor: Qt::color0);
639 QPainter painter1(&bitmap);
640 painter1.setPen(QPen(Qt::color1, border));
641 painter1.setBrush(QBrush(Qt::color1));
642 painter1.drawPath(path);
643 setMask(bitmap);
644
645 // Draw the border
646 pixmap = QPixmap(sz);
647 QPainter painter2(&pixmap);
648 painter2.setPen(QPen(palette().color(cr: QPalette::Window).darker(f: 160), border));
649 painter2.setBrush(palette().color(cr: QPalette::Window));
650 painter2.drawPath(path);
651
652 if (msecs > 0)
653 timerId = startTimer(interval: msecs);
654 show();
655}
656
657void QBalloonTip::mousePressEvent(QMouseEvent *e)
658{
659 close();
660 if (e->button() == Qt::LeftButton)
661 emit trayIcon->messageClicked();
662}
663
664void QBalloonTip::timerEvent(QTimerEvent *e)
665{
666 if (e->timerId() == timerId) {
667 killTimer(id: timerId);
668 if (!underMouse())
669 close();
670 return;
671 }
672 QWidget::timerEvent(event: e);
673}
674
675//////////////////////////////////////////////////////////////////////
676void QSystemTrayIconPrivate::install_sys_qpa()
677{
678 qpa_sys->init();
679 QObject::connect(sender: qpa_sys, SIGNAL(activated(QPlatformSystemTrayIcon::ActivationReason)),
680 receiver: q_func(), SLOT(_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason)));
681 QObject::connect(sender: qpa_sys, signal: &QPlatformSystemTrayIcon::messageClicked,
682 context: q_func(), slot: &QSystemTrayIcon::messageClicked);
683 updateMenu_sys();
684 updateIcon_sys();
685 updateToolTip_sys();
686}
687
688void QSystemTrayIconPrivate::remove_sys_qpa()
689{
690 QObject::disconnect(sender: qpa_sys, SIGNAL(activated(QPlatformSystemTrayIcon::ActivationReason)),
691 receiver: q_func(), SLOT(_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason)));
692 QObject::disconnect(sender: qpa_sys, signal: &QPlatformSystemTrayIcon::messageClicked,
693 receiver: q_func(), slot: &QSystemTrayIcon::messageClicked);
694 qpa_sys->cleanup();
695}
696
697void QSystemTrayIconPrivate::addPlatformMenu(QMenu *menu) const
698{
699#if QT_CONFIG(menu)
700 if (menu->platformMenu())
701 return; // The platform menu already exists.
702
703 // The recursion depth is the same as menu depth, so should not
704 // be higher than 3 levels.
705 const auto actions = menu->actions();
706 for (QAction *action : actions) {
707 if (action->menu())
708 addPlatformMenu(menu: action->menu());
709 }
710
711 // This menu should be processed *after* its children, otherwise
712 // setMenu() is not called on respective QPlatformMenuItems.
713 QPlatformMenu *platformMenu = qpa_sys->createMenu();
714 if (platformMenu)
715 menu->setPlatformMenu(platformMenu);
716#else
717 Q_UNUSED(menu);
718#endif // QT_CONFIG(menu)
719}
720
721QT_END_NAMESPACE
722
723#endif // QT_NO_SYSTEMTRAYICON
724
725#include "moc_qsystemtrayicon.cpp"
726#include "moc_qsystemtrayicon_p.cpp"
727

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtbase/src/widgets/util/qsystemtrayicon.cpp