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

Auto status change to "Under Review"

Approved

Status change > Approved

Approved

Status change > Approved

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