Revision control

++ // Copyright (C) 2017 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include "qquicklabsplatformsystemtrayicon_p.h"
++ #include "qquicklabsplatformmenu_p.h"
++ #include "qquicklabsplatformiconloader_p.h"
++
++ #include <QtCore/qloggingcategory.h>
++ #include <QtGui/qpa/qplatformtheme.h>
++ #include <QtGui/private/qguiapplication_p.h>
++
++ #include "widgets/qwidgetplatform_p.h"
++
++ QT_BEGIN_NAMESPACE
++
++ /*!
++ \qmltype SystemTrayIcon
++ \inherits QtObject
++ //! \nativetype QQuickLabsPlatformSystemTrayIcon
++ \inqmlmodule Qt.labs.platform
++ \since 5.8
++ \brief A system tray icon.
++
++ The SystemTrayIcon type provides an icon for an application in the system tray.
++
++ Many desktop platforms provide a special system tray or notification area,
++ where applications can display icons and notification messages.
++
++ \image {qtlabsplatform-systemtrayicon.png} {System tray icon}
++
++ The following example shows how to create a system tray icon, and how to make
++ use of the \l activated() signal:
++
++ \code
++ SystemTrayIcon {
++ visible: true
++ icon.source: "qrc:/images/tray-icon.png"
++
++ onActivated: {
++ window.show()
++ window.raise()
++ window.requestActivate()
++ }
++ }
++ \endcode
++
++ \section2 Tray menu
++
++ SystemTrayIcon can have a menu that opens when the icon is activated.
++
++ \image {qtlabsplatform-systemtrayicon-menu.png} {System tray icon with menu}
++
++ The following example illustrates how to assign a \l Menu to a system tray icon:
++
++ \code
++ SystemTrayIcon {
++ visible: true
++ icon.source: "qrc:/images/tray-icon.png"
++
++ menu: Menu {
++ MenuItem {
++ text: qsTr("Quit")
++ onTriggered: Qt.quit()
++ }
++ }
++ }
++ \endcode
++
++ \section2 Notification messages
++
++ SystemTrayIcon can display notification messages.
++
++ \image {qtlabsplatform-systemtrayicon-message.png} {System tray icon message popup}
++
++ The following example presents how to show a notification message using
++ \l showMessage(), and how to make use of the \l messageClicked() signal:
++
++ \code
++ SystemTrayIcon {
++ visible: true
++ icon.source: "qrc:/images/tray-icon.png"
++
++ onMessageClicked: console.log("Message clicked")
++ Component.onCompleted: showMessage("Message title", "Something important came up. Click this to know more.")
++ }
++ \endcode
++
++ \section2 Availability
++
++ A native system tray icon is currently \l available on the following platforms:
++
++ \list
++ \li All window managers and independent tray implementations for X11 that implement the
++ {freedesktop.org XEmbed system tray specification}.
++ \li All desktop environments that implement the
++ {freedesktop.org D-Bus StatusNotifierItem specification}, including recent versions of KDE and Unity.
++ \li All supported versions of macOS. Note that the Growl notification system must be installed
++ for showMessage() to display messages on OS X prior to 10.8 (Mountain Lion).
++ \endlist
++
++ \input includes/widgets.qdocinc 1
++
++ \labs
++
++ \sa Menu
++ */
++
++ /*!
++ \qmlsignal Qt.labs.platform::SystemTrayIcon::activated(ActivationReason reason)
++
++ This signal is emitted when the system tray icon is activated by the user. The
++ \a reason argument specifies how the system tray icon was activated.
++
++ Available reasons:
++
++ \value SystemTrayIcon.Unknown Unknown reason
++ \value SystemTrayIcon.Context The context menu for the system tray icon was requested
++ \value SystemTrayIcon.DoubleClick The system tray icon was double clicked
++ \value SystemTrayIcon.Trigger The system tray icon was clicked
++ \value SystemTrayIcon.MiddleClick The system tray icon was clicked with the middle mouse button
++ */
++
++ /*!
++ \qmlsignal Qt.labs.platform::SystemTrayIcon::messageClicked()
++
++ This signal is emitted when a notification message is clicked by the user.
++
++ \sa showMessage()
++ */
++
++ Q_STATIC_LOGGING_CATEGORY(qtLabsPlatformTray, "qt.labs.platform.tray")
++
++ QQuickLabsPlatformSystemTrayIcon::QQuickLabsPlatformSystemTrayIcon(QObject *parent)
++ : QObject(parent),
++ m_complete(false),
++ m_visible(false),
++ m_menu(nullptr),
++ m_iconLoader(nullptr),
++ m_handle(nullptr)
++ {
++ m_handle = QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon();
++ if (!m_handle)
++ m_handle = QWidgetPlatform::createSystemTrayIcon(this);
++ qCDebug(qtLabsPlatformTray) << "SystemTrayIcon ->" << m_handle;
++
++ if (m_handle) {
++ connect(m_handle, &QPlatformSystemTrayIcon::activated, this, &QQuickLabsPlatformSystemTrayIcon::activated);
++ connect(m_handle, &QPlatformSystemTrayIcon::messageClicked, this, &QQuickLabsPlatformSystemTrayIcon::messageClicked);
++ }
++ }
++
++ QQuickLabsPlatformSystemTrayIcon::~QQuickLabsPlatformSystemTrayIcon()
++ {
++ if (m_menu)
++ m_menu->setSystemTrayIcon(nullptr);
++ cleanup();
++ delete m_iconLoader;
++ m_iconLoader = nullptr;
++ delete m_handle;
++ m_handle = nullptr;
++ }
++
++ QPlatformSystemTrayIcon *QQuickLabsPlatformSystemTrayIcon::handle() const
++ {
++ return m_handle;
++ }
++
++ /*!
++ \readonly
++ \qmlproperty bool Qt.labs.platform::SystemTrayIcon::available
++
++ This property holds whether the system tray is available.
++ */
++ bool QQuickLabsPlatformSystemTrayIcon::isAvailable() const
++ {
++ return m_handle && m_handle->isSystemTrayAvailable();
++ }
++
++ /*!
++ \readonly
++ \qmlproperty bool Qt.labs.platform::SystemTrayIcon::supportsMessages
++
++ This property holds whether the system tray icon supports notification messages.
++
++ \sa showMessage()
++ */
++ bool QQuickLabsPlatformSystemTrayIcon::supportsMessages() const
++ {
++ return m_handle && m_handle->supportsMessages();
++ }
++
++ /*!
++ \qmlproperty bool Qt.labs.platform::SystemTrayIcon::visible
++
++ This property holds whether the system tray icon is visible.
++
++ The default value is \c false.
++ */
++ bool QQuickLabsPlatformSystemTrayIcon::isVisible() const
++ {
++ return m_visible;
++ }
++
++ void QQuickLabsPlatformSystemTrayIcon::setVisible(bool visible)
++ {
++ if (m_visible == visible)
++ return;
++
++ if (m_handle && m_complete) {
++ if (visible)
++ init();
++ else
++ cleanup();
++ }
++
++ m_visible = visible;
++ emit visibleChanged();
++ }
++
++ /*!
++ \qmlproperty string Qt.labs.platform::SystemTrayIcon::tooltip
++
++ This property holds the tooltip of the system tray icon.
++ */
++ QString QQuickLabsPlatformSystemTrayIcon::tooltip() const
++ {
++ return m_tooltip;
++ }
++
++ void QQuickLabsPlatformSystemTrayIcon::setTooltip(const QString &tooltip)
++ {
++ if (m_tooltip == tooltip)
++ return;
++
++ if (m_handle && m_complete)
++ m_handle->updateToolTip(tooltip);
++
++ m_tooltip = tooltip;
++ emit tooltipChanged();
++ }
++
++ /*!
++ \qmlproperty Menu Qt.labs.platform::SystemTrayIcon::menu
++
++ This property holds a menu for the system tray icon.
++ */
++ QQuickLabsPlatformMenu *QQuickLabsPlatformSystemTrayIcon::menu() const
++ {
++ return m_menu;
++ }
++
++ void QQuickLabsPlatformSystemTrayIcon::setMenu(QQuickLabsPlatformMenu *menu)
++ {
++ if (m_menu == menu)
++ return;
++
++ if (m_menu)
++ m_menu->setSystemTrayIcon(nullptr);
++
++ if (menu)
++ menu->setSystemTrayIcon(this);
++
++ if (m_handle && m_complete) {
++ if (menu && menu->create())
++ m_handle->updateMenu(menu->handle());
++ else
++ m_handle->updateMenu(nullptr);
++ }
++
++ m_menu = menu;
++ emit menuChanged();
++ }
++
++ /*!
++ \since Qt.labs.platform 1.1 (Qt 5.12)
++ \qmlproperty rect Qt.labs.platform::SystemTrayIcon::geometry
++
++ This property holds the geometry of the system tray icon.
++ */
++ QRect QQuickLabsPlatformSystemTrayIcon::geometry() const
++ {
++ return m_handle ? m_handle->geometry() : QRect();
++ }
++
++ /*!
++ \since Qt.labs.platform 1.1 (Qt 5.12)
++ \qmlproperty url Qt.labs.platform::SystemTrayIcon::icon.source
++ \qmlproperty string Qt.labs.platform::SystemTrayIcon::icon.name
++ \qmlproperty bool Qt.labs.platform::SystemTrayIcon::icon.mask
++
++ This property holds the system tray icon.
++
++ \code
++ SystemTrayIcon {
++ icon.mask: true
++ icon.source: "qrc:/images/tray-icon.png"
++ }
++ \endcode
++ */
++ QQuickLabsPlatformIcon QQuickLabsPlatformSystemTrayIcon::icon() const
++ {
++ if (!m_iconLoader)
++ return QQuickLabsPlatformIcon();
++
++ return m_iconLoader->icon();
++ }
++
++ void QQuickLabsPlatformSystemTrayIcon::setIcon(const QQuickLabsPlatformIcon &icon)
++ {
++ if (iconLoader()->icon() == icon)
++ return;
++
++ iconLoader()->setIcon(icon);
++ emit iconChanged();
++ }
++
++ /*!
++ \qmlmethod void Qt.labs.platform::SystemTrayIcon::show()
++
++ Shows the system tray icon.
++ */
++ void QQuickLabsPlatformSystemTrayIcon::show()
++ {
++ setVisible(true);
++ }
++
++ /*!
++ \qmlmethod void Qt.labs.platform::SystemTrayIcon::hide()
++
++ Hides the system tray icon.
++ */
++ void QQuickLabsPlatformSystemTrayIcon::hide()
++ {
++ setVisible(false);
++ }
++
++ /*!
++ \qmlmethod void Qt.labs.platform::SystemTrayIcon::showMessage(string title, string message, MessageIcon icon, int msecs)
++
++ Shows a system tray message with the given \a title, \a message and \a icon
++ for the time specified in \a msecs.
++
++ \note System tray messages are dependent on the system configuration and user preferences,
++ and may not appear at all. Therefore, it should not be relied upon as the sole means for providing
++ critical information.
++
++ \sa supportsMessages, messageClicked()
++ */
++ void QQuickLabsPlatformSystemTrayIcon::showMessage(const QString &title, const QString &msg, QPlatformSystemTrayIcon::MessageIcon icon, int msecs)
++ {
++ if (m_handle)
++ m_handle->showMessage(title, msg, QIcon(), icon, msecs);
++ }
++
++ void QQuickLabsPlatformSystemTrayIcon::init()
++ {
++ if (!m_handle)
++ return;
++
++ m_handle->init();
++ if (m_menu && m_menu->create())
++ m_handle->updateMenu(m_menu->handle());
++ m_handle->updateToolTip(m_tooltip);
++ if (m_iconLoader)
++ m_iconLoader->setEnabled(true);
++ }
++
++ void QQuickLabsPlatformSystemTrayIcon::cleanup()
++ {
++ if (m_handle)
++ m_handle->cleanup();
++ if (m_iconLoader)
++ m_iconLoader->setEnabled(false);
++ }
++
++ void QQuickLabsPlatformSystemTrayIcon::classBegin()
++ {
++ }
++
++ void QQuickLabsPlatformSystemTrayIcon::componentComplete()
++ {
++ m_complete = true;
++ if (m_visible)
++ init();
++ }
++
++ QQuickLabsPlatformIconLoader *QQuickLabsPlatformSystemTrayIcon::iconLoader() const
++ {
++ if (!m_iconLoader) {
++ QQuickLabsPlatformSystemTrayIcon *that = const_cast<QQuickLabsPlatformSystemTrayIcon *>(this);
++ static int slot = staticMetaObject.indexOfSlot("updateIcon()");
++ m_iconLoader = new QQuickLabsPlatformIconLoader(slot, that);
++ m_iconLoader->setEnabled(m_complete);
++ }
++ return m_iconLoader;
++ }
++
++ void QQuickLabsPlatformSystemTrayIcon::updateIcon()
++ {
++ if (!m_handle || !m_iconLoader)
++ return;
++
++ const QRect oldGeometry = m_handle->geometry();
++
++ m_handle->updateIcon(m_iconLoader->toQIcon());
++
++ if (oldGeometry != m_handle->geometry())
++ emit geometryChanged();
++ }
++
++ QT_END_NAMESPACE
++
++ #include "moc_qquicklabsplatformsystemtrayicon_p.cpp"