D-Bus system tray icon: submenus can be created after context menu
QMenuPrivate::init() calls QPlatformTheme::createPlatformMenu() to create a platform menu, but on Linux, that returns null for now. QSystemTrayIcon::setContextMenu() results in recursive calls to QSystemTrayIconPrivate::addPlatformMenu() which then calls QDBusTrayIcon::createMenu() for the context menu and each submenu. However if a submenu is added afterwards, a corresponding platform menu is not immediately created. Now copyActionToPlatformItem() will detect and create the missing platform submenu, by calling a new method: DBusPlatformMenu::createSubMenu(). This is because there is no way of knowing that it's a tray-specific context menu (which is so far the only case in which we use DBusPlatformMenu). So, QPlatformMenu::createSubMenu() needs to exist as a new QPA interface for this use case. Task-number: QTBUG-45803 Change-Id: Ib319e873082196515ea0580d70d069099cf2c175 Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>bb10
parent
2858a3c91b
commit
d8bfd812c3
|
|
@ -44,4 +44,9 @@ QPlatformMenuItem *QPlatformMenu::createMenuItem() const
|
|||
return QGuiApplicationPrivate::platformTheme()->createPlatformMenuItem();
|
||||
}
|
||||
|
||||
QPlatformMenu *QPlatformMenu::createSubMenu() const
|
||||
{
|
||||
return QGuiApplicationPrivate::platformTheme()->createPlatformMenu();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ public:
|
|||
virtual QPlatformMenuItem *menuItemForTag(quintptr tag) const = 0;
|
||||
|
||||
virtual QPlatformMenuItem *createMenuItem() const;
|
||||
virtual QPlatformMenu *createSubMenu() const;
|
||||
Q_SIGNALS:
|
||||
void aboutToShow();
|
||||
void aboutToHide();
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ void QDBusPlatformMenuItem::setIcon(const QIcon &icon)
|
|||
m_icon = icon;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set a submenu under this menu item.
|
||||
*/
|
||||
void QDBusPlatformMenuItem::setMenu(QPlatformMenu *menu)
|
||||
{
|
||||
m_subMenu = static_cast<QDBusPlatformMenu *>(menu);
|
||||
|
|
@ -242,8 +245,12 @@ const QList<QDBusPlatformMenuItem *> QDBusPlatformMenu::items() const
|
|||
QPlatformMenuItem *QDBusPlatformMenu::createMenuItem() const
|
||||
{
|
||||
QDBusPlatformMenuItem *ret = new QDBusPlatformMenuItem();
|
||||
ret->setMenu(const_cast<QDBusPlatformMenu *>(this));
|
||||
return ret;
|
||||
}
|
||||
|
||||
QPlatformMenu *QDBusPlatformMenu::createSubMenu() const
|
||||
{
|
||||
return new QDBusPlatformMenu;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ public:
|
|||
quintptr tag()const Q_DECL_OVERRIDE { return m_tag; }
|
||||
void setTag(quintptr tag) Q_DECL_OVERRIDE;
|
||||
|
||||
const QString text() { return m_text; }
|
||||
const QString text() const { return m_text; }
|
||||
void setText(const QString &text) Q_DECL_OVERRIDE;
|
||||
void setIcon(const QIcon &icon) Q_DECL_OVERRIDE;
|
||||
void setEnabled(bool enabled) Q_DECL_OVERRIDE;
|
||||
|
|
@ -150,6 +150,7 @@ public:
|
|||
const QList<QDBusPlatformMenuItem *> items() const;
|
||||
|
||||
QPlatformMenuItem *createMenuItem() const Q_DECL_OVERRIDE;
|
||||
QPlatformMenu *createSubMenu() const Q_DECL_OVERRIDE;
|
||||
|
||||
bool operator==(const QDBusPlatformMenu& other) { return m_tag == other.m_tag; }
|
||||
|
||||
|
|
@ -175,6 +176,7 @@ private:
|
|||
uint m_revision;
|
||||
QHash<quintptr, QDBusPlatformMenuItem *> m_itemsByTag;
|
||||
QList<QDBusPlatformMenuItem *> m_items;
|
||||
QDBusPlatformMenuItem *m_containingMenuItem;
|
||||
static QList<QDBusPlatformMenu *> m_topLevelMenus;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ void QMenuPrivate::setPlatformMenu(QPlatformMenu *menu)
|
|||
}
|
||||
|
||||
// forward declare function
|
||||
static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem* item);
|
||||
static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item, QPlatformMenu *itemsMenu);
|
||||
|
||||
void QMenuPrivate::syncPlatformMenu()
|
||||
{
|
||||
|
|
@ -200,7 +200,7 @@ void QMenuPrivate::syncPlatformMenu()
|
|||
menuItem->setTag(reinterpret_cast<quintptr>(action));
|
||||
QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()), Qt::QueuedConnection);
|
||||
QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()), Qt::QueuedConnection);
|
||||
copyActionToPlatformItem(action, menuItem);
|
||||
copyActionToPlatformItem(action, menuItem, platformMenu.data());
|
||||
platformMenu->insertMenuItem(menuItem, beforeItem);
|
||||
beforeItem = menuItem;
|
||||
}
|
||||
|
|
@ -3105,7 +3105,7 @@ QMenu::timerEvent(QTimerEvent *e)
|
|||
}
|
||||
}
|
||||
|
||||
static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem* item)
|
||||
static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item, QPlatformMenu *itemsMenu)
|
||||
{
|
||||
item->setText(action->text());
|
||||
item->setIsSeparator(action->isSeparator());
|
||||
|
|
@ -3131,6 +3131,8 @@ static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem* i
|
|||
item->setEnabled(action->isEnabled());
|
||||
|
||||
if (action->menu()) {
|
||||
if (!action->menu()->platformMenu())
|
||||
action->menu()->setPlatformMenu(itemsMenu->createSubMenu());
|
||||
item->setMenu(action->menu()->platformMenu());
|
||||
} else {
|
||||
item->setMenu(0);
|
||||
|
|
@ -3185,7 +3187,7 @@ void QMenu::actionEvent(QActionEvent *e)
|
|||
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()));
|
||||
copyActionToPlatformItem(e->action(), menuItem);
|
||||
copyActionToPlatformItem(e->action(), menuItem, d->platformMenu);
|
||||
QPlatformMenuItem* beforeItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->before()));
|
||||
d->platformMenu->insertMenuItem(menuItem, beforeItem);
|
||||
} else if (e->type() == QEvent::ActionRemoved) {
|
||||
|
|
@ -3195,7 +3197,7 @@ void QMenu::actionEvent(QActionEvent *e)
|
|||
} else if (e->type() == QEvent::ActionChanged) {
|
||||
QPlatformMenuItem *menuItem = d->platformMenu->menuItemForTag(reinterpret_cast<quintptr>(e->action()));
|
||||
if (menuItem) {
|
||||
copyActionToPlatformItem(e->action(), menuItem);
|
||||
copyActionToPlatformItem(e->action(), menuItem, d->platformMenu);
|
||||
d->platformMenu->syncMenuItem(menuItem);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue