Cocoa Menus: Give platform menu ownership back to QWidgets
We don't want to be in the situation where a QCocoaMenuItem
owns a QCocoaMenu (because that item is a submenu), and then
the actual QMenu "sees" that same QCocoaMenu being deleted.
Instead, since all the QCocoaMenu* classes inherit QObject,
we rely on meta-object properties to set the hierarchy and
climb the hierarchy when guessing the menu item's role.
This ammends most of commit 370e89f064.
Task-number: QTBUG-36785
Change-Id: I0e03acb593e93061c8c6c1fdd161669cf0d2a293
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
bb10
parent
15ec9907f9
commit
bf0336a025
|
|
@ -269,7 +269,7 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *
|
|||
QCocoaMenuItem *cocoaItem = static_cast<QCocoaMenuItem *>(menuItem);
|
||||
QCocoaMenuItem *beforeItem = static_cast<QCocoaMenuItem *>(before);
|
||||
|
||||
menuItem->setParent(this);
|
||||
SET_COCOA_MENU_ANCESTOR(menuItem, this);
|
||||
cocoaItem->sync();
|
||||
if (beforeItem) {
|
||||
int index = m_menuItems.indexOf(beforeItem);
|
||||
|
|
@ -326,8 +326,8 @@ void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem)
|
|||
return;
|
||||
}
|
||||
|
||||
if (menuItem->parent() == this)
|
||||
menuItem->setParent(0);
|
||||
if (COCOA_MENU_ANCESTOR(menuItem) == this)
|
||||
SET_COCOA_MENU_ANCESTOR(menuItem, 0);
|
||||
|
||||
m_menuItems.removeOne(cocoaItem);
|
||||
if (!cocoaItem->isMerged()) {
|
||||
|
|
@ -551,7 +551,7 @@ void QCocoaMenu::syncModalState(bool modal)
|
|||
void QCocoaMenu::setMenuBar(QCocoaMenuBar *menuBar)
|
||||
{
|
||||
m_menuBar = menuBar;
|
||||
setParent(menuBar);
|
||||
SET_COCOA_MENU_ANCESTOR(this, menuBar);
|
||||
}
|
||||
|
||||
QCocoaMenuBar *QCocoaMenu::menuBar() const
|
||||
|
|
|
|||
|
|
@ -118,6 +118,9 @@ private:
|
|||
quintptr m_tag;
|
||||
};
|
||||
|
||||
#define COCOA_MENU_ANCESTOR(m) ((m)->property("_qCocoaMenuAncestor").value<QObject *>())
|
||||
#define SET_COCOA_MENU_ANCESTOR(m, ancestor) (m)->setProperty("_qCocoaMenuAncestor", QVariant::fromValue<QObject *>(ancestor))
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -126,13 +126,13 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu)
|
|||
{
|
||||
if (menu == m_menu)
|
||||
return;
|
||||
if (m_menu && m_menu->parent() == this)
|
||||
m_menu->setParent(0);
|
||||
if (m_menu && COCOA_MENU_ANCESTOR(m_menu) == this)
|
||||
SET_COCOA_MENU_ANCESTOR(m_menu, 0);
|
||||
|
||||
QCocoaAutoReleasePool pool;
|
||||
m_menu = static_cast<QCocoaMenu *>(menu);
|
||||
if (m_menu) {
|
||||
m_menu->setParent(this);
|
||||
SET_COCOA_MENU_ANCESTOR(m_menu, this);
|
||||
} else {
|
||||
// we previously had a menu, but no longer
|
||||
// clear out our item so the nexy sync() call builds a new one
|
||||
|
|
@ -217,12 +217,12 @@ NSMenuItem *QCocoaMenuItem::sync()
|
|||
mergeItem = [loader preferencesMenuItem];
|
||||
break;
|
||||
case TextHeuristicRole: {
|
||||
QObject *p = parent();
|
||||
QObject *p = COCOA_MENU_ANCESTOR(this);
|
||||
int depth = 1;
|
||||
QCocoaMenuBar *menubar = 0;
|
||||
while (depth < 3 && p && !(menubar = qobject_cast<QCocoaMenuBar *>(p))) {
|
||||
++depth;
|
||||
p = p->parent();
|
||||
p = COCOA_MENU_ANCESTOR(p);
|
||||
}
|
||||
if (depth == 3 || !menubar)
|
||||
break; // Menu item too deep in the hierarchy, or not connected to any menubar
|
||||
|
|
|
|||
Loading…
Reference in New Issue