QCocoaMenu: De-pessimize the number of calls to validateMenuItem:
Calling -[NSMenu update] every time we add a new item can result in a quadratic behavior since the function itself will iterate over all the items in the menu. We solve this by using a 0-timer which will trigger the call to update the next time the event loop spins. Menurama manual test updated. Change-Id: Ic155d364515cc93eb81b1c8085c8e44c93799954 Task-number: QTBUG-62396 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>bb10
parent
c161c6db78
commit
f27d1ccbb2
|
|
@ -96,14 +96,18 @@ public:
|
|||
bool isOpen() const;
|
||||
void setIsOpen(bool isOpen);
|
||||
|
||||
void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
QCocoaMenuItem *itemOrNull(int index) const;
|
||||
void insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem);
|
||||
void scheduleUpdate();
|
||||
|
||||
QList<QCocoaMenuItem *> m_menuItems;
|
||||
NSMenu *m_nativeMenu;
|
||||
NSMenuItem *m_attachedItem;
|
||||
quintptr m_tag;
|
||||
int m_updateTimer;
|
||||
bool m_enabled:1;
|
||||
bool m_parentEnabled:1;
|
||||
bool m_visible:1;
|
||||
|
|
|
|||
|
|
@ -260,6 +260,7 @@ QT_BEGIN_NAMESPACE
|
|||
QCocoaMenu::QCocoaMenu() :
|
||||
m_attachedItem(0),
|
||||
m_tag(0),
|
||||
m_updateTimer(0),
|
||||
m_enabled(true),
|
||||
m_parentEnabled(true),
|
||||
m_visible(true),
|
||||
|
|
@ -410,6 +411,20 @@ QCocoaMenuItem *QCocoaMenu::itemOrNull(int index) const
|
|||
return m_menuItems.at(index);
|
||||
}
|
||||
|
||||
void QCocoaMenu::scheduleUpdate()
|
||||
{
|
||||
if (!m_updateTimer)
|
||||
m_updateTimer = startTimer(0);
|
||||
}
|
||||
|
||||
void QCocoaMenu::timerEvent(QTimerEvent *e)
|
||||
{
|
||||
if (e->timerId() == m_updateTimer) {
|
||||
m_updateTimer = 0;
|
||||
[m_nativeMenu update];
|
||||
}
|
||||
}
|
||||
|
||||
void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem)
|
||||
{
|
||||
QMacAutoReleasePool pool;
|
||||
|
|
@ -436,9 +451,9 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem)
|
|||
QCocoaMenuItem* beforeItem = itemOrNull(m_menuItems.indexOf(cocoaItem) + 1);
|
||||
insertNative(cocoaItem, beforeItem);
|
||||
} else {
|
||||
// Force NSMenuValidation to kick in. This is needed e.g.
|
||||
// Schedule NSMenuValidation to kick in. This is needed e.g.
|
||||
// when an item's enabled state changes after menuWillOpen:
|
||||
[m_nativeMenu update];
|
||||
scheduleUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,19 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
connect(ui->pushButton, &QPushButton::clicked, [=] {
|
||||
menuApp->populateMenu(ui->menuOn_Click, true /*clear*/);
|
||||
});
|
||||
|
||||
connect(ui->addManyButton, &QPushButton::clicked, [=] {
|
||||
QMenu *menu = new QMenu(QLatin1String("Many More ") +
|
||||
QString::number(ui->menuBar->actions().count()));
|
||||
ui->menuBar->insertMenu(ui->menuDynamic_Stuff->menuAction(), menu);
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
auto *action = menu->addAction(QLatin1String("Item ") + QString::number(i));
|
||||
if (i & 0x1)
|
||||
action->setEnabled(false);
|
||||
if (i & 0x2)
|
||||
action->setVisible(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
|
|
|
|||
|
|
@ -6,50 +6,60 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>429</width>
|
||||
<height>251</height>
|
||||
<width>486</width>
|
||||
<height>288</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>The "Help" menu should NOT be visible.
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>The "Help" menu should NOT be visible.
|
||||
|
||||
Click on "Dynamic Stuff" then move left and right to other menus. Disabled items should remain that way.</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="text">
|
||||
<string>Enable "Stuff" Menu</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Populate Dynamic Submenu</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="text">
|
||||
<string>Enable "Stuff" Menu</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<widget class="QPushButton" name="addManyButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
|
@ -57,7 +67,17 @@ Click on "Dynamic Stuff" then move left and right to other menus. Disa
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Populate Dynamic Submenu</string>
|
||||
<string>Add Many Items</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Adding hundreds of items should not block the UI for noticeable periods of time. Odd numbered items should be disabled, those with 2nd LSB on should be hidden.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -70,7 +90,7 @@ Click on "Dynamic Stuff" then move left and right to other menus. Disa
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>429</width>
|
||||
<width>486</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
|
|
|||
Loading…
Reference in New Issue