From 48dc5ed441d08b6cae251c2f4b83009e19791829 Mon Sep 17 00:00:00 2001 From: Dmitry Degtyarev Date: Wed, 1 Sep 2021 14:27:55 +0400 Subject: [PATCH] simplify how console handles action menu add all actions once to the menu in the menubar after that update action state before opening it create separate context menu when needed connect to QMenu::aboutToShow() signal outside of console move find results action adding to find dialog ctor also switch to using asynchronous popup() for context menu, it's better \ than synchronous exec() --- src/admc/console_widget/console_widget.cpp | 174 ++++++++++----------- src/admc/console_widget/console_widget.h | 10 +- src/admc/console_widget/console_widget_p.h | 10 +- src/admc/find_object_dialog.cpp | 10 +- src/admc/find_results.cpp | 6 - src/admc/find_results.h | 5 +- src/admc/main_window.cpp | 6 +- 7 files changed, 111 insertions(+), 110 deletions(-) diff --git a/src/admc/console_widget/console_widget.cpp b/src/admc/console_widget/console_widget.cpp index 1df7078e..c64cd06f 100644 --- a/src/admc/console_widget/console_widget.cpp +++ b/src/admc/console_widget/console_widget.cpp @@ -228,7 +228,7 @@ ConsoleWidget::ConsoleWidget(QWidget *parent) connect( d->scope_view, &QWidget::customContextMenuRequested, - d, &ConsoleWidgetPrivate::context_menu); + d, &ConsoleWidgetPrivate::on_context_menu); connect( qApp, &QApplication::focusChanged, @@ -238,26 +238,18 @@ ConsoleWidget::ConsoleWidget(QWidget *parent) d->update_view_actions(); } -void ConsoleWidget::connect_to_action_menu(QMenu *action_menu_arg) { - d->action_menu = action_menu_arg; +void ConsoleWidgetPrivate::on_context_menu(const QPoint &pos) { + const QModelIndex index = focused_view->indexAt(pos); - // Update actions right before action menu opens - connect( - d->action_menu, &QMenu::aboutToShow, - d, &ConsoleWidgetPrivate::on_action_menu_show); + if (index.isValid()) { + const QPoint global_pos = focused_view->mapToGlobal(pos); - // Open action menu as context menu for central widget - connect( - d, &ConsoleWidgetPrivate::context_menu, - [=](const QPoint pos) { - const QModelIndex index = d->focused_view->indexAt(pos); - - if (index.isValid()) { - const QPoint global_pos = d->focused_view->mapToGlobal(pos); - - d->action_menu->exec(global_pos); - } - }); + auto menu = new QMenu(q); + menu->setAttribute(Qt::WA_DeleteOnClose); + q->add_actions(menu); + q->update_actions(); + menu->popup(global_pos); + } } void ConsoleWidget::register_impl(const int type, ConsoleImpl *impl) { @@ -284,7 +276,7 @@ void ConsoleWidget::register_impl(const int type, ConsoleImpl *impl) { d, &ConsoleWidgetPrivate::on_results_activated); connect( results_view, &ResultsView::context_menu, - d, &ConsoleWidgetPrivate::context_menu); + d, &ConsoleWidgetPrivate::on_context_menu); } } @@ -579,10 +571,30 @@ void ConsoleWidgetPrivate::on_results_activated(const QModelIndex &index) { // Show/hide actions based on what's selected and emit the // signal -void ConsoleWidgetPrivate::on_action_menu_show() { - action_menu->clear(); +void ConsoleWidget::add_actions(QMenu *menu) { + // Add custom actions + const QList custom_action_list = d->get_custom_action_list(); - const QList selected_list = get_all_selected_items(); + for (QAction *action : custom_action_list) { + menu->addAction(action); + } + + menu->addSeparator(); + + // Add standard actions + menu->addAction(d->standard_action_map[StandardAction_Copy]); + menu->addAction(d->standard_action_map[StandardAction_Cut]); + menu->addAction(d->standard_action_map[StandardAction_Rename]); + menu->addAction(d->standard_action_map[StandardAction_Delete]); + menu->addAction(d->standard_action_map[StandardAction_Paste]); + menu->addAction(d->standard_action_map[StandardAction_Print]); + menu->addAction(d->standard_action_map[StandardAction_Refresh]); + menu->addSeparator(); + menu->addAction(d->standard_action_map[StandardAction_Properties]); +} + +void ConsoleWidget::update_actions() { + const QList selected_list = d->get_all_selected_items(); if (!selected_list.isEmpty() && !selected_list[0].isValid()) { return; @@ -591,43 +603,16 @@ void ConsoleWidgetPrivate::on_action_menu_show() { const bool single_selection = (selected_list.size() == 1); // - // Custom actions + // Collect information about action state from impl's // - const QSet type_set = get_selected_types(); - - // First, add all possible custom actions - const QList custom_action_list = [&]() { - QList out; - - for (const int type : type_set) { - ConsoleImpl *impl = impl_map[type]; - QList for_this_type = impl->get_all_custom_actions(); - - for (QAction *action : for_this_type) { - if (!out.contains(action)) { - out.append(action); - } - } - } - - return out; - }(); - - for (QAction *action : custom_action_list) { - action_menu->addAction(action); - } - - action_menu->addSeparator(); - - // Then show/hide custom actions const QSet visible_custom_action_set = [&]() { QSet out; for (int i = 0; i < selected_list.size(); i++) { const QModelIndex index = selected_list[i]; - ConsoleImpl *impl = get_impl(index); + ConsoleImpl *impl = d->get_impl(index); QSet for_this_index = impl->get_custom_actions(index, single_selection); if (i == 0) { @@ -649,7 +634,7 @@ void ConsoleWidgetPrivate::on_action_menu_show() { for (int i = 0; i < selected_list.size(); i++) { const QModelIndex index = selected_list[i]; - ConsoleImpl *impl = get_impl(index); + ConsoleImpl *impl = d->get_impl(index); QSet for_this_index = impl->get_disabled_custom_actions(index, single_selection); if (i == 0) { @@ -665,42 +650,13 @@ void ConsoleWidgetPrivate::on_action_menu_show() { return out; }(); - // Set visibility state for custom actions - for (QAction *action : custom_action_list) { - const bool visible = visible_custom_action_set.contains(action); - - action->setVisible(visible); - } - - // Set enabled state for custom actions - for (QAction *action : custom_action_list) { - const bool disabled = disabled_custom_action_set.contains(action); - - action->setDisabled(disabled); - } - - // - // Standard actions - // - - // Add all actions first - action_menu->addAction(standard_action_map[StandardAction_Copy]); - action_menu->addAction(standard_action_map[StandardAction_Cut]); - action_menu->addAction(standard_action_map[StandardAction_Rename]); - action_menu->addAction(standard_action_map[StandardAction_Delete]); - action_menu->addAction(standard_action_map[StandardAction_Paste]); - action_menu->addAction(standard_action_map[StandardAction_Print]); - action_menu->addAction(standard_action_map[StandardAction_Refresh]); - action_menu->addSeparator(); - action_menu->addAction(standard_action_map[StandardAction_Properties]); - const QSet visible_standard_actions = [&]() { QSet out; for (int i = 0; i < selected_list.size(); i++) { const QModelIndex index = selected_list[i]; - ConsoleImpl *impl = get_impl(index); + ConsoleImpl *impl = d->get_impl(index); QSet for_this_index = impl->get_standard_actions(index, single_selection); if (i == 0) { @@ -722,7 +678,7 @@ void ConsoleWidgetPrivate::on_action_menu_show() { for (int i = 0; i < selected_list.size(); i++) { const QModelIndex index = selected_list[i]; - ConsoleImpl *impl = get_impl(index); + ConsoleImpl *impl = d->get_impl(index); QSet for_this_index = impl->get_disabled_standard_actions(index, single_selection); if (i == 0) { @@ -738,19 +694,39 @@ void ConsoleWidgetPrivate::on_action_menu_show() { return out; }(); - // Set visibility state for standard actions - for (const StandardAction &action_enum : standard_action_list) { - const bool visible = visible_standard_actions.contains(action_enum); + // + // Apply action state + // + + const QList custom_action_list = d->get_custom_action_list(); + + // Show/hide custom actions + for (QAction *action : custom_action_list) { + const bool visible = visible_custom_action_set.contains(action); - QAction *action = standard_action_map[action_enum]; action->setVisible(visible); } - // Set enabled state for standard actions + // Enable/disable custom actions + for (QAction *action : custom_action_list) { + const bool disabled = disabled_custom_action_set.contains(action); + + action->setDisabled(disabled); + } + + // Show/hide standard actions + for (const StandardAction &action_enum : standard_action_list) { + const bool visible = visible_standard_actions.contains(action_enum); + + QAction *action = d->standard_action_map[action_enum]; + action->setVisible(visible); + } + + // Enable/disable standard actions for (const StandardAction &action_enum : standard_action_list) { const bool disabled = disabled_standard_actions.contains(action_enum); - QAction *action = standard_action_map[action_enum]; + QAction *action = d->standard_action_map[action_enum]; action->setDisabled(disabled); } } @@ -1211,3 +1187,21 @@ QSet ConsoleWidgetPrivate::get_selected_types() const { return out; } + +// Get all custom actions from impl's, in order +QList ConsoleWidgetPrivate::get_custom_action_list() const { + QList out; + + for (const int type : impl_map.keys()) { + ConsoleImpl *impl = impl_map[type]; + QList for_this_type = impl->get_all_custom_actions(); + + for (QAction *action : for_this_type) { + if (!out.contains(action)) { + out.append(action); + } + } + } + + return out; +} diff --git a/src/admc/console_widget/console_widget.h b/src/admc/console_widget/console_widget.h index 20d7a22f..d52e6eac 100644 --- a/src/admc/console_widget/console_widget.h +++ b/src/admc/console_widget/console_widget.h @@ -135,7 +135,15 @@ public: void set_scope_view_visible(const bool visible); - void connect_to_action_menu(QMenu *action_menu); + // Adds actions to a menu. Actions come from console + // itself as well as impl's. All impl's must be + // registered before this is called. + void add_actions(QMenu *menu); + + // Updates visibility and disability state of actions + // based on current selection. Call before showing the + // menu that contains console actions. + void update_actions(); QAction *refresh_current_scope_action() const; QAction *navigate_up_action() const; diff --git a/src/admc/console_widget/console_widget_p.h b/src/admc/console_widget/console_widget_p.h index a3580c16..6868bbbf 100644 --- a/src/admc/console_widget/console_widget_p.h +++ b/src/admc/console_widget/console_widget_p.h @@ -37,7 +37,6 @@ class ScopeProxyModel; class ConsoleDragModel; class QStandardItemModel; class ConsoleWidget; -class QMenu; class QSplitter; class ConsoleImpl; @@ -94,16 +93,13 @@ public: QList targets_past; QList targets_future; - QMenu *action_menu; QHash standard_action_map; ConsoleWidgetPrivate(ConsoleWidget *q_arg); - void open_action_menu_as_context_menu(const QPoint pos); void on_scope_expanded(const QModelIndex &index); void on_results_activated(const QModelIndex &index); - void on_action_menu_show(); - void on_context_menu(const QPoint pos); + void on_context_menu(const QPoint &pos); void update_navigation_actions(); void update_view_actions(); void on_current_scope_item_changed(const QModelIndex ¤t, const QModelIndex &); @@ -130,9 +126,7 @@ public: void on_standard_action(const StandardAction action_enum); QList get_all_selected_items() const; QSet get_selected_types() const; - -signals: - void context_menu(const QPoint pos); + QList get_custom_action_list() const; }; #endif /* CONSOLE_WIDGET_P_H */ diff --git a/src/admc/find_object_dialog.cpp b/src/admc/find_object_dialog.cpp index 36d35b52..7bdc9e53 100644 --- a/src/admc/find_object_dialog.cpp +++ b/src/admc/find_object_dialog.cpp @@ -25,6 +25,7 @@ #include "find_widget.h" #include "globals.h" #include "settings.h" +#include "console_widget/console_widget.h" #include #include @@ -46,7 +47,14 @@ FindObjectDialog::FindObjectDialog(const QList classes, const QString d layout->setMenuBar(menubar); layout->addWidget(find_widget); - find_widget->find_results->add_actions(action_menu, view_menu); + ConsoleWidget *console = find_widget->find_results->console; + console->add_actions(action_menu); + + view_menu->addAction(console->customize_columns_action()); settings_setup_dialog_geometry(SETTING_find_object_dialog_geometry, this); + + connect( + action_menu, &QMenu::aboutToShow, + console, &ConsoleWidget::update_actions); } diff --git a/src/admc/find_results.cpp b/src/admc/find_results.cpp index fcbb11ed..487fe9c5 100644 --- a/src/admc/find_results.cpp +++ b/src/admc/find_results.cpp @@ -79,12 +79,6 @@ FindResults::~FindResults() { settings_set_variant(SETTING_find_results_state, state); } -void FindResults::add_actions(QMenu *action_menu, QMenu *view_menu) { - console->connect_to_action_menu(action_menu); - - view_menu->addAction(console->customize_columns_action()); -} - void FindResults::clear() { console->delete_children(head_index); } diff --git a/src/admc/find_results.h b/src/admc/find_results.h index 126bd812..9758aca9 100644 --- a/src/admc/find_results.h +++ b/src/admc/find_results.h @@ -39,6 +39,8 @@ class FindResults final : public QWidget { Q_OBJECT public: + ConsoleWidget *console; + FindResults(); ~FindResults(); @@ -50,10 +52,7 @@ public: // NOTE: returned items need to be re-parented or deleted! QList> get_selected_rows() const; - void add_actions(QMenu *action_menu, QMenu *view_menu); - private: - ConsoleWidget *console; QPersistentModelIndex head_index; }; diff --git a/src/admc/main_window.cpp b/src/admc/main_window.cpp index 9d6fda68..f3406978 100644 --- a/src/admc/main_window.cpp +++ b/src/admc/main_window.cpp @@ -182,7 +182,7 @@ MainWindow::MainWindow() file_menu->addAction(quit_action); // Action - console->connect_to_action_menu(action_menu); + console->add_actions(action_menu); // View view_menu->addAction(console->set_results_to_icons_action()); @@ -277,6 +277,10 @@ MainWindow::MainWindow() this, &MainWindow::on_connect_options_dialog_accepted); on_connect_options_dialog_accepted(); + connect( + action_menu, &QMenu::aboutToShow, + console, &ConsoleWidget::update_actions); + const bool restored_geometry = settings_restore_geometry(SETTING_main_window_geometry, this); if (!restored_geometry) { resize(1024, 768);