##// END OF EJS Templates
Merge branch 'feature/CataloguePart7' into develop
trabillard -
r1383:4dfca649988f merge
parent child
Show More
@@ -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 }
@@ -1,27 +1,35
1 #ifndef SCIQLOP_ACTIONSGUICONTROLLER_H
1 #ifndef SCIQLOP_ACTIONSGUICONTROLLER_H
2 #define SCIQLOP_ACTIONSGUICONTROLLER_H
2 #define SCIQLOP_ACTIONSGUICONTROLLER_H
3
3
4 #include <Actions/SelectionZoneAction.h>
4 #include <Actions/SelectionZoneAction.h>
5 #include <Common/spimpl.h>
5 #include <Common/spimpl.h>
6
6
7 #include <memory>
7 #include <memory>
8
8
9 class ActionsGuiController {
9 class ActionsGuiController {
10 public:
10 public:
11 ActionsGuiController();
11 ActionsGuiController();
12
12
13 std::shared_ptr<SelectionZoneAction>
13 std::shared_ptr<SelectionZoneAction>
14 addSectionZoneAction(const QString &name, SelectionZoneAction::ExecuteFunction function);
14 addSectionZoneAction(const QString &name, SelectionZoneAction::ExecuteFunction function);
15
15
16 std::shared_ptr<SelectionZoneAction>
16 std::shared_ptr<SelectionZoneAction>
17 addSectionZoneAction(const QStringList &subMenuList, const QString &name,
17 addSectionZoneAction(const QStringList &subMenuList, const QString &name,
18 SelectionZoneAction::ExecuteFunction function);
18 SelectionZoneAction::ExecuteFunction function);
19
19
20 QVector<std::shared_ptr<SelectionZoneAction> > selectionZoneActions() const;
20 QVector<std::shared_ptr<SelectionZoneAction> > selectionZoneActions() const;
21
21
22 void removeAction(const std::shared_ptr<SelectionZoneAction> &action);
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
22 private:
30 private:
23 class ActionsGuiControllerPrivate;
31 class ActionsGuiControllerPrivate;
24 spimpl::unique_impl_ptr<ActionsGuiControllerPrivate> impl;
32 spimpl::unique_impl_ptr<ActionsGuiControllerPrivate> impl;
25 };
33 };
26
34
27 #endif // SCIQLOP_ACTIONSGUICONTROLLER_H
35 #endif // SCIQLOP_ACTIONSGUICONTROLLER_H
@@ -1,75 +1,82
1 #ifndef SCIQLOP_SELECTIONZONEACTION_H
1 #ifndef SCIQLOP_SELECTIONZONEACTION_H
2 #define SCIQLOP_SELECTIONZONEACTION_H
2 #define SCIQLOP_SELECTIONZONEACTION_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8
8
9 #include <functional>
9 #include <functional>
10
10
11 class VisualizationSelectionZoneItem;
11 class VisualizationSelectionZoneItem;
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_SelectionZoneAction)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_SelectionZoneAction)
14
14
15 /**
15 /**
16 * @brief The SelectionZoneAction class represents an action on a selection zone in the
16 * @brief The SelectionZoneAction class represents an action on a selection zone in the
17 * visualization.
17 * visualization.
18 *
18 *
19 * The action is a function that will be executed when the slot execute() is called.
19 * The action is a function that will be executed when the slot execute() is called.
20 */
20 */
21 class SelectionZoneAction : public QObject {
21 class SelectionZoneAction : public QObject {
22
22
23 Q_OBJECT
23 Q_OBJECT
24
24
25 public:
25 public:
26 /// Signature of the function associated to the action
26 /// Signature of the function associated to the action
27 using ExecuteFunction
27 using ExecuteFunction
28 = std::function<void(const QVector<VisualizationSelectionZoneItem *> &item)>;
28 = std::function<void(const QVector<VisualizationSelectionZoneItem *> &item)>;
29
29
30 using EnableFunction
30 using EnableFunction
31 = std::function<bool(const QVector<VisualizationSelectionZoneItem *> &item)>;
31 = std::function<bool(const QVector<VisualizationSelectionZoneItem *> &item)>;
32
32
33 /**
33 /**
34 * @param name the name of the action, displayed to the user
34 * @param name the name of the action, displayed to the user
35 * @param fun the function that will be called when the action is executed
35 * @param fun the function that will be called when the action is executed
36 * @sa execute()
36 * @sa execute()
37 */
37 */
38 explicit SelectionZoneAction(const QString &name, ExecuteFunction fun);
38 explicit SelectionZoneAction(const QString &name, ExecuteFunction fun);
39
39
40 /**
40 /**
41 * @param name the name of the action, displayed to the user
41 * @param name the name of the action, displayed to the user
42 * @param subMenusList the list of sub menus where the action should be inserted
42 * @param subMenusList the list of sub menus where the action should be inserted
43 * @param fun the function that will be called when the action is executed
43 * @param fun the function that will be called when the action is executed
44 * @sa execute()
44 * @sa execute()
45 */
45 */
46 explicit SelectionZoneAction(const QStringList &subMenuList, const QString &name,
46 explicit SelectionZoneAction(const QStringList &subMenuList, const QString &name,
47 ExecuteFunction fun);
47 ExecuteFunction fun);
48
48
49 /// Sets the function which determine if the action should be enabled or disabled
49 /// Sets the function which determine if the action should be enabled or disabled
50 void setEnableFunction(EnableFunction fun);
50 void setEnableFunction(EnableFunction fun);
51
51
52 /// Sets the shortcut displayed by the action.
52 /// Sets the shortcut displayed by the action.
53 /// Note: The shortcut is only displayed and not active because it is not permanently stored
53 /// Note: The shortcut is only displayed and not active because it is not permanently stored
54 void setDisplayedShortcut(const QKeySequence &shortcut);
54 void setDisplayedShortcut(const QKeySequence &shortcut);
55 QKeySequence displayedShortcut() const;
55 QKeySequence displayedShortcut() const;
56
56
57 /// The name of the action
57 /// The name of the action
58 QString name() const noexcept;
58 QString name() const noexcept;
59
59
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);
66
73
67 /// Returns true if the action is enabled
74 /// Returns true if the action is enabled
68 bool isEnabled(const QVector<VisualizationSelectionZoneItem *> &item);
75 bool isEnabled(const QVector<VisualizationSelectionZoneItem *> &item);
69
76
70 private:
77 private:
71 class SelectionZoneActionPrivate;
78 class SelectionZoneActionPrivate;
72 spimpl::unique_impl_ptr<SelectionZoneActionPrivate> impl;
79 spimpl::unique_impl_ptr<SelectionZoneActionPrivate> impl;
73 };
80 };
74
81
75 #endif // SCIQLOP_SELECTIONZONEACTION_H
82 #endif // SCIQLOP_SELECTIONZONEACTION_H
@@ -1,19 +1,20
1 #ifndef SCIQLOP_CATALOGUEACTIONMANAGER_H
1 #ifndef SCIQLOP_CATALOGUEACTIONMANAGER_H
2 #define SCIQLOP_CATALOGUEACTIONMANAGER_H
2 #define SCIQLOP_CATALOGUEACTIONMANAGER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5
5
6 class CatalogueExplorer;
6 class CatalogueExplorer;
7
7
8 class CatalogueActionManager {
8 class CatalogueActionManager {
9 public:
9 public:
10 CatalogueActionManager(CatalogueExplorer *catalogueExplorer);
10 CatalogueActionManager(CatalogueExplorer *catalogueExplorer);
11
11
12 void installSelectionZoneActions();
12 void installSelectionZoneActions();
13 void refreshCreateInCatalogueAction();
13
14
14 private:
15 private:
15 class CatalogueActionManagerPrivate;
16 class CatalogueActionManagerPrivate;
16 spimpl::unique_impl_ptr<CatalogueActionManagerPrivate> impl;
17 spimpl::unique_impl_ptr<CatalogueActionManagerPrivate> impl;
17 };
18 };
18
19
19 #endif // SCIQLOP_CATALOGUEACTIONMANAGER_H
20 #endif // SCIQLOP_CATALOGUEACTIONMANAGER_H
@@ -1,56 +1,57
1 #ifndef SCIQLOP_CATALOGUESIDEBARWIDGET_H
1 #ifndef SCIQLOP_CATALOGUESIDEBARWIDGET_H
2 #define SCIQLOP_CATALOGUESIDEBARWIDGET_H
2 #define SCIQLOP_CATALOGUESIDEBARWIDGET_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QLoggingCategory>
6 #include <QTreeWidgetItem>
6 #include <QTreeWidgetItem>
7 #include <QWidget>
7 #include <QWidget>
8
8
9 class CatalogueAbstractTreeItem;
9 class CatalogueAbstractTreeItem;
10 class DBCatalogue;
10 class DBCatalogue;
11
11
12 namespace Ui {
12 namespace Ui {
13 class CatalogueSideBarWidget;
13 class CatalogueSideBarWidget;
14 }
14 }
15
15
16 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget)
16 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget)
17
17
18 class CatalogueSideBarWidget : public QWidget {
18 class CatalogueSideBarWidget : public QWidget {
19 Q_OBJECT
19 Q_OBJECT
20
20
21 signals:
21 signals:
22 void catalogueSelected(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
22 void catalogueSelected(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
23 void databaseSelected(const QStringList &databases);
23 void databaseSelected(const QStringList &databases);
24 void allEventsSelected();
24 void allEventsSelected();
25 void trashSelected();
25 void trashSelected();
26 void selectionCleared();
26 void selectionCleared();
27 void catalogueSaved(const std::shared_ptr<DBCatalogue> &catalogue);
27 void catalogueSaved(const std::shared_ptr<DBCatalogue> &catalogue);
28 void catalogueListChanged();
28
29
29 public:
30 public:
30 explicit CatalogueSideBarWidget(QWidget *parent = 0);
31 explicit CatalogueSideBarWidget(QWidget *parent = 0);
31 virtual ~CatalogueSideBarWidget();
32 virtual ~CatalogueSideBarWidget();
32
33
33 CatalogueAbstractTreeItem *addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
34 CatalogueAbstractTreeItem *addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
34 const QString &repository);
35 const QString &repository);
35 void setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue, bool hasChanges);
36 void setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue, bool hasChanges);
36
37
37 QVector<std::shared_ptr<DBCatalogue> > getCatalogues(const QString &repository) const;
38 QVector<std::shared_ptr<DBCatalogue> > getCatalogues(const QString &repository) const;
38
39
39 // QWidget interface
40 // QWidget interface
40 protected:
41 protected:
41 void keyPressEvent(QKeyEvent *event);
42 void keyPressEvent(QKeyEvent *event);
42
43
43 private slots:
44 private slots:
44 void emitSelection();
45 void emitSelection();
45
46
46 private:
47 private:
47 Ui::CatalogueSideBarWidget *ui;
48 Ui::CatalogueSideBarWidget *ui;
48
49
49 class CatalogueSideBarWidgetPrivate;
50 class CatalogueSideBarWidgetPrivate;
50 spimpl::unique_impl_ptr<CatalogueSideBarWidgetPrivate> impl;
51 spimpl::unique_impl_ptr<CatalogueSideBarWidgetPrivate> impl;
51
52
52 private slots:
53 private slots:
53 void onContextMenuRequested(const QPoint &pos);
54 void onContextMenuRequested(const QPoint &pos);
54 };
55 };
55
56
56 #endif // SCIQLOP_CATALOGUESIDEBARWIDGET_H
57 #endif // SCIQLOP_CATALOGUESIDEBARWIDGET_H
@@ -1,28 +1,29
1 #ifndef SCIQLOP_CATALOGUETREEITEM_H
1 #ifndef SCIQLOP_CATALOGUETREEITEM_H
2 #define SCIQLOP_CATALOGUETREEITEM_H
2 #define SCIQLOP_CATALOGUETREEITEM_H
3
3
4 #include <Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h>
4 #include <Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h>
5 #include <Common/spimpl.h>
5 #include <Common/spimpl.h>
6
6
7 class DBCatalogue;
7 class DBCatalogue;
8
8
9
9
10 class CatalogueTreeItem : public CatalogueAbstractTreeItem {
10 class CatalogueTreeItem : public CatalogueAbstractTreeItem {
11 public:
11 public:
12 CatalogueTreeItem(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon, int type);
12 CatalogueTreeItem(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon, int type);
13
13
14 QVariant data(int column, int role) const override;
14 QVariant data(int column, int role) const override;
15 bool setData(int column, int role, const QVariant &value) override;
15 bool setData(int column, int role, const QVariant &value) override;
16 Qt::ItemFlags flags(int column) const override;
16 Qt::ItemFlags flags(int column) const override;
17 bool canDropMimeData(const QMimeData *data, Qt::DropAction action) override;
17 bool canDropMimeData(const QMimeData *data, Qt::DropAction action) override;
18 bool dropMimeData(const QMimeData *data, Qt::DropAction action) override;
18 bool dropMimeData(const QMimeData *data, Qt::DropAction action) override;
19
19
20 /// Returns the catalogue represented by the item
20 /// Returns the catalogue represented by the item
21 std::shared_ptr<DBCatalogue> catalogue() const;
21 std::shared_ptr<DBCatalogue> catalogue() const;
22 void replaceCatalogue(const std::shared_ptr<DBCatalogue> &catalogue);
22
23
23 private:
24 private:
24 class CatalogueTreeItemPrivate;
25 class CatalogueTreeItemPrivate;
25 spimpl::unique_impl_ptr<CatalogueTreeItemPrivate> impl;
26 spimpl::unique_impl_ptr<CatalogueTreeItemPrivate> impl;
26 };
27 };
27
28
28 #endif // SCIQLOP_CATALOGUETREEITEM_H
29 #endif // SCIQLOP_CATALOGUETREEITEM_H
@@ -1,148 +1,147
1 qxorm_dep = dependency('QxOrm', required : true, fallback:['QxOrm','qxorm_dep'])
1 qxorm_dep = dependency('QxOrm', required : true, fallback:['QxOrm','qxorm_dep'])
2 catalogueapi_dep = dependency('CatalogueAPI', required : true, fallback:['CatalogueAPI','CatalogueAPI_dep'])
2 catalogueapi_dep = dependency('CatalogueAPI', required : true, fallback:['CatalogueAPI','CatalogueAPI_dep'])
3
3
4 gui_moc_headers = [
4 gui_moc_headers = [
5 'include/DataSource/DataSourceWidget.h',
5 'include/DataSource/DataSourceWidget.h',
6 'include/Settings/SqpSettingsDialog.h',
6 'include/Settings/SqpSettingsDialog.h',
7 'include/Settings/SqpSettingsGeneralWidget.h',
7 'include/Settings/SqpSettingsGeneralWidget.h',
8 'include/SidePane/SqpSidePane.h',
8 'include/SidePane/SqpSidePane.h',
9 'include/SqpApplication.h',
9 'include/SqpApplication.h',
10 'include/DragAndDrop/DragDropScroller.h',
10 'include/DragAndDrop/DragDropScroller.h',
11 'include/DragAndDrop/DragDropTabSwitcher.h',
11 'include/DragAndDrop/DragDropTabSwitcher.h',
12 'include/TimeWidget/TimeWidget.h',
12 'include/TimeWidget/TimeWidget.h',
13 'include/Variable/VariableInspectorWidget.h',
13 'include/Variable/VariableInspectorWidget.h',
14 'include/Variable/RenameVariableDialog.h',
14 'include/Variable/RenameVariableDialog.h',
15 'include/Visualization/qcustomplot.h',
15 'include/Visualization/qcustomplot.h',
16 'include/Visualization/VisualizationGraphWidget.h',
16 'include/Visualization/VisualizationGraphWidget.h',
17 'include/Visualization/VisualizationTabWidget.h',
17 'include/Visualization/VisualizationTabWidget.h',
18 'include/Visualization/VisualizationWidget.h',
18 'include/Visualization/VisualizationWidget.h',
19 'include/Visualization/VisualizationZoneWidget.h',
19 'include/Visualization/VisualizationZoneWidget.h',
20 'include/Visualization/VisualizationDragDropContainer.h',
20 'include/Visualization/VisualizationDragDropContainer.h',
21 'include/Visualization/VisualizationDragWidget.h',
21 'include/Visualization/VisualizationDragWidget.h',
22 'include/Visualization/ColorScaleEditor.h',
22 'include/Visualization/ColorScaleEditor.h',
23 'include/Visualization/VisualizationSelectionZoneItem.h',
23 'include/Visualization/VisualizationSelectionZoneItem.h',
24 'include/Actions/SelectionZoneAction.h',
24 'include/Actions/SelectionZoneAction.h',
25 'include/Visualization/VisualizationMultiZoneSelectionDialog.h',
25 'include/Visualization/VisualizationMultiZoneSelectionDialog.h',
26 'include/Catalogue/CatalogueExplorer.h',
26 'include/Catalogue/CatalogueExplorer.h',
27 'include/Catalogue/CatalogueEventsWidget.h',
27 'include/Catalogue/CatalogueEventsWidget.h',
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/CreateEventDialog.h',
31 'include/Catalogue/CatalogueTreeModel.h',
32 'include/Catalogue/CatalogueTreeModel.h'
32 'include/Actions/FilteringAction.h'
33 ]
33 ]
34
34
35 gui_ui_files = [
35 gui_ui_files = [
36 'ui/DataSource/DataSourceWidget.ui',
36 'ui/DataSource/DataSourceWidget.ui',
37 'ui/Settings/SqpSettingsDialog.ui',
37 'ui/Settings/SqpSettingsDialog.ui',
38 'ui/Settings/SqpSettingsGeneralWidget.ui',
38 'ui/Settings/SqpSettingsGeneralWidget.ui',
39 'ui/SidePane/SqpSidePane.ui',
39 'ui/SidePane/SqpSidePane.ui',
40 'ui/TimeWidget/TimeWidget.ui',
40 'ui/TimeWidget/TimeWidget.ui',
41 'ui/Variable/VariableInspectorWidget.ui',
41 'ui/Variable/VariableInspectorWidget.ui',
42 'ui/Variable/RenameVariableDialog.ui',
42 'ui/Variable/RenameVariableDialog.ui',
43 'ui/Variable/VariableMenuHeaderWidget.ui',
43 'ui/Variable/VariableMenuHeaderWidget.ui',
44 'ui/Visualization/VisualizationGraphWidget.ui',
44 'ui/Visualization/VisualizationGraphWidget.ui',
45 'ui/Visualization/VisualizationTabWidget.ui',
45 'ui/Visualization/VisualizationTabWidget.ui',
46 'ui/Visualization/VisualizationWidget.ui',
46 'ui/Visualization/VisualizationWidget.ui',
47 'ui/Visualization/VisualizationZoneWidget.ui',
47 'ui/Visualization/VisualizationZoneWidget.ui',
48 'ui/Visualization/ColorScaleEditor.ui',
48 'ui/Visualization/ColorScaleEditor.ui',
49 'ui/Visualization/VisualizationMultiZoneSelectionDialog.ui',
49 'ui/Visualization/VisualizationMultiZoneSelectionDialog.ui',
50 'ui/Catalogue/CatalogueExplorer.ui',
50 'ui/Catalogue/CatalogueExplorer.ui',
51 'ui/Catalogue/CatalogueEventsWidget.ui',
51 'ui/Catalogue/CatalogueEventsWidget.ui',
52 'ui/Catalogue/CatalogueSideBarWidget.ui',
52 'ui/Catalogue/CatalogueSideBarWidget.ui',
53 'ui/Catalogue/CatalogueInspectorWidget.ui',
53 'ui/Catalogue/CatalogueInspectorWidget.ui'
54 'ui/Catalogue/CreateEventDialog.ui'
55 ]
54 ]
56
55
57 gui_qresources = ['resources/sqpguiresources.qrc']
56 gui_qresources = ['resources/sqpguiresources.qrc']
58
57
59 rcc_gen = generator(rcc,
58 rcc_gen = generator(rcc,
60 output : 'qrc_@BASENAME@.cpp',
59 output : 'qrc_@BASENAME@.cpp',
61 arguments : [
60 arguments : [
62 '--output',
61 '--output',
63 '@OUTPUT@',
62 '@OUTPUT@',
64 '@INPUT@',
63 '@INPUT@',
65 '@EXTRA_ARGS@'])
64 '@EXTRA_ARGS@'])
66
65
67 rcc_files = rcc_gen.process(gui_qresources, extra_args : ['-name', 'sqpguiresources'])
66 rcc_files = rcc_gen.process(gui_qresources, extra_args : ['-name', 'sqpguiresources'])
68
67
69 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
68 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
70 ui_files : gui_ui_files)
69 ui_files : gui_ui_files)
71
70
72 gui_sources = [
71 gui_sources = [
73 'src/SqpApplication.cpp',
72 'src/SqpApplication.cpp',
74 'src/DragAndDrop/DragDropGuiController.cpp',
73 'src/DragAndDrop/DragDropGuiController.cpp',
75 'src/DragAndDrop/DragDropScroller.cpp',
74 'src/DragAndDrop/DragDropScroller.cpp',
76 'src/DragAndDrop/DragDropTabSwitcher.cpp',
75 'src/DragAndDrop/DragDropTabSwitcher.cpp',
77 'src/Common/ColorUtils.cpp',
76 'src/Common/ColorUtils.cpp',
78 'src/Common/VisualizationDef.cpp',
77 'src/Common/VisualizationDef.cpp',
79 'src/DataSource/DataSourceTreeWidgetItem.cpp',
78 'src/DataSource/DataSourceTreeWidgetItem.cpp',
80 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
79 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
81 'src/DataSource/DataSourceWidget.cpp',
80 'src/DataSource/DataSourceWidget.cpp',
82 'src/DataSource/DataSourceTreeWidget.cpp',
81 'src/DataSource/DataSourceTreeWidget.cpp',
83 'src/Settings/SqpSettingsDialog.cpp',
82 'src/Settings/SqpSettingsDialog.cpp',
84 'src/Settings/SqpSettingsGeneralWidget.cpp',
83 'src/Settings/SqpSettingsGeneralWidget.cpp',
85 'src/SidePane/SqpSidePane.cpp',
84 'src/SidePane/SqpSidePane.cpp',
86 'src/TimeWidget/TimeWidget.cpp',
85 'src/TimeWidget/TimeWidget.cpp',
87 'src/Variable/VariableInspectorWidget.cpp',
86 'src/Variable/VariableInspectorWidget.cpp',
88 'src/Variable/VariableInspectorTableView.cpp',
87 'src/Variable/VariableInspectorTableView.cpp',
89 'src/Variable/VariableMenuHeaderWidget.cpp',
88 'src/Variable/VariableMenuHeaderWidget.cpp',
90 'src/Variable/RenameVariableDialog.cpp',
89 'src/Variable/RenameVariableDialog.cpp',
91 'src/Visualization/VisualizationGraphHelper.cpp',
90 'src/Visualization/VisualizationGraphHelper.cpp',
92 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
91 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
93 'src/Visualization/VisualizationGraphWidget.cpp',
92 'src/Visualization/VisualizationGraphWidget.cpp',
94 'src/Visualization/VisualizationTabWidget.cpp',
93 'src/Visualization/VisualizationTabWidget.cpp',
95 'src/Visualization/VisualizationWidget.cpp',
94 'src/Visualization/VisualizationWidget.cpp',
96 'src/Visualization/VisualizationZoneWidget.cpp',
95 'src/Visualization/VisualizationZoneWidget.cpp',
97 'src/Visualization/qcustomplot.cpp',
96 'src/Visualization/qcustomplot.cpp',
98 'src/Visualization/QCustomPlotSynchronizer.cpp',
97 'src/Visualization/QCustomPlotSynchronizer.cpp',
99 'src/Visualization/operations/FindVariableOperation.cpp',
98 'src/Visualization/operations/FindVariableOperation.cpp',
100 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
99 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
101 'src/Visualization/operations/MenuBuilder.cpp',
100 'src/Visualization/operations/MenuBuilder.cpp',
102 'src/Visualization/operations/RemoveVariableOperation.cpp',
101 'src/Visualization/operations/RemoveVariableOperation.cpp',
103 'src/Visualization/operations/RescaleAxeOperation.cpp',
102 'src/Visualization/operations/RescaleAxeOperation.cpp',
104 'src/Visualization/VisualizationDragDropContainer.cpp',
103 'src/Visualization/VisualizationDragDropContainer.cpp',
105 'src/Visualization/VisualizationDragWidget.cpp',
104 'src/Visualization/VisualizationDragWidget.cpp',
106 'src/Visualization/AxisRenderingUtils.cpp',
105 'src/Visualization/AxisRenderingUtils.cpp',
107 'src/Visualization/PlottablesRenderingUtils.cpp',
106 'src/Visualization/PlottablesRenderingUtils.cpp',
108 'src/Visualization/MacScrollBarStyle.cpp',
107 'src/Visualization/MacScrollBarStyle.cpp',
109 'src/Visualization/VisualizationCursorItem.cpp',
108 'src/Visualization/VisualizationCursorItem.cpp',
110 'src/Visualization/ColorScaleEditor.cpp',
109 'src/Visualization/ColorScaleEditor.cpp',
111 'src/Visualization/SqpColorScale.cpp',
110 'src/Visualization/SqpColorScale.cpp',
112 'src/Visualization/QCPColorMapIterator.cpp',
111 'src/Visualization/QCPColorMapIterator.cpp',
113 'src/Visualization/VisualizationSelectionZoneItem.cpp',
112 'src/Visualization/VisualizationSelectionZoneItem.cpp',
114 'src/Visualization/VisualizationSelectionZoneManager.cpp',
113 'src/Visualization/VisualizationSelectionZoneManager.cpp',
115 'src/Actions/SelectionZoneAction.cpp',
114 'src/Actions/SelectionZoneAction.cpp',
116 'src/Actions/ActionsGuiController.cpp',
115 'src/Actions/ActionsGuiController.cpp',
116 'src/Actions/FilteringAction.cpp',
117 'src/Visualization/VisualizationActionManager.cpp',
117 'src/Visualization/VisualizationActionManager.cpp',
118 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp',
118 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp',
119 'src/Catalogue/CatalogueExplorer.cpp',
119 'src/Catalogue/CatalogueExplorer.cpp',
120 'src/Catalogue/CatalogueEventsWidget.cpp',
120 'src/Catalogue/CatalogueEventsWidget.cpp',
121 'src/Catalogue/CatalogueSideBarWidget.cpp',
121 'src/Catalogue/CatalogueSideBarWidget.cpp',
122 'src/Catalogue/CatalogueInspectorWidget.cpp',
122 'src/Catalogue/CatalogueInspectorWidget.cpp',
123 'src/Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.cpp',
123 'src/Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.cpp',
124 'src/Catalogue/CatalogueTreeItems/CatalogueTreeItem.cpp',
124 'src/Catalogue/CatalogueTreeItems/CatalogueTreeItem.cpp',
125 'src/Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.cpp',
125 'src/Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.cpp',
126 'src/Catalogue/CatalogueEventsModel.cpp',
126 'src/Catalogue/CatalogueEventsModel.cpp',
127 'src/Catalogue/CatalogueExplorerHelper.cpp',
127 'src/Catalogue/CatalogueExplorerHelper.cpp',
128 'src/Catalogue/CatalogueActionManager.cpp',
128 'src/Catalogue/CatalogueActionManager.cpp',
129 'src/Catalogue/CreateEventDialog.cpp',
130 'src/Catalogue/CatalogueTreeModel.cpp'
129 'src/Catalogue/CatalogueTreeModel.cpp'
131 ]
130 ]
132
131
133 gui_inc = include_directories(['include'])
132 gui_inc = include_directories(['include'])
134
133
135 sciqlop_gui_lib = library('sciqlopgui',
134 sciqlop_gui_lib = library('sciqlopgui',
136 gui_sources,
135 gui_sources,
137 gui_moc_files,
136 gui_moc_files,
138 rcc_files,
137 rcc_files,
139 include_directories : [gui_inc],
138 include_directories : [gui_inc],
140 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep],
139 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep],
141 install : true
140 install : true
142 )
141 )
143
142
144 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
143 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
145 include_directories : gui_inc,
144 include_directories : gui_inc,
146 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep])
145 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep])
147
146
148
147
@@ -1,36 +1,52
1 #include "Actions/ActionsGuiController.h"
1 #include "Actions/ActionsGuiController.h"
2
2
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()
9 : impl{spimpl::make_unique_impl<ActionsGuiControllerPrivate>()}
10 : impl{spimpl::make_unique_impl<ActionsGuiControllerPrivate>()}
10 {
11 {
11 }
12 }
12
13
13 std::shared_ptr<SelectionZoneAction>
14 std::shared_ptr<SelectionZoneAction>
14 ActionsGuiController::addSectionZoneAction(const QString &name,
15 ActionsGuiController::addSectionZoneAction(const QString &name,
15 SelectionZoneAction::ExecuteFunction function)
16 SelectionZoneAction::ExecuteFunction function)
16 {
17 {
17 auto action = std::make_shared<SelectionZoneAction>(name, function);
18 auto action = std::make_shared<SelectionZoneAction>(name, function);
18 impl->m_SelectionZoneActions.push_back(action);
19 impl->m_SelectionZoneActions.push_back(action);
19
20
20 return action;
21 return action;
21 }
22 }
22
23
23 std::shared_ptr<SelectionZoneAction>
24 std::shared_ptr<SelectionZoneAction>
24 ActionsGuiController::addSectionZoneAction(const QStringList &subMenuList, const QString &name,
25 ActionsGuiController::addSectionZoneAction(const QStringList &subMenuList, const QString &name,
25 SelectionZoneAction::ExecuteFunction function)
26 SelectionZoneAction::ExecuteFunction function)
26 {
27 {
27 auto action = std::make_shared<SelectionZoneAction>(subMenuList, name, function);
28 auto action = std::make_shared<SelectionZoneAction>(subMenuList, name, function);
28 impl->m_SelectionZoneActions.push_back(action);
29 impl->m_SelectionZoneActions.push_back(action);
29
30
30 return action;
31 return action;
31 }
32 }
32
33
33 QVector<std::shared_ptr<SelectionZoneAction> > ActionsGuiController::selectionZoneActions() const
34 QVector<std::shared_ptr<SelectionZoneAction> > ActionsGuiController::selectionZoneActions() const
34 {
35 {
35 return impl->m_SelectionZoneActions;
36 return impl->m_SelectionZoneActions;
36 }
37 }
38
39 void ActionsGuiController::removeAction(const std::shared_ptr<SelectionZoneAction> &action)
40 {
41 impl->m_SelectionZoneActions.removeAll(action);
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 }
@@ -1,66 +1,77
1 #include <Actions/SelectionZoneAction.h>
1 #include <Actions/SelectionZoneAction.h>
2 #include <Visualization/VisualizationSelectionZoneItem.h>
2 #include <Visualization/VisualizationSelectionZoneItem.h>
3
3
4 Q_LOGGING_CATEGORY(LOG_SelectionZoneAction, "SelectionZoneAction")
4 Q_LOGGING_CATEGORY(LOG_SelectionZoneAction, "SelectionZoneAction")
5
5
6 struct SelectionZoneAction::SelectionZoneActionPrivate {
6 struct SelectionZoneAction::SelectionZoneActionPrivate {
7 explicit SelectionZoneActionPrivate(const QString &name, const QStringList &subMenuList,
7 explicit SelectionZoneActionPrivate(const QString &name, const QStringList &subMenuList,
8 SelectionZoneAction::ExecuteFunction fun)
8 SelectionZoneAction::ExecuteFunction fun)
9 : m_Name{name}, m_SubMenuList{subMenuList}, m_Fun{std::move(fun)}
9 : m_Name{name}, m_SubMenuList{subMenuList}, m_Fun{std::move(fun)}
10 {
10 {
11 }
11 }
12
12
13 QString m_Name;
13 QString m_Name;
14 QStringList m_SubMenuList;
14 QStringList m_SubMenuList;
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)
21 : impl{spimpl::make_unique_impl<SelectionZoneActionPrivate>(name, QStringList{},
22 : impl{spimpl::make_unique_impl<SelectionZoneActionPrivate>(name, QStringList{},
22 std::move(fun))}
23 std::move(fun))}
23 {
24 {
24 }
25 }
25
26
26 SelectionZoneAction::SelectionZoneAction(const QStringList &subMenuList, const QString &name,
27 SelectionZoneAction::SelectionZoneAction(const QStringList &subMenuList, const QString &name,
27 SelectionZoneAction::ExecuteFunction fun)
28 SelectionZoneAction::ExecuteFunction fun)
28 : impl{spimpl::make_unique_impl<SelectionZoneActionPrivate>(name, subMenuList,
29 : impl{spimpl::make_unique_impl<SelectionZoneActionPrivate>(name, subMenuList,
29 std::move(fun))}
30 std::move(fun))}
30 {
31 {
31 }
32 }
32
33
33 void SelectionZoneAction::setEnableFunction(EnableFunction fun)
34 void SelectionZoneAction::setEnableFunction(EnableFunction fun)
34 {
35 {
35 impl->m_EnableFun = std::move(fun);
36 impl->m_EnableFun = std::move(fun);
36 }
37 }
37
38
38 void SelectionZoneAction::setDisplayedShortcut(const QKeySequence &shortcut)
39 void SelectionZoneAction::setDisplayedShortcut(const QKeySequence &shortcut)
39 {
40 {
40 impl->m_DisplayedShortcut = shortcut;
41 impl->m_DisplayedShortcut = shortcut;
41 }
42 }
42
43
43 QKeySequence SelectionZoneAction::displayedShortcut() const
44 QKeySequence SelectionZoneAction::displayedShortcut() const
44 {
45 {
45 return impl->m_DisplayedShortcut;
46 return impl->m_DisplayedShortcut;
46 }
47 }
47
48
48 QString SelectionZoneAction::name() const noexcept
49 QString SelectionZoneAction::name() const noexcept
49 {
50 {
50 return impl->m_Name;
51 return impl->m_Name;
51 }
52 }
52
53
53 QStringList SelectionZoneAction::subMenuList() const noexcept
54 QStringList SelectionZoneAction::subMenuList() const noexcept
54 {
55 {
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);
61 }
72 }
62
73
63 bool SelectionZoneAction::isEnabled(const QVector<VisualizationSelectionZoneItem *> &item)
74 bool SelectionZoneAction::isEnabled(const QVector<VisualizationSelectionZoneItem *> &item)
64 {
75 {
65 return impl->m_EnableFun(item);
76 return impl->m_EnableFun(item);
66 }
77 }
@@ -1,145 +1,174
1 #include "Catalogue/CatalogueActionManager.h"
1 #include "Catalogue/CatalogueActionManager.h"
2
2
3 #include <Actions/ActionsGuiController.h>
3 #include <Actions/ActionsGuiController.h>
4 #include <Catalogue/CatalogueController.h>
4 #include <Catalogue/CatalogueController.h>
5 #include <DataSource/DataSourceItem.h>
5 #include <DataSource/DataSourceItem.h>
6 #include <SqpApplication.h>
6 #include <SqpApplication.h>
7 #include <Variable/Variable.h>
7 #include <Variable/Variable.h>
8 #include <Visualization/VisualizationGraphWidget.h>
8 #include <Visualization/VisualizationGraphWidget.h>
9 #include <Visualization/VisualizationSelectionZoneItem.h>
9 #include <Visualization/VisualizationSelectionZoneItem.h>
10
10
11 #include <Catalogue/CatalogueEventsWidget.h>
11 #include <Catalogue/CatalogueEventsWidget.h>
12 #include <Catalogue/CatalogueExplorer.h>
12 #include <Catalogue/CatalogueExplorer.h>
13 #include <Catalogue/CatalogueSideBarWidget.h>
13 #include <Catalogue/CatalogueSideBarWidget.h>
14 #include <Catalogue/CreateEventDialog.h>
15
14
16 #include <CatalogueDao.h>
15 #include <CatalogueDao.h>
17 #include <DBCatalogue.h>
16 #include <DBCatalogue.h>
18 #include <DBEvent.h>
17 #include <DBEvent.h>
19 #include <DBEventProduct.h>
18 #include <DBEventProduct.h>
20
19
21 #include <QBoxLayout>
20 #include <QBoxLayout>
22 #include <QComboBox>
21 #include <QComboBox>
23 #include <QDialog>
22 #include <QDialog>
24 #include <QDialogButtonBox>
23 #include <QDialogButtonBox>
25 #include <QLineEdit>
24 #include <QLineEdit>
26 #include <memory>
25 #include <memory>
27
26
27 const auto CATALOGUE_MENU_NAME = QObject::tr("Catalogues");
28 const auto CATALOGUE_CREATE_EVENT_MENU_NAME = QObject::tr("New Event...");
29
30 const auto DEFAULT_EVENT_NAME = QObject::tr("Event");
31 const auto DEFAULT_CATALOGUE_NAME = QObject::tr("Catalogue");
32
28 struct CatalogueActionManager::CatalogueActionManagerPrivate {
33 struct CatalogueActionManager::CatalogueActionManagerPrivate {
29
34
30 CatalogueExplorer *m_CatalogueExplorer = nullptr;
35 CatalogueExplorer *m_CatalogueExplorer = nullptr;
36 QVector<std::shared_ptr<SelectionZoneAction> > m_CreateInCatalogueActions;
31
37
32 CatalogueActionManagerPrivate(CatalogueExplorer *catalogueExplorer)
38 CatalogueActionManagerPrivate(CatalogueExplorer *catalogueExplorer)
33 : m_CatalogueExplorer(catalogueExplorer)
39 : m_CatalogueExplorer(catalogueExplorer)
34 {
40 {
35 }
41 }
36
42
37 void createEventFromZones(const QString &eventName,
43 void createEventFromZones(const QString &eventName,
38 const QVector<VisualizationSelectionZoneItem *> &zones,
44 const QVector<VisualizationSelectionZoneItem *> &zones,
39 const std::shared_ptr<DBCatalogue> &catalogue = nullptr)
45 const std::shared_ptr<DBCatalogue> &catalogue = nullptr)
40 {
46 {
41 auto event = std::make_shared<DBEvent>();
47 auto event = std::make_shared<DBEvent>();
42 event->setName(eventName);
48 event->setName(eventName);
43
49
44 std::list<DBEventProduct> productList;
50 std::list<DBEventProduct> productList;
45 for (auto zone : zones) {
51 for (auto zone : zones) {
46 auto graph = zone->parentGraphWidget();
52 auto graph = zone->parentGraphWidget();
47 for (auto var : graph->variables()) {
53 for (auto var : graph->variables()) {
48 auto eventProduct = std::make_shared<DBEventProduct>();
54 auto eventProduct = std::make_shared<DBEventProduct>();
49 eventProduct->setEvent(*event);
55 eventProduct->setEvent(*event);
50
56
51 auto productId
57 auto productId
52 = var->metadata().value(DataSourceItem::ID_DATA_KEY, "UnknownID").toString();
58 = var->metadata().value(DataSourceItem::ID_DATA_KEY, "UnknownID").toString();
53
59
54 auto zoneRange = zone->range();
60 auto zoneRange = zone->range();
55 eventProduct->setTStart(zoneRange.m_TStart);
61 eventProduct->setTStart(zoneRange.m_TStart);
56 eventProduct->setTEnd(zoneRange.m_TEnd);
62 eventProduct->setTEnd(zoneRange.m_TEnd);
57
63
58 eventProduct->setProductId(productId);
64 eventProduct->setProductId(productId);
59
65
60 productList.push_back(*eventProduct);
66 productList.push_back(*eventProduct);
61 }
67 }
62 }
68 }
63
69
64 event->setEventProducts(productList);
70 event->setEventProducts(productList);
65
71
66 sqpApp->catalogueController().addEvent(event);
72 sqpApp->catalogueController().addEvent(event);
67
73
68
74
69 if (catalogue) {
75 if (catalogue) {
70 catalogue->addEvent(event->getUniqId());
76 catalogue->addEvent(event->getUniqId());
71 sqpApp->catalogueController().updateCatalogue(catalogue);
77 sqpApp->catalogueController().updateCatalogue(catalogue);
72 m_CatalogueExplorer->sideBarWidget().setCatalogueChanges(catalogue, true);
78 m_CatalogueExplorer->sideBarWidget().setCatalogueChanges(catalogue, true);
73 if (m_CatalogueExplorer->eventsWidget().displayedCatalogues().contains(catalogue)) {
79 if (m_CatalogueExplorer->eventsWidget().displayedCatalogues().contains(catalogue)) {
74 m_CatalogueExplorer->eventsWidget().addEvent(event);
80 m_CatalogueExplorer->eventsWidget().addEvent(event);
75 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
81 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
76 }
82 }
77 }
83 }
78 else if (m_CatalogueExplorer->eventsWidget().isAllEventsDisplayed()) {
84 else if (m_CatalogueExplorer->eventsWidget().isAllEventsDisplayed()) {
79 m_CatalogueExplorer->eventsWidget().addEvent(event);
85 m_CatalogueExplorer->eventsWidget().addEvent(event);
80 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
86 m_CatalogueExplorer->eventsWidget().setEventChanges(event, true);
81 }
87 }
82 }
88 }
83 };
84
89
85 CatalogueActionManager::CatalogueActionManager(CatalogueExplorer *catalogueExplorer)
90 SelectionZoneAction::EnableFunction createEventEnableFuntion() const
86 : impl{spimpl::make_unique_impl<CatalogueActionManagerPrivate>(catalogueExplorer)}
87 {
88 }
89
90 void CatalogueActionManager::installSelectionZoneActions()
91 {
91 {
92 auto &actionController = sqpApp->actionsGuiController();
92 return [](auto zones) {
93
94 auto createEventEnableFuntion = [](auto zones) {
95
93
96 // Checks that all variables in the zones doesn't refer to the same product
94 // Checks that all variables in the zones doesn't refer to the same product
97 QSet<QString> usedDatasource;
95 QSet<QString> usedDatasource;
98 for (auto zone : zones) {
96 for (auto zone : zones) {
99 auto graph = zone->parentGraphWidget();
97 auto graph = zone->parentGraphWidget();
100 auto variables = graph->variables();
98 auto variables = graph->variables();
101
99
102 for (auto var : variables) {
100 for (auto var : variables) {
103 auto datasourceId = var->metadata().value(DataSourceItem::ID_DATA_KEY).toString();
101 auto datasourceId
102 = var->metadata().value(DataSourceItem::ID_DATA_KEY).toString();
104 if (!usedDatasource.contains(datasourceId)) {
103 if (!usedDatasource.contains(datasourceId)) {
105 usedDatasource.insert(datasourceId);
104 usedDatasource.insert(datasourceId);
106 }
105 }
107 else {
106 else {
108 return false;
107 return false;
109 }
108 }
110 }
109 }
111 }
110 }
112
111
113 return true;
112 return true;
114 };
113 };
114 }
115 };
115
116
116 auto createEventAction = actionController.addSectionZoneAction(
117 CatalogueActionManager::CatalogueActionManager(CatalogueExplorer *catalogueExplorer)
117 {QObject::tr("Catalogues")}, QObject::tr("New Event..."), [this](auto zones) {
118 : impl{spimpl::make_unique_impl<CatalogueActionManagerPrivate>(catalogueExplorer)}
118 CreateEventDialog dialog(
119 {
119 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT));
120 dialog.hideCatalogueChoice();
121 if (dialog.exec() == QDialog::Accepted) {
122 impl->createEventFromZones(dialog.eventName(), zones);
123 }
120 }
124 });
125 createEventAction->setEnableFunction(createEventEnableFuntion);
126
121
127 auto createEventInCatalogueAction = actionController.addSectionZoneAction(
122 void CatalogueActionManager::installSelectionZoneActions()
128 {QObject::tr("Catalogues")}, QObject::tr("New Event in Catalogue..."), [this](auto zones) {
123 {
129 CreateEventDialog dialog(
124 auto &actionController = sqpApp->actionsGuiController();
130 impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT));
125
131 if (dialog.exec() == QDialog::Accepted) {
126 auto createEventAction = actionController.addSectionZoneAction(
132 auto selectedCatalogue = dialog.selectedCatalogue();
127 {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}, QObject::tr("Without Catalogue"),
133 if (!selectedCatalogue) {
128 [this](auto zones) { impl->createEventFromZones(DEFAULT_EVENT_NAME, zones); });
134 selectedCatalogue = std::make_shared<DBCatalogue>();
129 createEventAction->setEnableFunction(impl->createEventEnableFuntion());
135 selectedCatalogue->setName(dialog.catalogueName());
130 createEventAction->setAllowedFiltering(false);
136 sqpApp->catalogueController().addCatalogue(selectedCatalogue);
131
137 impl->m_CatalogueExplorer->sideBarWidget().addCatalogue(selectedCatalogue,
132 auto createEventInNewCatalogueAction = actionController.addSectionZoneAction(
133 {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME}, QObject::tr("In New Catalogue"),
134 [this](auto zones) {
135
136 auto newCatalogue = std::make_shared<DBCatalogue>();
137 newCatalogue->setName(DEFAULT_CATALOGUE_NAME);
138 sqpApp->catalogueController().addCatalogue(newCatalogue);
139 impl->m_CatalogueExplorer->sideBarWidget().addCatalogue(newCatalogue,
138 REPOSITORY_DEFAULT);
140 REPOSITORY_DEFAULT);
141
142 impl->createEventFromZones(DEFAULT_EVENT_NAME, zones, newCatalogue);
143 });
144 createEventInNewCatalogueAction->setEnableFunction(impl->createEventEnableFuntion());
145 createEventInNewCatalogueAction->setAllowedFiltering(false);
146
147 refreshCreateInCatalogueAction();
148
149 actionController.addFilterForMenu({CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME});
139 }
150 }
140
151
141 impl->createEventFromZones(dialog.eventName(), zones, selectedCatalogue);
152 void CatalogueActionManager::refreshCreateInCatalogueAction()
153 {
154 auto &actionController = sqpApp->actionsGuiController();
155
156 for (auto action : impl->m_CreateInCatalogueActions) {
157 actionController.removeAction(action);
142 }
158 }
159 impl->m_CreateInCatalogueActions.clear();
160
161 auto allCatalogues
162 = impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT);
163
164 for (auto catalogue : allCatalogues) {
165 auto catalogueName = catalogue->getName();
166 auto createEventInCatalogueAction = actionController.addSectionZoneAction(
167 {CATALOGUE_MENU_NAME, CATALOGUE_CREATE_EVENT_MENU_NAME},
168 QObject::tr("In \"").append(catalogueName).append("\""), [this, catalogue](auto zones) {
169 impl->createEventFromZones(DEFAULT_EVENT_NAME, zones, catalogue);
143 });
170 });
144 createEventInCatalogueAction->setEnableFunction(createEventEnableFuntion);
171 createEventInCatalogueAction->setEnableFunction(impl->createEventEnableFuntion());
172 impl->m_CreateInCatalogueActions << createEventInCatalogueAction;
173 }
145 }
174 }
@@ -1,629 +1,617
1 #include "Catalogue/CatalogueEventsWidget.h"
1 #include "Catalogue/CatalogueEventsWidget.h"
2 #include "ui_CatalogueEventsWidget.h"
2 #include "ui_CatalogueEventsWidget.h"
3
3
4 #include <Catalogue/CatalogueController.h>
4 #include <Catalogue/CatalogueController.h>
5 #include <Catalogue/CatalogueEventsModel.h>
5 #include <Catalogue/CatalogueEventsModel.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
7 #include <CatalogueDao.h>
7 #include <CatalogueDao.h>
8 #include <DBCatalogue.h>
8 #include <DBCatalogue.h>
9 #include <DBEventProduct.h>
9 #include <DBEventProduct.h>
10 #include <DataSource/DataSourceController.h>
10 #include <DataSource/DataSourceController.h>
11 #include <DataSource/DataSourceItem.h>
11 #include <DataSource/DataSourceItem.h>
12 #include <SqpApplication.h>
12 #include <SqpApplication.h>
13 #include <Variable/Variable.h>
13 #include <Variable/Variable.h>
14 #include <Variable/VariableController.h>
14 #include <Variable/VariableController.h>
15 #include <Visualization/VisualizationGraphWidget.h>
15 #include <Visualization/VisualizationGraphWidget.h>
16 #include <Visualization/VisualizationTabWidget.h>
16 #include <Visualization/VisualizationTabWidget.h>
17 #include <Visualization/VisualizationWidget.h>
17 #include <Visualization/VisualizationWidget.h>
18 #include <Visualization/VisualizationZoneWidget.h>
18 #include <Visualization/VisualizationZoneWidget.h>
19
19
20 #include <QActionGroup>
20 #include <QDialog>
21 #include <QDialog>
21 #include <QDialogButtonBox>
22 #include <QDialogButtonBox>
22 #include <QKeyEvent>
23 #include <QKeyEvent>
23 #include <QListWidget>
24 #include <QListWidget>
25 #include <QMenu>
24 #include <QMessageBox>
26 #include <QMessageBox>
25
27
26 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
28 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
27
29
28 /// Percentage added to the range of a event when it is displayed
30 /// Percentage added to the range of a event when it is displayed
29 const auto EVENT_RANGE_MARGE = 30; // in %
31 const auto EVENT_RANGE_MARGE = 30; // in %
30
32
33 const QString NEW_ZONE_TEXT = QStringLiteral("New Zone");
34
31 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
35 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
32
36
33 CatalogueEventsModel *m_Model = nullptr;
37 CatalogueEventsModel *m_Model = nullptr;
34 QStringList m_ZonesForTimeMode;
38 QStringList m_ZonesForTimeMode;
35 QString m_ZoneForGraphMode;
39 QString m_ZoneForGraphMode;
36 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
40 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
37 bool m_AllEventDisplayed = false;
41 bool m_AllEventDisplayed = false;
38 QVector<VisualizationGraphWidget *> m_CustomGraphs;
42 QVector<VisualizationGraphWidget *> m_CustomGraphs;
39
43
40 VisualizationWidget *m_VisualizationWidget = nullptr;
44 VisualizationWidget *m_VisualizationWidget = nullptr;
41
45
42 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
46 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
43 {
47 {
44 widget->ui->treeView->setSortingEnabled(false);
48 widget->ui->treeView->setSortingEnabled(false);
45 m_Model->setSourceCatalogues(m_DisplayedCatalogues);
49 m_Model->setSourceCatalogues(m_DisplayedCatalogues);
46 m_Model->setEvents(events);
50 m_Model->setEvents(events);
47 widget->ui->treeView->setSortingEnabled(true);
51 widget->ui->treeView->setSortingEnabled(true);
48
52
49 for (auto event : events) {
53 for (auto event : events) {
50 if (sqpApp->catalogueController().eventHasChanges(event)) {
54 if (sqpApp->catalogueController().eventHasChanges(event)) {
51 auto index = m_Model->indexOf(event);
55 auto index = m_Model->indexOf(event);
52 widget->setEventChanges(event, true);
56 widget->setEventChanges(event, true);
53 }
57 }
54 }
58 }
55 }
59 }
56
60
57 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
61 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
58 {
62 {
59 treeView->setSortingEnabled(false);
63 treeView->setSortingEnabled(false);
60 m_Model->addEvent(event);
64 m_Model->addEvent(event);
61 treeView->setSortingEnabled(true);
65 treeView->setSortingEnabled(true);
62 }
66 }
63
67
64 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
68 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
65 {
69 {
66 treeView->setSortingEnabled(false);
70 treeView->setSortingEnabled(false);
67 m_Model->removeEvent(event);
71 m_Model->removeEvent(event);
68 treeView->setSortingEnabled(true);
72 treeView->setSortingEnabled(true);
69 }
73 }
70
74
71 QStringList getAvailableVisualizationZoneList() const
75 QStringList getAvailableVisualizationZoneList() const
72 {
76 {
73 if (m_VisualizationWidget) {
77 if (m_VisualizationWidget) {
74 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
78 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
75 return tab->availableZoneWidgets();
79 return tab->availableZoneWidgets();
76 }
80 }
77 }
81 }
78
82
79 return QStringList{};
83 return QStringList{};
80 }
84 }
81
85
82 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
86 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
83 bool allowMultiSelection, const QPoint &location)
87 bool allowMultiSelection, bool addNewZoneOption, const QPoint &location)
84 {
88 {
85 auto availableZones = getAvailableVisualizationZoneList();
89 auto availableZones = getAvailableVisualizationZoneList();
86 if (availableZones.isEmpty()) {
90 if (!addNewZoneOption && availableZones.isEmpty()) {
87 return QStringList{};
91 return QStringList{};
88 }
92 }
89
93
90 QDialog d(parent, Qt::Tool);
94 QActionGroup actionGroup{parent};
91 d.setWindowTitle("Choose a zone");
95 actionGroup.setExclusive(!allowMultiSelection);
92 auto layout = new QVBoxLayout{&d};
93 layout->setContentsMargins(0, 0, 0, 0);
94 auto listWidget = new QListWidget{&d};
95 layout->addWidget(listWidget);
96
97 QSet<QListWidgetItem *> checkedItems;
98 for (auto zone : availableZones) {
99 auto item = new QListWidgetItem{zone};
100 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
101 if (selectedZones.contains(zone)) {
102 item->setCheckState(Qt::Checked);
103 checkedItems << item;
104 }
105 else {
106 item->setCheckState(Qt::Unchecked);
107 }
108
109 listWidget->addItem(item);
110 }
111
96
112 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
97 QVector<QAction *> zoneActions;
113 layout->addWidget(buttonBox);
114
98
115 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
99 QMenu selectionMenu{parent};
116 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
117
100
118 QObject::connect(listWidget, &QListWidget::itemChanged,
101 if (addNewZoneOption) {
119 [&checkedItems, allowMultiSelection, listWidget](auto item) {
102 availableZones.prepend(NEW_ZONE_TEXT);
120 if (item->checkState() == Qt::Checked) {
121 if (!allowMultiSelection) {
122 for (auto checkedItem : checkedItems) {
123 listWidget->blockSignals(true);
124 checkedItem->setCheckState(Qt::Unchecked);
125 listWidget->blockSignals(false);
126 }
103 }
127
104
128 checkedItems.clear();
105 selectionMenu.addSeparator();
129 }
106 for (auto zone : availableZones) {
130 checkedItems << item;
107 auto zoneAction = selectionMenu.addAction(zone);
131 }
108 zoneAction->setCheckable(true);
132 else {
109 zoneAction->setChecked(selectedZones.contains(zone));
133 checkedItems.remove(item);
110 actionGroup.addAction(zoneAction);
111 zoneActions << zoneAction;
134 }
112 }
135 });
113
114 auto resultAction = selectionMenu.exec(QCursor::pos());
136
115
137 QStringList result;
116 QStringList result;
138
117
139 d.setMinimumWidth(120);
118 if (resultAction == nullptr) {
140 d.resize(d.minimumSizeHint());
119 result = selectedZones;
141 d.move(location);
142 if (d.exec() == QDialog::Accepted) {
143 for (auto item : checkedItems) {
144 result += item->text();
145 }
146 }
120 }
147 else {
121 else {
148 result = selectedZones;
122 for (auto zoneAction : zoneActions) {
123 if (zoneAction->isChecked()) {
124 result << zoneAction->text();
125 }
126 }
149 }
127 }
150
128
151 return result;
129 return result;
152 }
130 }
153
131
154 void updateForTimeMode(QTreeView *treeView)
132 void updateForTimeMode(QTreeView *treeView)
155 {
133 {
156 auto selectedRows = treeView->selectionModel()->selectedRows();
134 auto selectedRows = treeView->selectionModel()->selectedRows();
157
135
158 if (selectedRows.count() == 1) {
136 if (selectedRows.count() == 1) {
159 auto event = m_Model->getEvent(selectedRows.first());
137 auto event = m_Model->getEvent(selectedRows.first());
160 if (event) {
138 if (event) {
161 if (m_VisualizationWidget) {
139 if (m_VisualizationWidget) {
162 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
140 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
163
141
164 for (auto zoneName : m_ZonesForTimeMode) {
142 for (auto zoneName : m_ZonesForTimeMode) {
165 if (auto zone = tab->getZoneWithName(zoneName)) {
143 if (auto zone = tab->getZoneWithName(zoneName)) {
166 SqpRange eventRange;
144 SqpRange eventRange;
167 eventRange.m_TStart = event->getTStart();
145 eventRange.m_TStart = event->getTStart();
168 eventRange.m_TEnd = event->getTEnd();
146 eventRange.m_TEnd = event->getTEnd();
169 zone->setZoneRange(eventRange);
147 zone->setZoneRange(eventRange);
170 }
148 }
171 }
149 }
172 }
150 }
173 else {
151 else {
174 qCWarning(LOG_CatalogueEventsWidget())
152 qCWarning(LOG_CatalogueEventsWidget())
175 << "updateTimeZone: no tab found in the visualization";
153 << "updateTimeZone: no tab found in the visualization";
176 }
154 }
177 }
155 }
178 else {
156 else {
179 qCWarning(LOG_CatalogueEventsWidget())
157 qCWarning(LOG_CatalogueEventsWidget())
180 << "updateTimeZone: visualization widget not found";
158 << "updateTimeZone: visualization widget not found";
181 }
159 }
182 }
160 }
183 }
161 }
184 else {
162 else {
185 qCWarning(LOG_CatalogueEventsWidget())
163 qCWarning(LOG_CatalogueEventsWidget())
186 << "updateTimeZone: not compatible with multiple events selected";
164 << "updateTimeZone: not compatible with multiple events selected";
187 }
165 }
188 }
166 }
189
167
190 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
168 QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event)
191 {
169 {
192 // Retrieves the range of each product and the maximum size
170 // Retrieves the range of each product and the maximum size
193 QVector<SqpRange> graphRanges;
171 QVector<SqpRange> graphRanges;
194 double maxDt = 0;
172 double maxDt = 0;
195 for (auto eventProduct : event->getEventProducts()) {
173 for (auto eventProduct : event->getEventProducts()) {
196 SqpRange eventRange;
174 SqpRange eventRange;
197 eventRange.m_TStart = eventProduct.getTStart();
175 eventRange.m_TStart = eventProduct.getTStart();
198 eventRange.m_TEnd = eventProduct.getTEnd();
176 eventRange.m_TEnd = eventProduct.getTEnd();
199 graphRanges << eventRange;
177 graphRanges << eventRange;
200
178
201 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
179 auto dt = eventRange.m_TEnd - eventRange.m_TStart;
202 if (dt > maxDt) {
180 if (dt > maxDt) {
203 maxDt = dt;
181 maxDt = dt;
204 }
182 }
205 }
183 }
206
184
207 // Adds the marge
185 // Adds the marge
208 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
186 maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0;
209
187
210 // Corrects the graph ranges so that they all have the same size
188 // Corrects the graph ranges so that they all have the same size
211 QVector<SqpRange> correctedGraphRanges;
189 QVector<SqpRange> correctedGraphRanges;
212 for (auto range : graphRanges) {
190 for (auto range : graphRanges) {
213 auto dt = range.m_TEnd - range.m_TStart;
191 auto dt = range.m_TEnd - range.m_TStart;
214 auto diff = qAbs((maxDt - dt) / 2.0);
192 auto diff = qAbs((maxDt - dt) / 2.0);
215
193
216 SqpRange correctedRange;
194 SqpRange correctedRange;
217 correctedRange.m_TStart = range.m_TStart - diff;
195 correctedRange.m_TStart = range.m_TStart - diff;
218 correctedRange.m_TEnd = range.m_TEnd + diff;
196 correctedRange.m_TEnd = range.m_TEnd + diff;
219
197
220 correctedGraphRanges << correctedRange;
198 correctedGraphRanges << correctedRange;
221 }
199 }
222
200
223 return correctedGraphRanges;
201 return correctedGraphRanges;
224 }
202 }
225
203
226 void updateForGraphMode(CatalogueEventsWidget *catalogueEventWidget)
204 void updateForGraphMode(CatalogueEventsWidget *catalogueEventWidget)
227 {
205 {
228 auto selectedRows = catalogueEventWidget->ui->treeView->selectionModel()->selectedRows();
206 auto selectedRows = catalogueEventWidget->ui->treeView->selectionModel()->selectedRows();
229 if (selectedRows.count() != 1) {
207 if (selectedRows.count() != 1) {
230 qCWarning(LOG_CatalogueEventsWidget())
208 qCWarning(LOG_CatalogueEventsWidget())
231 << "updateGraphMode: not compatible with multiple events selected";
209 << "updateGraphMode: not compatible with multiple events selected";
232 return;
210 return;
233 }
211 }
234
212
235 if (!m_VisualizationWidget) {
213 if (!m_VisualizationWidget) {
236 qCWarning(LOG_CatalogueEventsWidget())
214 qCWarning(LOG_CatalogueEventsWidget())
237 << "updateGraphMode: visualization widget not found";
215 << "updateGraphMode: visualization widget not found";
238 return;
216 return;
239 }
217 }
240
218
241 auto event = m_Model->getEvent(selectedRows.first());
219 auto event = m_Model->getEvent(selectedRows.first());
242 if (!event) {
220 if (!event) {
243 // A event product is probably selected
221 // A event product is probably selected
244 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
222 qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected";
245 return;
223 return;
246 }
224 }
247
225
248 auto tab = m_VisualizationWidget->currentTabWidget();
226 auto tab = m_VisualizationWidget->currentTabWidget();
249 if (!tab) {
227 if (!tab) {
250 qCWarning(LOG_CatalogueEventsWidget())
228 qCWarning(LOG_CatalogueEventsWidget())
251 << "updateGraphMode: no tab found in the visualization";
229 << "updateGraphMode: no tab found in the visualization";
252 return;
230 return;
253 }
231 }
254
232
233 auto isNewZone = m_ZoneForGraphMode == NEW_ZONE_TEXT;
255 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
234 auto zone = tab->getZoneWithName(m_ZoneForGraphMode);
256 if (!zone) {
235 if (!isNewZone && !zone) {
257 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
236 qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found";
258 return;
237 return;
259 }
238 }
260
239
261 // Closes the previous graph and delete the asociated variables
240 // Closes the previous graph and delete the asociated variables
262 for (auto graph : m_CustomGraphs) {
241 for (auto graph : m_CustomGraphs) {
263 graph->close();
242 graph->close();
264 auto variables = graph->variables().toVector();
243 auto variables = graph->variables().toVector();
265
244
266 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
245 QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables",
267 Qt::QueuedConnection,
246 Qt::QueuedConnection,
268 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
247 Q_ARG(QVector<std::shared_ptr<Variable> >, variables));
269 }
248 }
270 m_CustomGraphs.clear();
249 m_CustomGraphs.clear();
271
250
272 // Closes the remaining graphs inside the zone
251 // Closes the remaining graphs inside the zone
252 if (zone) {
273 zone->closeAllGraphs();
253 zone->closeAllGraphs();
254 }
255
256 // Creates the zone if needed
257 if (isNewZone) {
258 zone = tab->createEmptyZone(0);
259 m_ZoneForGraphMode = zone->name();
260 }
274
261
275 // Calculates the range of each graph which will be created
262 // Calculates the range of each graph which will be created
276 auto graphRange = getGraphRanges(event);
263 auto graphRange = getGraphRanges(event);
277
264
278 // Loops through the event products and create the graph
265 // Loops through the event products and create the graph
279 auto itRange = graphRange.cbegin();
266 auto itRange = graphRange.cbegin();
280 for (auto eventProduct : event->getEventProducts()) {
267 for (auto eventProduct : event->getEventProducts()) {
281 auto productId = eventProduct.getProductId();
268 auto productId = eventProduct.getProductId();
282
269
283 auto range = *itRange;
270 auto range = *itRange;
284 ++itRange;
271 ++itRange;
285
272
286 SqpRange productRange;
273 SqpRange productRange;
287 productRange.m_TStart = eventProduct.getTStart();
274 productRange.m_TStart = eventProduct.getTStart();
288 productRange.m_TEnd = eventProduct.getTEnd();
275 productRange.m_TEnd = eventProduct.getTEnd();
289
276
290 auto context = new QObject{catalogueEventWidget};
277 auto context = new QObject{catalogueEventWidget};
291 QObject::connect(
278 QObject::connect(
292 &sqpApp->variableController(), &VariableController::variableAdded, context,
279 &sqpApp->variableController(), &VariableController::variableAdded, context,
293 [this, catalogueEventWidget, zone, context, event, range, productRange,
280 [this, catalogueEventWidget, zone, context, event, range, productRange,
294 productId](auto variable) {
281 productId](auto variable) {
295
282
296 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
283 if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString()
297 == productId) {
284 == productId) {
298 auto graph = zone->createGraph(variable);
285 auto graph = zone->createGraph(variable);
299 graph->setAutoRangeOnVariableInitialization(false);
286 graph->setAutoRangeOnVariableInitialization(false);
300
287
301 auto selectionZone
288 auto selectionZone
302 = graph->addSelectionZone(event->getName(), productRange);
289 = graph->addSelectionZone(event->getName(), productRange);
303 emit catalogueEventWidget->selectionZoneAdded(event, productId,
290 emit catalogueEventWidget->selectionZoneAdded(event, productId,
304 selectionZone);
291 selectionZone);
305 m_CustomGraphs << graph;
292 m_CustomGraphs << graph;
306
293
307 graph->setGraphRange(range, true);
294 graph->setGraphRange(range, true);
308
295
309 // Removes the graph from the graph list if it is closed manually
296 // Removes the graph from the graph list if it is closed manually
310 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
297 QObject::connect(graph, &VisualizationGraphWidget::destroyed,
311 [this, graph]() { m_CustomGraphs.removeAll(graph); });
298 [this, graph]() { m_CustomGraphs.removeAll(graph); });
312
299
313 delete context; // removes the connection
300 delete context; // removes the connection
314 }
301 }
315 },
302 },
316 Qt::QueuedConnection);
303 Qt::QueuedConnection);
317
304
318 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
305 QMetaObject::invokeMethod(&sqpApp->dataSourceController(),
319 "requestVariableFromProductIdKey", Qt::QueuedConnection,
306 "requestVariableFromProductIdKey", Qt::QueuedConnection,
320 Q_ARG(QString, productId));
307 Q_ARG(QString, productId));
321 }
308 }
322 }
309 }
323
310
324 void getSelectedItems(
311 void getSelectedItems(
325 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
312 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
326 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
313 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
327 {
314 {
328 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
315 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
329 auto itemType = m_Model->itemTypeOf(rowIndex);
316 auto itemType = m_Model->itemTypeOf(rowIndex);
330 if (itemType == CatalogueEventsModel::ItemType::Event) {
317 if (itemType == CatalogueEventsModel::ItemType::Event) {
331 events << m_Model->getEvent(rowIndex);
318 events << m_Model->getEvent(rowIndex);
332 }
319 }
333 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
320 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
334 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
321 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
335 m_Model->getEventProduct(rowIndex));
322 m_Model->getEventProduct(rowIndex));
336 }
323 }
337 }
324 }
338 }
325 }
339 };
326 };
340
327
341 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
328 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
342 : QWidget(parent),
329 : QWidget(parent),
343 ui(new Ui::CatalogueEventsWidget),
330 ui(new Ui::CatalogueEventsWidget),
344 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
331 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
345 {
332 {
346 ui->setupUi(this);
333 ui->setupUi(this);
347
334
348 impl->m_Model = new CatalogueEventsModel{this};
335 impl->m_Model = new CatalogueEventsModel{this};
349 ui->treeView->setModel(impl->m_Model);
336 ui->treeView->setModel(impl->m_Model);
350
337
351 ui->treeView->setSortingEnabled(true);
338 ui->treeView->setSortingEnabled(true);
352 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
339 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
353 ui->treeView->setDragEnabled(true);
340 ui->treeView->setDragEnabled(true);
354
341
355
342
356 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
343 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
357 if (checked) {
344 if (checked) {
358 ui->btnChart->setChecked(false);
345 ui->btnChart->setChecked(false);
359 impl->m_ZonesForTimeMode
346 impl->m_ZonesForTimeMode
360 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
347 = impl->selectZone(this, impl->m_ZonesForTimeMode, true, false,
361 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
348 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
362
349
363 impl->updateForTimeMode(ui->treeView);
350 impl->updateForTimeMode(ui->treeView);
364 }
351 }
365 });
352 });
366
353
367 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
354 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
368 if (checked) {
355 if (checked) {
369 ui->btnTime->setChecked(false);
356 ui->btnTime->setChecked(false);
357
370 impl->m_ZoneForGraphMode
358 impl->m_ZoneForGraphMode
371 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
359 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false, true,
372 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
360 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
373 .value(0);
361 .value(0);
374
362
375 impl->updateForGraphMode(this);
363 impl->updateForGraphMode(this);
376 }
364 }
377 });
365 });
378
366
379 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
367 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
380 QVector<std::shared_ptr<DBEvent> > events;
368 QVector<std::shared_ptr<DBEvent> > events;
381 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
369 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
382 impl->getSelectedItems(ui->treeView, events, eventProducts);
370 impl->getSelectedItems(ui->treeView, events, eventProducts);
383
371
384 if (!events.isEmpty() && eventProducts.isEmpty()) {
372 if (!events.isEmpty() && eventProducts.isEmpty()) {
385
373
386 auto canRemoveEvent
374 auto canRemoveEvent
387 = !this->isAllEventsDisplayed()
375 = !this->isAllEventsDisplayed()
388 || (QMessageBox::warning(
376 || (QMessageBox::warning(
389 this, tr("Remove Event(s)"),
377 this, tr("Remove Event(s)"),
390 tr("The selected event(s) will be permanently removed "
378 tr("The selected event(s) will be permanently removed "
391 "from the repository!\nAre you sure you want to continue?"),
379 "from the repository!\nAre you sure you want to continue?"),
392 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
380 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
393 == QMessageBox::Yes);
381 == QMessageBox::Yes);
394
382
395 if (canRemoveEvent) {
383 if (canRemoveEvent) {
396 for (auto event : events) {
384 for (auto event : events) {
397 if (this->isAllEventsDisplayed()) {
385 if (this->isAllEventsDisplayed()) {
398 sqpApp->catalogueController().removeEvent(event);
386 sqpApp->catalogueController().removeEvent(event);
399 impl->removeEvent(event, ui->treeView);
387 impl->removeEvent(event, ui->treeView);
400 }
388 }
401 else {
389 else {
402 QVector<std::shared_ptr<DBCatalogue> > modifiedCatalogues;
390 QVector<std::shared_ptr<DBCatalogue> > modifiedCatalogues;
403 for (auto catalogue : this->displayedCatalogues()) {
391 for (auto catalogue : this->displayedCatalogues()) {
404 if (catalogue->removeEvent(event->getUniqId())) {
392 if (catalogue->removeEvent(event->getUniqId())) {
405 sqpApp->catalogueController().updateCatalogue(catalogue);
393 sqpApp->catalogueController().updateCatalogue(catalogue);
406 modifiedCatalogues << catalogue;
394 modifiedCatalogues << catalogue;
407 }
395 }
408 }
396 }
409 if (!modifiedCatalogues.empty()) {
397 if (!modifiedCatalogues.empty()) {
410 emit eventCataloguesModified(modifiedCatalogues);
398 emit eventCataloguesModified(modifiedCatalogues);
411 }
399 }
412 }
400 }
413 impl->m_Model->removeEvent(event);
401 impl->m_Model->removeEvent(event);
414 }
402 }
415
403
416
404
417 emit this->eventsRemoved(events);
405 emit this->eventsRemoved(events);
418 }
406 }
419 }
407 }
420 });
408 });
421
409
422 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
410 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
423 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
411 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
424 &CatalogueEventsWidget::emitSelection);
412 &CatalogueEventsWidget::emitSelection);
425
413
426 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
414 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
427 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
415 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
428 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
416 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
429 ui->btnChart->setEnabled(isNotMultiSelection);
417 ui->btnChart->setEnabled(isNotMultiSelection);
430 ui->btnTime->setEnabled(isNotMultiSelection);
418 ui->btnTime->setEnabled(isNotMultiSelection);
431
419
432 if (isNotMultiSelection && ui->btnTime->isChecked()) {
420 if (isNotMultiSelection && ui->btnTime->isChecked()) {
433 impl->updateForTimeMode(ui->treeView);
421 impl->updateForTimeMode(ui->treeView);
434 }
422 }
435 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
423 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
436 impl->updateForGraphMode(this);
424 impl->updateForGraphMode(this);
437 }
425 }
438
426
439 QVector<std::shared_ptr<DBEvent> > events;
427 QVector<std::shared_ptr<DBEvent> > events;
440 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
428 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
441 impl->getSelectedItems(ui->treeView, events, eventProducts);
429 impl->getSelectedItems(ui->treeView, events, eventProducts);
442 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
430 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
443 });
431 });
444
432
445 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
433 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
446 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
434 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
447 QHeaderView::Stretch);
435 QHeaderView::Stretch);
448 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
436 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
449 QHeaderView::ResizeToContents);
437 QHeaderView::ResizeToContents);
450 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
438 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
451 QHeaderView::Interactive);
439 QHeaderView::Interactive);
452 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::TStart,
440 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::TStart,
453 QHeaderView::ResizeToContents);
441 QHeaderView::ResizeToContents);
454 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::TEnd,
442 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::TEnd,
455 QHeaderView::ResizeToContents);
443 QHeaderView::ResizeToContents);
456 ui->treeView->header()->setSortIndicatorShown(true);
444 ui->treeView->header()->setSortIndicatorShown(true);
457
445
458 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
446 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
459 auto allEvents = impl->m_Model->events();
447 auto allEvents = impl->m_Model->events();
460 for (auto event : allEvents) {
448 for (auto event : allEvents) {
461 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
449 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
462 }
450 }
463 });
451 });
464
452
465 populateWithAllEvents();
453 populateWithAllEvents();
466 }
454 }
467
455
468 CatalogueEventsWidget::~CatalogueEventsWidget()
456 CatalogueEventsWidget::~CatalogueEventsWidget()
469 {
457 {
470 delete ui;
458 delete ui;
471 }
459 }
472
460
473 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
461 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
474 {
462 {
475 impl->m_VisualizationWidget = visualization;
463 impl->m_VisualizationWidget = visualization;
476 }
464 }
477
465
478 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
466 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
479 {
467 {
480 impl->addEvent(event, ui->treeView);
468 impl->addEvent(event, ui->treeView);
481 }
469 }
482
470
483 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
471 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
484 {
472 {
485 impl->m_Model->refreshEvent(event);
473 impl->m_Model->refreshEvent(event);
486
474
487 auto eventIndex = impl->m_Model->indexOf(event);
475 auto eventIndex = impl->m_Model->indexOf(event);
488 auto validationIndex
476 auto validationIndex
489 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
477 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
490
478
491 if (validationIndex.isValid()) {
479 if (validationIndex.isValid()) {
492 if (hasChanges) {
480 if (hasChanges) {
493 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
481 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
494 auto widget = CatalogueExplorerHelper::buildValidationWidget(
482 auto widget = CatalogueExplorerHelper::buildValidationWidget(
495 ui->treeView,
483 ui->treeView,
496 [this, event]() {
484 [this, event]() {
497 sqpApp->catalogueController().saveEvent(event);
485 sqpApp->catalogueController().saveEvent(event);
498 setEventChanges(event, false);
486 setEventChanges(event, false);
499 },
487 },
500 [this, event]() {
488 [this, event]() {
501 bool removed = false;
489 bool removed = false;
502 sqpApp->catalogueController().discardEvent(event, removed);
490 sqpApp->catalogueController().discardEvent(event, removed);
503 if (removed) {
491 if (removed) {
504 impl->m_Model->removeEvent(event);
492 impl->m_Model->removeEvent(event);
505 }
493 }
506 else {
494 else {
507 setEventChanges(event, false);
495 setEventChanges(event, false);
508 impl->m_Model->refreshEvent(event, true);
496 impl->m_Model->refreshEvent(event, true);
509 }
497 }
510 emitSelection();
498 emitSelection();
511 });
499 });
512 ui->treeView->setIndexWidget(validationIndex, widget);
500 ui->treeView->setIndexWidget(validationIndex, widget);
513 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
501 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
514 QHeaderView::ResizeToContents);
502 QHeaderView::ResizeToContents);
515 }
503 }
516 }
504 }
517 else {
505 else {
518 // Note: the widget is destroyed
506 // Note: the widget is destroyed
519 ui->treeView->setIndexWidget(validationIndex, nullptr);
507 ui->treeView->setIndexWidget(validationIndex, nullptr);
520 }
508 }
521 }
509 }
522 else {
510 else {
523 qCWarning(LOG_CatalogueEventsWidget())
511 qCWarning(LOG_CatalogueEventsWidget())
524 << "setEventChanges: the event is not displayed in the model.";
512 << "setEventChanges: the event is not displayed in the model.";
525 }
513 }
526 }
514 }
527
515
528 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
516 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
529 {
517 {
530 return impl->m_DisplayedCatalogues;
518 return impl->m_DisplayedCatalogues;
531 }
519 }
532
520
533 bool CatalogueEventsWidget::isAllEventsDisplayed() const
521 bool CatalogueEventsWidget::isAllEventsDisplayed() const
534 {
522 {
535 return impl->m_AllEventDisplayed;
523 return impl->m_AllEventDisplayed;
536 }
524 }
537
525
538 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
526 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
539 {
527 {
540 return impl->m_Model->indexOf(event).isValid();
528 return impl->m_Model->indexOf(event).isValid();
541 }
529 }
542
530
543 void CatalogueEventsWidget::refreshEvent(const std::shared_ptr<DBEvent> &event)
531 void CatalogueEventsWidget::refreshEvent(const std::shared_ptr<DBEvent> &event)
544 {
532 {
545 impl->m_Model->refreshEvent(event, true);
533 impl->m_Model->refreshEvent(event, true);
546 }
534 }
547
535
548 void CatalogueEventsWidget::populateWithCatalogues(
536 void CatalogueEventsWidget::populateWithCatalogues(
549 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
537 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
550 {
538 {
551 impl->m_DisplayedCatalogues = catalogues;
539 impl->m_DisplayedCatalogues = catalogues;
552 impl->m_AllEventDisplayed = false;
540 impl->m_AllEventDisplayed = false;
553
541
554 QSet<QUuid> eventIds;
542 QSet<QUuid> eventIds;
555 QVector<std::shared_ptr<DBEvent> > events;
543 QVector<std::shared_ptr<DBEvent> > events;
556
544
557 for (auto catalogue : catalogues) {
545 for (auto catalogue : catalogues) {
558 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
546 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
559 for (auto event : catalogueEvents) {
547 for (auto event : catalogueEvents) {
560 if (!eventIds.contains(event->getUniqId())) {
548 if (!eventIds.contains(event->getUniqId())) {
561 events << event;
549 events << event;
562 eventIds.insert(event->getUniqId());
550 eventIds.insert(event->getUniqId());
563 }
551 }
564 }
552 }
565 }
553 }
566
554
567 impl->setEvents(events, this);
555 impl->setEvents(events, this);
568 }
556 }
569
557
570 void CatalogueEventsWidget::populateWithAllEvents()
558 void CatalogueEventsWidget::populateWithAllEvents()
571 {
559 {
572 impl->m_DisplayedCatalogues.clear();
560 impl->m_DisplayedCatalogues.clear();
573 impl->m_AllEventDisplayed = true;
561 impl->m_AllEventDisplayed = true;
574
562
575 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
563 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
576
564
577 QVector<std::shared_ptr<DBEvent> > events;
565 QVector<std::shared_ptr<DBEvent> > events;
578 for (auto event : allEvents) {
566 for (auto event : allEvents) {
579 events << event;
567 events << event;
580 }
568 }
581
569
582 impl->setEvents(events, this);
570 impl->setEvents(events, this);
583 }
571 }
584
572
585 void CatalogueEventsWidget::clear()
573 void CatalogueEventsWidget::clear()
586 {
574 {
587 impl->m_DisplayedCatalogues.clear();
575 impl->m_DisplayedCatalogues.clear();
588 impl->m_AllEventDisplayed = false;
576 impl->m_AllEventDisplayed = false;
589 impl->setEvents({}, this);
577 impl->setEvents({}, this);
590 }
578 }
591
579
592 void CatalogueEventsWidget::refresh()
580 void CatalogueEventsWidget::refresh()
593 {
581 {
594 if (isAllEventsDisplayed()) {
582 if (isAllEventsDisplayed()) {
595 populateWithAllEvents();
583 populateWithAllEvents();
596 }
584 }
597 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
585 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
598 populateWithCatalogues(impl->m_DisplayedCatalogues);
586 populateWithCatalogues(impl->m_DisplayedCatalogues);
599 }
587 }
600 }
588 }
601
589
602 void CatalogueEventsWidget::emitSelection()
590 void CatalogueEventsWidget::emitSelection()
603 {
591 {
604 QVector<std::shared_ptr<DBEvent> > events;
592 QVector<std::shared_ptr<DBEvent> > events;
605 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
593 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
606 impl->getSelectedItems(ui->treeView, events, eventProducts);
594 impl->getSelectedItems(ui->treeView, events, eventProducts);
607
595
608 if (!events.isEmpty() && eventProducts.isEmpty()) {
596 if (!events.isEmpty() && eventProducts.isEmpty()) {
609 emit eventsSelected(events);
597 emit eventsSelected(events);
610 }
598 }
611 else if (events.isEmpty() && !eventProducts.isEmpty()) {
599 else if (events.isEmpty() && !eventProducts.isEmpty()) {
612 emit eventProductsSelected(eventProducts);
600 emit eventProductsSelected(eventProducts);
613 }
601 }
614 else {
602 else {
615 emit selectionCleared();
603 emit selectionCleared();
616 }
604 }
617 }
605 }
618
606
619
607
620 void CatalogueEventsWidget::keyPressEvent(QKeyEvent *event)
608 void CatalogueEventsWidget::keyPressEvent(QKeyEvent *event)
621 {
609 {
622 switch (event->key()) {
610 switch (event->key()) {
623 case Qt::Key_Delete: {
611 case Qt::Key_Delete: {
624 ui->btnRemove->click();
612 ui->btnRemove->click();
625 }
613 }
626 default:
614 default:
627 break;
615 break;
628 }
616 }
629 }
617 }
@@ -1,203 +1,207
1 #include "Catalogue/CatalogueExplorer.h"
1 #include "Catalogue/CatalogueExplorer.h"
2 #include "ui_CatalogueExplorer.h"
2 #include "ui_CatalogueExplorer.h"
3
3
4 #include <Catalogue/CatalogueActionManager.h>
4 #include <Catalogue/CatalogueActionManager.h>
5 #include <Catalogue/CatalogueController.h>
5 #include <Catalogue/CatalogueController.h>
6 #include <SqpApplication.h>
6 #include <SqpApplication.h>
7 #include <Visualization/VisualizationGraphWidget.h>
7 #include <Visualization/VisualizationGraphWidget.h>
8 #include <Visualization/VisualizationSelectionZoneItem.h>
8 #include <Visualization/VisualizationSelectionZoneItem.h>
9 #include <Visualization/VisualizationWidget.h>
9 #include <Visualization/VisualizationWidget.h>
10
10
11 #include <DBCatalogue.h>
11 #include <DBCatalogue.h>
12 #include <DBEvent.h>
12 #include <DBEvent.h>
13 #include <DBEventProduct.h>
13 #include <DBEventProduct.h>
14
14
15 #include <unordered_map>
15 #include <unordered_map>
16
16
17 struct CatalogueExplorer::CatalogueExplorerPrivate {
17 struct CatalogueExplorer::CatalogueExplorerPrivate {
18 CatalogueActionManager m_ActionManager;
18 CatalogueActionManager m_ActionManager;
19 std::unordered_map<std::shared_ptr<DBEvent>, QVector<VisualizationSelectionZoneItem *> >
19 std::unordered_map<std::shared_ptr<DBEvent>, QVector<VisualizationSelectionZoneItem *> >
20 m_SelectionZonesPerEvents;
20 m_SelectionZonesPerEvents;
21
21
22 QMetaObject::Connection m_Conn;
22 QMetaObject::Connection m_Conn;
23
23
24 CatalogueExplorerPrivate(CatalogueExplorer *catalogueExplorer)
24 CatalogueExplorerPrivate(CatalogueExplorer *catalogueExplorer)
25 : m_ActionManager(catalogueExplorer)
25 : m_ActionManager(catalogueExplorer)
26 {
26 {
27 }
27 }
28 };
28 };
29
29
30 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
30 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
31 : QDialog(parent, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
31 : QDialog(parent, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
32 ui(new Ui::CatalogueExplorer),
32 ui(new Ui::CatalogueExplorer),
33 impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>(this)}
33 impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>(this)}
34 {
34 {
35 ui->setupUi(this);
35 ui->setupUi(this);
36
36
37 impl->m_ActionManager.installSelectionZoneActions();
37 impl->m_ActionManager.installSelectionZoneActions();
38
38
39 // Updates events and inspector when something is selected in the catalogue widget
39 // Updates events and inspector when something is selected in the catalogue widget
40 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) {
40 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) {
41 if (catalogues.count() == 1) {
41 if (catalogues.count() == 1) {
42 ui->inspector->setCatalogue(catalogues.first());
42 ui->inspector->setCatalogue(catalogues.first());
43 }
43 }
44 else {
44 else {
45 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
45 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
46 }
46 }
47
47
48 ui->events->populateWithCatalogues(catalogues);
48 ui->events->populateWithCatalogues(catalogues);
49 });
49 });
50
50
51 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databases) {
51 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databases) {
52 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
52 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
53 });
53 });
54
54
55 connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected, [this]() {
55 connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected, [this]() {
56 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
56 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
57 ui->events->clear();
57 ui->events->clear();
58 });
58 });
59
59
60 connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected, [this]() {
60 connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected, [this]() {
61 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
61 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
62 ui->events->populateWithAllEvents();
62 ui->events->populateWithAllEvents();
63 });
63 });
64
64
65 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databaseList) {
65 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databaseList) {
66 QVector<std::shared_ptr<DBCatalogue> > catalogueList;
66 QVector<std::shared_ptr<DBCatalogue> > catalogueList;
67 for (auto database : databaseList) {
67 for (auto database : databaseList) {
68 catalogueList.append(ui->catalogues->getCatalogues(database));
68 catalogueList.append(ui->catalogues->getCatalogues(database));
69 }
69 }
70 ui->events->populateWithCatalogues(catalogueList);
70 ui->events->populateWithCatalogues(catalogueList);
71 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
71 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
72 });
72 });
73
73
74 connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared, [this]() {
74 connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared, [this]() {
75 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
75 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
76 ui->events->clear();
76 ui->events->clear();
77 });
77 });
78
78
79 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSaved, ui->events,
79 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSaved, ui->events,
80 &CatalogueEventsWidget::refresh);
80 &CatalogueEventsWidget::refresh);
81
81
82 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueListChanged,
83 [this]() { impl->m_ActionManager.refreshCreateInCatalogueAction(); });
84
82 // Updates the inspectot when something is selected in the events
85 // Updates the inspectot when something is selected in the events
83 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
86 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
84 if (events.count() == 1) {
87 if (events.count() == 1) {
85 ui->inspector->setEvent(events.first());
88 ui->inspector->setEvent(events.first());
86 }
89 }
87 else {
90 else {
88 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
91 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
89 }
92 }
90 });
93 });
91
94
92 connect(ui->events, &CatalogueEventsWidget::eventProductsSelected, [this](auto eventProducts) {
95 connect(ui->events, &CatalogueEventsWidget::eventProductsSelected, [this](auto eventProducts) {
93 if (eventProducts.count() == 1) {
96 if (eventProducts.count() == 1) {
94 ui->inspector->setEventProduct(eventProducts.first().first,
97 ui->inspector->setEventProduct(eventProducts.first().first,
95 eventProducts.first().second);
98 eventProducts.first().second);
96 }
99 }
97 else {
100 else {
98 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
101 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
99 }
102 }
100 });
103 });
101
104
102 connect(ui->events, &CatalogueEventsWidget::selectionCleared,
105 connect(ui->events, &CatalogueEventsWidget::selectionCleared,
103 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
106 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
104
107
105 // Manage Selection Zones associated to events
108 // Manage Selection Zones associated to events
106 connect(ui->events, &CatalogueEventsWidget::selectionZoneAdded,
109 connect(ui->events, &CatalogueEventsWidget::selectionZoneAdded,
107 [this](auto event, auto productId, auto zone) {
110 [this](auto event, auto productId, auto zone) {
108 this->addSelectionZoneItem(event, productId, zone);
111 this->addSelectionZoneItem(event, productId, zone);
109 });
112 });
110
113
111 connect(ui->events, &CatalogueEventsWidget::eventsRemoved, [this](auto events) {
114 connect(ui->events, &CatalogueEventsWidget::eventsRemoved, [this](auto events) {
112 for (auto event : events) {
115 for (auto event : events) {
113 auto associatedSelectionZonesIt = impl->m_SelectionZonesPerEvents.find(event);
116 auto associatedSelectionZonesIt = impl->m_SelectionZonesPerEvents.find(event);
114 if (associatedSelectionZonesIt != impl->m_SelectionZonesPerEvents.cend()) {
117 if (associatedSelectionZonesIt != impl->m_SelectionZonesPerEvents.cend()) {
115 for (auto selectionZone : associatedSelectionZonesIt->second) {
118 for (auto selectionZone : associatedSelectionZonesIt->second) {
116 auto parentGraph = selectionZone->parentGraphWidget();
119 auto parentGraph = selectionZone->parentGraphWidget();
117 parentGraph->removeSelectionZone(selectionZone);
120 parentGraph->removeSelectionZone(selectionZone);
118 }
121 }
119
122
120 impl->m_SelectionZonesPerEvents.erase(event);
123 impl->m_SelectionZonesPerEvents.erase(event);
121 }
124 }
122 }
125 }
123 });
126 });
124
127
125 // Updates changes from the inspector
128 // Updates changes from the inspector
126 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) {
129 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) {
127 sqpApp->catalogueController().updateCatalogue(catalogue);
130 sqpApp->catalogueController().updateCatalogue(catalogue);
128 ui->catalogues->setCatalogueChanges(catalogue, true);
131 ui->catalogues->setCatalogueChanges(catalogue, true);
132 impl->m_ActionManager.refreshCreateInCatalogueAction();
129 });
133 });
130
134
131 connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, [this](auto event) {
135 connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, [this](auto event) {
132 sqpApp->catalogueController().updateEvent(event);
136 sqpApp->catalogueController().updateEvent(event);
133 ui->events->setEventChanges(event, true);
137 ui->events->setEventChanges(event, true);
134 });
138 });
135
139
136 connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated,
140 connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated,
137 [this](auto event, auto eventProduct) {
141 [this](auto event, auto eventProduct) {
138 sqpApp->catalogueController().updateEventProduct(eventProduct);
142 sqpApp->catalogueController().updateEventProduct(eventProduct);
139 ui->events->setEventChanges(event, true);
143 ui->events->setEventChanges(event, true);
140 });
144 });
141
145
142 connect(ui->events, &CatalogueEventsWidget::eventCataloguesModified,
146 connect(ui->events, &CatalogueEventsWidget::eventCataloguesModified,
143 [this](const QVector<std::shared_ptr<DBCatalogue> > &catalogues) {
147 [this](const QVector<std::shared_ptr<DBCatalogue> > &catalogues) {
144 for (auto catalogue : catalogues) {
148 for (auto catalogue : catalogues) {
145 ui->catalogues->setCatalogueChanges(catalogue, true);
149 ui->catalogues->setCatalogueChanges(catalogue, true);
146 }
150 }
147 });
151 });
148 }
152 }
149
153
150 CatalogueExplorer::~CatalogueExplorer()
154 CatalogueExplorer::~CatalogueExplorer()
151 {
155 {
152 disconnect(impl->m_Conn);
156 disconnect(impl->m_Conn);
153 delete ui;
157 delete ui;
154 }
158 }
155
159
156 void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization)
160 void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization)
157 {
161 {
158 ui->events->setVisualizationWidget(visualization);
162 ui->events->setVisualizationWidget(visualization);
159 }
163 }
160
164
161 CatalogueEventsWidget &CatalogueExplorer::eventsWidget() const
165 CatalogueEventsWidget &CatalogueExplorer::eventsWidget() const
162 {
166 {
163 return *ui->events;
167 return *ui->events;
164 }
168 }
165
169
166 CatalogueSideBarWidget &CatalogueExplorer::sideBarWidget() const
170 CatalogueSideBarWidget &CatalogueExplorer::sideBarWidget() const
167 {
171 {
168 return *ui->catalogues;
172 return *ui->catalogues;
169 }
173 }
170
174
171 void CatalogueExplorer::clearSelectionZones()
175 void CatalogueExplorer::clearSelectionZones()
172 {
176 {
173 impl->m_SelectionZonesPerEvents.clear();
177 impl->m_SelectionZonesPerEvents.clear();
174 }
178 }
175
179
176 void CatalogueExplorer::addSelectionZoneItem(const std::shared_ptr<DBEvent> &event,
180 void CatalogueExplorer::addSelectionZoneItem(const std::shared_ptr<DBEvent> &event,
177 const QString &productId,
181 const QString &productId,
178 VisualizationSelectionZoneItem *selectionZone)
182 VisualizationSelectionZoneItem *selectionZone)
179 {
183 {
180 impl->m_SelectionZonesPerEvents[event] << selectionZone;
184 impl->m_SelectionZonesPerEvents[event] << selectionZone;
181 connect(selectionZone, &VisualizationSelectionZoneItem::rangeEdited,
185 connect(selectionZone, &VisualizationSelectionZoneItem::rangeEdited,
182 [event, productId, this](auto range) {
186 [event, productId, this](auto range) {
183 auto productList = event->getEventProducts();
187 auto productList = event->getEventProducts();
184 for (auto &product : productList) {
188 for (auto &product : productList) {
185 if (product.getProductId() == productId) {
189 if (product.getProductId() == productId) {
186 product.setTStart(range.m_TStart);
190 product.setTStart(range.m_TStart);
187 product.setTEnd(range.m_TEnd);
191 product.setTEnd(range.m_TEnd);
188 }
192 }
189 }
193 }
190 event->setEventProducts(productList);
194 event->setEventProducts(productList);
191 sqpApp->catalogueController().updateEvent(event);
195 sqpApp->catalogueController().updateEvent(event);
192 ui->events->refreshEvent(event);
196 ui->events->refreshEvent(event);
193 ui->events->setEventChanges(event, true);
197 ui->events->setEventChanges(event, true);
194 ui->inspector->refresh();
198 ui->inspector->refresh();
195 });
199 });
196
200
197 impl->m_Conn = connect(selectionZone, &VisualizationSelectionZoneItem::destroyed,
201 impl->m_Conn = connect(selectionZone, &VisualizationSelectionZoneItem::destroyed,
198 [event, selectionZone, this]() {
202 [event, selectionZone, this]() {
199 if (!impl->m_SelectionZonesPerEvents.empty()) {
203 if (!impl->m_SelectionZonesPerEvents.empty()) {
200 impl->m_SelectionZonesPerEvents[event].removeAll(selectionZone);
204 impl->m_SelectionZonesPerEvents[event].removeAll(selectionZone);
201 }
205 }
202 });
206 });
203 }
207 }
@@ -1,447 +1,461
1 #include "Catalogue/CatalogueSideBarWidget.h"
1 #include "Catalogue/CatalogueSideBarWidget.h"
2 #include "ui_CatalogueSideBarWidget.h"
2 #include "ui_CatalogueSideBarWidget.h"
3 #include <SqpApplication.h>
3 #include <SqpApplication.h>
4
4
5 #include <Catalogue/CatalogueController.h>
5 #include <Catalogue/CatalogueController.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
7 #include <Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.h>
7 #include <Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.h>
8 #include <Catalogue/CatalogueTreeItems/CatalogueTreeItem.h>
8 #include <Catalogue/CatalogueTreeItems/CatalogueTreeItem.h>
9 #include <Catalogue/CatalogueTreeModel.h>
9 #include <Catalogue/CatalogueTreeModel.h>
10 #include <CatalogueDao.h>
10 #include <CatalogueDao.h>
11 #include <Common/MimeTypesDef.h>
11 #include <Common/MimeTypesDef.h>
12 #include <ComparaisonPredicate.h>
12 #include <ComparaisonPredicate.h>
13 #include <DBCatalogue.h>
13 #include <DBCatalogue.h>
14
14
15 #include <QKeyEvent>
15 #include <QKeyEvent>
16 #include <QMenu>
16 #include <QMenu>
17 #include <QMessageBox>
17 #include <QMessageBox>
18 #include <QMimeData>
18 #include <QMimeData>
19
19
20 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
20 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
21
21
22
22
23 constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
23 constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1;
24 constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
24 constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2;
25 constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
25 constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3;
26 constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
26 constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4;
27
27
28 const auto DEFAULT_CATALOGUE_NAME = QObject::tr("Catalogue");
29
28
30
29 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
31 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
30
32
31 CatalogueTreeModel *m_TreeModel = nullptr;
33 CatalogueTreeModel *m_TreeModel = nullptr;
32
34
33 void configureTreeWidget(QTreeView *treeView);
35 void configureTreeWidget(QTreeView *treeView);
34 QModelIndex addDatabaseItem(const QString &name);
36 QModelIndex addDatabaseItem(const QString &name);
35 CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
37 CatalogueAbstractTreeItem *getDatabaseItem(const QString &name);
36 CatalogueAbstractTreeItem *addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
38 CatalogueAbstractTreeItem *addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
37 const QModelIndex &databaseIndex);
39 const QModelIndex &databaseIndex);
38
40
39 CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
41 CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const;
40 void setHasChanges(bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget);
42 void setHasChanges(bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget);
41 bool hasChanges(const QModelIndex &index, QTreeView *treeView);
43 bool hasChanges(const QModelIndex &index, QTreeView *treeView);
42
44
43 int selectionType(QTreeView *treeView) const
45 int selectionType(QTreeView *treeView) const
44 {
46 {
45 auto selectedItems = treeView->selectionModel()->selectedRows();
47 auto selectedItems = treeView->selectionModel()->selectedRows();
46 if (selectedItems.isEmpty()) {
48 if (selectedItems.isEmpty()) {
47 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
49 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
48 }
50 }
49 else {
51 else {
50 auto firstIndex = selectedItems.first();
52 auto firstIndex = selectedItems.first();
51 auto firstItem = m_TreeModel->item(firstIndex);
53 auto firstItem = m_TreeModel->item(firstIndex);
52 if (!firstItem) {
54 if (!firstItem) {
53 Q_ASSERT(false);
55 Q_ASSERT(false);
54 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
56 return CatalogueAbstractTreeItem::DEFAULT_TYPE;
55 }
57 }
56 auto selectionType = firstItem->type();
58 auto selectionType = firstItem->type();
57
59
58 for (auto itemIndex : selectedItems) {
60 for (auto itemIndex : selectedItems) {
59 auto item = m_TreeModel->item(itemIndex);
61 auto item = m_TreeModel->item(itemIndex);
60 if (!item || item->type() != selectionType) {
62 if (!item || item->type() != selectionType) {
61 // Incoherent multi selection
63 // Incoherent multi selection
62 selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE;
64 selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE;
63 break;
65 break;
64 }
66 }
65 }
67 }
66
68
67 return selectionType;
69 return selectionType;
68 }
70 }
69 }
71 }
70
72
71 QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const
73 QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const
72 {
74 {
73 QVector<std::shared_ptr<DBCatalogue> > catalogues;
75 QVector<std::shared_ptr<DBCatalogue> > catalogues;
74 auto selectedItems = treeView->selectionModel()->selectedRows();
76 auto selectedItems = treeView->selectionModel()->selectedRows();
75 for (auto itemIndex : selectedItems) {
77 for (auto itemIndex : selectedItems) {
76 auto item = m_TreeModel->item(itemIndex);
78 auto item = m_TreeModel->item(itemIndex);
77 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
79 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
78 catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
80 catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue());
79 }
81 }
80 }
82 }
81
83
82 return catalogues;
84 return catalogues;
83 }
85 }
84
86
85 QStringList selectedRepositories(QTreeView *treeView) const
87 QStringList selectedRepositories(QTreeView *treeView) const
86 {
88 {
87 QStringList repositories;
89 QStringList repositories;
88 auto selectedItems = treeView->selectionModel()->selectedRows();
90 auto selectedItems = treeView->selectionModel()->selectedRows();
89 for (auto itemIndex : selectedItems) {
91 for (auto itemIndex : selectedItems) {
90 auto item = m_TreeModel->item(itemIndex);
92 auto item = m_TreeModel->item(itemIndex);
91 if (item && item->type() == DATABASE_ITEM_TYPE) {
93 if (item && item->type() == DATABASE_ITEM_TYPE) {
92 repositories.append(item->text());
94 repositories.append(item->text());
93 }
95 }
94 }
96 }
95
97
96 return repositories;
98 return repositories;
97 }
99 }
98 };
100 };
99
101
100 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
102 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
101 : QWidget(parent),
103 : QWidget(parent),
102 ui(new Ui::CatalogueSideBarWidget),
104 ui(new Ui::CatalogueSideBarWidget),
103 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
105 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
104 {
106 {
105 ui->setupUi(this);
107 ui->setupUi(this);
106
108
107 impl->m_TreeModel = new CatalogueTreeModel(this);
109 impl->m_TreeModel = new CatalogueTreeModel(this);
108 ui->treeView->setModel(impl->m_TreeModel);
110 ui->treeView->setModel(impl->m_TreeModel);
109
111
110 impl->configureTreeWidget(ui->treeView);
112 impl->configureTreeWidget(ui->treeView);
113 emit catalogueListChanged();
111
114
112 ui->treeView->header()->setStretchLastSection(false);
115 ui->treeView->header()->setStretchLastSection(false);
113 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
116 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
114 ui->treeView->header()->setSectionResizeMode((int)CatalogueTreeModel::Column::Name,
117 ui->treeView->header()->setSectionResizeMode((int)CatalogueTreeModel::Column::Name,
115 QHeaderView::Stretch);
118 QHeaderView::Stretch);
116
119
117 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueSideBarWidget::emitSelection);
120 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueSideBarWidget::emitSelection);
118 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this,
121 connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this,
119 &CatalogueSideBarWidget::emitSelection);
122 &CatalogueSideBarWidget::emitSelection);
120
123
121
124
122 connect(ui->btnAdd, &QToolButton::clicked, [this]() {
125 connect(ui->btnAdd, &QToolButton::clicked, [this]() {
123 auto catalogue = std::make_shared<DBCatalogue>();
126 auto catalogue = std::make_shared<DBCatalogue>();
124 catalogue->setName(QString("Cat"));
127 catalogue->setName(DEFAULT_CATALOGUE_NAME);
125 sqpApp->catalogueController().addCatalogue(catalogue);
128 sqpApp->catalogueController().addCatalogue(catalogue);
126 auto item = this->addCatalogue(catalogue, REPOSITORY_DEFAULT);
129 auto item = this->addCatalogue(catalogue, REPOSITORY_DEFAULT);
127 this->setCatalogueChanges(catalogue, true);
130 this->setCatalogueChanges(catalogue, true);
128 ui->treeView->edit(impl->m_TreeModel->indexOf(item));
131 ui->treeView->edit(impl->m_TreeModel->indexOf(item));
129
132
130 });
133 });
131
134
132
135
133 connect(impl->m_TreeModel, &CatalogueTreeModel::itemDropped,
136 connect(impl->m_TreeModel, &CatalogueTreeModel::itemDropped,
134 [this](auto index, auto mimeData, auto action) {
137 [this](auto index, auto mimeData, auto action) {
135 auto item = impl->m_TreeModel->item(index);
138 auto item = impl->m_TreeModel->item(index);
139
136 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
140 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
137 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
141 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
138 this->setCatalogueChanges(catalogue, true);
142 this->setCatalogueChanges(catalogue, true);
139 }
143 }
140
144
141 if (action == Qt::MoveAction) {
145 if (action == Qt::MoveAction) {
142 /// Display a save button on source catalogues
146 /// Display a save button on source catalogues
143 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
147 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
144 mimeData->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
148 mimeData->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
145 for (auto catalogue : sourceCatalogues) {
149 for (auto catalogue : sourceCatalogues) {
146 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
150 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
151 catalogueItem->replaceCatalogue(catalogue);
147 this->setCatalogueChanges(catalogue, true);
152 this->setCatalogueChanges(catalogue, true);
148 }
153 }
149 }
154 }
155
156 this->emitSelection();
150 }
157 }
151 });
158 });
152
159
153 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
160 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
154 QVector<QPair<std::shared_ptr<DBCatalogue>, CatalogueAbstractTreeItem *> >
161 QVector<QPair<std::shared_ptr<DBCatalogue>, CatalogueAbstractTreeItem *> >
155 cataloguesToItems;
162 cataloguesToItems;
156 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
163 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
157
164
158 for (auto index : selectedIndexes) {
165 for (auto index : selectedIndexes) {
159 auto item = impl->m_TreeModel->item(index);
166 auto item = impl->m_TreeModel->item(index);
160 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
167 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
161 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
168 auto catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
162 cataloguesToItems << qMakePair(catalogue, item);
169 cataloguesToItems << qMakePair(catalogue, item);
163 }
170 }
164 }
171 }
165
172
166 if (!cataloguesToItems.isEmpty()) {
173 if (!cataloguesToItems.isEmpty()) {
167
174
168 if (QMessageBox::warning(this, tr("Remove Catalogue(s)"),
175 if (QMessageBox::warning(this, tr("Remove Catalogue(s)"),
169 tr("The selected catalogues(s) will be completly removed "
176 tr("The selected catalogues(s) will be completly removed "
170 "from the repository!\nAre you sure you want to continue?"),
177 "from the repository!\nAre you sure you want to continue?"),
171 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
178 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
172 == QMessageBox::Yes) {
179 == QMessageBox::Yes) {
173
180
174 for (auto catalogueToItem : cataloguesToItems) {
181 for (auto catalogueToItem : cataloguesToItems) {
175 sqpApp->catalogueController().removeCatalogue(catalogueToItem.first);
182 sqpApp->catalogueController().removeCatalogue(catalogueToItem.first);
176 impl->m_TreeModel->removeChildItem(
183 impl->m_TreeModel->removeChildItem(
177 catalogueToItem.second,
184 catalogueToItem.second,
178 impl->m_TreeModel->indexOf(catalogueToItem.second->parent()));
185 impl->m_TreeModel->indexOf(catalogueToItem.second->parent()));
179 }
186 }
180 emitSelection();
187 emitSelection();
188 emit catalogueListChanged();
181 }
189 }
182 }
190 }
183 });
191 });
184
192
185 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [this](auto index) {
193 connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [this](auto index) {
186 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
194 auto selectedIndexes = ui->treeView->selectionModel()->selectedRows();
187 if (selectedIndexes.contains(index)) {
195 if (selectedIndexes.contains(index)) {
188 this->emitSelection();
196 this->emitSelection();
189 }
197 }
190 impl->setHasChanges(true, index, this);
198 impl->setHasChanges(true, index, this);
199 emit this->catalogueListChanged();
191 });
200 });
192
201
193 ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
202 ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
194 connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
203 connect(ui->treeView, &QTreeView::customContextMenuRequested, this,
195 &CatalogueSideBarWidget::onContextMenuRequested);
204 &CatalogueSideBarWidget::onContextMenuRequested);
196 }
205 }
197
206
198 CatalogueSideBarWidget::~CatalogueSideBarWidget()
207 CatalogueSideBarWidget::~CatalogueSideBarWidget()
199 {
208 {
200 delete ui;
209 delete ui;
201 }
210 }
202
211
203 CatalogueAbstractTreeItem *
212 CatalogueAbstractTreeItem *
204 CatalogueSideBarWidget::addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
213 CatalogueSideBarWidget::addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue,
205 const QString &repository)
214 const QString &repository)
206 {
215 {
207 auto repositoryItem = impl->getDatabaseItem(repository);
216 auto repositoryItem = impl->getDatabaseItem(repository);
208 return impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem));
217 auto catalogueItem
218 = impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem));
219
220 emit catalogueListChanged();
221
222 return catalogueItem;
209 }
223 }
210
224
211 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
225 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
212 bool hasChanges)
226 bool hasChanges)
213 {
227 {
214 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
228 if (auto catalogueItem = impl->getCatalogueItem(catalogue)) {
215 auto index = impl->m_TreeModel->indexOf(catalogueItem);
229 auto index = impl->m_TreeModel->indexOf(catalogueItem);
216 impl->setHasChanges(hasChanges, index, this);
230 impl->setHasChanges(hasChanges, index, this);
217 // catalogueItem->refresh();
231 // catalogueItem->refresh();
218 }
232 }
219 }
233 }
220
234
221 QVector<std::shared_ptr<DBCatalogue> >
235 QVector<std::shared_ptr<DBCatalogue> >
222 CatalogueSideBarWidget::getCatalogues(const QString &repository) const
236 CatalogueSideBarWidget::getCatalogues(const QString &repository) const
223 {
237 {
224 QVector<std::shared_ptr<DBCatalogue> > result;
238 QVector<std::shared_ptr<DBCatalogue> > result;
225 auto repositoryItem = impl->getDatabaseItem(repository);
239 auto repositoryItem = impl->getDatabaseItem(repository);
226 for (auto child : repositoryItem->children()) {
240 for (auto child : repositoryItem->children()) {
227 if (child->type() == CATALOGUE_ITEM_TYPE) {
241 if (child->type() == CATALOGUE_ITEM_TYPE) {
228 auto catalogueItem = static_cast<CatalogueTreeItem *>(child);
242 auto catalogueItem = static_cast<CatalogueTreeItem *>(child);
229 result << catalogueItem->catalogue();
243 result << catalogueItem->catalogue();
230 }
244 }
231 else {
245 else {
232 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogues: invalid structure";
246 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogues: invalid structure";
233 }
247 }
234 }
248 }
235
249
236 return result;
250 return result;
237 }
251 }
238
252
239 void CatalogueSideBarWidget::emitSelection()
253 void CatalogueSideBarWidget::emitSelection()
240 {
254 {
241 auto selectionType = impl->selectionType(ui->treeView);
255 auto selectionType = impl->selectionType(ui->treeView);
242
256
243 switch (selectionType) {
257 switch (selectionType) {
244 case CATALOGUE_ITEM_TYPE:
258 case CATALOGUE_ITEM_TYPE:
245 emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView));
259 emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView));
246 break;
260 break;
247 case DATABASE_ITEM_TYPE:
261 case DATABASE_ITEM_TYPE:
248 emit this->databaseSelected(impl->selectedRepositories(ui->treeView));
262 emit this->databaseSelected(impl->selectedRepositories(ui->treeView));
249 break;
263 break;
250 case ALL_EVENT_ITEM_TYPE:
264 case ALL_EVENT_ITEM_TYPE:
251 emit this->allEventsSelected();
265 emit this->allEventsSelected();
252 break;
266 break;
253 case TRASH_ITEM_TYPE:
267 case TRASH_ITEM_TYPE:
254 emit this->trashSelected();
268 emit this->trashSelected();
255 break;
269 break;
256 default:
270 default:
257 emit this->selectionCleared();
271 emit this->selectionCleared();
258 break;
272 break;
259 }
273 }
260 }
274 }
261
275
262 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
276 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
263 {
277 {
264 QMenu menu{this};
278 QMenu menu{this};
265
279
266 auto currentIndex = ui->treeView->currentIndex();
280 auto currentIndex = ui->treeView->currentIndex();
267 auto currentItem = impl->m_TreeModel->item(currentIndex);
281 auto currentItem = impl->m_TreeModel->item(currentIndex);
268 if (!currentItem) {
282 if (!currentItem) {
269 return;
283 return;
270 }
284 }
271
285
272 switch (currentItem->type()) {
286 switch (currentItem->type()) {
273 case CATALOGUE_ITEM_TYPE:
287 case CATALOGUE_ITEM_TYPE:
274 menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
288 menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); });
275 break;
289 break;
276 case DATABASE_ITEM_TYPE:
290 case DATABASE_ITEM_TYPE:
277 break;
291 break;
278 case ALL_EVENT_ITEM_TYPE:
292 case ALL_EVENT_ITEM_TYPE:
279 break;
293 break;
280 case TRASH_ITEM_TYPE:
294 case TRASH_ITEM_TYPE:
281 menu.addAction("Empty Trash", []() {
295 menu.addAction("Empty Trash", []() {
282 // TODO
296 // TODO
283 });
297 });
284 break;
298 break;
285 default:
299 default:
286 break;
300 break;
287 }
301 }
288
302
289 if (!menu.isEmpty()) {
303 if (!menu.isEmpty()) {
290 menu.exec(ui->treeView->mapToGlobal(pos));
304 menu.exec(ui->treeView->mapToGlobal(pos));
291 }
305 }
292 }
306 }
293
307
294 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
308 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView)
295 {
309 {
296 auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
310 auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events",
297 ALL_EVENT_ITEM_TYPE};
311 ALL_EVENT_ITEM_TYPE};
298 auto allEventIndex = m_TreeModel->addTopLevelItem(allEventsItem);
312 auto allEventIndex = m_TreeModel->addTopLevelItem(allEventsItem);
299 treeView->setCurrentIndex(allEventIndex);
313 treeView->setCurrentIndex(allEventIndex);
300
314
301 auto trashItem
315 auto trashItem
302 = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
316 = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE};
303 m_TreeModel->addTopLevelItem(trashItem);
317 m_TreeModel->addTopLevelItem(trashItem);
304
318
305 auto separator = new QFrame{treeView};
319 auto separator = new QFrame{treeView};
306 separator->setFrameShape(QFrame::HLine);
320 separator->setFrameShape(QFrame::HLine);
307 auto separatorItem
321 auto separatorItem
308 = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
322 = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE};
309 separatorItem->setEnabled(false);
323 separatorItem->setEnabled(false);
310 auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
324 auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem);
311 treeView->setIndexWidget(separatorIndex, separator);
325 treeView->setIndexWidget(separatorIndex, separator);
312
326
313 auto repositories = sqpApp->catalogueController().getRepositories();
327 auto repositories = sqpApp->catalogueController().getRepositories();
314 for (auto dbname : repositories) {
328 for (auto dbname : repositories) {
315 auto dbIndex = addDatabaseItem(dbname);
329 auto dbIndex = addDatabaseItem(dbname);
316 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
330 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
317 for (auto catalogue : catalogues) {
331 for (auto catalogue : catalogues) {
318 addCatalogueItem(catalogue, dbIndex);
332 addCatalogueItem(catalogue, dbIndex);
319 }
333 }
320 }
334 }
321
335
322 treeView->expandAll();
336 treeView->expandAll();
323 }
337 }
324
338
325 QModelIndex
339 QModelIndex
326 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
340 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name)
327 {
341 {
328 auto databaseItem
342 auto databaseItem
329 = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
343 = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE};
330 auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
344 auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem);
331
345
332 return databaseIndex;
346 return databaseIndex;
333 }
347 }
334
348
335 CatalogueAbstractTreeItem *
349 CatalogueAbstractTreeItem *
336 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
350 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name)
337 {
351 {
338 for (auto item : m_TreeModel->topLevelItems()) {
352 for (auto item : m_TreeModel->topLevelItems()) {
339 if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
353 if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) {
340 return item;
354 return item;
341 }
355 }
342 }
356 }
343
357
344 return nullptr;
358 return nullptr;
345 }
359 }
346
360
347 CatalogueAbstractTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
361 CatalogueAbstractTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
348 const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
362 const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex)
349 {
363 {
350 auto catalogueItem
364 auto catalogueItem
351 = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
365 = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE};
352 m_TreeModel->addChildItem(catalogueItem, databaseIndex);
366 m_TreeModel->addChildItem(catalogueItem, databaseIndex);
353
367
354 return catalogueItem;
368 return catalogueItem;
355 }
369 }
356
370
357 CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
371 CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
358 const std::shared_ptr<DBCatalogue> &catalogue) const
372 const std::shared_ptr<DBCatalogue> &catalogue) const
359 {
373 {
360 for (auto item : m_TreeModel->topLevelItems()) {
374 for (auto item : m_TreeModel->topLevelItems()) {
361 if (item->type() == DATABASE_ITEM_TYPE) {
375 if (item->type() == DATABASE_ITEM_TYPE) {
362 for (auto childItem : item->children()) {
376 for (auto childItem : item->children()) {
363 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
377 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
364 auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
378 auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem);
365 if (catalogueItem->catalogue()->getUniqId() == catalogue->getUniqId()) {
379 if (catalogueItem->catalogue()->getUniqId() == catalogue->getUniqId()) {
366 return catalogueItem;
380 return catalogueItem;
367 }
381 }
368 }
382 }
369 else {
383 else {
370 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
384 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
371 "structure. A database item should "
385 "structure. A database item should "
372 "only contain catalogues.";
386 "only contain catalogues.";
373 Q_ASSERT(false);
387 Q_ASSERT(false);
374 }
388 }
375 }
389 }
376 }
390 }
377 }
391 }
378
392
379 return nullptr;
393 return nullptr;
380 }
394 }
381
395
382 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(
396 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(
383 bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget)
397 bool value, const QModelIndex &index, CatalogueSideBarWidget *sideBarWidget)
384 {
398 {
385 std::shared_ptr<DBCatalogue> catalogue = nullptr;
399 std::shared_ptr<DBCatalogue> catalogue = nullptr;
386 auto item = m_TreeModel->item(index);
400 auto item = m_TreeModel->item(index);
387 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
401 if (item && item->type() == CATALOGUE_ITEM_TYPE) {
388 catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
402 catalogue = static_cast<CatalogueTreeItem *>(item)->catalogue();
389 }
403 }
390
404
391 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
405 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
392 if (value) {
406 if (value) {
393 if (!hasChanges(validationIndex, sideBarWidget->ui->treeView)) {
407 if (!hasChanges(validationIndex, sideBarWidget->ui->treeView)) {
394 auto widget = CatalogueExplorerHelper::buildValidationWidget(
408 auto widget = CatalogueExplorerHelper::buildValidationWidget(
395 sideBarWidget->ui->treeView,
409 sideBarWidget->ui->treeView,
396 [this, validationIndex, sideBarWidget, catalogue]() {
410 [this, validationIndex, sideBarWidget, catalogue]() {
397 if (catalogue) {
411 if (catalogue) {
398 sqpApp->catalogueController().saveCatalogue(catalogue);
412 sqpApp->catalogueController().saveCatalogue(catalogue);
399 emit sideBarWidget->catalogueSaved(catalogue);
413 emit sideBarWidget->catalogueSaved(catalogue);
400 }
414 }
401 setHasChanges(false, validationIndex, sideBarWidget);
415 setHasChanges(false, validationIndex, sideBarWidget);
402 },
416 },
403 [this, validationIndex, sideBarWidget, catalogue, item]() {
417 [this, validationIndex, sideBarWidget, catalogue, item]() {
404 if (catalogue) {
418 if (catalogue) {
405 bool removed;
419 bool removed;
406 sqpApp->catalogueController().discardCatalogue(catalogue, removed);
420 sqpApp->catalogueController().discardCatalogue(catalogue, removed);
407
421
408 if (removed) {
422 if (removed) {
409 m_TreeModel->removeChildItem(item,
423 m_TreeModel->removeChildItem(item,
410 m_TreeModel->indexOf(item->parent()));
424 m_TreeModel->indexOf(item->parent()));
411 }
425 }
412 else {
426 else {
413 m_TreeModel->refresh(m_TreeModel->indexOf(item));
427 m_TreeModel->refresh(m_TreeModel->indexOf(item));
414 setHasChanges(false, validationIndex, sideBarWidget);
428 setHasChanges(false, validationIndex, sideBarWidget);
415 }
429 }
416 sideBarWidget->emitSelection();
430 sideBarWidget->emitSelection();
417 }
431 }
418 });
432 });
419 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, widget);
433 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, widget);
420 sideBarWidget->ui->treeView->header()->resizeSection(
434 sideBarWidget->ui->treeView->header()->resizeSection(
421 (int)CatalogueTreeModel::Column::Validation, QHeaderView::ResizeToContents);
435 (int)CatalogueTreeModel::Column::Validation, QHeaderView::ResizeToContents);
422 }
436 }
423 }
437 }
424 else {
438 else {
425 // Note: the widget is destroyed
439 // Note: the widget is destroyed
426 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, nullptr);
440 sideBarWidget->ui->treeView->setIndexWidget(validationIndex, nullptr);
427 }
441 }
428 }
442 }
429
443
430 bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
444 bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index,
431 QTreeView *treeView)
445 QTreeView *treeView)
432 {
446 {
433 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
447 auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation);
434 return treeView->indexWidget(validationIndex) != nullptr;
448 return treeView->indexWidget(validationIndex) != nullptr;
435 }
449 }
436
450
437
451
438 void CatalogueSideBarWidget::keyPressEvent(QKeyEvent *event)
452 void CatalogueSideBarWidget::keyPressEvent(QKeyEvent *event)
439 {
453 {
440 switch (event->key()) {
454 switch (event->key()) {
441 case Qt::Key_Delete: {
455 case Qt::Key_Delete: {
442 ui->btnRemove->click();
456 ui->btnRemove->click();
443 }
457 }
444 default:
458 default:
445 break;
459 break;
446 }
460 }
447 }
461 }
@@ -1,126 +1,131
1 #include "Catalogue/CatalogueTreeItems/CatalogueTreeItem.h"
1 #include "Catalogue/CatalogueTreeItems/CatalogueTreeItem.h"
2 #include <Catalogue/CatalogueExplorerHelper.h>
2 #include <Catalogue/CatalogueExplorerHelper.h>
3
3
4 #include <Catalogue/CatalogueController.h>
4 #include <Catalogue/CatalogueController.h>
5 #include <Common/MimeTypesDef.h>
5 #include <Common/MimeTypesDef.h>
6 #include <QIcon>
6 #include <QIcon>
7 #include <QMimeData>
7 #include <QMimeData>
8 #include <SqpApplication.h>
8 #include <SqpApplication.h>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 #include <DBCatalogue.h>
12 #include <DBCatalogue.h>
13
13
14 struct CatalogueTreeItem::CatalogueTreeItemPrivate {
14 struct CatalogueTreeItem::CatalogueTreeItemPrivate {
15
15
16 std::shared_ptr<DBCatalogue> m_Catalogue;
16 std::shared_ptr<DBCatalogue> m_Catalogue;
17 QIcon m_Icon;
17 QIcon m_Icon;
18
18
19 CatalogueTreeItemPrivate(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon)
19 CatalogueTreeItemPrivate(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon)
20 : m_Catalogue(catalogue), m_Icon(icon)
20 : m_Catalogue(catalogue), m_Icon(icon)
21 {
21 {
22 }
22 }
23 };
23 };
24
24
25
25
26 CatalogueTreeItem::CatalogueTreeItem(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon,
26 CatalogueTreeItem::CatalogueTreeItem(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon,
27 int type)
27 int type)
28 : CatalogueAbstractTreeItem(type),
28 : CatalogueAbstractTreeItem(type),
29 impl{spimpl::make_unique_impl<CatalogueTreeItemPrivate>(catalogue, icon)}
29 impl{spimpl::make_unique_impl<CatalogueTreeItemPrivate>(catalogue, icon)}
30 {
30 {
31 }
31 }
32
32
33 QVariant CatalogueTreeItem::data(int column, int role) const
33 QVariant CatalogueTreeItem::data(int column, int role) const
34 {
34 {
35 if (column == 0) {
35 if (column == 0) {
36 switch (role) {
36 switch (role) {
37 case Qt::EditRole: // fallthrough
37 case Qt::EditRole: // fallthrough
38 case Qt::DisplayRole:
38 case Qt::DisplayRole:
39 return impl->m_Catalogue->getName();
39 return impl->m_Catalogue->getName();
40 case Qt::DecorationRole:
40 case Qt::DecorationRole:
41 return impl->m_Icon;
41 return impl->m_Icon;
42 default:
42 default:
43 break;
43 break;
44 }
44 }
45 }
45 }
46
46
47 return QVariant();
47 return QVariant();
48 }
48 }
49
49
50 bool CatalogueTreeItem::setData(int column, int role, const QVariant &value)
50 bool CatalogueTreeItem::setData(int column, int role, const QVariant &value)
51 {
51 {
52 bool result = false;
52 bool result = false;
53
53
54 if (role == Qt::EditRole && column == 0) {
54 if (role == Qt::EditRole && column == 0) {
55 auto newName = value.toString();
55 auto newName = value.toString();
56 if (newName != impl->m_Catalogue->getName()) {
56 if (newName != impl->m_Catalogue->getName()) {
57 impl->m_Catalogue->setName(newName);
57 impl->m_Catalogue->setName(newName);
58 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
58 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
59 result = true;
59 result = true;
60 }
60 }
61 }
61 }
62
62
63 return result;
63 return result;
64 }
64 }
65
65
66 Qt::ItemFlags CatalogueTreeItem::flags(int column) const
66 Qt::ItemFlags CatalogueTreeItem::flags(int column) const
67 {
67 {
68 if (column == 0) {
68 if (column == 0) {
69 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable
69 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable
70 | Qt::ItemIsDropEnabled;
70 | Qt::ItemIsDropEnabled;
71 }
71 }
72 else {
72 else {
73 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
73 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
74 }
74 }
75 }
75 }
76
76
77 bool CatalogueTreeItem::canDropMimeData(const QMimeData *data, Qt::DropAction action)
77 bool CatalogueTreeItem::canDropMimeData(const QMimeData *data, Qt::DropAction action)
78 {
78 {
79 // Check that the event is not dropped on the same catalogue
79 // Check that the event is not dropped on the same catalogue
80 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
80 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
81 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
81 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
82 for (auto catalogue : sourceCatalogues) {
82 for (auto catalogue : sourceCatalogues) {
83 if (catalogue->getUniqId() == impl->m_Catalogue->getUniqId()) {
83 if (catalogue->getUniqId() == impl->m_Catalogue->getUniqId()) {
84 return false;
84 return false;
85 }
85 }
86 }
86 }
87
87
88 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
88 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
89 auto canDrop = data->hasFormat(MIME_TYPE_EVENT_LIST);
89 auto canDrop = data->hasFormat(MIME_TYPE_EVENT_LIST);
90
90
91 for (auto event : events) {
91 for (auto event : events) {
92 canDrop &= (event->getRepository() == impl->m_Catalogue->getRepository());
92 canDrop &= (event->getRepository() == impl->m_Catalogue->getRepository());
93 }
93 }
94
94
95 return canDrop;
95 return canDrop;
96 }
96 }
97
97
98 bool CatalogueTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action)
98 bool CatalogueTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action)
99 {
99 {
100 Q_ASSERT(canDropMimeData(data, action));
100 Q_ASSERT(canDropMimeData(data, action));
101 // Warning: Check that the events aren't already in the catalogue
101 // Warning: Check that the events aren't already in the catalogue
102 // No need to check check for the repository: inter-repository drop is forbidden in
102 // No need to check check for the repository: inter-repository drop is forbidden in
103 // canDropMimeData
103 // canDropMimeData
104
104
105 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
105 auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST));
106 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
106 auto sourceCatalogues = sqpApp->catalogueController().cataloguesForMimeData(
107 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
107 data->data(MIME_TYPE_SOURCE_CATALOGUE_LIST));
108
108
109 for (auto event : events) {
109 for (auto event : events) {
110
110
111 if (action == Qt::MoveAction) {
111 if (action == Qt::MoveAction) {
112 for (auto catalogue : sourceCatalogues) {
112 for (auto catalogue : sourceCatalogues) {
113 catalogue->removeEvent(event->getUniqId());
113 catalogue->removeEvent(event->getUniqId());
114 sqpApp->catalogueController().updateCatalogue(catalogue);
114 sqpApp->catalogueController().updateCatalogue(catalogue);
115 }
115 }
116 }
116 }
117
117
118 impl->m_Catalogue->addEvent(event->getUniqId());
118 impl->m_Catalogue->addEvent(event->getUniqId());
119 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
119 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
120 }
120 }
121 }
121 }
122
122
123 std::shared_ptr<DBCatalogue> CatalogueTreeItem::catalogue() const
123 std::shared_ptr<DBCatalogue> CatalogueTreeItem::catalogue() const
124 {
124 {
125 return impl->m_Catalogue;
125 return impl->m_Catalogue;
126 }
126 }
127
128 void CatalogueTreeItem::replaceCatalogue(const std::shared_ptr<DBCatalogue> &catalogue)
129 {
130 impl->m_Catalogue = catalogue;
131 }
@@ -1,1053 +1,1077
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationCursorItem.h"
3 #include "Visualization/VisualizationCursorItem.h"
4 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationDefs.h"
5 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphHelper.h"
6 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationGraphRenderingDelegate.h"
7 #include "Visualization/VisualizationMultiZoneSelectionDialog.h"
7 #include "Visualization/VisualizationMultiZoneSelectionDialog.h"
8 #include "Visualization/VisualizationSelectionZoneItem.h"
8 #include "Visualization/VisualizationSelectionZoneItem.h"
9 #include "Visualization/VisualizationSelectionZoneManager.h"
9 #include "Visualization/VisualizationSelectionZoneManager.h"
10 #include "Visualization/VisualizationWidget.h"
10 #include "Visualization/VisualizationWidget.h"
11 #include "Visualization/VisualizationZoneWidget.h"
11 #include "Visualization/VisualizationZoneWidget.h"
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>
18 #include <Data/SpectrogramSeries.h>
19 #include <Data/SpectrogramSeries.h>
19 #include <DragAndDrop/DragDropGuiController.h>
20 #include <DragAndDrop/DragDropGuiController.h>
20 #include <Settings/SqpSettingsDefs.h>
21 #include <Settings/SqpSettingsDefs.h>
21 #include <SqpApplication.h>
22 #include <SqpApplication.h>
22 #include <Time/TimeController.h>
23 #include <Time/TimeController.h>
23 #include <Variable/Variable.h>
24 #include <Variable/Variable.h>
24 #include <Variable/VariableController.h>
25 #include <Variable/VariableController.h>
25
26
26 #include <unordered_map>
27 #include <unordered_map>
27
28
28 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
29 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
29
30
30 namespace {
31 namespace {
31
32
32 /// Key pressed to enable drag&drop in all modes
33 /// Key pressed to enable drag&drop in all modes
33 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
34 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
34
35
35 /// Key pressed to enable zoom on horizontal axis
36 /// Key pressed to enable zoom on horizontal axis
36 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
37 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
37
38
38 /// Key pressed to enable zoom on vertical axis
39 /// Key pressed to enable zoom on vertical axis
39 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
40 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
40
41
41 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
42 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
42 const auto PAN_SPEED = 5;
43 const auto PAN_SPEED = 5;
43
44
44 /// Key pressed to enable a calibration pan
45 /// Key pressed to enable a calibration pan
45 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
46 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
46
47
47 /// Key pressed to enable multi selection of selection zones
48 /// Key pressed to enable multi selection of selection zones
48 const auto MULTI_ZONE_SELECTION_MODIFIER = Qt::ControlModifier;
49 const auto MULTI_ZONE_SELECTION_MODIFIER = Qt::ControlModifier;
49
50
50 /// Minimum size for the zoom box, in percentage of the axis range
51 /// Minimum size for the zoom box, in percentage of the axis range
51 const auto ZOOM_BOX_MIN_SIZE = 0.8;
52 const auto ZOOM_BOX_MIN_SIZE = 0.8;
52
53
53 /// Format of the dates appearing in the label of a cursor
54 /// Format of the dates appearing in the label of a cursor
54 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
55 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
55
56
56 } // namespace
57 } // namespace
57
58
58 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
59 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
59
60
60 explicit VisualizationGraphWidgetPrivate(const QString &name)
61 explicit VisualizationGraphWidgetPrivate(const QString &name)
61 : m_Name{name},
62 : m_Name{name},
62 m_Flags{GraphFlag::EnableAll},
63 m_Flags{GraphFlag::EnableAll},
63 m_IsCalibration{false},
64 m_IsCalibration{false},
64 m_RenderingDelegate{nullptr}
65 m_RenderingDelegate{nullptr}
65 {
66 {
66 }
67 }
67
68
68 void updateData(PlottablesMap &plottables, std::shared_ptr<Variable> variable,
69 void updateData(PlottablesMap &plottables, std::shared_ptr<Variable> variable,
69 const SqpRange &range)
70 const SqpRange &range)
70 {
71 {
71 VisualizationGraphHelper::updateData(plottables, variable, range);
72 VisualizationGraphHelper::updateData(plottables, variable, range);
72
73
73 // Prevents that data has changed to update rendering
74 // Prevents that data has changed to update rendering
74 m_RenderingDelegate->onPlotUpdated();
75 m_RenderingDelegate->onPlotUpdated();
75 }
76 }
76
77
77 QString m_Name;
78 QString m_Name;
78 // 1 variable -> n qcpplot
79 // 1 variable -> n qcpplot
79 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
80 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
80 GraphFlags m_Flags;
81 GraphFlags m_Flags;
81 bool m_IsCalibration;
82 bool m_IsCalibration;
82 /// Delegate used to attach rendering features to the plot
83 /// Delegate used to attach rendering features to the plot
83 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
84 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
84
85
85 QCPItemRect *m_DrawingZoomRect = nullptr;
86 QCPItemRect *m_DrawingZoomRect = nullptr;
86 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
87 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
87
88
88 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
89 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
89 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
90 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
90
91
91 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
92 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
92 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
93 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
93 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
94 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
94
95
95 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
96 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
96
97
97 bool m_VariableAutoRangeOnInit = true;
98 bool m_VariableAutoRangeOnInit = true;
98
99
99 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
100 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
100 {
101 {
101 removeDrawingRect(plot);
102 removeDrawingRect(plot);
102
103
103 auto axisPos = posToAxisPos(pos, plot);
104 auto axisPos = posToAxisPos(pos, plot);
104
105
105 m_DrawingZoomRect = new QCPItemRect{&plot};
106 m_DrawingZoomRect = new QCPItemRect{&plot};
106 QPen p;
107 QPen p;
107 p.setWidth(2);
108 p.setWidth(2);
108 m_DrawingZoomRect->setPen(p);
109 m_DrawingZoomRect->setPen(p);
109
110
110 m_DrawingZoomRect->topLeft->setCoords(axisPos);
111 m_DrawingZoomRect->topLeft->setCoords(axisPos);
111 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
112 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
112 }
113 }
113
114
114 void removeDrawingRect(QCustomPlot &plot)
115 void removeDrawingRect(QCustomPlot &plot)
115 {
116 {
116 if (m_DrawingZoomRect) {
117 if (m_DrawingZoomRect) {
117 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
118 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
118 m_DrawingZoomRect = nullptr;
119 m_DrawingZoomRect = nullptr;
119 plot.replot(QCustomPlot::rpQueuedReplot);
120 plot.replot(QCustomPlot::rpQueuedReplot);
120 }
121 }
121 }
122 }
122
123
123 void startDrawingZone(const QPoint &pos, VisualizationGraphWidget *graph)
124 void startDrawingZone(const QPoint &pos, VisualizationGraphWidget *graph)
124 {
125 {
125 endDrawingZone(graph);
126 endDrawingZone(graph);
126
127
127 auto axisPos = posToAxisPos(pos, graph->plot());
128 auto axisPos = posToAxisPos(pos, graph->plot());
128
129
129 m_DrawingZone = new VisualizationSelectionZoneItem{&graph->plot()};
130 m_DrawingZone = new VisualizationSelectionZoneItem{&graph->plot()};
130 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
131 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
131 m_DrawingZone->setEditionEnabled(false);
132 m_DrawingZone->setEditionEnabled(false);
132 }
133 }
133
134
134 void endDrawingZone(VisualizationGraphWidget *graph)
135 void endDrawingZone(VisualizationGraphWidget *graph)
135 {
136 {
136 if (m_DrawingZone) {
137 if (m_DrawingZone) {
137 auto drawingZoneRange = m_DrawingZone->range();
138 auto drawingZoneRange = m_DrawingZone->range();
138 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
139 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
139 m_DrawingZone->setEditionEnabled(true);
140 m_DrawingZone->setEditionEnabled(true);
140 addSelectionZone(m_DrawingZone);
141 addSelectionZone(m_DrawingZone);
141 }
142 }
142 else {
143 else {
143 graph->plot().removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
144 graph->plot().removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
144 }
145 }
145
146
146 graph->plot().replot(QCustomPlot::rpQueuedReplot);
147 graph->plot().replot(QCustomPlot::rpQueuedReplot);
147 m_DrawingZone = nullptr;
148 m_DrawingZone = nullptr;
148 }
149 }
149 }
150 }
150
151
151 void setSelectionZonesEditionEnabled(bool value)
152 void setSelectionZonesEditionEnabled(bool value)
152 {
153 {
153 for (auto s : m_SelectionZones) {
154 for (auto s : m_SelectionZones) {
154 s->setEditionEnabled(value);
155 s->setEditionEnabled(value);
155 }
156 }
156 }
157 }
157
158
158 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
159 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
159
160
160 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
161 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
161 const QCustomPlot &plot) const
162 const QCustomPlot &plot) const
162 {
163 {
163 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
164 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
164 auto minDistanceToZone = -1;
165 auto minDistanceToZone = -1;
165 for (auto zone : m_SelectionZones) {
166 for (auto zone : m_SelectionZones) {
166 auto distanceToZone = zone->selectTest(pos, false);
167 auto distanceToZone = zone->selectTest(pos, false);
167 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
168 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
168 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
169 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
169 selectionZoneItemUnderCursor = zone;
170 selectionZoneItemUnderCursor = zone;
170 }
171 }
171 }
172 }
172
173
173 return selectionZoneItemUnderCursor;
174 return selectionZoneItemUnderCursor;
174 }
175 }
175
176
176 QVector<VisualizationSelectionZoneItem *> selectionZonesAt(const QPoint &pos,
177 QVector<VisualizationSelectionZoneItem *> selectionZonesAt(const QPoint &pos,
177 const QCustomPlot &plot) const
178 const QCustomPlot &plot) const
178 {
179 {
179 QVector<VisualizationSelectionZoneItem *> zones;
180 QVector<VisualizationSelectionZoneItem *> zones;
180 for (auto zone : m_SelectionZones) {
181 for (auto zone : m_SelectionZones) {
181 auto distanceToZone = zone->selectTest(pos, false);
182 auto distanceToZone = zone->selectTest(pos, false);
182 if (distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
183 if (distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
183 zones << zone;
184 zones << zone;
184 }
185 }
185 }
186 }
186
187
187 return zones;
188 return zones;
188 }
189 }
189
190
190 void moveSelectionZoneOnTop(VisualizationSelectionZoneItem *zone, QCustomPlot &plot)
191 void moveSelectionZoneOnTop(VisualizationSelectionZoneItem *zone, QCustomPlot &plot)
191 {
192 {
192 if (!m_SelectionZones.isEmpty() && m_SelectionZones.last() != zone) {
193 if (!m_SelectionZones.isEmpty() && m_SelectionZones.last() != zone) {
193 zone->moveToTop();
194 zone->moveToTop();
194 m_SelectionZones.removeAll(zone);
195 m_SelectionZones.removeAll(zone);
195 m_SelectionZones.append(zone);
196 m_SelectionZones.append(zone);
196 }
197 }
197 }
198 }
198
199
199 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
200 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
200 {
201 {
201 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
202 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
202 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
203 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
203 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
204 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
204 }
205 }
205
206
206 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
207 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
207 {
208 {
208 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
209 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
209 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
210 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
210 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
211 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
211 }
212 }
212 };
213 };
213
214
214 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
215 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
215 : VisualizationDragWidget{parent},
216 : VisualizationDragWidget{parent},
216 ui{new Ui::VisualizationGraphWidget},
217 ui{new Ui::VisualizationGraphWidget},
217 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
218 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
218 {
219 {
219 ui->setupUi(this);
220 ui->setupUi(this);
220
221
221 // 'Close' options : widget is deleted when closed
222 // 'Close' options : widget is deleted when closed
222 setAttribute(Qt::WA_DeleteOnClose);
223 setAttribute(Qt::WA_DeleteOnClose);
223
224
224 // Set qcpplot properties :
225 // Set qcpplot properties :
225 // - zoom is enabled
226 // - zoom is enabled
226 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
227 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
227 ui->widget->setInteractions(QCP::iRangeZoom);
228 ui->widget->setInteractions(QCP::iRangeZoom);
228 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
229 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
229
230
230 // The delegate must be initialized after the ui as it uses the plot
231 // The delegate must be initialized after the ui as it uses the plot
231 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
232 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
232
233
233 // Init the cursors
234 // Init the cursors
234 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
235 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
235 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
236 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
236 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
237 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
237 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
238 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
238
239
239 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
240 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
240 connect(ui->widget, &QCustomPlot::mouseRelease, this,
241 connect(ui->widget, &QCustomPlot::mouseRelease, this,
241 &VisualizationGraphWidget::onMouseRelease);
242 &VisualizationGraphWidget::onMouseRelease);
242 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
243 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
243 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
244 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
244 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
245 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
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 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
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);
252 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
253 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
253 &VisualizationGraphWidget::onGraphMenuRequested);
254 &VisualizationGraphWidget::onGraphMenuRequested);
254
255
255 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
256 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
256 &VariableController::onRequestDataLoading);
257 &VariableController::onRequestDataLoading);
257
258
258 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
259 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
259 &VisualizationGraphWidget::onUpdateVarDisplaying);
260 &VisualizationGraphWidget::onUpdateVarDisplaying);
260
261
261 // Necessary for all platform since Qt::AA_EnableHighDpiScaling is enable.
262 // Necessary for all platform since Qt::AA_EnableHighDpiScaling is enable.
262 plot().setPlottingHint(QCP::phFastPolylines, true);
263 plot().setPlottingHint(QCP::phFastPolylines, true);
263 }
264 }
264
265
265
266
266 VisualizationGraphWidget::~VisualizationGraphWidget()
267 VisualizationGraphWidget::~VisualizationGraphWidget()
267 {
268 {
268 delete ui;
269 delete ui;
269 }
270 }
270
271
271 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
272 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
272 {
273 {
273 auto parent = parentWidget();
274 auto parent = parentWidget();
274 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
275 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
275 parent = parent->parentWidget();
276 parent = parent->parentWidget();
276 }
277 }
277
278
278 return qobject_cast<VisualizationZoneWidget *>(parent);
279 return qobject_cast<VisualizationZoneWidget *>(parent);
279 }
280 }
280
281
281 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
282 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
282 {
283 {
283 auto parent = parentWidget();
284 auto parent = parentWidget();
284 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
285 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
285 parent = parent->parentWidget();
286 parent = parent->parentWidget();
286 }
287 }
287
288
288 return qobject_cast<VisualizationWidget *>(parent);
289 return qobject_cast<VisualizationWidget *>(parent);
289 }
290 }
290
291
291 void VisualizationGraphWidget::setFlags(GraphFlags flags)
292 void VisualizationGraphWidget::setFlags(GraphFlags flags)
292 {
293 {
293 impl->m_Flags = std::move(flags);
294 impl->m_Flags = std::move(flags);
294 }
295 }
295
296
296 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
297 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
297 {
298 {
298 /// Lambda used to set graph's units and range according to the variable passed in parameter
299 /// Lambda used to set graph's units and range according to the variable passed in parameter
299 auto loadRange = [this](std::shared_ptr<Variable> variable, const SqpRange &range) {
300 auto loadRange = [this](std::shared_ptr<Variable> variable, const SqpRange &range) {
300 impl->m_RenderingDelegate->setAxesUnits(*variable);
301 impl->m_RenderingDelegate->setAxesUnits(*variable);
301
302
302 this->setFlags(GraphFlag::DisableAll);
303 this->setFlags(GraphFlag::DisableAll);
303 setGraphRange(range);
304 setGraphRange(range);
304 this->setFlags(GraphFlag::EnableAll);
305 this->setFlags(GraphFlag::EnableAll);
305 emit requestDataLoading({variable}, range, false);
306 emit requestDataLoading({variable}, range, false);
306 };
307 };
307
308
308 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
309 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
309
310
310 // Calls update of graph's range and units when the data of the variable have been initialized.
311 // Calls update of graph's range and units when the data of the variable have been initialized.
311 // Note: we use QueuedConnection here as the update event must be called in the UI thread
312 // Note: we use QueuedConnection here as the update event must be called in the UI thread
312 connect(variable.get(), &Variable::dataInitialized, this,
313 connect(variable.get(), &Variable::dataInitialized, this,
313 [ varW = std::weak_ptr<Variable>{variable}, range, loadRange, this ]() {
314 [ varW = std::weak_ptr<Variable>{variable}, range, loadRange, this ]() {
314 if (auto var = varW.lock()) {
315 if (auto var = varW.lock()) {
315 // If the variable is the first added in the graph, we load its range
316 // If the variable is the first added in the graph, we load its range
316 auto firstVariableInGraph = range == INVALID_RANGE;
317 auto firstVariableInGraph = range == INVALID_RANGE;
317 auto loadedRange = graphRange();
318 auto loadedRange = graphRange();
318 if (impl->m_VariableAutoRangeOnInit) {
319 if (impl->m_VariableAutoRangeOnInit) {
319 loadedRange = firstVariableInGraph ? var->range() : range;
320 loadedRange = firstVariableInGraph ? var->range() : range;
320 }
321 }
321 loadRange(var, loadedRange);
322 loadRange(var, loadedRange);
322 setYRange(var);
323 setYRange(var);
323 }
324 }
324 },
325 },
325 Qt::QueuedConnection);
326 Qt::QueuedConnection);
326
327
327 // Uses delegate to create the qcpplot components according to the variable
328 // Uses delegate to create the qcpplot components according to the variable
328 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
329 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
329
330
330 // Sets graph properties
331 // Sets graph properties
331 impl->m_RenderingDelegate->setGraphProperties(*variable, createdPlottables);
332 impl->m_RenderingDelegate->setGraphProperties(*variable, createdPlottables);
332
333
333 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
334 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
334
335
335 // If the variable already has its data loaded, load its units and its range in the graph
336 // If the variable already has its data loaded, load its units and its range in the graph
336 if (variable->dataSeries() != nullptr) {
337 if (variable->dataSeries() != nullptr) {
337 loadRange(variable, range);
338 loadRange(variable, range);
338 }
339 }
339
340
340 emit variableAdded(variable);
341 emit variableAdded(variable);
341 }
342 }
342
343
343 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
344 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
344 {
345 {
345 // Each component associated to the variable :
346 // Each component associated to the variable :
346 // - is removed from qcpplot (which deletes it)
347 // - is removed from qcpplot (which deletes it)
347 // - is no longer referenced in the map
348 // - is no longer referenced in the map
348 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
349 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
349 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
350 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
350 emit variableAboutToBeRemoved(variable);
351 emit variableAboutToBeRemoved(variable);
351
352
352 auto &plottablesMap = variableIt->second;
353 auto &plottablesMap = variableIt->second;
353
354
354 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
355 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
355 plottableIt != plottableEnd;) {
356 plottableIt != plottableEnd;) {
356 ui->widget->removePlottable(plottableIt->second);
357 ui->widget->removePlottable(plottableIt->second);
357 plottableIt = plottablesMap.erase(plottableIt);
358 plottableIt = plottablesMap.erase(plottableIt);
358 }
359 }
359
360
360 impl->m_VariableToPlotMultiMap.erase(variableIt);
361 impl->m_VariableToPlotMultiMap.erase(variableIt);
361 }
362 }
362
363
363 // Updates graph
364 // Updates graph
364 ui->widget->replot();
365 ui->widget->replot();
365 }
366 }
366
367
367 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
368 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
368 {
369 {
369 auto variables = QList<std::shared_ptr<Variable> >{};
370 auto variables = QList<std::shared_ptr<Variable> >{};
370 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
371 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
371 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
372 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
372 variables << it->first;
373 variables << it->first;
373 }
374 }
374
375
375 return variables;
376 return variables;
376 }
377 }
377
378
378 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
379 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
379 {
380 {
380 if (!variable) {
381 if (!variable) {
381 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
382 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
382 return;
383 return;
383 }
384 }
384
385
385 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
386 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
386 }
387 }
387
388
388 SqpRange VisualizationGraphWidget::graphRange() const noexcept
389 SqpRange VisualizationGraphWidget::graphRange() const noexcept
389 {
390 {
390 auto graphRange = ui->widget->xAxis->range();
391 auto graphRange = ui->widget->xAxis->range();
391 return SqpRange{graphRange.lower, graphRange.upper};
392 return SqpRange{graphRange.lower, graphRange.upper};
392 }
393 }
393
394
394 void VisualizationGraphWidget::setGraphRange(const SqpRange &range, bool calibration)
395 void VisualizationGraphWidget::setGraphRange(const SqpRange &range, bool calibration)
395 {
396 {
396 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
397 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
397
398
398 if (calibration) {
399 if (calibration) {
399 impl->m_IsCalibration = true;
400 impl->m_IsCalibration = true;
400 }
401 }
401
402
402 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
403 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
403 ui->widget->replot();
404 ui->widget->replot();
404
405
405 if (calibration) {
406 if (calibration) {
406 impl->m_IsCalibration = false;
407 impl->m_IsCalibration = false;
407 }
408 }
408
409
409 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
410 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
410 }
411 }
411
412
412 void VisualizationGraphWidget::setAutoRangeOnVariableInitialization(bool value)
413 void VisualizationGraphWidget::setAutoRangeOnVariableInitialization(bool value)
413 {
414 {
414 impl->m_VariableAutoRangeOnInit = value;
415 impl->m_VariableAutoRangeOnInit = value;
415 }
416 }
416
417
417 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
418 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
418 {
419 {
419 QVector<SqpRange> ranges;
420 QVector<SqpRange> ranges;
420 for (auto zone : impl->m_SelectionZones) {
421 for (auto zone : impl->m_SelectionZones) {
421 ranges << zone->range();
422 ranges << zone->range();
422 }
423 }
423
424
424 return ranges;
425 return ranges;
425 }
426 }
426
427
427 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
428 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
428 {
429 {
429 for (const auto &range : ranges) {
430 for (const auto &range : ranges) {
430 // note: ownership is transfered to QCustomPlot
431 // note: ownership is transfered to QCustomPlot
431 auto zone = new VisualizationSelectionZoneItem(&plot());
432 auto zone = new VisualizationSelectionZoneItem(&plot());
432 zone->setRange(range.m_TStart, range.m_TEnd);
433 zone->setRange(range.m_TStart, range.m_TEnd);
433 impl->addSelectionZone(zone);
434 impl->addSelectionZone(zone);
434 }
435 }
435
436
436 plot().replot(QCustomPlot::rpQueuedReplot);
437 plot().replot(QCustomPlot::rpQueuedReplot);
437 }
438 }
438
439
439 VisualizationSelectionZoneItem *VisualizationGraphWidget::addSelectionZone(const QString &name,
440 VisualizationSelectionZoneItem *VisualizationGraphWidget::addSelectionZone(const QString &name,
440 const SqpRange &range)
441 const SqpRange &range)
441 {
442 {
442 // note: ownership is transfered to QCustomPlot
443 // note: ownership is transfered to QCustomPlot
443 auto zone = new VisualizationSelectionZoneItem(&plot());
444 auto zone = new VisualizationSelectionZoneItem(&plot());
444 zone->setName(name);
445 zone->setName(name);
445 zone->setRange(range.m_TStart, range.m_TEnd);
446 zone->setRange(range.m_TStart, range.m_TEnd);
446 impl->addSelectionZone(zone);
447 impl->addSelectionZone(zone);
447
448
448 plot().replot(QCustomPlot::rpQueuedReplot);
449 plot().replot(QCustomPlot::rpQueuedReplot);
449
450
450 return zone;
451 return zone;
451 }
452 }
452
453
453 void VisualizationGraphWidget::removeSelectionZone(VisualizationSelectionZoneItem *selectionZone)
454 void VisualizationGraphWidget::removeSelectionZone(VisualizationSelectionZoneItem *selectionZone)
454 {
455 {
455 parentVisualizationWidget()->selectionZoneManager().setSelected(selectionZone, false);
456 parentVisualizationWidget()->selectionZoneManager().setSelected(selectionZone, false);
456
457
457 if (impl->m_HoveredZone == selectionZone) {
458 if (impl->m_HoveredZone == selectionZone) {
458 impl->m_HoveredZone = nullptr;
459 impl->m_HoveredZone = nullptr;
459 setCursor(Qt::ArrowCursor);
460 setCursor(Qt::ArrowCursor);
460 }
461 }
461
462
462 impl->m_SelectionZones.removeAll(selectionZone);
463 impl->m_SelectionZones.removeAll(selectionZone);
463 plot().removeItem(selectionZone);
464 plot().removeItem(selectionZone);
464 plot().replot(QCustomPlot::rpQueuedReplot);
465 plot().replot(QCustomPlot::rpQueuedReplot);
465 }
466 }
466
467
467 void VisualizationGraphWidget::undoZoom()
468 void VisualizationGraphWidget::undoZoom()
468 {
469 {
469 auto zoom = impl->m_ZoomStack.pop();
470 auto zoom = impl->m_ZoomStack.pop();
470 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
471 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
471 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
472 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
472
473
473 axisX->setRange(zoom.first);
474 axisX->setRange(zoom.first);
474 axisY->setRange(zoom.second);
475 axisY->setRange(zoom.second);
475
476
476 plot().replot(QCustomPlot::rpQueuedReplot);
477 plot().replot(QCustomPlot::rpQueuedReplot);
477 }
478 }
478
479
479 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
480 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
480 {
481 {
481 if (visitor) {
482 if (visitor) {
482 visitor->visit(this);
483 visitor->visit(this);
483 }
484 }
484 else {
485 else {
485 qCCritical(LOG_VisualizationGraphWidget())
486 qCCritical(LOG_VisualizationGraphWidget())
486 << tr("Can't visit widget : the visitor is null");
487 << tr("Can't visit widget : the visitor is null");
487 }
488 }
488 }
489 }
489
490
490 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
491 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
491 {
492 {
492 auto isSpectrogram = [](const auto &variable) {
493 auto isSpectrogram = [](const auto &variable) {
493 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
494 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
494 };
495 };
495
496
496 // - A spectrogram series can't be dropped on graph with existing plottables
497 // - A spectrogram series can't be dropped on graph with existing plottables
497 // - No data series can be dropped on graph with existing spectrogram series
498 // - No data series can be dropped on graph with existing spectrogram series
498 return isSpectrogram(variable)
499 return isSpectrogram(variable)
499 ? impl->m_VariableToPlotMultiMap.empty()
500 ? impl->m_VariableToPlotMultiMap.empty()
500 : std::none_of(
501 : std::none_of(
501 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
502 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
502 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
503 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
503 }
504 }
504
505
505 bool VisualizationGraphWidget::contains(const Variable &variable) const
506 bool VisualizationGraphWidget::contains(const Variable &variable) const
506 {
507 {
507 // Finds the variable among the keys of the map
508 // Finds the variable among the keys of the map
508 auto variablePtr = &variable;
509 auto variablePtr = &variable;
509 auto findVariable
510 auto findVariable
510 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
511 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
511
512
512 auto end = impl->m_VariableToPlotMultiMap.cend();
513 auto end = impl->m_VariableToPlotMultiMap.cend();
513 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
514 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
514 return it != end;
515 return it != end;
515 }
516 }
516
517
517 QString VisualizationGraphWidget::name() const
518 QString VisualizationGraphWidget::name() const
518 {
519 {
519 return impl->m_Name;
520 return impl->m_Name;
520 }
521 }
521
522
522 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
523 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
523 {
524 {
524 auto mimeData = new QMimeData;
525 auto mimeData = new QMimeData;
525
526
526 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
527 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
527 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
528 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
528 && selectionZoneItemUnderCursor) {
529 && selectionZoneItemUnderCursor) {
529 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
530 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
530 selectionZoneItemUnderCursor->range()));
531 selectionZoneItemUnderCursor->range()));
531 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
532 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
532 selectionZoneItemUnderCursor->range()));
533 selectionZoneItemUnderCursor->range()));
533 }
534 }
534 else {
535 else {
535 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
536 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
536
537
537 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
538 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
538 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
539 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
539 }
540 }
540
541
541 return mimeData;
542 return mimeData;
542 }
543 }
543
544
544 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
545 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
545 {
546 {
546 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
547 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
547 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
548 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
548 && selectionZoneItemUnderCursor) {
549 && selectionZoneItemUnderCursor) {
549
550
550 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
551 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
551 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
552 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
552
553
553 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
554 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
554 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
555 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
555 .toSize();
556 .toSize();
556
557
557 auto pixmap = QPixmap(zoneSize);
558 auto pixmap = QPixmap(zoneSize);
558 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
559 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
559
560
560 return pixmap;
561 return pixmap;
561 }
562 }
562
563
563 return QPixmap();
564 return QPixmap();
564 }
565 }
565
566
566 bool VisualizationGraphWidget::isDragAllowed() const
567 bool VisualizationGraphWidget::isDragAllowed() const
567 {
568 {
568 return true;
569 return true;
569 }
570 }
570
571
571 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
572 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
572 {
573 {
573 if (highlighted) {
574 if (highlighted) {
574 plot().setBackground(QBrush(QColor("#BBD5EE")));
575 plot().setBackground(QBrush(QColor("#BBD5EE")));
575 }
576 }
576 else {
577 else {
577 plot().setBackground(QBrush(Qt::white));
578 plot().setBackground(QBrush(Qt::white));
578 }
579 }
579
580
580 plot().update();
581 plot().update();
581 }
582 }
582
583
583 void VisualizationGraphWidget::addVerticalCursor(double time)
584 void VisualizationGraphWidget::addVerticalCursor(double time)
584 {
585 {
585 impl->m_VerticalCursor->setPosition(time);
586 impl->m_VerticalCursor->setPosition(time);
586 impl->m_VerticalCursor->setVisible(true);
587 impl->m_VerticalCursor->setVisible(true);
587
588
588 auto text
589 auto text
589 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
590 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
590 impl->m_VerticalCursor->setLabelText(text);
591 impl->m_VerticalCursor->setLabelText(text);
591 }
592 }
592
593
593 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
594 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
594 {
595 {
595 impl->m_VerticalCursor->setAbsolutePosition(position);
596 impl->m_VerticalCursor->setAbsolutePosition(position);
596 impl->m_VerticalCursor->setVisible(true);
597 impl->m_VerticalCursor->setVisible(true);
597
598
598 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
599 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
599 auto text
600 auto text
600 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
601 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
601 impl->m_VerticalCursor->setLabelText(text);
602 impl->m_VerticalCursor->setLabelText(text);
602 }
603 }
603
604
604 void VisualizationGraphWidget::removeVerticalCursor()
605 void VisualizationGraphWidget::removeVerticalCursor()
605 {
606 {
606 impl->m_VerticalCursor->setVisible(false);
607 impl->m_VerticalCursor->setVisible(false);
607 plot().replot(QCustomPlot::rpQueuedReplot);
608 plot().replot(QCustomPlot::rpQueuedReplot);
608 }
609 }
609
610
610 void VisualizationGraphWidget::addHorizontalCursor(double value)
611 void VisualizationGraphWidget::addHorizontalCursor(double value)
611 {
612 {
612 impl->m_HorizontalCursor->setPosition(value);
613 impl->m_HorizontalCursor->setPosition(value);
613 impl->m_HorizontalCursor->setVisible(true);
614 impl->m_HorizontalCursor->setVisible(true);
614 impl->m_HorizontalCursor->setLabelText(QString::number(value));
615 impl->m_HorizontalCursor->setLabelText(QString::number(value));
615 }
616 }
616
617
617 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
618 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
618 {
619 {
619 impl->m_HorizontalCursor->setAbsolutePosition(position);
620 impl->m_HorizontalCursor->setAbsolutePosition(position);
620 impl->m_HorizontalCursor->setVisible(true);
621 impl->m_HorizontalCursor->setVisible(true);
621
622
622 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
623 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
623 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
624 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
624 }
625 }
625
626
626 void VisualizationGraphWidget::removeHorizontalCursor()
627 void VisualizationGraphWidget::removeHorizontalCursor()
627 {
628 {
628 impl->m_HorizontalCursor->setVisible(false);
629 impl->m_HorizontalCursor->setVisible(false);
629 plot().replot(QCustomPlot::rpQueuedReplot);
630 plot().replot(QCustomPlot::rpQueuedReplot);
630 }
631 }
631
632
632 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
633 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
633 {
634 {
634 Q_UNUSED(event);
635 Q_UNUSED(event);
635
636
637 for (auto i : impl->m_SelectionZones) {
638 parentVisualizationWidget()->selectionZoneManager().setSelected(i, false);
639 }
640
636 // Prevents that all variables will be removed from graph when it will be closed
641 // Prevents that all variables will be removed from graph when it will be closed
637 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
642 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
638 emit variableAboutToBeRemoved(variableEntry.first);
643 emit variableAboutToBeRemoved(variableEntry.first);
639 }
644 }
640 }
645 }
641
646
642 void VisualizationGraphWidget::enterEvent(QEvent *event)
647 void VisualizationGraphWidget::enterEvent(QEvent *event)
643 {
648 {
644 Q_UNUSED(event);
649 Q_UNUSED(event);
645 impl->m_RenderingDelegate->showGraphOverlay(true);
650 impl->m_RenderingDelegate->showGraphOverlay(true);
646 }
651 }
647
652
648 void VisualizationGraphWidget::leaveEvent(QEvent *event)
653 void VisualizationGraphWidget::leaveEvent(QEvent *event)
649 {
654 {
650 Q_UNUSED(event);
655 Q_UNUSED(event);
651 impl->m_RenderingDelegate->showGraphOverlay(false);
656 impl->m_RenderingDelegate->showGraphOverlay(false);
652
657
653 if (auto parentZone = parentZoneWidget()) {
658 if (auto parentZone = parentZoneWidget()) {
654 parentZone->notifyMouseLeaveGraph(this);
659 parentZone->notifyMouseLeaveGraph(this);
655 }
660 }
656 else {
661 else {
657 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
662 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
658 }
663 }
659
664
660 if (impl->m_HoveredZone) {
665 if (impl->m_HoveredZone) {
661 impl->m_HoveredZone->setHovered(false);
666 impl->m_HoveredZone->setHovered(false);
662 impl->m_HoveredZone = nullptr;
667 impl->m_HoveredZone = nullptr;
663 }
668 }
664 }
669 }
665
670
666 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
671 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
667 {
672 {
668 return *ui->widget;
673 return *ui->widget;
669 }
674 }
670
675
671 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
676 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
672 {
677 {
673 QMenu graphMenu{};
678 QMenu graphMenu{};
674
679
675 // Iterates on variables (unique keys)
680 // Iterates on variables (unique keys)
676 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
681 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
677 end = impl->m_VariableToPlotMultiMap.cend();
682 end = impl->m_VariableToPlotMultiMap.cend();
678 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
683 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
679 // 'Remove variable' action
684 // 'Remove variable' action
680 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
685 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
681 [ this, var = it->first ]() { removeVariable(var); });
686 [ this, var = it->first ]() { removeVariable(var); });
682 }
687 }
683
688
684 if (!impl->m_ZoomStack.isEmpty()) {
689 if (!impl->m_ZoomStack.isEmpty()) {
685 if (!graphMenu.isEmpty()) {
690 if (!graphMenu.isEmpty()) {
686 graphMenu.addSeparator();
691 graphMenu.addSeparator();
687 }
692 }
688
693
689 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
694 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
690 }
695 }
691
696
692 // Selection Zone Actions
697 // Selection Zone Actions
693 auto selectionZoneItem = impl->selectionZoneAt(pos, plot());
698 auto selectionZoneItem = impl->selectionZoneAt(pos, plot());
694 if (selectionZoneItem) {
699 if (selectionZoneItem) {
695 auto selectedItems = parentVisualizationWidget()->selectionZoneManager().selectedItems();
700 auto selectedItems = parentVisualizationWidget()->selectionZoneManager().selectedItems();
696 selectedItems.removeAll(selectionZoneItem);
701 selectedItems.removeAll(selectionZoneItem);
697 selectedItems.prepend(selectionZoneItem); // Put the current selection zone first
702 selectedItems.prepend(selectionZoneItem); // Put the current selection zone first
698
703
699 auto zoneActions = sqpApp->actionsGuiController().selectionZoneActions();
704 auto zoneActions = sqpApp->actionsGuiController().selectionZoneActions();
700 if (!zoneActions.isEmpty() && !graphMenu.isEmpty()) {
705 if (!zoneActions.isEmpty() && !graphMenu.isEmpty()) {
701 graphMenu.addSeparator();
706 graphMenu.addSeparator();
702 }
707 }
703
708
704 QHash<QString, QMenu *> subMenus;
709 QHash<QString, QMenu *> subMenus;
705 QHash<QString, bool> subMenusEnabled;
710 QHash<QString, bool> subMenusEnabled;
711 QHash<QString, FilteringAction *> filteredMenu;
706
712
707 for (auto zoneAction : zoneActions) {
713 for (auto zoneAction : zoneActions) {
708
714
709 auto isEnabled = zoneAction->isEnabled(selectedItems);
715 auto isEnabled = zoneAction->isEnabled(selectedItems);
710
716
711 auto menu = &graphMenu;
717 auto menu = &graphMenu;
718 QString menuPath;
712 for (auto subMenuName : zoneAction->subMenuList()) {
719 for (auto subMenuName : zoneAction->subMenuList()) {
713 if (!subMenus.contains(subMenuName)) {
720 menuPath += '/';
721 menuPath += subMenuName;
722
723 if (!subMenus.contains(menuPath)) {
714 menu = menu->addMenu(subMenuName);
724 menu = menu->addMenu(subMenuName);
715 subMenus[subMenuName] = menu;
725 subMenus[menuPath] = menu;
716 subMenusEnabled[subMenuName] = isEnabled;
726 subMenusEnabled[menuPath] = isEnabled;
717 }
727 }
718 else {
728 else {
719 menu = subMenus.value(subMenuName);
729 menu = subMenus.value(menuPath);
720 if (isEnabled) {
730 if (isEnabled) {
721 // 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
722 subMenusEnabled[subMenuName] = true;
732 subMenusEnabled[menuPath] = true;
733 }
723 }
734 }
724 }
735 }
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 }
725 }
745 }
726
746
727 auto action = menu->addAction(zoneAction->name());
747 auto action = menu->addAction(zoneAction->name());
728 action->setEnabled(isEnabled);
748 action->setEnabled(isEnabled);
729 action->setShortcut(zoneAction->displayedShortcut());
749 action->setShortcut(zoneAction->displayedShortcut());
730 QObject::connect(action, &QAction::triggered,
750 QObject::connect(action, &QAction::triggered,
731 [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); });
751 [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); });
752
753 if (filterAction && zoneAction->isFilteringAllowed()) {
754 filterAction->addActionToFilter(action);
755 }
732 }
756 }
733
757
734 for (auto it = subMenus.cbegin(); it != subMenus.cend(); ++it) {
758 for (auto it = subMenus.cbegin(); it != subMenus.cend(); ++it) {
735 it.value()->setEnabled(subMenusEnabled[it.key()]);
759 it.value()->setEnabled(subMenusEnabled[it.key()]);
736 }
760 }
737 }
761 }
738
762
739 if (!graphMenu.isEmpty()) {
763 if (!graphMenu.isEmpty()) {
740 graphMenu.exec(QCursor::pos());
764 graphMenu.exec(QCursor::pos());
741 }
765 }
742 }
766 }
743
767
744 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
768 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
745 {
769 {
746 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
770 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
747 << QThread::currentThread()->objectName() << "DoAcqui"
771 << QThread::currentThread()->objectName() << "DoAcqui"
748 << impl->m_Flags.testFlag(GraphFlag::EnableAcquisition);
772 << impl->m_Flags.testFlag(GraphFlag::EnableAcquisition);
749
773
750 auto graphRange = SqpRange{t1.lower, t1.upper};
774 auto graphRange = SqpRange{t1.lower, t1.upper};
751 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
775 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
752
776
753 if (impl->m_Flags.testFlag(GraphFlag::EnableAcquisition)) {
777 if (impl->m_Flags.testFlag(GraphFlag::EnableAcquisition)) {
754 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
778 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
755
779
756 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
780 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
757 end = impl->m_VariableToPlotMultiMap.end();
781 end = impl->m_VariableToPlotMultiMap.end();
758 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
782 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
759 variableUnderGraphVector.push_back(it->first);
783 variableUnderGraphVector.push_back(it->first);
760 }
784 }
761 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
785 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
762 !impl->m_IsCalibration);
786 !impl->m_IsCalibration);
763 }
787 }
764
788
765 if (impl->m_Flags.testFlag(GraphFlag::EnableSynchronization) && !impl->m_IsCalibration) {
789 if (impl->m_Flags.testFlag(GraphFlag::EnableSynchronization) && !impl->m_IsCalibration) {
766 qCDebug(LOG_VisualizationGraphWidget())
790 qCDebug(LOG_VisualizationGraphWidget())
767 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
791 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
768 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
792 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
769 emit synchronize(graphRange, oldGraphRange);
793 emit synchronize(graphRange, oldGraphRange);
770 }
794 }
771
795
772 auto pos = mapFromGlobal(QCursor::pos());
796 auto pos = mapFromGlobal(QCursor::pos());
773 auto axisPos = impl->posToAxisPos(pos, plot());
797 auto axisPos = impl->posToAxisPos(pos, plot());
774 if (auto parentZone = parentZoneWidget()) {
798 if (auto parentZone = parentZoneWidget()) {
775 if (impl->pointIsInAxisRect(axisPos, plot())) {
799 if (impl->pointIsInAxisRect(axisPos, plot())) {
776 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
800 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
777 }
801 }
778 else {
802 else {
779 parentZone->notifyMouseLeaveGraph(this);
803 parentZone->notifyMouseLeaveGraph(this);
780 }
804 }
781 }
805 }
782 else {
806 else {
783 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
807 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
784 }
808 }
785
809
786 // Quits calibration
810 // Quits calibration
787 impl->m_IsCalibration = false;
811 impl->m_IsCalibration = false;
788 }
812 }
789
813
790 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
814 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
791 {
815 {
792 impl->m_RenderingDelegate->onMouseDoubleClick(event);
816 impl->m_RenderingDelegate->onMouseDoubleClick(event);
793 }
817 }
794
818
795 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
819 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
796 {
820 {
797 // Handles plot rendering when mouse is moving
821 // Handles plot rendering when mouse is moving
798 impl->m_RenderingDelegate->onMouseMove(event);
822 impl->m_RenderingDelegate->onMouseMove(event);
799
823
800 auto axisPos = impl->posToAxisPos(event->pos(), plot());
824 auto axisPos = impl->posToAxisPos(event->pos(), plot());
801
825
802 // Zoom box and zone drawing
826 // Zoom box and zone drawing
803 if (impl->m_DrawingZoomRect) {
827 if (impl->m_DrawingZoomRect) {
804 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
828 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
805 }
829 }
806 else if (impl->m_DrawingZone) {
830 else if (impl->m_DrawingZone) {
807 impl->m_DrawingZone->setEnd(axisPos.x());
831 impl->m_DrawingZone->setEnd(axisPos.x());
808 }
832 }
809
833
810 // Cursor
834 // Cursor
811 if (auto parentZone = parentZoneWidget()) {
835 if (auto parentZone = parentZoneWidget()) {
812 if (impl->pointIsInAxisRect(axisPos, plot())) {
836 if (impl->pointIsInAxisRect(axisPos, plot())) {
813 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
837 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
814 }
838 }
815 else {
839 else {
816 parentZone->notifyMouseLeaveGraph(this);
840 parentZone->notifyMouseLeaveGraph(this);
817 }
841 }
818 }
842 }
819 else {
843 else {
820 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
844 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
821 }
845 }
822
846
823 // Search for the selection zone under the mouse
847 // Search for the selection zone under the mouse
824 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
848 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
825 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
849 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
826 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
850 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
827
851
828 // Sets the appropriate cursor shape
852 // Sets the appropriate cursor shape
829 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
853 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
830 setCursor(cursorShape);
854 setCursor(cursorShape);
831
855
832 // Manages the hovered zone
856 // Manages the hovered zone
833 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
857 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
834 if (impl->m_HoveredZone) {
858 if (impl->m_HoveredZone) {
835 impl->m_HoveredZone->setHovered(false);
859 impl->m_HoveredZone->setHovered(false);
836 }
860 }
837 selectionZoneItemUnderCursor->setHovered(true);
861 selectionZoneItemUnderCursor->setHovered(true);
838 impl->m_HoveredZone = selectionZoneItemUnderCursor;
862 impl->m_HoveredZone = selectionZoneItemUnderCursor;
839 plot().replot(QCustomPlot::rpQueuedReplot);
863 plot().replot(QCustomPlot::rpQueuedReplot);
840 }
864 }
841 }
865 }
842 else {
866 else {
843 // There is no zone under the mouse or the interaction mode is not "selection zones"
867 // There is no zone under the mouse or the interaction mode is not "selection zones"
844 if (impl->m_HoveredZone) {
868 if (impl->m_HoveredZone) {
845 impl->m_HoveredZone->setHovered(false);
869 impl->m_HoveredZone->setHovered(false);
846 impl->m_HoveredZone = nullptr;
870 impl->m_HoveredZone = nullptr;
847 }
871 }
848
872
849 setCursor(Qt::ArrowCursor);
873 setCursor(Qt::ArrowCursor);
850 }
874 }
851
875
852 impl->m_HasMovedMouse = true;
876 impl->m_HasMovedMouse = true;
853 VisualizationDragWidget::mouseMoveEvent(event);
877 VisualizationDragWidget::mouseMoveEvent(event);
854 }
878 }
855
879
856 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
880 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
857 {
881 {
858 auto value = event->angleDelta().x() + event->angleDelta().y();
882 auto value = event->angleDelta().x() + event->angleDelta().y();
859 if (value != 0) {
883 if (value != 0) {
860
884
861 auto direction = value > 0 ? 1.0 : -1.0;
885 auto direction = value > 0 ? 1.0 : -1.0;
862 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
886 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
863 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
887 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
864 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
888 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
865
889
866 auto zoomOrientations = QFlags<Qt::Orientation>{};
890 auto zoomOrientations = QFlags<Qt::Orientation>{};
867 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
891 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
868 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
892 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
869
893
870 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
894 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
871
895
872 if (!isZoomX && !isZoomY) {
896 if (!isZoomX && !isZoomY) {
873 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
897 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
874 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
898 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
875
899
876 axis->setRange(axis->range() + diff);
900 axis->setRange(axis->range() + diff);
877
901
878 if (plot().noAntialiasingOnDrag()) {
902 if (plot().noAntialiasingOnDrag()) {
879 plot().setNotAntialiasedElements(QCP::aeAll);
903 plot().setNotAntialiasedElements(QCP::aeAll);
880 }
904 }
881
905
882 plot().replot(QCustomPlot::rpQueuedReplot);
906 plot().replot(QCustomPlot::rpQueuedReplot);
883 }
907 }
884 }
908 }
885 }
909 }
886
910
887 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
911 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
888 {
912 {
889 auto isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
913 auto isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
890 auto isSelectionZoneMode
914 auto isSelectionZoneMode
891 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
915 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
892 auto isLeftClick = event->buttons().testFlag(Qt::LeftButton);
916 auto isLeftClick = event->buttons().testFlag(Qt::LeftButton);
893
917
894 if (!isDragDropClick && isLeftClick) {
918 if (!isDragDropClick && isLeftClick) {
895 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
919 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
896 // Starts a zoom box
920 // Starts a zoom box
897 impl->startDrawingRect(event->pos(), plot());
921 impl->startDrawingRect(event->pos(), plot());
898 }
922 }
899 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
923 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
900 // Starts a new selection zone
924 // Starts a new selection zone
901 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
925 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
902 if (!zoneAtPos) {
926 if (!zoneAtPos) {
903 impl->startDrawingZone(event->pos(), this);
927 impl->startDrawingZone(event->pos(), this);
904 }
928 }
905 }
929 }
906 }
930 }
907
931
908 // Allows mouse panning only in default mode
932 // Allows mouse panning only in default mode
909 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
933 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
910 == SqpApplication::PlotsInteractionMode::None
934 == SqpApplication::PlotsInteractionMode::None
911 && !isDragDropClick);
935 && !isDragDropClick);
912
936
913 // Allows zone edition only in selection zone mode without drag&drop
937 // Allows zone edition only in selection zone mode without drag&drop
914 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
938 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
915
939
916 // Selection / Deselection
940 // Selection / Deselection
917 if (isSelectionZoneMode) {
941 if (isSelectionZoneMode) {
918 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
942 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
919 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
943 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
920
944
921
945
922 if (selectionZoneItemUnderCursor && !selectionZoneItemUnderCursor->selected()
946 if (selectionZoneItemUnderCursor && !selectionZoneItemUnderCursor->selected()
923 && !isMultiSelectionClick) {
947 && !isMultiSelectionClick) {
924 parentVisualizationWidget()->selectionZoneManager().select(
948 parentVisualizationWidget()->selectionZoneManager().select(
925 {selectionZoneItemUnderCursor});
949 {selectionZoneItemUnderCursor});
926 }
950 }
927 else if (!selectionZoneItemUnderCursor && !isMultiSelectionClick && isLeftClick) {
951 else if (!selectionZoneItemUnderCursor && !isMultiSelectionClick && isLeftClick) {
928 parentVisualizationWidget()->selectionZoneManager().clearSelection();
952 parentVisualizationWidget()->selectionZoneManager().clearSelection();
929 }
953 }
930 else {
954 else {
931 // No selection change
955 // No selection change
932 }
956 }
933
957
934 if (selectionZoneItemUnderCursor && isLeftClick) {
958 if (selectionZoneItemUnderCursor && isLeftClick) {
935 selectionZoneItemUnderCursor->setAssociatedEditedZones(
959 selectionZoneItemUnderCursor->setAssociatedEditedZones(
936 parentVisualizationWidget()->selectionZoneManager().selectedItems());
960 parentVisualizationWidget()->selectionZoneManager().selectedItems());
937 }
961 }
938 }
962 }
939
963
940
964
941 impl->m_HasMovedMouse = false;
965 impl->m_HasMovedMouse = false;
942 VisualizationDragWidget::mousePressEvent(event);
966 VisualizationDragWidget::mousePressEvent(event);
943 }
967 }
944
968
945 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
969 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
946 {
970 {
947 if (impl->m_DrawingZoomRect) {
971 if (impl->m_DrawingZoomRect) {
948
972
949 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
973 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
950 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
974 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
951
975
952 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
976 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
953 impl->m_DrawingZoomRect->bottomRight->coords().x()};
977 impl->m_DrawingZoomRect->bottomRight->coords().x()};
954
978
955 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
979 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
956 impl->m_DrawingZoomRect->bottomRight->coords().y()};
980 impl->m_DrawingZoomRect->bottomRight->coords().y()};
957
981
958 impl->removeDrawingRect(plot());
982 impl->removeDrawingRect(plot());
959
983
960 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
984 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
961 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
985 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
962 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
986 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
963 axisX->setRange(newAxisXRange);
987 axisX->setRange(newAxisXRange);
964 axisY->setRange(newAxisYRange);
988 axisY->setRange(newAxisYRange);
965
989
966 plot().replot(QCustomPlot::rpQueuedReplot);
990 plot().replot(QCustomPlot::rpQueuedReplot);
967 }
991 }
968 }
992 }
969
993
970 impl->endDrawingZone(this);
994 impl->endDrawingZone(this);
971
995
972 // Selection / Deselection
996 // Selection / Deselection
973 auto isSelectionZoneMode
997 auto isSelectionZoneMode
974 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
998 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
975 if (isSelectionZoneMode) {
999 if (isSelectionZoneMode) {
976 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
1000 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
977 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
1001 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
978 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton
1002 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton
979 && !impl->m_HasMovedMouse) {
1003 && !impl->m_HasMovedMouse) {
980
1004
981 auto zonesUnderCursor = impl->selectionZonesAt(event->pos(), plot());
1005 auto zonesUnderCursor = impl->selectionZonesAt(event->pos(), plot());
982 if (zonesUnderCursor.count() > 1) {
1006 if (zonesUnderCursor.count() > 1) {
983 // There are multiple zones under the mouse.
1007 // There are multiple zones under the mouse.
984 // Performs the selection with a selection dialog.
1008 // Performs the selection with a selection dialog.
985 VisualizationMultiZoneSelectionDialog dialog{this};
1009 VisualizationMultiZoneSelectionDialog dialog{this};
986 dialog.setZones(zonesUnderCursor);
1010 dialog.setZones(zonesUnderCursor);
987 dialog.move(mapToGlobal(event->pos() - QPoint(dialog.width() / 2, 20)));
1011 dialog.move(mapToGlobal(event->pos() - QPoint(dialog.width() / 2, 20)));
988 dialog.activateWindow();
1012 dialog.activateWindow();
989 dialog.raise();
1013 dialog.raise();
990 if (dialog.exec() == QDialog::Accepted) {
1014 if (dialog.exec() == QDialog::Accepted) {
991 auto selection = dialog.selectedZones();
1015 auto selection = dialog.selectedZones();
992
1016
993 if (!isMultiSelectionClick) {
1017 if (!isMultiSelectionClick) {
994 parentVisualizationWidget()->selectionZoneManager().clearSelection();
1018 parentVisualizationWidget()->selectionZoneManager().clearSelection();
995 }
1019 }
996
1020
997 for (auto it = selection.cbegin(); it != selection.cend(); ++it) {
1021 for (auto it = selection.cbegin(); it != selection.cend(); ++it) {
998 auto zone = it.key();
1022 auto zone = it.key();
999 auto isSelected = it.value();
1023 auto isSelected = it.value();
1000 parentVisualizationWidget()->selectionZoneManager().setSelected(zone,
1024 parentVisualizationWidget()->selectionZoneManager().setSelected(zone,
1001 isSelected);
1025 isSelected);
1002
1026
1003 if (isSelected) {
1027 if (isSelected) {
1004 // Puts the zone on top of the stack so it can be moved or resized
1028 // Puts the zone on top of the stack so it can be moved or resized
1005 impl->moveSelectionZoneOnTop(zone, plot());
1029 impl->moveSelectionZoneOnTop(zone, plot());
1006 }
1030 }
1007 }
1031 }
1008 }
1032 }
1009 }
1033 }
1010 else {
1034 else {
1011 if (!isMultiSelectionClick) {
1035 if (!isMultiSelectionClick) {
1012 parentVisualizationWidget()->selectionZoneManager().select(
1036 parentVisualizationWidget()->selectionZoneManager().select(
1013 {selectionZoneItemUnderCursor});
1037 {selectionZoneItemUnderCursor});
1014 impl->moveSelectionZoneOnTop(selectionZoneItemUnderCursor, plot());
1038 impl->moveSelectionZoneOnTop(selectionZoneItemUnderCursor, plot());
1015 }
1039 }
1016 else {
1040 else {
1017 parentVisualizationWidget()->selectionZoneManager().setSelected(
1041 parentVisualizationWidget()->selectionZoneManager().setSelected(
1018 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
1042 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
1019 || event->button() == Qt::RightButton);
1043 || event->button() == Qt::RightButton);
1020 }
1044 }
1021 }
1045 }
1022 }
1046 }
1023 else {
1047 else {
1024 // No selection change
1048 // No selection change
1025 }
1049 }
1026 }
1050 }
1027 }
1051 }
1028
1052
1029 void VisualizationGraphWidget::onDataCacheVariableUpdated()
1053 void VisualizationGraphWidget::onDataCacheVariableUpdated()
1030 {
1054 {
1031 auto graphRange = ui->widget->xAxis->range();
1055 auto graphRange = ui->widget->xAxis->range();
1032 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
1056 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
1033
1057
1034 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
1058 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
1035 auto variable = variableEntry.first;
1059 auto variable = variableEntry.first;
1036 qCDebug(LOG_VisualizationGraphWidget())
1060 qCDebug(LOG_VisualizationGraphWidget())
1037 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
1061 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
1038 qCDebug(LOG_VisualizationGraphWidget())
1062 qCDebug(LOG_VisualizationGraphWidget())
1039 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
1063 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
1040 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
1064 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
1041 impl->updateData(variableEntry.second, variable, variable->range());
1065 impl->updateData(variableEntry.second, variable, variable->range());
1042 }
1066 }
1043 }
1067 }
1044 }
1068 }
1045
1069
1046 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
1070 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
1047 const SqpRange &range)
1071 const SqpRange &range)
1048 {
1072 {
1049 auto it = impl->m_VariableToPlotMultiMap.find(variable);
1073 auto it = impl->m_VariableToPlotMultiMap.find(variable);
1050 if (it != impl->m_VariableToPlotMultiMap.end()) {
1074 if (it != impl->m_VariableToPlotMultiMap.end()) {
1051 impl->updateData(it->second, variable, range);
1075 impl->updateData(it->second, variable, range);
1052 }
1076 }
1053 }
1077 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now