@@ -0,0 +1,19 | |||
|
1 | #ifndef SCIQLOP_FILTERINGACTION_H | |
|
2 | #define SCIQLOP_FILTERINGACTION_H | |
|
3 | ||
|
4 | #include <Common/spimpl.h> | |
|
5 | #include <QWidgetAction> | |
|
6 | ||
|
7 | /// A LineEdit inside an action which is able to filter other actions | |
|
8 | class FilteringAction : public QWidgetAction { | |
|
9 | public: | |
|
10 | FilteringAction(QWidget *parent); | |
|
11 | ||
|
12 | void addActionToFilter(QAction *action); | |
|
13 | ||
|
14 | private: | |
|
15 | class FilteringActionPrivate; | |
|
16 | spimpl::unique_impl_ptr<FilteringActionPrivate> impl; | |
|
17 | }; | |
|
18 | ||
|
19 | #endif // SCIQLOP_FILTERINGACTION_H |
@@ -0,0 +1,27 | |||
|
1 | #include "Actions/FilteringAction.h" | |
|
2 | ||
|
3 | #include <QLineEdit> | |
|
4 | ||
|
5 | struct FilteringAction::FilteringActionPrivate { | |
|
6 | QLineEdit *m_FilterLineEdit; | |
|
7 | QVector<QAction *> m_FilteredActions; | |
|
8 | }; | |
|
9 | ||
|
10 | FilteringAction::FilteringAction(QWidget *parent) | |
|
11 | : QWidgetAction(parent), impl{spimpl::make_unique_impl<FilteringActionPrivate>()} | |
|
12 | { | |
|
13 | impl->m_FilterLineEdit = new QLineEdit(parent); | |
|
14 | setDefaultWidget(impl->m_FilterLineEdit); | |
|
15 | ||
|
16 | connect(impl->m_FilterLineEdit, &QLineEdit::textEdited, [this](auto text) { | |
|
17 | for (auto action : impl->m_FilteredActions) { | |
|
18 | auto match = action->text().contains(text, Qt::CaseInsensitive); | |
|
19 | action->setVisible(match); | |
|
20 | } | |
|
21 | }); | |
|
22 | } | |
|
23 | ||
|
24 | void FilteringAction::addActionToFilter(QAction *action) | |
|
25 | { | |
|
26 | impl->m_FilteredActions << action; | |
|
27 | } |
@@ -21,6 +21,12 public: | |||
|
21 | 21 | |
|
22 | 22 | void removeAction(const std::shared_ptr<SelectionZoneAction> &action); |
|
23 | 23 | |
|
24 | /// Sets a flag to say that the specified menu can be filtered, usually via a FilteringAction | |
|
25 | void addFilterForMenu(const QStringList &menuPath); | |
|
26 | ||
|
27 | /// Returns true if the menu can be filtered | |
|
28 | bool isMenuFiltered(const QStringList &menuPath) const; | |
|
29 | ||
|
24 | 30 | private: |
|
25 | 31 | class ActionsGuiControllerPrivate; |
|
26 | 32 | spimpl::unique_impl_ptr<ActionsGuiControllerPrivate> impl; |
@@ -60,6 +60,13 public: | |||
|
60 | 60 | /// The path in the sub menus, if any |
|
61 | 61 | QStringList subMenuList() const noexcept; |
|
62 | 62 | |
|
63 | /// Sets if filtering the action is allowed via a FilteringAction | |
|
64 | void setAllowedFiltering(bool value); | |
|
65 | ||
|
66 | /// Returns true if filtering the action is allowed via a FilteringAction. By default it is | |
|
67 | /// allowed. | |
|
68 | bool isFilteringAllowed() const; | |
|
69 | ||
|
63 | 70 | public slots: |
|
64 | 71 | /// Executes the action |
|
65 | 72 | void execute(const QVector<VisualizationSelectionZoneItem *> &item); |
@@ -28,7 +28,8 gui_moc_headers = [ | |||
|
28 | 28 | 'include/Catalogue/CatalogueSideBarWidget.h', |
|
29 | 29 | 'include/Catalogue/CatalogueInspectorWidget.h', |
|
30 | 30 | 'include/Catalogue/CatalogueEventsModel.h', |
|
31 | 'include/Catalogue/CatalogueTreeModel.h' | |
|
31 | 'include/Catalogue/CatalogueTreeModel.h', | |
|
32 | 'include/Actions/FilteringAction.h' | |
|
32 | 33 | ] |
|
33 | 34 | |
|
34 | 35 | gui_ui_files = [ |
@@ -112,6 +113,7 gui_sources = [ | |||
|
112 | 113 | 'src/Visualization/VisualizationSelectionZoneManager.cpp', |
|
113 | 114 | 'src/Actions/SelectionZoneAction.cpp', |
|
114 | 115 | 'src/Actions/ActionsGuiController.cpp', |
|
116 | 'src/Actions/FilteringAction.cpp', | |
|
115 | 117 | 'src/Visualization/VisualizationActionManager.cpp', |
|
116 | 118 | 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp', |
|
117 | 119 | 'src/Catalogue/CatalogueExplorer.cpp', |
@@ -3,6 +3,7 | |||
|
3 | 3 | struct ActionsGuiController::ActionsGuiControllerPrivate { |
|
4 | 4 | |
|
5 | 5 | QVector<std::shared_ptr<SelectionZoneAction> > m_SelectionZoneActions; |
|
6 | QSet<QStringList> m_FilteredMenu; | |
|
6 | 7 | }; |
|
7 | 8 | |
|
8 | 9 | ActionsGuiController::ActionsGuiController() |
@@ -39,3 +40,13 void ActionsGuiController::removeAction(const std::shared_ptr<SelectionZoneActio | |||
|
39 | 40 | { |
|
40 | 41 | impl->m_SelectionZoneActions.removeAll(action); |
|
41 | 42 | } |
|
43 | ||
|
44 | void ActionsGuiController::addFilterForMenu(const QStringList &menuPath) | |
|
45 | { | |
|
46 | impl->m_FilteredMenu.insert(menuPath); | |
|
47 | } | |
|
48 | ||
|
49 | bool ActionsGuiController::isMenuFiltered(const QStringList &menuPath) const | |
|
50 | { | |
|
51 | return impl->m_FilteredMenu.contains(menuPath); | |
|
52 | } |
@@ -15,6 +15,7 struct SelectionZoneAction::SelectionZoneActionPrivate { | |||
|
15 | 15 | QKeySequence m_DisplayedShortcut; |
|
16 | 16 | SelectionZoneAction::ExecuteFunction m_Fun; |
|
17 | 17 | SelectionZoneAction::EnableFunction m_EnableFun = [](auto zones) { return true; }; |
|
18 | bool m_FilteringAllowed = true; | |
|
18 | 19 | }; |
|
19 | 20 | |
|
20 | 21 | SelectionZoneAction::SelectionZoneAction(const QString &name, ExecuteFunction fun) |
@@ -55,6 +56,16 QStringList SelectionZoneAction::subMenuList() const noexcept | |||
|
55 | 56 | return impl->m_SubMenuList; |
|
56 | 57 | } |
|
57 | 58 | |
|
59 | void SelectionZoneAction::setAllowedFiltering(bool value) | |
|
60 | { | |
|
61 | impl->m_FilteringAllowed = value; | |
|
62 | } | |
|
63 | ||
|
64 | bool SelectionZoneAction::isFilteringAllowed() const | |
|
65 | { | |
|
66 | return impl->m_FilteringAllowed; | |
|
67 | } | |
|
68 | ||
|
58 | 69 | void SelectionZoneAction::execute(const QVector<VisualizationSelectionZoneItem *> &item) |
|
59 | 70 | { |
|
60 | 71 | impl->m_Fun(item); |
@@ -127,6 +127,7 void CatalogueActionManager::installSelectionZoneActions() | |||
|
127 | 127 | {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}, QObject::tr("Without Catalogue"), |
|
128 | 128 | [this](auto zones) { impl->createEventFromZones(DEFAULT_EVENT_NAME, zones); }); |
|
129 | 129 | createEventAction->setEnableFunction(impl->createEventEnableFuntion()); |
|
130 | createEventAction->setAllowedFiltering(false); | |
|
130 | 131 | |
|
131 | 132 | auto createEventInNewCatalogueAction = actionController.addSectionZoneAction( |
|
132 | 133 | {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}, QObject::tr("In New Catalogue"), |
@@ -141,9 +142,11 void CatalogueActionManager::installSelectionZoneActions() | |||
|
141 | 142 | impl->createEventFromZones(DEFAULT_EVENT_NAME, zones, newCatalogue); |
|
142 | 143 | }); |
|
143 | 144 | createEventInNewCatalogueAction->setEnableFunction(impl->createEventEnableFuntion()); |
|
144 | ||
|
145 | createEventInNewCatalogueAction->setAllowedFiltering(false); | |
|
145 | 146 | |
|
146 | 147 | refreshCreateInCatalogueAction(); |
|
148 | ||
|
149 | actionController.addFilterForMenu({CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}); | |
|
147 | 150 | } |
|
148 | 151 | |
|
149 | 152 | void CatalogueActionManager::refreshCreateInCatalogueAction() |
@@ -12,6 +12,7 | |||
|
12 | 12 | #include "ui_VisualizationGraphWidget.h" |
|
13 | 13 | |
|
14 | 14 | #include <Actions/ActionsGuiController.h> |
|
15 | #include <Actions/FilteringAction.h> | |
|
15 | 16 | #include <Common/MimeTypesDef.h> |
|
16 | 17 | #include <Data/ArrayData.h> |
|
17 | 18 | #include <Data/IDataSeries.h> |
@@ -245,7 +246,7 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget | |||
|
245 | 246 | &VisualizationGraphWidget::onMouseDoubleClick); |
|
246 | 247 | connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>( |
|
247 | 248 | &QCPAxis::rangeChanged), |
|
248 |
|
|
|
249 | this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection); | |
|
249 | 250 | |
|
250 | 251 | // Activates menu when right clicking on the graph |
|
251 | 252 | ui->widget->setContextMenuPolicy(Qt::CustomContextMenu); |
@@ -707,32 +708,51 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept | |||
|
707 | 708 | |
|
708 | 709 | QHash<QString, QMenu *> subMenus; |
|
709 | 710 | QHash<QString, bool> subMenusEnabled; |
|
711 | QHash<QString, FilteringAction *> filteredMenu; | |
|
710 | 712 | |
|
711 | 713 | for (auto zoneAction : zoneActions) { |
|
712 | 714 | |
|
713 | 715 | auto isEnabled = zoneAction->isEnabled(selectedItems); |
|
714 | 716 | |
|
715 | 717 | auto menu = &graphMenu; |
|
718 | QString menuPath; | |
|
716 | 719 | for (auto subMenuName : zoneAction->subMenuList()) { |
|
717 | if (!subMenus.contains(subMenuName)) { | |
|
720 | menuPath += '/'; | |
|
721 | menuPath += subMenuName; | |
|
722 | ||
|
723 | if (!subMenus.contains(menuPath)) { | |
|
718 | 724 | menu = menu->addMenu(subMenuName); |
|
719 |
subMenus[ |
|
|
720 |
subMenusEnabled[ |
|
|
725 | subMenus[menuPath] = menu; | |
|
726 | subMenusEnabled[menuPath] = isEnabled; | |
|
721 | 727 | } |
|
722 | 728 | else { |
|
723 |
menu = subMenus.value( |
|
|
729 | menu = subMenus.value(menuPath); | |
|
724 | 730 | if (isEnabled) { |
|
725 | 731 | // The sub menu is enabled if at least one of its actions is enabled |
|
726 |
subMenusEnabled[ |
|
|
732 | subMenusEnabled[menuPath] = true; | |
|
727 | 733 | } |
|
728 | 734 | } |
|
729 | 735 | } |
|
730 | 736 | |
|
737 | FilteringAction *filterAction = nullptr; | |
|
738 | if (sqpApp->actionsGuiController().isMenuFiltered(zoneAction->subMenuList())) { | |
|
739 | filterAction = filteredMenu.value(menuPath); | |
|
740 | if (!filterAction) { | |
|
741 | filterAction = new FilteringAction{this}; | |
|
742 | filteredMenu[menuPath] = filterAction; | |
|
743 | menu->addAction(filterAction); | |
|
744 | } | |
|
745 | } | |
|
746 | ||
|
731 | 747 | auto action = menu->addAction(zoneAction->name()); |
|
732 | 748 | action->setEnabled(isEnabled); |
|
733 | 749 | action->setShortcut(zoneAction->displayedShortcut()); |
|
734 | 750 | QObject::connect(action, &QAction::triggered, |
|
735 | 751 | [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); }); |
|
752 | ||
|
753 | if (filterAction && zoneAction->isFilteringAllowed()) { | |
|
754 | filterAction->addActionToFilter(action); | |
|
755 | } | |
|
736 | 756 | } |
|
737 | 757 | |
|
738 | 758 | for (auto it = subMenus.cbegin(); it != subMenus.cend(); ++it) { |
General Comments 0
You need to be logged in to leave comments.
Login now