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