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