@@ -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 | void removeAction(const std::shared_ptr<SelectionZoneAction> &action); |
|
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 | private: |
|
30 | private: | |
25 | class ActionsGuiControllerPrivate; |
|
31 | class ActionsGuiControllerPrivate; | |
26 | spimpl::unique_impl_ptr<ActionsGuiControllerPrivate> impl; |
|
32 | spimpl::unique_impl_ptr<ActionsGuiControllerPrivate> impl; |
@@ -60,6 +60,13 public: | |||||
60 | /// The path in the sub menus, if any |
|
60 | /// The path in the sub menus, if any | |
61 | QStringList subMenuList() const noexcept; |
|
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 | public slots: |
|
70 | public slots: | |
64 | /// Executes the action |
|
71 | /// Executes the action | |
65 | void execute(const QVector<VisualizationSelectionZoneItem *> &item); |
|
72 | void execute(const QVector<VisualizationSelectionZoneItem *> &item); |
@@ -28,7 +28,8 gui_moc_headers = [ | |||||
28 | 'include/Catalogue/CatalogueSideBarWidget.h', |
|
28 | 'include/Catalogue/CatalogueSideBarWidget.h', | |
29 | 'include/Catalogue/CatalogueInspectorWidget.h', |
|
29 | 'include/Catalogue/CatalogueInspectorWidget.h', | |
30 | 'include/Catalogue/CatalogueEventsModel.h', |
|
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 | gui_ui_files = [ |
|
35 | gui_ui_files = [ | |
@@ -112,6 +113,7 gui_sources = [ | |||||
112 | 'src/Visualization/VisualizationSelectionZoneManager.cpp', |
|
113 | 'src/Visualization/VisualizationSelectionZoneManager.cpp', | |
113 | 'src/Actions/SelectionZoneAction.cpp', |
|
114 | 'src/Actions/SelectionZoneAction.cpp', | |
114 | 'src/Actions/ActionsGuiController.cpp', |
|
115 | 'src/Actions/ActionsGuiController.cpp', | |
|
116 | 'src/Actions/FilteringAction.cpp', | |||
115 | 'src/Visualization/VisualizationActionManager.cpp', |
|
117 | 'src/Visualization/VisualizationActionManager.cpp', | |
116 | 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp', |
|
118 | 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp', | |
117 | 'src/Catalogue/CatalogueExplorer.cpp', |
|
119 | 'src/Catalogue/CatalogueExplorer.cpp', |
@@ -3,6 +3,7 | |||||
3 | struct ActionsGuiController::ActionsGuiControllerPrivate { |
|
3 | struct ActionsGuiController::ActionsGuiControllerPrivate { | |
4 |
|
4 | |||
5 | QVector<std::shared_ptr<SelectionZoneAction> > m_SelectionZoneActions; |
|
5 | QVector<std::shared_ptr<SelectionZoneAction> > m_SelectionZoneActions; | |
|
6 | QSet<QStringList> m_FilteredMenu; | |||
6 | }; |
|
7 | }; | |
7 |
|
8 | |||
8 | ActionsGuiController::ActionsGuiController() |
|
9 | ActionsGuiController::ActionsGuiController() | |
@@ -39,3 +40,13 void ActionsGuiController::removeAction(const std::shared_ptr<SelectionZoneActio | |||||
39 | { |
|
40 | { | |
40 | impl->m_SelectionZoneActions.removeAll(action); |
|
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 | QKeySequence m_DisplayedShortcut; |
|
15 | QKeySequence m_DisplayedShortcut; | |
16 | SelectionZoneAction::ExecuteFunction m_Fun; |
|
16 | SelectionZoneAction::ExecuteFunction m_Fun; | |
17 | SelectionZoneAction::EnableFunction m_EnableFun = [](auto zones) { return true; }; |
|
17 | SelectionZoneAction::EnableFunction m_EnableFun = [](auto zones) { return true; }; | |
|
18 | bool m_FilteringAllowed = true; | |||
18 | }; |
|
19 | }; | |
19 |
|
20 | |||
20 | SelectionZoneAction::SelectionZoneAction(const QString &name, ExecuteFunction fun) |
|
21 | SelectionZoneAction::SelectionZoneAction(const QString &name, ExecuteFunction fun) | |
@@ -55,6 +56,16 QStringList SelectionZoneAction::subMenuList() const noexcept | |||||
55 | return impl->m_SubMenuList; |
|
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 | void SelectionZoneAction::execute(const QVector<VisualizationSelectionZoneItem *> &item) |
|
69 | void SelectionZoneAction::execute(const QVector<VisualizationSelectionZoneItem *> &item) | |
59 | { |
|
70 | { | |
60 | impl->m_Fun(item); |
|
71 | impl->m_Fun(item); |
@@ -127,6 +127,7 void CatalogueActionManager::installSelectionZoneActions() | |||||
127 | {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}, QObject::tr("Without Catalogue"), |
|
127 | {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}, QObject::tr("Without Catalogue"), | |
128 | [this](auto zones) { impl->createEventFromZones(DEFAULT_EVENT_NAME, zones); }); |
|
128 | [this](auto zones) { impl->createEventFromZones(DEFAULT_EVENT_NAME, zones); }); | |
129 | createEventAction->setEnableFunction(impl->createEventEnableFuntion()); |
|
129 | createEventAction->setEnableFunction(impl->createEventEnableFuntion()); | |
|
130 | createEventAction->setAllowedFiltering(false); | |||
130 |
|
131 | |||
131 | auto createEventInNewCatalogueAction = actionController.addSectionZoneAction( |
|
132 | auto createEventInNewCatalogueAction = actionController.addSectionZoneAction( | |
132 | {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}, QObject::tr("In New Catalogue"), |
|
133 | {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}, QObject::tr("In New Catalogue"), | |
@@ -141,9 +142,11 void CatalogueActionManager::installSelectionZoneActions() | |||||
141 | impl->createEventFromZones(DEFAULT_EVENT_NAME, zones, newCatalogue); |
|
142 | impl->createEventFromZones(DEFAULT_EVENT_NAME, zones, newCatalogue); | |
142 | }); |
|
143 | }); | |
143 | createEventInNewCatalogueAction->setEnableFunction(impl->createEventEnableFuntion()); |
|
144 | createEventInNewCatalogueAction->setEnableFunction(impl->createEventEnableFuntion()); | |
144 |
|
145 | createEventInNewCatalogueAction->setAllowedFiltering(false); | ||
145 |
|
146 | |||
146 | refreshCreateInCatalogueAction(); |
|
147 | refreshCreateInCatalogueAction(); | |
|
148 | ||||
|
149 | actionController.addFilterForMenu({CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}); | |||
147 | } |
|
150 | } | |
148 |
|
151 | |||
149 | void CatalogueActionManager::refreshCreateInCatalogueAction() |
|
152 | void CatalogueActionManager::refreshCreateInCatalogueAction() |
@@ -12,6 +12,7 | |||||
12 | #include "ui_VisualizationGraphWidget.h" |
|
12 | #include "ui_VisualizationGraphWidget.h" | |
13 |
|
13 | |||
14 | #include <Actions/ActionsGuiController.h> |
|
14 | #include <Actions/ActionsGuiController.h> | |
|
15 | #include <Actions/FilteringAction.h> | |||
15 | #include <Common/MimeTypesDef.h> |
|
16 | #include <Common/MimeTypesDef.h> | |
16 | #include <Data/ArrayData.h> |
|
17 | #include <Data/ArrayData.h> | |
17 | #include <Data/IDataSeries.h> |
|
18 | #include <Data/IDataSeries.h> | |
@@ -245,7 +246,7 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget | |||||
245 | &VisualizationGraphWidget::onMouseDoubleClick); |
|
246 | &VisualizationGraphWidget::onMouseDoubleClick); | |
246 | connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>( |
|
247 | connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>( | |
247 | &QCPAxis::rangeChanged), |
|
248 | &QCPAxis::rangeChanged), | |
248 |
|
|
249 | this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection); | |
249 |
|
250 | |||
250 | // Activates menu when right clicking on the graph |
|
251 | // Activates menu when right clicking on the graph | |
251 | ui->widget->setContextMenuPolicy(Qt::CustomContextMenu); |
|
252 | ui->widget->setContextMenuPolicy(Qt::CustomContextMenu); | |
@@ -707,32 +708,51 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept | |||||
707 |
|
708 | |||
708 | QHash<QString, QMenu *> subMenus; |
|
709 | QHash<QString, QMenu *> subMenus; | |
709 | QHash<QString, bool> subMenusEnabled; |
|
710 | QHash<QString, bool> subMenusEnabled; | |
|
711 | QHash<QString, FilteringAction *> filteredMenu; | |||
710 |
|
712 | |||
711 | for (auto zoneAction : zoneActions) { |
|
713 | for (auto zoneAction : zoneActions) { | |
712 |
|
714 | |||
713 | auto isEnabled = zoneAction->isEnabled(selectedItems); |
|
715 | auto isEnabled = zoneAction->isEnabled(selectedItems); | |
714 |
|
716 | |||
715 | auto menu = &graphMenu; |
|
717 | auto menu = &graphMenu; | |
|
718 | QString menuPath; | |||
716 | for (auto subMenuName : zoneAction->subMenuList()) { |
|
719 | for (auto subMenuName : zoneAction->subMenuList()) { | |
717 | if (!subMenus.contains(subMenuName)) { |
|
720 | menuPath += '/'; | |
|
721 | menuPath += subMenuName; | |||
|
722 | ||||
|
723 | if (!subMenus.contains(menuPath)) { | |||
718 | menu = menu->addMenu(subMenuName); |
|
724 | menu = menu->addMenu(subMenuName); | |
719 |
subMenus[ |
|
725 | subMenus[menuPath] = menu; | |
720 |
subMenusEnabled[ |
|
726 | subMenusEnabled[menuPath] = isEnabled; | |
721 | } |
|
727 | } | |
722 | else { |
|
728 | else { | |
723 |
menu = subMenus.value( |
|
729 | menu = subMenus.value(menuPath); | |
724 | if (isEnabled) { |
|
730 | if (isEnabled) { | |
725 | // The sub menu is enabled if at least one of its actions is enabled |
|
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 | auto action = menu->addAction(zoneAction->name()); |
|
747 | auto action = menu->addAction(zoneAction->name()); | |
732 | action->setEnabled(isEnabled); |
|
748 | action->setEnabled(isEnabled); | |
733 | action->setShortcut(zoneAction->displayedShortcut()); |
|
749 | action->setShortcut(zoneAction->displayedShortcut()); | |
734 | QObject::connect(action, &QAction::triggered, |
|
750 | QObject::connect(action, &QAction::triggered, | |
735 | [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); }); |
|
751 | [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); }); | |
|
752 | ||||
|
753 | if (filterAction && zoneAction->isFilteringAllowed()) { | |||
|
754 | filterAction->addActionToFilter(action); | |||
|
755 | } | |||
736 | } |
|
756 | } | |
737 |
|
757 | |||
738 | for (auto it = subMenus.cbegin(); it != subMenus.cend(); ++it) { |
|
758 | for (auto it = subMenus.cbegin(); it != subMenus.cend(); ++it) { |
General Comments 0
You need to be logged in to leave comments.
Login now