summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Gräßlin <mgraesslin@kde.org>2014-01-29 10:57:34 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-17 16:47:05 +0100
commit824f080468b02ad0a82e42bbd120b55c0bce1769 (patch)
treeba6a531b43016bb0f31c4e674a7ba2922d7c5623
parent6aef733a7a80cc937ba67c982a41a7338379d401 (diff)
Allow QPlatformSystemTrayIcon to create the QPlatformMenu
In case the QPlatformTheme does not provide a QPlatformMenu the QPlatformSystemTrayIcon is not able to forward the menu because the QPlatformMenu pointer passed to updateMenu is always null. Providing a QPlatformMenu in the QPlatformTheme implementation should not be a requirement for having the menu in the system tray icon. There are cases where no QPlatformMenu should be created by the theme, e.g. if the X11 implementation of QSystemTrayIcon gets provided by the xcb plugin. The change adds a virtual method to QPlatformSystemTrayIcon to create a QPlatformMenu. This method is called from the QPA implementation of QSystemTrayIcon if the QMenu's platformMenu is not present. Thus the system tray icon is able to provide a custom implementation of the menu. This gets installed through a new internal method in QMenu to set the platform menu. It creates the required connections and sync the state to the QMenu to the newly created QPlatformMenu. Last but not least QPlatformMenu is extended by a method to create a QPlatformMenuItem. The default implementation delegates to the platform theme. This allows to provide the menu item implementation for the system tray icon without providing the QPlatformMenuItem through the platform theme. Change-Id: I17234bd8bcf8c05f8bd786feff0cf8f860430e82 Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com> Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com> Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-rw-r--r--src/gui/kernel/kernel.pri3
-rw-r--r--src/gui/kernel/qplatformmenu.cpp55
-rw-r--r--src/gui/kernel/qplatformmenu.h2
-rw-r--r--src/gui/kernel/qplatformsystemtrayicon.h2
-rw-r--r--src/gui/kernel/qplatformsystemtrayicon_qpa.cpp16
-rw-r--r--src/widgets/util/qsystemtrayicon_qpa.cpp8
-rw-r--r--src/widgets/widgets/qmenu.cpp48
-rw-r--r--src/widgets/widgets/qmenu.h1
-rw-r--r--src/widgets/widgets/qmenu_p.h2
9 files changed, 132 insertions, 5 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index d9bcbf316f..e9e4a1d818 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -121,7 +121,8 @@ SOURCES += \
kernel/qplatformservices.cpp \
kernel/qplatformscreenpageflipper.cpp \
kernel/qplatformsystemtrayicon_qpa.cpp \
- kernel/qplatformsessionmanager.cpp
+ kernel/qplatformsessionmanager.cpp \
+ kernel/qplatformmenu.cpp
contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) {
HEADERS += \
diff --git a/src/gui/kernel/qplatformmenu.cpp b/src/gui/kernel/qplatformmenu.cpp
new file mode 100644
index 0000000000..54c340abf9
--- /dev/null
+++ b/src/gui/kernel/qplatformmenu.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Martin Graesslin <mgraesslin@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformmenu.h"
+
+#include <qpa/qplatformtheme.h>
+#include <private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QPlatformMenuItem *QPlatformMenu::createMenuItem() const
+{
+ return QGuiApplicationPrivate::platformTheme()->createPlatformMenuItem();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h
index 3485cc58dd..9326a2b3a1 100644
--- a/src/gui/kernel/qplatformmenu.h
+++ b/src/gui/kernel/qplatformmenu.h
@@ -116,6 +116,8 @@ public:
virtual QPlatformMenuItem *menuItemAt(int position) const = 0;
virtual QPlatformMenuItem *menuItemForTag(quintptr tag) const = 0;
+
+ virtual QPlatformMenuItem *createMenuItem() const;
Q_SIGNALS:
void aboutToShow();
void aboutToHide();
diff --git a/src/gui/kernel/qplatformsystemtrayicon.h b/src/gui/kernel/qplatformsystemtrayicon.h
index 2c05b1a7fa..6bad643c7c 100644
--- a/src/gui/kernel/qplatformsystemtrayicon.h
+++ b/src/gui/kernel/qplatformsystemtrayicon.h
@@ -83,6 +83,8 @@ public:
virtual bool isSystemTrayAvailable() const = 0;
virtual bool supportsMessages() const = 0;
+ virtual QPlatformMenu *createMenu() const;
+
Q_SIGNALS:
void activated(QPlatformSystemTrayIcon::ActivationReason reason);
void messageClicked();
diff --git a/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp b/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp
index c4cec40a10..bc37f99210 100644
--- a/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp
+++ b/src/gui/kernel/qplatformsystemtrayicon_qpa.cpp
@@ -159,6 +159,22 @@ QPlatformSystemTrayIcon::~QPlatformSystemTrayIcon()
\sa activated()
*/
+/*!
+ This method is called in case there is no QPlatformMenu available when
+ updating the menu. This allows the abstraction to provide a menu for the
+ system tray icon even if normally a non-native menu is used.
+
+ The default implementation returns a null pointer.
+
+ \sa updateMenu()
+ \since 5.3
+ */
+
+QPlatformMenu *QPlatformSystemTrayIcon::createMenu() const
+{
+ return Q_NULLPTR;
+}
+
QT_END_NAMESPACE
#include "moc_qplatformsystemtrayicon.cpp"
diff --git a/src/widgets/util/qsystemtrayicon_qpa.cpp b/src/widgets/util/qsystemtrayicon_qpa.cpp
index 3ce89e352d..f98aeaf678 100644
--- a/src/widgets/util/qsystemtrayicon_qpa.cpp
+++ b/src/widgets/util/qsystemtrayicon_qpa.cpp
@@ -99,8 +99,14 @@ void QSystemTrayIconPrivate::updateIcon_sys()
void QSystemTrayIconPrivate::updateMenu_sys()
{
- if (qpa_sys && menu)
+ if (qpa_sys && menu) {
+ if (!menu->platformMenu()) {
+ QPlatformMenu *platformMenu = qpa_sys->createMenu();
+ if (platformMenu)
+ menu->setPlatformMenu(platformMenu);
+ }
qpa_sys->updateMenu(menu->platformMenu());
+ }
}
void QSystemTrayIconPrivate::updateToolTip_sys()
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index d1b0da1a55..edfeb840b1 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -153,13 +153,48 @@ void QMenuPrivate::init()
scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone;
}
- platformMenu = QGuiApplicationPrivate::platformTheme()->createPlatformMenu();
+ setPlatformMenu(QGuiApplicationPrivate::platformTheme()->createPlatformMenu());
+}
+
+void QMenuPrivate::setPlatformMenu(QPlatformMenu *menu)
+{
+ Q_Q(QMenu);
+ if (!platformMenu.isNull() && !platformMenu->parent())
+ delete platformMenu.data();
+
+ platformMenu = menu;
if (!platformMenu.isNull()) {
QObject::connect(platformMenu, SIGNAL(aboutToShow()), q, SIGNAL(aboutToShow()));
QObject::connect(platformMenu, SIGNAL(aboutToHide()), q, SIGNAL(aboutToHide()));
}
}
+// forward declare function
+static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem* item);
+
+void QMenuPrivate::syncPlatformMenu()
+{
+ Q_Q(QMenu);
+ if (platformMenu.isNull())
+ return;
+
+ QPlatformMenuItem *beforeItem = Q_NULLPTR;
+ QListIterator<QAction*> it(q->actions());
+ it.toBack();
+ while (it.hasPrevious()) {
+ QPlatformMenuItem *menuItem = platformMenu->createMenuItem();
+ QAction *action = it.previous();
+ menuItem->setTag(reinterpret_cast<quintptr>(action));
+ QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()));
+ QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()));
+ copyActionToPlatformItem(action, menuItem);
+ platformMenu->insertMenuItem(menuItem, beforeItem);
+ beforeItem = menuItem;
+ }
+ platformMenu->syncSeparatorsCollapsible(collapsibleSeparators);
+ platformMenu->setEnabled(q->isEnabled());
+}
+
int QMenuPrivate::scrollerHeight() const
{
Q_Q(const QMenu);
@@ -2976,8 +3011,7 @@ void QMenu::actionEvent(QActionEvent *e)
if (!d->platformMenu.isNull()) {
if (e->type() == QEvent::ActionAdded) {
- QPlatformMenuItem *menuItem =
- QGuiApplicationPrivate::platformTheme()->createPlatformMenuItem();
+ QPlatformMenuItem *menuItem = d->platformMenu->createMenuItem();
menuItem->setTag(reinterpret_cast<quintptr>(e->action()));
QObject::connect(menuItem, SIGNAL(activated()), e->action(), SLOT(trigger()));
QObject::connect(menuItem, SIGNAL(hovered()), e->action(), SIGNAL(hovered()));
@@ -3154,6 +3188,14 @@ QPlatformMenu *QMenu::platformMenu()
return d_func()->platformMenu;
}
+/*!\internal
+*/
+void QMenu::setPlatformMenu(QPlatformMenu *platformMenu)
+{
+ d_func()->setPlatformMenu(platformMenu);
+ d_func()->syncPlatformMenu();
+}
+
/*!
\property QMenu::separatorsCollapsible
\since 4.2
diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h
index 7a128e871c..8a8eaf3bae 100644
--- a/src/widgets/widgets/qmenu.h
+++ b/src/widgets/widgets/qmenu.h
@@ -140,6 +140,7 @@ public:
void setNoReplayFor(QWidget *widget);
QPlatformMenu *platformMenu();
+ void setPlatformMenu(QPlatformMenu *platformMenu);
#ifdef Q_OS_WINCE
HMENU wceMenu();
diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h
index 71a3fca237..afd34a5c47 100644
--- a/src/widgets/widgets/qmenu_p.h
+++ b/src/widgets/widgets/qmenu_p.h
@@ -108,6 +108,8 @@ public:
#endif
}
void init();
+ void setPlatformMenu(QPlatformMenu *menu);
+ void syncPlatformMenu();
static QMenuPrivate *get(QMenu *m) { return m->d_func(); }
int scrollerHeight() const;