From a5766cb1f6bfcd208814b0b71322128ecb47039a Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 31 Aug 2022 17:50:54 +0400 Subject: [PATCH] Allow inserting actions in the middle of Menu. --- ui/widgets/menu/menu.cpp | 42 ++++++++++++++++++++++----------------- ui/widgets/menu/menu.h | 3 +++ ui/widgets/popup_menu.cpp | 6 ++++++ ui/widgets/popup_menu.h | 3 +++ 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/ui/widgets/menu/menu.cpp b/ui/widgets/menu/menu.cpp index 40308c6..10197e1 100644 --- a/ui/widgets/menu/menu.cpp +++ b/ui/widgets/menu/menu.cpp @@ -94,21 +94,30 @@ not_null Menu::addAction( } not_null Menu::addAction(base::unique_qptr widget) { - const auto action = widget->action(); - _actions.emplace_back(action); + return insertAction(_actions.size(), std::move(widget)); +} - widget->setParent(this); +not_null Menu::insertAction( + int position, + base::unique_qptr widget) { + Expects(position >= 0 && position <= _actions.size()); + Expects(position >= 0 && position <= _actionWidgets.size()); - const auto top = _actionWidgets.empty() - ? 0 - : _actionWidgets.back()->y() + _actionWidgets.back()->height(); + const auto raw = widget.get(); + const auto action = raw->action(); + _actions.insert(begin(_actions) + position, action); - widget->moveToLeft(0, top); - widget->show(); + raw->setParent(this); + raw->show(); + raw->setIndex(position); + for (auto i = position, to = int(_actionWidgets.size()); i != to; ++i) { + _actionWidgets[i]->setIndex(i + 1); + } + _actionWidgets.insert( + begin(_actionWidgets) + position, + std::move(widget)); - widget->setIndex(_actionWidgets.size()); - - widget->selects( + raw->selects( ) | rpl::start_with_next([=](const CallbackData &data) { if (!data.selected) { if (!findSelectedAction() @@ -128,16 +137,16 @@ not_null Menu::addAction(base::unique_qptr widget) { if (_activatedCallback) { _activatedCallback(data); } - }, widget->lifetime()); + }, raw->lifetime()); - widget->clicks( + raw->clicks( ) | rpl::start_with_next([=](const CallbackData &data) { if (_triggeredCallback) { _triggeredCallback(data); } - }, widget->lifetime()); + }, raw->lifetime()); - QObject::connect(action.get(), &QAction::changed, widget.get(), [=] { + QObject::connect(action.get(), &QAction::changed, raw, [=] { // Select an item under mouse that was disabled and became enabled. if (_lastSelectedByMouse && !findSelectedAction() @@ -146,9 +155,6 @@ not_null Menu::addAction(base::unique_qptr widget) { } }); - const auto raw = widget.get(); - _actionWidgets.push_back(std::move(widget)); - const auto recountWidth = [=] { return _forceWidth ? _forceWidth diff --git a/ui/widgets/menu/menu.h b/ui/widgets/menu/menu.h index 288ec38..b4bb56d 100644 --- a/ui/widgets/menu/menu.h +++ b/ui/widgets/menu/menu.h @@ -53,6 +53,9 @@ public: const style::icon *iconOver = nullptr); not_null addSeparator( const style::MenuSeparator *st = nullptr); + not_null insertAction( + int position, + base::unique_qptr widget); void clearActions(); void finishAnimating(); diff --git a/ui/widgets/popup_menu.cpp b/ui/widgets/popup_menu.cpp index 9f979b4..bffff75 100644 --- a/ui/widgets/popup_menu.cpp +++ b/ui/widgets/popup_menu.cpp @@ -407,6 +407,12 @@ not_null PopupMenu::addSeparator(const style::MenuSeparator *st) { return _menu->addSeparator(st); } +not_null PopupMenu::insertAction( + int position, + base::unique_qptr widget) { + return _menu->insertAction(position, std::move(widget)); +} + void PopupMenu::clearActions() { _submenus.clear(); return _menu->clearActions(); diff --git a/ui/widgets/popup_menu.h b/ui/widgets/popup_menu.h index 53c1029..e9d60e5 100644 --- a/ui/widgets/popup_menu.h +++ b/ui/widgets/popup_menu.h @@ -51,6 +51,9 @@ public: const style::icon *iconOver = nullptr); not_null addSeparator( const style::MenuSeparator *st = nullptr); + not_null insertAction( + int position, + base::unique_qptr widget); void clearActions(); [[nodiscard]] const std::vector> &actions() const;