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

Auto status change to "Under Review"

Approved

Status change > Approved

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