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>
This commit is contained in:
parent
6aef733a7a
commit
824f080468
@ -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 += \
|
||||
|
55
src/gui/kernel/qplatformmenu.cpp
Normal file
55
src/gui/kernel/qplatformmenu.cpp
Normal file
@ -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
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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"
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -140,6 +140,7 @@ public:
|
||||
|
||||
void setNoReplayFor(QWidget *widget);
|
||||
QPlatformMenu *platformMenu();
|
||||
void setPlatformMenu(QPlatformMenu *platformMenu);
|
||||
|
||||
#ifdef Q_OS_WINCE
|
||||
HMENU wceMenu();
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user