From 02c1bd567451152e4f15f674a21ca118421c3c3e Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 8 Sep 2021 14:36:59 +0300 Subject: [PATCH] Allow enabling + selecting menu item under cursor. --- ui/widgets/menu/menu.cpp | 19 +++++++++++++++++-- ui/widgets/menu/menu.h | 1 + ui/widgets/menu/menu_action.cpp | 5 +++-- ui/widgets/menu/menu_item_base.cpp | 2 +- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/ui/widgets/menu/menu.cpp b/ui/widgets/menu/menu.cpp index 1b34316..b5fb3c9 100644 --- a/ui/widgets/menu/menu.cpp +++ b/ui/widgets/menu/menu.cpp @@ -110,10 +110,12 @@ not_null Menu::addAction(base::unique_qptr widget) { if (!findSelectedAction() && data.index < _actionWidgets.size() && _childShownAction == data.action) { - _actionWidgets[data.index]->setSelected(true); + const auto widget = _actionWidgets[data.index].get(); + widget->setSelected(true, widget->lastTriggeredSource()); } return; } + _lastSelectedByMouse = (data.source == TriggeredSource::Mouse); for (auto i = 0; i < _actionWidgets.size(); i++) { if (i != data.index) { _actionWidgets[i]->setSelected(false); @@ -131,6 +133,15 @@ not_null Menu::addAction(base::unique_qptr widget) { } }, widget->lifetime()); + QObject::connect(action.get(), &QAction::changed, widget.get(), [=] { + // Select an item under mouse that was disabled and became enabled. + if (_lastSelectedByMouse + && !findSelectedAction() + && action->isEnabled()) { + updateSelected(QCursor::pos()); + } + }); + const auto raw = widget.get(); _actionWidgets.push_back(std::move(widget)); @@ -222,6 +233,9 @@ void Menu::updateSelected(QPoint globalPosition) { for (const auto &widget : _actionWidgets) { const auto widgetRect = QRect(widget->pos(), widget->size()); if (widgetRect.contains(p)) { + _lastSelectedByMouse = true; + + // It may actually fail to become selected (if it is disabled). widget->setSelected(true); break; } @@ -271,7 +285,8 @@ void Menu::handleKeyPress(not_null e) { } else if (newSelected >= _actions.size()) { newSelected -= _actions.size(); } - } while (newSelected != start && (!_actionWidgets[newSelected]->isEnabled())); + } while (newSelected != start + && (!_actionWidgets[newSelected]->isEnabled())); if (_actionWidgets[newSelected]->isEnabled()) { setSelected(newSelected, false); diff --git a/ui/widgets/menu/menu.h b/ui/widgets/menu/menu.h index c28acec..d60547b 100644 --- a/ui/widgets/menu/menu.h +++ b/ui/widgets/menu/menu.h @@ -120,6 +120,7 @@ private: std::vector> _actionWidgets; int _forceWidth = 0; + bool _lastSelectedByMouse = false; QPointer _childShownAction; diff --git a/ui/widgets/menu/menu_action.cpp b/ui/widgets/menu/menu_action.cpp index 2f11c73..c174578 100644 --- a/ui/widgets/menu/menu_action.cpp +++ b/ui/widgets/menu/menu_action.cpp @@ -84,13 +84,13 @@ bool Action::hasSubmenu() const { } void Action::paint(Painter &p) { - const auto enabled = _action->isEnabled(); + const auto enabled = isEnabled(); const auto selected = isSelected(); if (selected && _st.itemBgOver->c.alpha() < 255) { p.fillRect(0, 0, width(), _height, _st.itemBg); } p.fillRect(0, 0, width(), _height, selected ? _st.itemBgOver : _st.itemBg); - if (isEnabled()) { + if (enabled) { paintRipple(p, 0, 0); } if (const auto icon = (selected ? _iconOver : _icon)) { @@ -124,6 +124,7 @@ void Action::paint(Painter &p) { } void Action::processAction() { + setPointerCursor(isEnabled()); if (_action->text().isEmpty()) { _shortcut = QString(); _text.clear(); diff --git a/ui/widgets/menu/menu_item_base.cpp b/ui/widgets/menu/menu_item_base.cpp index 4bce600..8907bfa 100644 --- a/ui/widgets/menu/menu_item_base.cpp +++ b/ui/widgets/menu/menu_item_base.cpp @@ -17,7 +17,7 @@ ItemBase::ItemBase( void ItemBase::setSelected( bool selected, TriggeredSource source) { - if (!isEnabled()) { + if (selected && !isEnabled()) { return; } if (_selected.current() != selected) {