##// END OF EJS Templates
Put the align actions in sub menus
trabillard -
r1118:f354146de80e
parent child
Show More
@@ -1,22 +1,27
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
16 std::shared_ptr<SelectionZoneAction>
17 addSectionZoneAction(const QStringList &subMenuList, const QString &name,
18 SelectionZoneAction::ExecuteFunction function);
19
15 QVector<std::shared_ptr<SelectionZoneAction> > selectionZoneActions() const;
20 QVector<std::shared_ptr<SelectionZoneAction> > selectionZoneActions() const;
16
21
17 private:
22 private:
18 class ActionsGuiControllerPrivate;
23 class ActionsGuiControllerPrivate;
19 spimpl::unique_impl_ptr<ActionsGuiControllerPrivate> impl;
24 spimpl::unique_impl_ptr<ActionsGuiControllerPrivate> impl;
20 };
25 };
21
26
22 #endif // SCIQLOP_ACTIONSGUICONTROLLER_H
27 #endif // SCIQLOP_ACTIONSGUICONTROLLER_H
@@ -1,63 +1,75
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 /**
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
43 * @param fun the function that will be called when the action is executed
44 * @sa execute()
45 */
46 explicit SelectionZoneAction(const QStringList &subMenuList, const QString &name,
47 ExecuteFunction fun);
48
40 /// 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
41 void setEnableFunction(EnableFunction fun);
50 void setEnableFunction(EnableFunction fun);
42
51
43 /// Sets the shortcut displayed by the action.
52 /// Sets the shortcut displayed by the action.
44 /// 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
45 void setDisplayedShortcut(const QKeySequence &shortcut);
54 void setDisplayedShortcut(const QKeySequence &shortcut);
46 QKeySequence displayedShortcut() const;
55 QKeySequence displayedShortcut() const;
47
56
48 /// The name of the action
57 /// The name of the action
49 QString name() const noexcept;
58 QString name() const noexcept;
50
59
60 /// The path in the sub menus, if any
61 QStringList subMenuList() const noexcept;
62
51 public slots:
63 public slots:
52 /// Executes the action
64 /// Executes the action
53 void execute(const QVector<VisualizationSelectionZoneItem *> &item);
65 void execute(const QVector<VisualizationSelectionZoneItem *> &item);
54
66
55 /// Returns true if the action is enabled
67 /// Returns true if the action is enabled
56 bool isEnabled(const QVector<VisualizationSelectionZoneItem *> &item);
68 bool isEnabled(const QVector<VisualizationSelectionZoneItem *> &item);
57
69
58 private:
70 private:
59 class SelectionZoneActionPrivate;
71 class SelectionZoneActionPrivate;
60 spimpl::unique_impl_ptr<SelectionZoneActionPrivate> impl;
72 spimpl::unique_impl_ptr<SelectionZoneActionPrivate> impl;
61 };
73 };
62
74
63 #endif // SCIQLOP_SELECTIONZONEACTION_H
75 #endif // SCIQLOP_SELECTIONZONEACTION_H
@@ -1,26 +1,36
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 };
6 };
7
7
8 ActionsGuiController::ActionsGuiController()
8 ActionsGuiController::ActionsGuiController()
9 : impl{spimpl::make_unique_impl<ActionsGuiControllerPrivate>()}
9 : impl{spimpl::make_unique_impl<ActionsGuiControllerPrivate>()}
10 {
10 {
11 }
11 }
12
12
13 std::shared_ptr<SelectionZoneAction>
13 std::shared_ptr<SelectionZoneAction>
14 ActionsGuiController::addSectionZoneAction(const QString &name,
14 ActionsGuiController::addSectionZoneAction(const QString &name,
15 SelectionZoneAction::ExecuteFunction function)
15 SelectionZoneAction::ExecuteFunction function)
16 {
16 {
17 auto action = std::make_shared<SelectionZoneAction>(name, function);
17 auto action = std::make_shared<SelectionZoneAction>(name, function);
18 impl->m_SelectionZoneActions.push_back(action);
18 impl->m_SelectionZoneActions.push_back(action);
19
19
20 return action;
20 return action;
21 }
21 }
22
22
23 std::shared_ptr<SelectionZoneAction>
24 ActionsGuiController::addSectionZoneAction(const QStringList &subMenuList, const QString &name,
25 SelectionZoneAction::ExecuteFunction function)
26 {
27 auto action = std::make_shared<SelectionZoneAction>(subMenuList, name, function);
28 impl->m_SelectionZoneActions.push_back(action);
29
30 return action;
31 }
32
23 QVector<std::shared_ptr<SelectionZoneAction> > ActionsGuiController::selectionZoneActions() const
33 QVector<std::shared_ptr<SelectionZoneAction> > ActionsGuiController::selectionZoneActions() const
24 {
34 {
25 return impl->m_SelectionZoneActions;
35 return impl->m_SelectionZoneActions;
26 }
36 }
@@ -1,52 +1,66
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,
7 explicit SelectionZoneActionPrivate(const QString &name, const QStringList &subMenuList,
8 SelectionZoneAction::ExecuteFunction fun)
8 SelectionZoneAction::ExecuteFunction fun)
9 : m_Name{name}, 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 QKeySequence m_DisplayedShortcut;
15 QKeySequence m_DisplayedShortcut;
15 SelectionZoneAction::ExecuteFunction m_Fun;
16 SelectionZoneAction::ExecuteFunction m_Fun;
16 SelectionZoneAction::EnableFunction m_EnableFun = [](auto zones) { return true; };
17 SelectionZoneAction::EnableFunction m_EnableFun = [](auto zones) { return true; };
17 };
18 };
18
19
19 SelectionZoneAction::SelectionZoneAction(const QString &name, ExecuteFunction fun)
20 SelectionZoneAction::SelectionZoneAction(const QString &name, ExecuteFunction fun)
20 : impl{spimpl::make_unique_impl<SelectionZoneActionPrivate>(name, std::move(fun))}
21 : impl{spimpl::make_unique_impl<SelectionZoneActionPrivate>(name, QStringList{},
22 std::move(fun))}
23 {
24 }
25
26 SelectionZoneAction::SelectionZoneAction(const QStringList &subMenuList, const QString &name,
27 SelectionZoneAction::ExecuteFunction fun)
28 : impl{spimpl::make_unique_impl<SelectionZoneActionPrivate>(name, subMenuList,
29 std::move(fun))}
21 {
30 {
22 }
31 }
23
32
24 void SelectionZoneAction::setEnableFunction(EnableFunction fun)
33 void SelectionZoneAction::setEnableFunction(EnableFunction fun)
25 {
34 {
26 impl->m_EnableFun = std::move(fun);
35 impl->m_EnableFun = std::move(fun);
27 }
36 }
28
37
29 void SelectionZoneAction::setDisplayedShortcut(const QKeySequence &shortcut)
38 void SelectionZoneAction::setDisplayedShortcut(const QKeySequence &shortcut)
30 {
39 {
31 impl->m_DisplayedShortcut = shortcut;
40 impl->m_DisplayedShortcut = shortcut;
32 }
41 }
33
42
34 QKeySequence SelectionZoneAction::displayedShortcut() const
43 QKeySequence SelectionZoneAction::displayedShortcut() const
35 {
44 {
36 return impl->m_DisplayedShortcut;
45 return impl->m_DisplayedShortcut;
37 }
46 }
38
47
39 QString SelectionZoneAction::name() const noexcept
48 QString SelectionZoneAction::name() const noexcept
40 {
49 {
41 return impl->m_Name;
50 return impl->m_Name;
42 }
51 }
43
52
53 QStringList SelectionZoneAction::subMenuList() const noexcept
54 {
55 return impl->m_SubMenuList;
56 }
57
44 void SelectionZoneAction::execute(const QVector<VisualizationSelectionZoneItem *> &item)
58 void SelectionZoneAction::execute(const QVector<VisualizationSelectionZoneItem *> &item)
45 {
59 {
46 impl->m_Fun(item);
60 impl->m_Fun(item);
47 }
61 }
48
62
49 bool SelectionZoneAction::isEnabled(const QVector<VisualizationSelectionZoneItem *> &item)
63 bool SelectionZoneAction::isEnabled(const QVector<VisualizationSelectionZoneItem *> &item)
50 {
64 {
51 return impl->m_EnableFun(item);
65 return impl->m_EnableFun(item);
52 }
66 }
@@ -1,109 +1,109
1 #include "Visualization/VisualizationActionManager.h"
1 #include "Visualization/VisualizationActionManager.h"
2 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/VisualizationGraphWidget.h"
3 #include "Visualization/VisualizationSelectionZoneItem.h"
3 #include "Visualization/VisualizationSelectionZoneItem.h"
4
4
5 #include <Actions/ActionsGuiController.h>
5 #include <Actions/ActionsGuiController.h>
6 #include <SqpApplication.h>
6 #include <SqpApplication.h>
7
7
8 VisualizationActionManager::VisualizationActionManager() {}
8 VisualizationActionManager::VisualizationActionManager() {}
9
9
10 void VisualizationActionManager::installSelectionZoneActions()
10 void VisualizationActionManager::installSelectionZoneActions()
11 {
11 {
12 auto &actionController = sqpApp->actionsGuiController();
12 auto &actionController = sqpApp->actionsGuiController();
13
13
14 auto removeZonesAction
14 auto removeZonesAction
15 = actionController.addSectionZoneAction("Remove Selected Zone(s)", [](auto zones) {
15 = actionController.addSectionZoneAction("Remove Selected Zone(s)", [](auto zones) {
16 for (auto selectionZone : zones) {
16 for (auto selectionZone : zones) {
17 if (auto graph = selectionZone->parentGraphWidget()) {
17 if (auto graph = selectionZone->parentGraphWidget()) {
18 graph->removeSelectionZone(selectionZone);
18 graph->removeSelectionZone(selectionZone);
19 }
19 }
20 }
20 }
21 });
21 });
22 removeZonesAction->setDisplayedShortcut(QKeySequence::Delete);
22 removeZonesAction->setDisplayedShortcut(QKeySequence::Delete);
23
23
24 auto alignEnableFuntion = [](auto items) { return items.count() > 1; };
24 auto alignEnableFuntion = [](auto items) { return items.count() > 1; };
25
25
26 // Vertical alignment actions
26 // Vertical alignment actions
27 auto alignLeftAction
27 auto alignLeftAction = actionController.addSectionZoneAction(
28 = actionController.addSectionZoneAction("Align Vertically / Left", [](auto zones) {
28 QStringList{"Align Vertically"}, "Left", [](auto zones) {
29 Q_ASSERT(zones.count() > 1);
29 Q_ASSERT(zones.count() > 1);
30 auto ref = zones.takeFirst();
30 auto ref = zones.takeFirst();
31 ref->alignZonesVerticallyOnLeft(zones, false);
31 ref->alignZonesVerticallyOnLeft(zones, false);
32 });
32 });
33 alignLeftAction->setEnableFunction(alignEnableFuntion);
33 alignLeftAction->setEnableFunction(alignEnableFuntion);
34
34
35 auto alignLeftBorderAction
35 auto alignLeftBorderAction = actionController.addSectionZoneAction(
36 = actionController.addSectionZoneAction("Align Vertically / Left Borders", [](auto zones) {
36 QStringList{"Align Vertically"}, "Left Borders", [](auto zones) {
37 Q_ASSERT(zones.count() > 1);
37 Q_ASSERT(zones.count() > 1);
38 auto ref = zones.takeFirst();
38 auto ref = zones.takeFirst();
39 ref->alignZonesVerticallyOnLeft(zones, true);
39 ref->alignZonesVerticallyOnLeft(zones, true);
40 });
40 });
41 alignLeftBorderAction->setEnableFunction(alignEnableFuntion);
41 alignLeftBorderAction->setEnableFunction(alignEnableFuntion);
42
42
43 auto alignRightAction
43 auto alignRightAction = actionController.addSectionZoneAction(
44 = actionController.addSectionZoneAction("Align Vertically / Right", [](auto zones) {
44 QStringList{"Align Vertically"}, "Right", [](auto zones) {
45 Q_ASSERT(zones.count() > 1);
45 Q_ASSERT(zones.count() > 1);
46 auto ref = zones.takeFirst();
46 auto ref = zones.takeFirst();
47 ref->alignZonesVerticallyOnRight(zones, false);
47 ref->alignZonesVerticallyOnRight(zones, false);
48 });
48 });
49 alignRightAction->setEnableFunction(alignEnableFuntion);
49 alignRightAction->setEnableFunction(alignEnableFuntion);
50
50
51 auto alignRightBorderAction
51 auto alignRightBorderAction = actionController.addSectionZoneAction(
52 = actionController.addSectionZoneAction("Align Vertically / Right Borders", [](auto zones) {
52 QStringList{"Align Vertically"}, "Right Borders", [](auto zones) {
53 Q_ASSERT(zones.count() > 1);
53 Q_ASSERT(zones.count() > 1);
54 auto ref = zones.takeFirst();
54 auto ref = zones.takeFirst();
55 ref->alignZonesVerticallyOnRight(zones, true);
55 ref->alignZonesVerticallyOnRight(zones, true);
56 });
56 });
57 alignRightBorderAction->setEnableFunction(alignEnableFuntion);
57 alignRightBorderAction->setEnableFunction(alignEnableFuntion);
58
58
59 auto alignLeftAndRightAction = actionController.addSectionZoneAction(
59 auto alignLeftAndRightAction = actionController.addSectionZoneAction(
60 "Align Vertically / Left and Right", [](auto zones) {
60 QStringList{"Align Vertically"}, "Left and Right", [](auto zones) {
61 Q_ASSERT(zones.count() > 1);
61 Q_ASSERT(zones.count() > 1);
62 auto ref = zones.takeFirst();
62 auto ref = zones.takeFirst();
63 ref->alignZonesVerticallyOnLeft(zones, false);
63 ref->alignZonesVerticallyOnLeft(zones, false);
64 ref->alignZonesVerticallyOnRight(zones, true);
64 ref->alignZonesVerticallyOnRight(zones, true);
65 });
65 });
66 alignLeftAndRightAction->setEnableFunction(alignEnableFuntion);
66 alignLeftAndRightAction->setEnableFunction(alignEnableFuntion);
67
67
68 // Temporal alignment actions
68 // Temporal alignment actions
69 auto alignLeftTemporallyAction
69 auto alignLeftTemporallyAction = actionController.addSectionZoneAction(
70 = actionController.addSectionZoneAction("Align Temporally / Left", [](auto zones) {
70 QStringList{"Align Temporally"}, "Left", [](auto zones) {
71 Q_ASSERT(zones.count() > 1);
71 Q_ASSERT(zones.count() > 1);
72 auto ref = zones.takeFirst();
72 auto ref = zones.takeFirst();
73 ref->alignZonesTemporallyOnLeft(zones, false);
73 ref->alignZonesTemporallyOnLeft(zones, false);
74 });
74 });
75 alignLeftTemporallyAction->setEnableFunction(alignEnableFuntion);
75 alignLeftTemporallyAction->setEnableFunction(alignEnableFuntion);
76
76
77 auto alignLeftBorderTemporallyAction
77 auto alignLeftBorderTemporallyAction = actionController.addSectionZoneAction(
78 = actionController.addSectionZoneAction("Align Temporally / Left Borders", [](auto zones) {
78 QStringList{"Align Temporally"}, "Left Borders", [](auto zones) {
79 Q_ASSERT(zones.count() > 1);
79 Q_ASSERT(zones.count() > 1);
80 auto ref = zones.takeFirst();
80 auto ref = zones.takeFirst();
81 ref->alignZonesTemporallyOnLeft(zones, true);
81 ref->alignZonesTemporallyOnLeft(zones, true);
82 });
82 });
83 alignLeftBorderTemporallyAction->setEnableFunction(alignEnableFuntion);
83 alignLeftBorderTemporallyAction->setEnableFunction(alignEnableFuntion);
84
84
85 auto alignRightTemporallyAction
85 auto alignRightTemporallyAction = actionController.addSectionZoneAction(
86 = actionController.addSectionZoneAction("Align Temporally / Right", [](auto zones) {
86 QStringList{"Align Temporally"}, "Right", [](auto zones) {
87 Q_ASSERT(zones.count() > 1);
87 Q_ASSERT(zones.count() > 1);
88 auto ref = zones.takeFirst();
88 auto ref = zones.takeFirst();
89 ref->alignZonesTemporallyOnRight(zones, false);
89 ref->alignZonesTemporallyOnRight(zones, false);
90 });
90 });
91 alignRightTemporallyAction->setEnableFunction(alignEnableFuntion);
91 alignRightTemporallyAction->setEnableFunction(alignEnableFuntion);
92
92
93 auto alignRightBorderTemporallyAction
93 auto alignRightBorderTemporallyAction = actionController.addSectionZoneAction(
94 = actionController.addSectionZoneAction("Align Temporally / Right Borders", [](auto zones) {
94 QStringList{"Align Temporally"}, "Right Borders", [](auto zones) {
95 Q_ASSERT(zones.count() > 1);
95 Q_ASSERT(zones.count() > 1);
96 auto ref = zones.takeFirst();
96 auto ref = zones.takeFirst();
97 ref->alignZonesTemporallyOnRight(zones, true);
97 ref->alignZonesTemporallyOnRight(zones, true);
98 });
98 });
99 alignRightBorderTemporallyAction->setEnableFunction(alignEnableFuntion);
99 alignRightBorderTemporallyAction->setEnableFunction(alignEnableFuntion);
100
100
101 auto alignLeftAndRightTemporallyAction = actionController.addSectionZoneAction(
101 auto alignLeftAndRightTemporallyAction = actionController.addSectionZoneAction(
102 "Align Temporally / Left and Right", [](auto zones) {
102 QStringList{"Align Temporally"}, "Left and Right", [](auto zones) {
103 Q_ASSERT(zones.count() > 1);
103 Q_ASSERT(zones.count() > 1);
104 auto ref = zones.takeFirst();
104 auto ref = zones.takeFirst();
105 ref->alignZonesTemporallyOnLeft(zones, false);
105 ref->alignZonesTemporallyOnLeft(zones, false);
106 ref->alignZonesTemporallyOnRight(zones, true);
106 ref->alignZonesTemporallyOnRight(zones, true);
107 });
107 });
108 alignLeftAndRightTemporallyAction->setEnableFunction(alignEnableFuntion);
108 alignLeftAndRightTemporallyAction->setEnableFunction(alignEnableFuntion);
109 }
109 }
@@ -1,911 +1,938
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/VisualizationSelectionZoneItem.h"
7 #include "Visualization/VisualizationSelectionZoneItem.h"
8 #include "Visualization/VisualizationSelectionZoneManager.h"
8 #include "Visualization/VisualizationSelectionZoneManager.h"
9 #include "Visualization/VisualizationWidget.h"
9 #include "Visualization/VisualizationWidget.h"
10 #include "Visualization/VisualizationZoneWidget.h"
10 #include "Visualization/VisualizationZoneWidget.h"
11 #include "ui_VisualizationGraphWidget.h"
11 #include "ui_VisualizationGraphWidget.h"
12
12
13 #include <Actions/ActionsGuiController.h>
13 #include <Actions/ActionsGuiController.h>
14 #include <Common/MimeTypesDef.h>
14 #include <Common/MimeTypesDef.h>
15 #include <Data/ArrayData.h>
15 #include <Data/ArrayData.h>
16 #include <Data/IDataSeries.h>
16 #include <Data/IDataSeries.h>
17 #include <Data/SpectrogramSeries.h>
17 #include <Data/SpectrogramSeries.h>
18 #include <DragAndDrop/DragDropGuiController.h>
18 #include <DragAndDrop/DragDropGuiController.h>
19 #include <Settings/SqpSettingsDefs.h>
19 #include <Settings/SqpSettingsDefs.h>
20 #include <SqpApplication.h>
20 #include <SqpApplication.h>
21 #include <Time/TimeController.h>
21 #include <Time/TimeController.h>
22 #include <Variable/Variable.h>
22 #include <Variable/Variable.h>
23 #include <Variable/VariableController.h>
23 #include <Variable/VariableController.h>
24
24
25 #include <unordered_map>
25 #include <unordered_map>
26
26
27 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
27 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
28
28
29 namespace {
29 namespace {
30
30
31 /// Key pressed to enable drag&drop in all modes
31 /// Key pressed to enable drag&drop in all modes
32 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
32 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
33
33
34 /// Key pressed to enable zoom on horizontal axis
34 /// Key pressed to enable zoom on horizontal axis
35 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
35 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
36
36
37 /// Key pressed to enable zoom on vertical axis
37 /// Key pressed to enable zoom on vertical axis
38 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
38 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
39
39
40 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
40 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
41 const auto PAN_SPEED = 5;
41 const auto PAN_SPEED = 5;
42
42
43 /// Key pressed to enable a calibration pan
43 /// Key pressed to enable a calibration pan
44 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
44 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
45
45
46 /// Key pressed to enable multi selection of selection zones
46 /// Key pressed to enable multi selection of selection zones
47 const auto MULTI_ZONE_SELECTION_MODIFIER = Qt::ControlModifier;
47 const auto MULTI_ZONE_SELECTION_MODIFIER = Qt::ControlModifier;
48
48
49 /// Minimum size for the zoom box, in percentage of the axis range
49 /// Minimum size for the zoom box, in percentage of the axis range
50 const auto ZOOM_BOX_MIN_SIZE = 0.8;
50 const auto ZOOM_BOX_MIN_SIZE = 0.8;
51
51
52 /// Format of the dates appearing in the label of a cursor
52 /// Format of the dates appearing in the label of a cursor
53 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
53 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
54
54
55 } // namespace
55 } // namespace
56
56
57 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
57 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
58
58
59 explicit VisualizationGraphWidgetPrivate(const QString &name)
59 explicit VisualizationGraphWidgetPrivate(const QString &name)
60 : m_Name{name},
60 : m_Name{name},
61 m_DoAcquisition{true},
61 m_DoAcquisition{true},
62 m_IsCalibration{false},
62 m_IsCalibration{false},
63 m_RenderingDelegate{nullptr}
63 m_RenderingDelegate{nullptr}
64 {
64 {
65 }
65 }
66
66
67 void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
67 void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
68 const SqpRange &range)
68 const SqpRange &range)
69 {
69 {
70 VisualizationGraphHelper::updateData(plottables, dataSeries, range);
70 VisualizationGraphHelper::updateData(plottables, dataSeries, range);
71
71
72 // Prevents that data has changed to update rendering
72 // Prevents that data has changed to update rendering
73 m_RenderingDelegate->onPlotUpdated();
73 m_RenderingDelegate->onPlotUpdated();
74 }
74 }
75
75
76 QString m_Name;
76 QString m_Name;
77 // 1 variable -> n qcpplot
77 // 1 variable -> n qcpplot
78 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
78 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
79 bool m_DoAcquisition;
79 bool m_DoAcquisition;
80 bool m_IsCalibration;
80 bool m_IsCalibration;
81 /// Delegate used to attach rendering features to the plot
81 /// Delegate used to attach rendering features to the plot
82 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
82 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
83
83
84 QCPItemRect *m_DrawingZoomRect = nullptr;
84 QCPItemRect *m_DrawingZoomRect = nullptr;
85 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
85 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
86
86
87 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
87 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
88 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
88 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
89
89
90 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
90 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
91 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
91 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
92 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
92 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
93
93
94 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
94 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
95
95
96 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
96 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
97 {
97 {
98 removeDrawingRect(plot);
98 removeDrawingRect(plot);
99
99
100 auto axisPos = posToAxisPos(pos, plot);
100 auto axisPos = posToAxisPos(pos, plot);
101
101
102 m_DrawingZoomRect = new QCPItemRect{&plot};
102 m_DrawingZoomRect = new QCPItemRect{&plot};
103 QPen p;
103 QPen p;
104 p.setWidth(2);
104 p.setWidth(2);
105 m_DrawingZoomRect->setPen(p);
105 m_DrawingZoomRect->setPen(p);
106
106
107 m_DrawingZoomRect->topLeft->setCoords(axisPos);
107 m_DrawingZoomRect->topLeft->setCoords(axisPos);
108 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
108 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
109 }
109 }
110
110
111 void removeDrawingRect(QCustomPlot &plot)
111 void removeDrawingRect(QCustomPlot &plot)
112 {
112 {
113 if (m_DrawingZoomRect) {
113 if (m_DrawingZoomRect) {
114 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
114 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
115 m_DrawingZoomRect = nullptr;
115 m_DrawingZoomRect = nullptr;
116 plot.replot(QCustomPlot::rpQueuedReplot);
116 plot.replot(QCustomPlot::rpQueuedReplot);
117 }
117 }
118 }
118 }
119
119
120 void startDrawingZone(const QPoint &pos, VisualizationGraphWidget *graph)
120 void startDrawingZone(const QPoint &pos, VisualizationGraphWidget *graph)
121 {
121 {
122 endDrawingZone(graph);
122 endDrawingZone(graph);
123
123
124 auto axisPos = posToAxisPos(pos, graph->plot());
124 auto axisPos = posToAxisPos(pos, graph->plot());
125
125
126 m_DrawingZone = new VisualizationSelectionZoneItem{&graph->plot()};
126 m_DrawingZone = new VisualizationSelectionZoneItem{&graph->plot()};
127 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
127 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
128 m_DrawingZone->setEditionEnabled(false);
128 m_DrawingZone->setEditionEnabled(false);
129 }
129 }
130
130
131 void endDrawingZone(VisualizationGraphWidget *graph)
131 void endDrawingZone(VisualizationGraphWidget *graph)
132 {
132 {
133 if (m_DrawingZone) {
133 if (m_DrawingZone) {
134 auto drawingZoneRange = m_DrawingZone->range();
134 auto drawingZoneRange = m_DrawingZone->range();
135 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
135 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
136 m_DrawingZone->setEditionEnabled(true);
136 m_DrawingZone->setEditionEnabled(true);
137 addSelectionZone(m_DrawingZone);
137 addSelectionZone(m_DrawingZone);
138 }
138 }
139 else {
139 else {
140 graph->plot().removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
140 graph->plot().removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
141 }
141 }
142
142
143 graph->plot().replot(QCustomPlot::rpQueuedReplot);
143 graph->plot().replot(QCustomPlot::rpQueuedReplot);
144 m_DrawingZone = nullptr;
144 m_DrawingZone = nullptr;
145 }
145 }
146 }
146 }
147
147
148 void setSelectionZonesEditionEnabled(bool value)
148 void setSelectionZonesEditionEnabled(bool value)
149 {
149 {
150 for (auto s : m_SelectionZones) {
150 for (auto s : m_SelectionZones) {
151 s->setEditionEnabled(value);
151 s->setEditionEnabled(value);
152 }
152 }
153 }
153 }
154
154
155 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
155 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
156
156
157 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
157 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
158 const QCustomPlot &plot) const
158 const QCustomPlot &plot) const
159 {
159 {
160 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
160 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
161 auto minDistanceToZone = -1;
161 auto minDistanceToZone = -1;
162 for (auto zone : m_SelectionZones) {
162 for (auto zone : m_SelectionZones) {
163 auto distanceToZone = zone->selectTest(pos, false);
163 auto distanceToZone = zone->selectTest(pos, false);
164 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
164 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
165 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
165 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
166 selectionZoneItemUnderCursor = zone;
166 selectionZoneItemUnderCursor = zone;
167 }
167 }
168 }
168 }
169
169
170 return selectionZoneItemUnderCursor;
170 return selectionZoneItemUnderCursor;
171 }
171 }
172
172
173 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
173 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
174 {
174 {
175 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
175 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
176 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
176 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
177 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
177 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
178 }
178 }
179
179
180 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
180 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
181 {
181 {
182 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
182 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
183 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
183 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
184 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
184 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
185 }
185 }
186 };
186 };
187
187
188 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
188 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
189 : VisualizationDragWidget{parent},
189 : VisualizationDragWidget{parent},
190 ui{new Ui::VisualizationGraphWidget},
190 ui{new Ui::VisualizationGraphWidget},
191 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
191 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
192 {
192 {
193 ui->setupUi(this);
193 ui->setupUi(this);
194
194
195 // 'Close' options : widget is deleted when closed
195 // 'Close' options : widget is deleted when closed
196 setAttribute(Qt::WA_DeleteOnClose);
196 setAttribute(Qt::WA_DeleteOnClose);
197
197
198 // Set qcpplot properties :
198 // Set qcpplot properties :
199 // - zoom is enabled
199 // - zoom is enabled
200 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
200 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
201 ui->widget->setInteractions(QCP::iRangeZoom);
201 ui->widget->setInteractions(QCP::iRangeZoom);
202 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
202 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
203
203
204 // The delegate must be initialized after the ui as it uses the plot
204 // The delegate must be initialized after the ui as it uses the plot
205 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
205 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
206
206
207 // Init the cursors
207 // Init the cursors
208 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
208 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
209 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
209 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
210 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
210 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
211 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
211 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
212
212
213 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
213 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
214 connect(ui->widget, &QCustomPlot::mouseRelease, this,
214 connect(ui->widget, &QCustomPlot::mouseRelease, this,
215 &VisualizationGraphWidget::onMouseRelease);
215 &VisualizationGraphWidget::onMouseRelease);
216 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
216 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
217 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
217 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
218 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
218 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
219 &VisualizationGraphWidget::onMouseDoubleClick);
219 &VisualizationGraphWidget::onMouseDoubleClick);
220 connect(
220 connect(
221 ui->widget->xAxis,
221 ui->widget->xAxis,
222 static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(&QCPAxis::rangeChanged),
222 static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(&QCPAxis::rangeChanged),
223 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
223 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
224
224
225 // Activates menu when right clicking on the graph
225 // Activates menu when right clicking on the graph
226 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
226 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
227 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
227 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
228 &VisualizationGraphWidget::onGraphMenuRequested);
228 &VisualizationGraphWidget::onGraphMenuRequested);
229
229
230 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
230 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
231 &VariableController::onRequestDataLoading);
231 &VariableController::onRequestDataLoading);
232
232
233 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
233 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
234 &VisualizationGraphWidget::onUpdateVarDisplaying);
234 &VisualizationGraphWidget::onUpdateVarDisplaying);
235
235
236 #ifdef Q_OS_MAC
236 #ifdef Q_OS_MAC
237 plot().setPlottingHint(QCP::phFastPolylines, true);
237 plot().setPlottingHint(QCP::phFastPolylines, true);
238 #endif
238 #endif
239 }
239 }
240
240
241
241
242 VisualizationGraphWidget::~VisualizationGraphWidget()
242 VisualizationGraphWidget::~VisualizationGraphWidget()
243 {
243 {
244 delete ui;
244 delete ui;
245 }
245 }
246
246
247 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
247 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
248 {
248 {
249 auto parent = parentWidget();
249 auto parent = parentWidget();
250 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
250 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
251 parent = parent->parentWidget();
251 parent = parent->parentWidget();
252 }
252 }
253
253
254 return qobject_cast<VisualizationZoneWidget *>(parent);
254 return qobject_cast<VisualizationZoneWidget *>(parent);
255 }
255 }
256
256
257 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
257 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
258 {
258 {
259 auto parent = parentWidget();
259 auto parent = parentWidget();
260 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
260 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
261 parent = parent->parentWidget();
261 parent = parent->parentWidget();
262 }
262 }
263
263
264 return qobject_cast<VisualizationWidget *>(parent);
264 return qobject_cast<VisualizationWidget *>(parent);
265 }
265 }
266
266
267 void VisualizationGraphWidget::enableAcquisition(bool enable)
267 void VisualizationGraphWidget::enableAcquisition(bool enable)
268 {
268 {
269 impl->m_DoAcquisition = enable;
269 impl->m_DoAcquisition = enable;
270 }
270 }
271
271
272 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
272 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
273 {
273 {
274 // Uses delegate to create the qcpplot components according to the variable
274 // Uses delegate to create the qcpplot components according to the variable
275 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
275 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
276
276
277 if (auto dataSeries = variable->dataSeries()) {
277 if (auto dataSeries = variable->dataSeries()) {
278 // Set axes properties according to the units of the data series
278 // Set axes properties according to the units of the data series
279 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
279 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
280
280
281 // Sets rendering properties for the new plottables
281 // Sets rendering properties for the new plottables
282 // Warning: this method must be called after setAxesProperties(), as it can access to some
282 // Warning: this method must be called after setAxesProperties(), as it can access to some
283 // axes properties that have to be initialized
283 // axes properties that have to be initialized
284 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
284 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
285 }
285 }
286
286
287 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
287 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
288
288
289 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
289 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
290
290
291 this->enableAcquisition(false);
291 this->enableAcquisition(false);
292 this->setGraphRange(range);
292 this->setGraphRange(range);
293 this->enableAcquisition(true);
293 this->enableAcquisition(true);
294
294
295 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
295 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
296
296
297 emit variableAdded(variable);
297 emit variableAdded(variable);
298 }
298 }
299
299
300 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
300 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
301 {
301 {
302 // Each component associated to the variable :
302 // Each component associated to the variable :
303 // - is removed from qcpplot (which deletes it)
303 // - is removed from qcpplot (which deletes it)
304 // - is no longer referenced in the map
304 // - is no longer referenced in the map
305 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
305 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
306 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
306 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
307 emit variableAboutToBeRemoved(variable);
307 emit variableAboutToBeRemoved(variable);
308
308
309 auto &plottablesMap = variableIt->second;
309 auto &plottablesMap = variableIt->second;
310
310
311 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
311 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
312 plottableIt != plottableEnd;) {
312 plottableIt != plottableEnd;) {
313 ui->widget->removePlottable(plottableIt->second);
313 ui->widget->removePlottable(plottableIt->second);
314 plottableIt = plottablesMap.erase(plottableIt);
314 plottableIt = plottablesMap.erase(plottableIt);
315 }
315 }
316
316
317 impl->m_VariableToPlotMultiMap.erase(variableIt);
317 impl->m_VariableToPlotMultiMap.erase(variableIt);
318 }
318 }
319
319
320 // Updates graph
320 // Updates graph
321 ui->widget->replot();
321 ui->widget->replot();
322 }
322 }
323
323
324 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
324 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
325 {
325 {
326 auto variables = QList<std::shared_ptr<Variable> >{};
326 auto variables = QList<std::shared_ptr<Variable> >{};
327 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
327 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
328 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
328 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
329 variables << it->first;
329 variables << it->first;
330 }
330 }
331
331
332 return variables;
332 return variables;
333 }
333 }
334
334
335 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
335 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
336 {
336 {
337 if (!variable) {
337 if (!variable) {
338 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
338 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
339 return;
339 return;
340 }
340 }
341
341
342 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
342 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
343 }
343 }
344
344
345 SqpRange VisualizationGraphWidget::graphRange() const noexcept
345 SqpRange VisualizationGraphWidget::graphRange() const noexcept
346 {
346 {
347 auto graphRange = ui->widget->xAxis->range();
347 auto graphRange = ui->widget->xAxis->range();
348 return SqpRange{graphRange.lower, graphRange.upper};
348 return SqpRange{graphRange.lower, graphRange.upper};
349 }
349 }
350
350
351 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
351 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
352 {
352 {
353 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
353 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
354 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
354 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
355 ui->widget->replot();
355 ui->widget->replot();
356 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
356 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
357 }
357 }
358
358
359 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
359 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
360 {
360 {
361 QVector<SqpRange> ranges;
361 QVector<SqpRange> ranges;
362 for (auto zone : impl->m_SelectionZones) {
362 for (auto zone : impl->m_SelectionZones) {
363 ranges << zone->range();
363 ranges << zone->range();
364 }
364 }
365
365
366 return ranges;
366 return ranges;
367 }
367 }
368
368
369 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
369 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
370 {
370 {
371 for (const auto &range : ranges) {
371 for (const auto &range : ranges) {
372 // note: ownership is transfered to QCustomPlot
372 // note: ownership is transfered to QCustomPlot
373 auto zone = new VisualizationSelectionZoneItem(&plot());
373 auto zone = new VisualizationSelectionZoneItem(&plot());
374 zone->setRange(range.m_TStart, range.m_TEnd);
374 zone->setRange(range.m_TStart, range.m_TEnd);
375 impl->addSelectionZone(zone);
375 impl->addSelectionZone(zone);
376 }
376 }
377
377
378 plot().replot(QCustomPlot::rpQueuedReplot);
378 plot().replot(QCustomPlot::rpQueuedReplot);
379 }
379 }
380
380
381 void VisualizationGraphWidget::removeSelectionZone(VisualizationSelectionZoneItem *selectionZone)
381 void VisualizationGraphWidget::removeSelectionZone(VisualizationSelectionZoneItem *selectionZone)
382 {
382 {
383 parentVisualizationWidget()->selectionZoneManager().setSelected(selectionZone, false);
383 parentVisualizationWidget()->selectionZoneManager().setSelected(selectionZone, false);
384
384
385 if (impl->m_HoveredZone == selectionZone) {
385 if (impl->m_HoveredZone == selectionZone) {
386 impl->m_HoveredZone = nullptr;
386 impl->m_HoveredZone = nullptr;
387 setCursor(Qt::ArrowCursor);
387 setCursor(Qt::ArrowCursor);
388 }
388 }
389
389
390 impl->m_SelectionZones.removeAll(selectionZone);
390 impl->m_SelectionZones.removeAll(selectionZone);
391 plot().removeItem(selectionZone);
391 plot().removeItem(selectionZone);
392 plot().replot(QCustomPlot::rpQueuedReplot);
392 plot().replot(QCustomPlot::rpQueuedReplot);
393 }
393 }
394
394
395 void VisualizationGraphWidget::undoZoom()
395 void VisualizationGraphWidget::undoZoom()
396 {
396 {
397 auto zoom = impl->m_ZoomStack.pop();
397 auto zoom = impl->m_ZoomStack.pop();
398 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
398 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
399 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
399 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
400
400
401 axisX->setRange(zoom.first);
401 axisX->setRange(zoom.first);
402 axisY->setRange(zoom.second);
402 axisY->setRange(zoom.second);
403
403
404 plot().replot(QCustomPlot::rpQueuedReplot);
404 plot().replot(QCustomPlot::rpQueuedReplot);
405 }
405 }
406
406
407 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
407 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
408 {
408 {
409 if (visitor) {
409 if (visitor) {
410 visitor->visit(this);
410 visitor->visit(this);
411 }
411 }
412 else {
412 else {
413 qCCritical(LOG_VisualizationGraphWidget())
413 qCCritical(LOG_VisualizationGraphWidget())
414 << tr("Can't visit widget : the visitor is null");
414 << tr("Can't visit widget : the visitor is null");
415 }
415 }
416 }
416 }
417
417
418 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
418 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
419 {
419 {
420 auto isSpectrogram = [](const auto &variable) {
420 auto isSpectrogram = [](const auto &variable) {
421 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
421 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
422 };
422 };
423
423
424 // - A spectrogram series can't be dropped on graph with existing plottables
424 // - A spectrogram series can't be dropped on graph with existing plottables
425 // - No data series can be dropped on graph with existing spectrogram series
425 // - No data series can be dropped on graph with existing spectrogram series
426 return isSpectrogram(variable)
426 return isSpectrogram(variable)
427 ? impl->m_VariableToPlotMultiMap.empty()
427 ? impl->m_VariableToPlotMultiMap.empty()
428 : std::none_of(
428 : std::none_of(
429 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
429 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
430 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
430 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
431 }
431 }
432
432
433 bool VisualizationGraphWidget::contains(const Variable &variable) const
433 bool VisualizationGraphWidget::contains(const Variable &variable) const
434 {
434 {
435 // Finds the variable among the keys of the map
435 // Finds the variable among the keys of the map
436 auto variablePtr = &variable;
436 auto variablePtr = &variable;
437 auto findVariable
437 auto findVariable
438 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
438 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
439
439
440 auto end = impl->m_VariableToPlotMultiMap.cend();
440 auto end = impl->m_VariableToPlotMultiMap.cend();
441 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
441 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
442 return it != end;
442 return it != end;
443 }
443 }
444
444
445 QString VisualizationGraphWidget::name() const
445 QString VisualizationGraphWidget::name() const
446 {
446 {
447 return impl->m_Name;
447 return impl->m_Name;
448 }
448 }
449
449
450 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
450 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
451 {
451 {
452 auto mimeData = new QMimeData;
452 auto mimeData = new QMimeData;
453
453
454 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
454 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
455 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
455 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
456 && selectionZoneItemUnderCursor) {
456 && selectionZoneItemUnderCursor) {
457 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
457 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
458 selectionZoneItemUnderCursor->range()));
458 selectionZoneItemUnderCursor->range()));
459 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
459 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
460 selectionZoneItemUnderCursor->range()));
460 selectionZoneItemUnderCursor->range()));
461 }
461 }
462 else {
462 else {
463 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
463 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
464
464
465 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
465 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
466 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
466 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
467 }
467 }
468
468
469 return mimeData;
469 return mimeData;
470 }
470 }
471
471
472 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
472 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
473 {
473 {
474 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
474 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
475 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
475 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
476 && selectionZoneItemUnderCursor) {
476 && selectionZoneItemUnderCursor) {
477
477
478 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
478 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
479 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
479 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
480
480
481 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
481 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
482 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
482 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
483 .toSize();
483 .toSize();
484
484
485 auto pixmap = QPixmap(zoneSize);
485 auto pixmap = QPixmap(zoneSize);
486 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
486 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
487
487
488 return pixmap;
488 return pixmap;
489 }
489 }
490
490
491 return QPixmap();
491 return QPixmap();
492 }
492 }
493
493
494 bool VisualizationGraphWidget::isDragAllowed() const
494 bool VisualizationGraphWidget::isDragAllowed() const
495 {
495 {
496 return true;
496 return true;
497 }
497 }
498
498
499 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
499 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
500 {
500 {
501 if (highlighted) {
501 if (highlighted) {
502 plot().setBackground(QBrush(QColor("#BBD5EE")));
502 plot().setBackground(QBrush(QColor("#BBD5EE")));
503 }
503 }
504 else {
504 else {
505 plot().setBackground(QBrush(Qt::white));
505 plot().setBackground(QBrush(Qt::white));
506 }
506 }
507
507
508 plot().update();
508 plot().update();
509 }
509 }
510
510
511 void VisualizationGraphWidget::addVerticalCursor(double time)
511 void VisualizationGraphWidget::addVerticalCursor(double time)
512 {
512 {
513 impl->m_VerticalCursor->setPosition(time);
513 impl->m_VerticalCursor->setPosition(time);
514 impl->m_VerticalCursor->setVisible(true);
514 impl->m_VerticalCursor->setVisible(true);
515
515
516 auto text
516 auto text
517 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
517 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
518 impl->m_VerticalCursor->setLabelText(text);
518 impl->m_VerticalCursor->setLabelText(text);
519 }
519 }
520
520
521 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
521 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
522 {
522 {
523 impl->m_VerticalCursor->setAbsolutePosition(position);
523 impl->m_VerticalCursor->setAbsolutePosition(position);
524 impl->m_VerticalCursor->setVisible(true);
524 impl->m_VerticalCursor->setVisible(true);
525
525
526 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
526 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
527 auto text
527 auto text
528 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
528 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
529 impl->m_VerticalCursor->setLabelText(text);
529 impl->m_VerticalCursor->setLabelText(text);
530 }
530 }
531
531
532 void VisualizationGraphWidget::removeVerticalCursor()
532 void VisualizationGraphWidget::removeVerticalCursor()
533 {
533 {
534 impl->m_VerticalCursor->setVisible(false);
534 impl->m_VerticalCursor->setVisible(false);
535 plot().replot(QCustomPlot::rpQueuedReplot);
535 plot().replot(QCustomPlot::rpQueuedReplot);
536 }
536 }
537
537
538 void VisualizationGraphWidget::addHorizontalCursor(double value)
538 void VisualizationGraphWidget::addHorizontalCursor(double value)
539 {
539 {
540 impl->m_HorizontalCursor->setPosition(value);
540 impl->m_HorizontalCursor->setPosition(value);
541 impl->m_HorizontalCursor->setVisible(true);
541 impl->m_HorizontalCursor->setVisible(true);
542 impl->m_HorizontalCursor->setLabelText(QString::number(value));
542 impl->m_HorizontalCursor->setLabelText(QString::number(value));
543 }
543 }
544
544
545 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
545 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
546 {
546 {
547 impl->m_HorizontalCursor->setAbsolutePosition(position);
547 impl->m_HorizontalCursor->setAbsolutePosition(position);
548 impl->m_HorizontalCursor->setVisible(true);
548 impl->m_HorizontalCursor->setVisible(true);
549
549
550 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
550 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
551 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
551 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
552 }
552 }
553
553
554 void VisualizationGraphWidget::removeHorizontalCursor()
554 void VisualizationGraphWidget::removeHorizontalCursor()
555 {
555 {
556 impl->m_HorizontalCursor->setVisible(false);
556 impl->m_HorizontalCursor->setVisible(false);
557 plot().replot(QCustomPlot::rpQueuedReplot);
557 plot().replot(QCustomPlot::rpQueuedReplot);
558 }
558 }
559
559
560 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
560 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
561 {
561 {
562 Q_UNUSED(event);
562 Q_UNUSED(event);
563
563
564 // Prevents that all variables will be removed from graph when it will be closed
564 // Prevents that all variables will be removed from graph when it will be closed
565 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
565 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
566 emit variableAboutToBeRemoved(variableEntry.first);
566 emit variableAboutToBeRemoved(variableEntry.first);
567 }
567 }
568 }
568 }
569
569
570 void VisualizationGraphWidget::enterEvent(QEvent *event)
570 void VisualizationGraphWidget::enterEvent(QEvent *event)
571 {
571 {
572 Q_UNUSED(event);
572 Q_UNUSED(event);
573 impl->m_RenderingDelegate->showGraphOverlay(true);
573 impl->m_RenderingDelegate->showGraphOverlay(true);
574 }
574 }
575
575
576 void VisualizationGraphWidget::leaveEvent(QEvent *event)
576 void VisualizationGraphWidget::leaveEvent(QEvent *event)
577 {
577 {
578 Q_UNUSED(event);
578 Q_UNUSED(event);
579 impl->m_RenderingDelegate->showGraphOverlay(false);
579 impl->m_RenderingDelegate->showGraphOverlay(false);
580
580
581 if (auto parentZone = parentZoneWidget()) {
581 if (auto parentZone = parentZoneWidget()) {
582 parentZone->notifyMouseLeaveGraph(this);
582 parentZone->notifyMouseLeaveGraph(this);
583 }
583 }
584 else {
584 else {
585 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
585 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
586 }
586 }
587
587
588 if (impl->m_HoveredZone) {
588 if (impl->m_HoveredZone) {
589 impl->m_HoveredZone->setHovered(false);
589 impl->m_HoveredZone->setHovered(false);
590 impl->m_HoveredZone = nullptr;
590 impl->m_HoveredZone = nullptr;
591 }
591 }
592 }
592 }
593
593
594 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
594 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
595 {
595 {
596 return *ui->widget;
596 return *ui->widget;
597 }
597 }
598
598
599 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
599 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
600 {
600 {
601 QMenu graphMenu{};
601 QMenu graphMenu{};
602
602
603 // Iterates on variables (unique keys)
603 // Iterates on variables (unique keys)
604 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
604 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
605 end = impl->m_VariableToPlotMultiMap.cend();
605 end = impl->m_VariableToPlotMultiMap.cend();
606 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
606 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
607 // 'Remove variable' action
607 // 'Remove variable' action
608 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
608 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
609 [ this, var = it->first ]() { removeVariable(var); });
609 [ this, var = it->first ]() { removeVariable(var); });
610 }
610 }
611
611
612 if (!impl->m_ZoomStack.isEmpty()) {
612 if (!impl->m_ZoomStack.isEmpty()) {
613 if (!graphMenu.isEmpty()) {
613 if (!graphMenu.isEmpty()) {
614 graphMenu.addSeparator();
614 graphMenu.addSeparator();
615 }
615 }
616
616
617 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
617 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
618 }
618 }
619
619
620 // Selection Zone Actions
620 auto selectionZoneItem = impl->selectionZoneAt(pos, plot());
621 auto selectionZoneItem = impl->selectionZoneAt(pos, plot());
621 if (selectionZoneItem) {
622 if (selectionZoneItem) {
622 auto selectedItems = parentVisualizationWidget()->selectionZoneManager().selectedItems();
623 auto selectedItems = parentVisualizationWidget()->selectionZoneManager().selectedItems();
623 selectedItems.removeAll(selectionZoneItem);
624 selectedItems.removeAll(selectionZoneItem);
624 selectedItems.prepend(selectionZoneItem); // Put the current selection zone first
625 selectedItems.prepend(selectionZoneItem); // Put the current selection zone first
625
626
626 auto zoneActions = sqpApp->actionsGuiController().selectionZoneActions();
627 auto zoneActions = sqpApp->actionsGuiController().selectionZoneActions();
627 if (!zoneActions.isEmpty() && !graphMenu.isEmpty()) {
628 if (!zoneActions.isEmpty() && !graphMenu.isEmpty()) {
628 graphMenu.addSeparator();
629 graphMenu.addSeparator();
629 }
630 }
630
631
632 QHash<QString, QMenu *> subMenus;
633 QHash<QString, bool> subMenusEnabled;
634
631 for (auto zoneAction : zoneActions) {
635 for (auto zoneAction : zoneActions) {
632 auto action = graphMenu.addAction(zoneAction->name());
636
633 action->setEnabled(zoneAction->isEnabled(selectedItems));
637 auto isEnabled = zoneAction->isEnabled(selectedItems);
638
639 auto menu = &graphMenu;
640 for (auto subMenuName : zoneAction->subMenuList()) {
641 if (!subMenus.contains(subMenuName)) {
642 menu = menu->addMenu(subMenuName);
643 subMenus[subMenuName] = menu;
644 subMenusEnabled[subMenuName] = isEnabled;
645 }
646 else {
647 menu = subMenus.value(subMenuName);
648 if (isEnabled) {
649 // The sub menu is enabled if at least one of its actions is enabled
650 subMenusEnabled[subMenuName] = true;
651 }
652 }
653 }
654
655 auto action = menu->addAction(zoneAction->name());
656 action->setEnabled(isEnabled);
634 action->setShortcut(zoneAction->displayedShortcut());
657 action->setShortcut(zoneAction->displayedShortcut());
635 QObject::connect(action, &QAction::triggered,
658 QObject::connect(action, &QAction::triggered,
636 [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); });
659 [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); });
637 }
660 }
661
662 for (auto it = subMenus.cbegin(); it != subMenus.cend(); ++it) {
663 it.value()->setEnabled(subMenusEnabled[it.key()]);
664 }
638 }
665 }
639
666
640 if (!graphMenu.isEmpty()) {
667 if (!graphMenu.isEmpty()) {
641 graphMenu.exec(QCursor::pos());
668 graphMenu.exec(QCursor::pos());
642 }
669 }
643 }
670 }
644
671
645 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
672 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
646 {
673 {
647 qCDebug(LOG_VisualizationGraphWidget())
674 qCDebug(LOG_VisualizationGraphWidget())
648 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
675 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
649 << QThread::currentThread()->objectName() << "DoAcqui" << impl->m_DoAcquisition;
676 << QThread::currentThread()->objectName() << "DoAcqui" << impl->m_DoAcquisition;
650
677
651 auto graphRange = SqpRange{t1.lower, t1.upper};
678 auto graphRange = SqpRange{t1.lower, t1.upper};
652 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
679 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
653
680
654 if (impl->m_DoAcquisition) {
681 if (impl->m_DoAcquisition) {
655 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
682 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
656
683
657 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
684 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
658 end = impl->m_VariableToPlotMultiMap.end();
685 end = impl->m_VariableToPlotMultiMap.end();
659 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
686 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
660 variableUnderGraphVector.push_back(it->first);
687 variableUnderGraphVector.push_back(it->first);
661 }
688 }
662 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
689 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
663 !impl->m_IsCalibration);
690 !impl->m_IsCalibration);
664
691
665 if (!impl->m_IsCalibration) {
692 if (!impl->m_IsCalibration) {
666 qCDebug(LOG_VisualizationGraphWidget())
693 qCDebug(LOG_VisualizationGraphWidget())
667 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
694 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
668 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
695 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
669 emit synchronize(graphRange, oldGraphRange);
696 emit synchronize(graphRange, oldGraphRange);
670 }
697 }
671 }
698 }
672
699
673 auto pos = mapFromGlobal(QCursor::pos());
700 auto pos = mapFromGlobal(QCursor::pos());
674 auto axisPos = impl->posToAxisPos(pos, plot());
701 auto axisPos = impl->posToAxisPos(pos, plot());
675 if (auto parentZone = parentZoneWidget()) {
702 if (auto parentZone = parentZoneWidget()) {
676 if (impl->pointIsInAxisRect(axisPos, plot())) {
703 if (impl->pointIsInAxisRect(axisPos, plot())) {
677 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
704 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
678 }
705 }
679 else {
706 else {
680 parentZone->notifyMouseLeaveGraph(this);
707 parentZone->notifyMouseLeaveGraph(this);
681 }
708 }
682 }
709 }
683 else {
710 else {
684 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
711 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
685 }
712 }
686 }
713 }
687
714
688 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
715 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
689 {
716 {
690 impl->m_RenderingDelegate->onMouseDoubleClick(event);
717 impl->m_RenderingDelegate->onMouseDoubleClick(event);
691 }
718 }
692
719
693 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
720 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
694 {
721 {
695 // Handles plot rendering when mouse is moving
722 // Handles plot rendering when mouse is moving
696 impl->m_RenderingDelegate->onMouseMove(event);
723 impl->m_RenderingDelegate->onMouseMove(event);
697
724
698 auto axisPos = impl->posToAxisPos(event->pos(), plot());
725 auto axisPos = impl->posToAxisPos(event->pos(), plot());
699
726
700 // Zoom box and zone drawing
727 // Zoom box and zone drawing
701 if (impl->m_DrawingZoomRect) {
728 if (impl->m_DrawingZoomRect) {
702 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
729 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
703 }
730 }
704 else if (impl->m_DrawingZone) {
731 else if (impl->m_DrawingZone) {
705 impl->m_DrawingZone->setEnd(axisPos.x());
732 impl->m_DrawingZone->setEnd(axisPos.x());
706 }
733 }
707
734
708 // Cursor
735 // Cursor
709 if (auto parentZone = parentZoneWidget()) {
736 if (auto parentZone = parentZoneWidget()) {
710 if (impl->pointIsInAxisRect(axisPos, plot())) {
737 if (impl->pointIsInAxisRect(axisPos, plot())) {
711 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
738 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
712 }
739 }
713 else {
740 else {
714 parentZone->notifyMouseLeaveGraph(this);
741 parentZone->notifyMouseLeaveGraph(this);
715 }
742 }
716 }
743 }
717 else {
744 else {
718 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
745 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
719 }
746 }
720
747
721 // Search for the selection zone under the mouse
748 // Search for the selection zone under the mouse
722 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
749 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
723 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
750 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
724 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
751 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
725
752
726 // Sets the appropriate cursor shape
753 // Sets the appropriate cursor shape
727 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
754 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
728 setCursor(cursorShape);
755 setCursor(cursorShape);
729
756
730 // Manages the hovered zone
757 // Manages the hovered zone
731 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
758 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
732 if (impl->m_HoveredZone) {
759 if (impl->m_HoveredZone) {
733 impl->m_HoveredZone->setHovered(false);
760 impl->m_HoveredZone->setHovered(false);
734 }
761 }
735 selectionZoneItemUnderCursor->setHovered(true);
762 selectionZoneItemUnderCursor->setHovered(true);
736 impl->m_HoveredZone = selectionZoneItemUnderCursor;
763 impl->m_HoveredZone = selectionZoneItemUnderCursor;
737 plot().replot(QCustomPlot::rpQueuedReplot);
764 plot().replot(QCustomPlot::rpQueuedReplot);
738 }
765 }
739 }
766 }
740 else {
767 else {
741 // There is no zone under the mouse or the interaction mode is not "selection zones"
768 // There is no zone under the mouse or the interaction mode is not "selection zones"
742 if (impl->m_HoveredZone) {
769 if (impl->m_HoveredZone) {
743 impl->m_HoveredZone->setHovered(false);
770 impl->m_HoveredZone->setHovered(false);
744 impl->m_HoveredZone = nullptr;
771 impl->m_HoveredZone = nullptr;
745 }
772 }
746
773
747 setCursor(Qt::ArrowCursor);
774 setCursor(Qt::ArrowCursor);
748 }
775 }
749
776
750 impl->m_HasMovedMouse = true;
777 impl->m_HasMovedMouse = true;
751 VisualizationDragWidget::mouseMoveEvent(event);
778 VisualizationDragWidget::mouseMoveEvent(event);
752 }
779 }
753
780
754 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
781 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
755 {
782 {
756 auto value = event->angleDelta().x() + event->angleDelta().y();
783 auto value = event->angleDelta().x() + event->angleDelta().y();
757 if (value != 0) {
784 if (value != 0) {
758
785
759 auto direction = value > 0 ? 1.0 : -1.0;
786 auto direction = value > 0 ? 1.0 : -1.0;
760 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
787 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
761 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
788 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
762 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
789 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
763
790
764 auto zoomOrientations = QFlags<Qt::Orientation>{};
791 auto zoomOrientations = QFlags<Qt::Orientation>{};
765 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
792 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
766 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
793 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
767
794
768 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
795 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
769
796
770 if (!isZoomX && !isZoomY) {
797 if (!isZoomX && !isZoomY) {
771 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
798 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
772 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
799 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
773
800
774 axis->setRange(axis->range() + diff);
801 axis->setRange(axis->range() + diff);
775
802
776 if (plot().noAntialiasingOnDrag()) {
803 if (plot().noAntialiasingOnDrag()) {
777 plot().setNotAntialiasedElements(QCP::aeAll);
804 plot().setNotAntialiasedElements(QCP::aeAll);
778 }
805 }
779
806
780 plot().replot(QCustomPlot::rpQueuedReplot);
807 plot().replot(QCustomPlot::rpQueuedReplot);
781 }
808 }
782 }
809 }
783 }
810 }
784
811
785 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
812 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
786 {
813 {
787 auto isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
814 auto isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
788 auto isSelectionZoneMode
815 auto isSelectionZoneMode
789 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
816 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
790 auto isLeftClick = event->buttons().testFlag(Qt::LeftButton);
817 auto isLeftClick = event->buttons().testFlag(Qt::LeftButton);
791
818
792 if (!isDragDropClick && isLeftClick) {
819 if (!isDragDropClick && isLeftClick) {
793 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
820 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
794 // Starts a zoom box
821 // Starts a zoom box
795 impl->startDrawingRect(event->pos(), plot());
822 impl->startDrawingRect(event->pos(), plot());
796 }
823 }
797 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
824 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
798 // Starts a new selection zone
825 // Starts a new selection zone
799 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
826 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
800 if (!zoneAtPos) {
827 if (!zoneAtPos) {
801 impl->startDrawingZone(event->pos(), this);
828 impl->startDrawingZone(event->pos(), this);
802 }
829 }
803 }
830 }
804 }
831 }
805
832
806 // Allows mouse panning only in default mode
833 // Allows mouse panning only in default mode
807 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
834 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
808 == SqpApplication::PlotsInteractionMode::None
835 == SqpApplication::PlotsInteractionMode::None
809 && !isDragDropClick);
836 && !isDragDropClick);
810
837
811 // Allows zone edition only in selection zone mode without drag&drop
838 // Allows zone edition only in selection zone mode without drag&drop
812 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
839 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
813
840
814 // Selection / Deselection
841 // Selection / Deselection
815 if (isSelectionZoneMode) {
842 if (isSelectionZoneMode) {
816 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
843 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
817 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
844 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
818 if (selectionZoneItemUnderCursor && isLeftClick) {
845 if (selectionZoneItemUnderCursor && isLeftClick) {
819 selectionZoneItemUnderCursor->setAssociatedEditedZones(
846 selectionZoneItemUnderCursor->setAssociatedEditedZones(
820 parentVisualizationWidget()->selectionZoneManager().selectedItems());
847 parentVisualizationWidget()->selectionZoneManager().selectedItems());
821 }
848 }
822 else if (!isMultiSelectionClick && isLeftClick) {
849 else if (!isMultiSelectionClick && isLeftClick) {
823 parentVisualizationWidget()->selectionZoneManager().clearSelection();
850 parentVisualizationWidget()->selectionZoneManager().clearSelection();
824 }
851 }
825 else {
852 else {
826 // No selection change
853 // No selection change
827 }
854 }
828 }
855 }
829
856
830
857
831 impl->m_HasMovedMouse = false;
858 impl->m_HasMovedMouse = false;
832 VisualizationDragWidget::mousePressEvent(event);
859 VisualizationDragWidget::mousePressEvent(event);
833 }
860 }
834
861
835 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
862 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
836 {
863 {
837 if (impl->m_DrawingZoomRect) {
864 if (impl->m_DrawingZoomRect) {
838
865
839 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
866 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
840 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
867 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
841
868
842 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
869 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
843 impl->m_DrawingZoomRect->bottomRight->coords().x()};
870 impl->m_DrawingZoomRect->bottomRight->coords().x()};
844
871
845 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
872 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
846 impl->m_DrawingZoomRect->bottomRight->coords().y()};
873 impl->m_DrawingZoomRect->bottomRight->coords().y()};
847
874
848 impl->removeDrawingRect(plot());
875 impl->removeDrawingRect(plot());
849
876
850 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
877 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
851 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
878 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
852 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
879 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
853 axisX->setRange(newAxisXRange);
880 axisX->setRange(newAxisXRange);
854 axisY->setRange(newAxisYRange);
881 axisY->setRange(newAxisYRange);
855
882
856 plot().replot(QCustomPlot::rpQueuedReplot);
883 plot().replot(QCustomPlot::rpQueuedReplot);
857 }
884 }
858 }
885 }
859
886
860 impl->endDrawingZone(this);
887 impl->endDrawingZone(this);
861
888
862 impl->m_IsCalibration = false;
889 impl->m_IsCalibration = false;
863
890
864 // Selection / Deselection
891 // Selection / Deselection
865 auto isSelectionZoneMode
892 auto isSelectionZoneMode
866 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
893 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
867 if (isSelectionZoneMode) {
894 if (isSelectionZoneMode) {
868 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
895 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
869 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
896 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
870 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton) {
897 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton) {
871 if (!isMultiSelectionClick && !impl->m_HasMovedMouse) {
898 if (!isMultiSelectionClick && !impl->m_HasMovedMouse) {
872 parentVisualizationWidget()->selectionZoneManager().select(
899 parentVisualizationWidget()->selectionZoneManager().select(
873 {selectionZoneItemUnderCursor});
900 {selectionZoneItemUnderCursor});
874 }
901 }
875 else if (!impl->m_HasMovedMouse) {
902 else if (!impl->m_HasMovedMouse) {
876 parentVisualizationWidget()->selectionZoneManager().setSelected(
903 parentVisualizationWidget()->selectionZoneManager().setSelected(
877 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
904 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
878 || event->button() == Qt::RightButton);
905 || event->button() == Qt::RightButton);
879 }
906 }
880 }
907 }
881 else {
908 else {
882 // No selection change
909 // No selection change
883 }
910 }
884 }
911 }
885 }
912 }
886
913
887 void VisualizationGraphWidget::onDataCacheVariableUpdated()
914 void VisualizationGraphWidget::onDataCacheVariableUpdated()
888 {
915 {
889 auto graphRange = ui->widget->xAxis->range();
916 auto graphRange = ui->widget->xAxis->range();
890 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
917 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
891
918
892 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
919 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
893 auto variable = variableEntry.first;
920 auto variable = variableEntry.first;
894 qCDebug(LOG_VisualizationGraphWidget())
921 qCDebug(LOG_VisualizationGraphWidget())
895 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
922 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
896 qCDebug(LOG_VisualizationGraphWidget())
923 qCDebug(LOG_VisualizationGraphWidget())
897 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
924 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
898 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
925 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
899 impl->updateData(variableEntry.second, variable->dataSeries(), variable->range());
926 impl->updateData(variableEntry.second, variable->dataSeries(), variable->range());
900 }
927 }
901 }
928 }
902 }
929 }
903
930
904 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
931 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
905 const SqpRange &range)
932 const SqpRange &range)
906 {
933 {
907 auto it = impl->m_VariableToPlotMultiMap.find(variable);
934 auto it = impl->m_VariableToPlotMultiMap.find(variable);
908 if (it != impl->m_VariableToPlotMultiMap.end()) {
935 if (it != impl->m_VariableToPlotMultiMap.end()) {
909 impl->updateData(it->second, variable->dataSeries(), range);
936 impl->updateData(it->second, variable->dataSeries(), range);
910 }
937 }
911 }
938 }
General Comments 4
Under Review
author

Auto status change to "Under Review"

Approved

Status change > Approved

Approved

Status change > Approved

You need to be logged in to leave comments. Login now