diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2017-06-15 00:16:57 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2017-06-21 12:14:31 +0000 |
commit | 1ffede10a0b2d2f0dc64fcce4f54263d9d30e57e (patch) | |
tree | ceb41443e1aab54322ba8afa90d3e85796c3276b /src/quicktemplates2/qquickmenu.cpp | |
parent | 39b4ac1e79415e8da2545a9a9002a9d674da77a1 (diff) |
Add Menu::currentIndex
De-couple current index management from the content item. Instead of
manipulating the content item's current index directly from C++, offer
a currentIndex property that can be visualized by the style, also when
not using a ListView. This is essentially the same technique ComboBox
uses to control the highlighted index in the popup ListView.
[ChangeLog][Controls][Menu] Added currentIndex property for styling
purposes.
Change-Id: Idf7746d9c08fc9ca9a0dfd15225ebae5a29243c9
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/quicktemplates2/qquickmenu.cpp')
-rw-r--r-- | src/quicktemplates2/qquickmenu.cpp | 80 |
1 files changed, 51 insertions, 29 deletions
diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp index d0f305a4..4afac541 100644 --- a/src/quicktemplates2/qquickmenu.cpp +++ b/src/quicktemplates2/qquickmenu.cpp @@ -187,6 +187,7 @@ static bool shouldCascade() QQuickMenuPrivate::QQuickMenuPrivate() : cascade(shouldCascade()), hoverTimer(0), + currentIndex(-1), overlap(0), contentItem(nullptr), contentModel(nullptr), @@ -372,7 +373,7 @@ void QQuickMenuPrivate::onItemHovered() int index = contentModel->indexOf(button, nullptr); if (index != -1) { - setCurrentIndex(index); + setCurrentIndex(index, Qt::OtherFocusReason); if (oldCurrentItem != currentItem) { if (oldCurrentItem) closeSubMenu(oldCurrentItem->subMenu()); @@ -412,7 +413,8 @@ void QQuickMenuPrivate::onItemActiveFocusChanged() return; int indexOfItem = contentModel->indexOf(item, nullptr); - setCurrentIndex(indexOfItem); + QQuickControl *control = qobject_cast<QQuickControl *>(item); + setCurrentIndex(indexOfItem, control ? control->focusReason() : Qt::OtherFocusReason); } void QQuickMenuPrivate::openSubMenu(QQuickMenuItem *item, bool activate) @@ -444,7 +446,7 @@ void QQuickMenuPrivate::openSubMenu(QQuickMenuItem *item, bool activate) p->allowHorizontalFlip = cascade; p->parentMenu = q; if (activate) - p->setCurrentIndex(0); + p->setCurrentIndex(0, Qt::PopupFocusReason); subMenu->setCascade(cascade); subMenu->open(); @@ -494,51 +496,55 @@ void QQuickMenuPrivate::stopHoverTimer() hoverTimer = 0; } -int QQuickMenuPrivate::currentIndex() const +void QQuickMenuPrivate::setCurrentIndex(int index, Qt::FocusReason reason) { - QVariant index = contentItem->property("currentIndex"); - if (!index.isValid()) - return -1; - return index.toInt(); -} - -void QQuickMenuPrivate::setCurrentIndex(int index) -{ - contentItem->setProperty("currentIndex", index); - - QQuickMenuItem *newCurrentItem = contentItem->property("currentItem").value<QQuickMenuItem *>(); + Q_Q(QQuickMenu); + if (currentIndex == index) + return; + QQuickMenuItem *newCurrentItem = qobject_cast<QQuickMenuItem *>(itemAt(index)); if (currentItem != newCurrentItem) { stopHoverTimer(); - if (currentItem) + if (currentItem) { currentItem->setHighlighted(false); - if (newCurrentItem) + if (!newCurrentItem && window) { + QQuickItem *focusItem = QQuickItemPrivate::get(contentItem)->subFocusItem; + if (focusItem) + QQuickWindowPrivate::get(window)->clearFocusInScope(contentItem, focusItem, Qt::OtherFocusReason); + } + } + if (newCurrentItem) { newCurrentItem->setHighlighted(true); + newCurrentItem->forceActiveFocus(reason); + } currentItem = newCurrentItem; } + + currentIndex = index; + emit q->currentIndexChanged(); } void QQuickMenuPrivate::activateNextItem() { - int index = currentIndex(); + int index = currentIndex; int count = contentModel->count(); while (++index < count) { QQuickItem *item = itemAt(index); if (!item || !item->activeFocusOnTab()) continue; - item->forceActiveFocus(Qt::TabFocusReason); + setCurrentIndex(index, Qt::TabFocusReason); break; } } void QQuickMenuPrivate::activatePreviousItem() { - int index = currentIndex(); + int index = currentIndex; while (--index >= 0) { QQuickItem *item = itemAt(index); if (!item || !item->activeFocusOnTab()) continue; - item->forceActiveFocus(Qt::BacktabFocusReason); + setCurrentIndex(index, Qt::BacktabFocusReason); break; } } @@ -1036,6 +1042,28 @@ void QQuickMenu::setDelegate(QQmlComponent *delegate) /*! \since QtQuick.Controls 2.3 (Qt 5.10) + \qmlproperty int QtQuick.Controls::Menu::currentIndex + + This property holds the index of the currently highlighted item. + + Menu items can be highlighted by mouse hover or keyboard navigation. + + \sa MenuItem::highlighted +*/ +int QQuickMenu::currentIndex() const +{ + Q_D(const QQuickMenu); + return d->currentIndex; +} + +void QQuickMenu::setCurrentIndex(int index) +{ + Q_D(QQuickMenu); + d->setCurrentIndex(index, Qt::OtherFocusReason); +} + +/*! + \since QtQuick.Controls 2.3 (Qt 5.10) \qmlmethod void QtQuick.Controls::Menu::popup(MenuItem item = null) Opens the menu at the mouse cursor on desktop platforms that have a mouse cursor @@ -1128,7 +1156,7 @@ void QQuickMenu::popup(QQmlV4Function *args) setPosition(pos); if (menuItem) - d->setCurrentIndex(d->contentModel->indexOf(menuItem, nullptr)); + d->setCurrentIndex(d->contentModel->indexOf(menuItem, nullptr), Qt::PopupFocusReason); open(); } @@ -1162,13 +1190,7 @@ void QQuickMenu::itemChange(QQuickItem::ItemChange change, const QQuickItem::Ite if (!data.boolValue && d->cascade) { // Ensure that when the menu isn't visible, there's no current item // the next time it's opened. - QQuickItem *focusItem = QQuickItemPrivate::get(d->contentItem)->subFocusItem; - if (focusItem) { - QQuickWindow *window = QQuickPopup::window(); - if (window) - QQuickWindowPrivate::get(window)->clearFocusInScope(d->contentItem, focusItem, Qt::OtherFocusReason); - } - d->setCurrentIndex(-1); + d->setCurrentIndex(-1, Qt::OtherFocusReason); } } } |