QQuickMenu: add a little delay for opening sub-menus on hover
This improves the usability on desktop. When a menu has multiple sub- menu items, they don't all trigger a sub-menu (and close immediately) while moving mouse over the items. Change-Id: Ie4c9e409da8d6877e35506bffb94ed57f5985dcd Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
This commit is contained in:
parent
0a62e444e8
commit
0673dd4ff1
|
@ -59,6 +59,9 @@
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// copied from qfusionstyle.cpp
|
||||
static const int SUBMENU_DELAY = 225;
|
||||
|
||||
/*!
|
||||
\qmltype Menu
|
||||
\inherits Popup
|
||||
|
@ -183,6 +186,7 @@ static bool shouldCascade()
|
|||
|
||||
QQuickMenuPrivate::QQuickMenuPrivate()
|
||||
: cascade(shouldCascade()),
|
||||
hoverTimer(0),
|
||||
overlap(0),
|
||||
contentItem(nullptr),
|
||||
contentModel(nullptr),
|
||||
|
@ -371,7 +375,7 @@ void QQuickMenuPrivate::onItemHovered()
|
|||
if (currentItem) {
|
||||
QQuickMenu *subMenu = currentItem->menu();
|
||||
if (subMenu && subMenu->cascade())
|
||||
openSubMenu(currentItem, false);
|
||||
startHoverTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -468,6 +472,23 @@ void QQuickMenuPrivate::closeSubMenu(QQuickMenu *subMenu)
|
|||
}
|
||||
}
|
||||
|
||||
void QQuickMenuPrivate::startHoverTimer()
|
||||
{
|
||||
Q_Q(QQuickMenu);
|
||||
stopHoverTimer();
|
||||
hoverTimer = q->startTimer(SUBMENU_DELAY);
|
||||
}
|
||||
|
||||
void QQuickMenuPrivate::stopHoverTimer()
|
||||
{
|
||||
Q_Q(QQuickMenu);
|
||||
if (!hoverTimer)
|
||||
return;
|
||||
|
||||
q->killTimer(hoverTimer);
|
||||
hoverTimer = 0;
|
||||
}
|
||||
|
||||
int QQuickMenuPrivate::currentIndex() const
|
||||
{
|
||||
QVariant index = contentItem->property("currentIndex");
|
||||
|
@ -483,6 +504,7 @@ void QQuickMenuPrivate::setCurrentIndex(int index)
|
|||
QQuickMenuItem *newCurrentItem = contentItem->property("currentItem").value<QQuickMenuItem *>();
|
||||
|
||||
if (currentItem != newCurrentItem) {
|
||||
stopHoverTimer();
|
||||
if (currentItem)
|
||||
currentItem->setHighlighted(false);
|
||||
if (newCurrentItem)
|
||||
|
@ -1013,6 +1035,15 @@ void QQuickMenu::keyReleaseEvent(QKeyEvent *event)
|
|||
item->forceActiveFocus();
|
||||
}
|
||||
|
||||
void QQuickMenu::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
Q_D(QQuickMenu);
|
||||
if (event->timerId() == d->hoverTimer) {
|
||||
d->openSubMenu(d->currentItem, false);
|
||||
d->stopHoverTimer();
|
||||
}
|
||||
}
|
||||
|
||||
QFont QQuickMenu::defaultFont() const
|
||||
{
|
||||
return QQuickControlPrivate::themeFont(QPlatformTheme::MenuFont);
|
||||
|
|
|
@ -111,6 +111,8 @@ Q_SIGNALS:
|
|||
Q_REVISION(3) void delegateChanged();
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
|
||||
QFont defaultFont() const override;
|
||||
QPalette defaultPalette() const override;
|
||||
|
||||
|
|
|
@ -102,6 +102,9 @@ public:
|
|||
void openSubMenu(QQuickMenuItem *item, bool activate);
|
||||
void closeSubMenu(QQuickMenu *subMenu);
|
||||
|
||||
void startHoverTimer();
|
||||
void stopHoverTimer();
|
||||
|
||||
int currentIndex() const;
|
||||
void setCurrentIndex(int index);
|
||||
|
||||
|
@ -111,6 +114,7 @@ public:
|
|||
static void contentData_clear(QQmlListProperty<QObject> *prop);
|
||||
|
||||
bool cascade;
|
||||
int hoverTimer;
|
||||
qreal overlap;
|
||||
QPointer<QQuickMenu> parentMenu;
|
||||
QPointer<QQuickMenuItem> currentItem;
|
||||
|
|
|
@ -636,7 +636,9 @@ void tst_menu::subMenuMouse()
|
|||
QCOMPARE(mainMenu->isVisible(), cascade);
|
||||
QVERIFY(subMenu1->isVisible());
|
||||
QVERIFY(!subMenu2->isVisible());
|
||||
QCOMPARE(subSubMenu1->isVisible(), cascade);
|
||||
QVERIFY(!subSubMenu1->isVisible());
|
||||
if (cascade)
|
||||
QTRY_VERIFY(subSubMenu1->isVisible());
|
||||
|
||||
// close the sub-sub-menu with mouse hover over another parent menu item
|
||||
QQuickMenuItem *subMenuItem1 = qobject_cast<QQuickMenuItem *>(subMenu1->itemAt(0));
|
||||
|
@ -653,7 +655,9 @@ void tst_menu::subMenuMouse()
|
|||
QCOMPARE(mainMenu->isVisible(), cascade);
|
||||
QVERIFY(subMenu1->isVisible());
|
||||
QVERIFY(!subMenu2->isVisible());
|
||||
QCOMPARE(subSubMenu1->isVisible(), cascade);
|
||||
QVERIFY(!subSubMenu1->isVisible());
|
||||
if (cascade)
|
||||
QTRY_VERIFY(subSubMenu1->isVisible());
|
||||
|
||||
// close sub-menu and sub-sub-menu with mouse hover in the main menu
|
||||
QQuickMenuItem *mainMenuItem1 = qobject_cast<QQuickMenuItem *>(mainMenu->itemAt(0));
|
||||
|
|
Loading…
Reference in New Issue