##// END OF EJS Templates
Handles double click on color scale...
Alexandre Leroux -
r1043:4ab6e8aca534
parent child
Show More
@@ -1,39 +1,40
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
2 #define SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
2 #define SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5
5
6 #include <Visualization/VisualizationDefs.h>
6 #include <Visualization/VisualizationDefs.h>
7
7
8 class IDataSeries;
8 class IDataSeries;
9 class QCustomPlot;
9 class QCustomPlot;
10 class QMouseEvent;
10 class QMouseEvent;
11 class Unit;
11 class Unit;
12 class VisualizationGraphWidget;
12 class VisualizationGraphWidget;
13
13
14 class VisualizationGraphRenderingDelegate {
14 class VisualizationGraphRenderingDelegate {
15 public:
15 public:
16 /// Ctor
16 /// Ctor
17 /// @param graphWidget the graph widget to which the delegate is associated
17 /// @param graphWidget the graph widget to which the delegate is associated
18 /// @remarks the graph widget must exist throughout the life cycle of the delegate
18 /// @remarks the graph widget must exist throughout the life cycle of the delegate
19 explicit VisualizationGraphRenderingDelegate(VisualizationGraphWidget &graphWidget);
19 explicit VisualizationGraphRenderingDelegate(VisualizationGraphWidget &graphWidget);
20
20
21 void onMouseDoubleClick(QMouseEvent *event) noexcept;
21 void onMouseMove(QMouseEvent *event) noexcept;
22 void onMouseMove(QMouseEvent *event) noexcept;
22
23
23 /// Sets properties of the plot's axes from the data series passed as parameter
24 /// Sets properties of the plot's axes from the data series passed as parameter
24 void setAxesProperties(std::shared_ptr<IDataSeries> dataSeries) noexcept;
25 void setAxesProperties(std::shared_ptr<IDataSeries> dataSeries) noexcept;
25
26
26 /// Sets rendering properties of the plottables passed as parameter, from the data series that
27 /// Sets rendering properties of the plottables passed as parameter, from the data series that
27 /// generated these
28 /// generated these
28 void setPlottablesProperties(std::shared_ptr<IDataSeries> dataSeries,
29 void setPlottablesProperties(std::shared_ptr<IDataSeries> dataSeries,
29 PlottablesMap &plottables) noexcept;
30 PlottablesMap &plottables) noexcept;
30
31
31 /// Shows or hides graph overlay (name, close button, etc.)
32 /// Shows or hides graph overlay (name, close button, etc.)
32 void showGraphOverlay(bool show) noexcept;
33 void showGraphOverlay(bool show) noexcept;
33
34
34 private:
35 private:
35 class VisualizationGraphRenderingDelegatePrivate;
36 class VisualizationGraphRenderingDelegatePrivate;
36 spimpl::unique_impl_ptr<VisualizationGraphRenderingDelegatePrivate> impl;
37 spimpl::unique_impl_ptr<VisualizationGraphRenderingDelegatePrivate> impl;
37 };
38 };
38
39
39 #endif // SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
40 #endif // SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
@@ -1,121 +1,123
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 VisualizationZoneWidget;
20 class VisualizationZoneWidget;
21
21
22 namespace Ui {
22 namespace Ui {
23 class VisualizationGraphWidget;
23 class VisualizationGraphWidget;
24 } // namespace Ui
24 } // namespace Ui
25
25
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
27 Q_OBJECT
27 Q_OBJECT
28
28
29 friend class QCustomPlotSynchronizer;
29 friend class QCustomPlotSynchronizer;
30 friend class VisualizationGraphRenderingDelegate;
30 friend class VisualizationGraphRenderingDelegate;
31
31
32 public:
32 public:
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
34 virtual ~VisualizationGraphWidget();
34 virtual ~VisualizationGraphWidget();
35
35
36 VisualizationZoneWidget *parentZoneWidget() const noexcept;
36 VisualizationZoneWidget *parentZoneWidget() const noexcept;
37
37
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
39 void enableAcquisition(bool enable);
39 void enableAcquisition(bool enable);
40
40
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
42
42
43 /// Removes a variable from the graph
43 /// Removes a variable from the graph
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
45
45
46 /// Returns the list of all variables used in the graph
46 /// Returns the list of all variables used in the graph
47 QList<std::shared_ptr<Variable> > variables() const;
47 QList<std::shared_ptr<Variable> > variables() const;
48
48
49 /// Sets the y-axis range based on the data of a variable
49 /// Sets the y-axis range based on the data of a variable
50 void setYRange(std::shared_ptr<Variable> variable);
50 void setYRange(std::shared_ptr<Variable> variable);
51 SqpRange graphRange() const noexcept;
51 SqpRange graphRange() const noexcept;
52 void setGraphRange(const SqpRange &range);
52 void setGraphRange(const SqpRange &range);
53
53
54 // IVisualizationWidget interface
54 // IVisualizationWidget interface
55 void accept(IVisualizationWidgetVisitor *visitor) override;
55 void accept(IVisualizationWidgetVisitor *visitor) override;
56 bool canDrop(const Variable &variable) const override;
56 bool canDrop(const Variable &variable) const override;
57 bool contains(const Variable &variable) const override;
57 bool contains(const Variable &variable) const override;
58 QString name() const override;
58 QString name() const override;
59
59
60 // VisualisationDragWidget
60 // VisualisationDragWidget
61 QMimeData *mimeData() const override;
61 QMimeData *mimeData() const override;
62 bool isDragAllowed() const override;
62 bool isDragAllowed() const override;
63 void highlightForMerge(bool highlighted) override;
63 void highlightForMerge(bool highlighted) override;
64
64
65 // Cursors
65 // Cursors
66 /// Adds or moves the vertical cursor at the specified value on the x-axis
66 /// Adds or moves the vertical cursor at the specified value on the x-axis
67 void addVerticalCursor(double time);
67 void addVerticalCursor(double time);
68 /// Adds or moves the vertical cursor at the specified value on the x-axis
68 /// Adds or moves the vertical cursor at the specified value on the x-axis
69 void addVerticalCursorAtViewportPosition(double position);
69 void addVerticalCursorAtViewportPosition(double position);
70 void removeVerticalCursor();
70 void removeVerticalCursor();
71 /// Adds or moves the vertical cursor at the specified value on the y-axis
71 /// Adds or moves the vertical cursor at the specified value on the y-axis
72 void addHorizontalCursor(double value);
72 void addHorizontalCursor(double value);
73 /// Adds or moves the vertical cursor at the specified value on the y-axis
73 /// Adds or moves the vertical cursor at the specified value on the y-axis
74 void addHorizontalCursorAtViewportPosition(double position);
74 void addHorizontalCursorAtViewportPosition(double position);
75 void removeHorizontalCursor();
75 void removeHorizontalCursor();
76
76
77 signals:
77 signals:
78 void synchronize(const SqpRange &range, const SqpRange &oldRange);
78 void synchronize(const SqpRange &range, const SqpRange &oldRange);
79 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
79 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
80 bool synchronise);
80 bool synchronise);
81
81
82 /// Signal emitted when the variable is about to be removed from the graph
82 /// Signal emitted when the variable is about to be removed from the graph
83 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
83 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
84 /// Signal emitted when the variable has been added to the graph
84 /// Signal emitted when the variable has been added to the graph
85 void variableAdded(std::shared_ptr<Variable> var);
85 void variableAdded(std::shared_ptr<Variable> var);
86
86
87 protected:
87 protected:
88 void closeEvent(QCloseEvent *event) override;
88 void closeEvent(QCloseEvent *event) override;
89 void enterEvent(QEvent *event) override;
89 void enterEvent(QEvent *event) override;
90 void leaveEvent(QEvent *event) override;
90 void leaveEvent(QEvent *event) override;
91
91
92 QCustomPlot &plot() noexcept;
92 QCustomPlot &plot() noexcept;
93
93
94 private:
94 private:
95 Ui::VisualizationGraphWidget *ui;
95 Ui::VisualizationGraphWidget *ui;
96
96
97 class VisualizationGraphWidgetPrivate;
97 class VisualizationGraphWidgetPrivate;
98 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
98 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
99
99
100 private slots:
100 private slots:
101 /// Slot called when right clicking on the graph (displays a menu)
101 /// Slot called when right clicking on the graph (displays a menu)
102 void onGraphMenuRequested(const QPoint &pos) noexcept;
102 void onGraphMenuRequested(const QPoint &pos) noexcept;
103
103
104 /// Rescale the X axe to range parameter
104 /// Rescale the X axe to range parameter
105 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
105 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
106
106
107 /// Slot called when a mouse double click was made
108 void onMouseDoubleClick(QMouseEvent *event) noexcept;
107 /// Slot called when a mouse move was made
109 /// Slot called when a mouse move was made
108 void onMouseMove(QMouseEvent *event) noexcept;
110 void onMouseMove(QMouseEvent *event) noexcept;
109 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
111 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
110 void onMouseWheel(QWheelEvent *event) noexcept;
112 void onMouseWheel(QWheelEvent *event) noexcept;
111 /// Slot called when a mouse press was made, to activate the calibration of a graph
113 /// Slot called when a mouse press was made, to activate the calibration of a graph
112 void onMousePress(QMouseEvent *event) noexcept;
114 void onMousePress(QMouseEvent *event) noexcept;
113 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
115 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
114 void onMouseRelease(QMouseEvent *event) noexcept;
116 void onMouseRelease(QMouseEvent *event) noexcept;
115
117
116 void onDataCacheVariableUpdated();
118 void onDataCacheVariableUpdated();
117
119
118 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
120 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
119 };
121 };
120
122
121 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
123 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,245 +1,255
1 #include "Visualization/VisualizationGraphRenderingDelegate.h"
1 #include "Visualization/VisualizationGraphRenderingDelegate.h"
2 #include "Visualization/AxisRenderingUtils.h"
2 #include "Visualization/AxisRenderingUtils.h"
3 #include "Visualization/ColorScaleEditor.h"
3 #include "Visualization/PlottablesRenderingUtils.h"
4 #include "Visualization/PlottablesRenderingUtils.h"
4 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/qcustomplot.h"
6 #include "Visualization/qcustomplot.h"
6
7
7 #include <Common/DateUtils.h>
8 #include <Common/DateUtils.h>
8
9
9 #include <Data/IDataSeries.h>
10 #include <Data/IDataSeries.h>
10
11
11 #include <SqpApplication.h>
12 #include <SqpApplication.h>
12
13
13 namespace {
14 namespace {
14
15
15 /// Name of the axes layer in QCustomPlot
16 /// Name of the axes layer in QCustomPlot
16 const auto AXES_LAYER = QStringLiteral("axes");
17 const auto AXES_LAYER = QStringLiteral("axes");
17
18
18 /// Icon used to show x-axis properties
19 /// Icon used to show x-axis properties
19 const auto HIDE_AXIS_ICON_PATH = QStringLiteral(":/icones/down.png");
20 const auto HIDE_AXIS_ICON_PATH = QStringLiteral(":/icones/down.png");
20
21
21 /// Name of the overlay layer in QCustomPlot
22 /// Name of the overlay layer in QCustomPlot
22 const auto OVERLAY_LAYER = QStringLiteral("overlay");
23 const auto OVERLAY_LAYER = QStringLiteral("overlay");
23
24
24 /// Pixmap used to show x-axis properties
25 /// Pixmap used to show x-axis properties
25 const auto SHOW_AXIS_ICON_PATH = QStringLiteral(":/icones/up.png");
26 const auto SHOW_AXIS_ICON_PATH = QStringLiteral(":/icones/up.png");
26
27
27 const auto TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
28 const auto TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
28
29
29 /// Offset used to shift the tooltip of the mouse
30 /// Offset used to shift the tooltip of the mouse
30 const auto TOOLTIP_OFFSET = QPoint{20, 20};
31 const auto TOOLTIP_OFFSET = QPoint{20, 20};
31
32
32 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
33 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
33 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
34 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
34
35
35 /// Timeout after which the tooltip is displayed
36 /// Timeout after which the tooltip is displayed
36 const auto TOOLTIP_TIMEOUT = 500;
37 const auto TOOLTIP_TIMEOUT = 500;
37
38
38 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
39 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
39 {
40 {
40 tracer.setInterpolating(false);
41 tracer.setInterpolating(false);
41 tracer.setStyle(QCPItemTracer::tsCircle);
42 tracer.setStyle(QCPItemTracer::tsCircle);
42 tracer.setSize(3);
43 tracer.setSize(3);
43 tracer.setPen(QPen(Qt::black));
44 tracer.setPen(QPen(Qt::black));
44 tracer.setBrush(Qt::black);
45 tracer.setBrush(Qt::black);
45 }
46 }
46
47
47 QPixmap pixmap(const QString &iconPath) noexcept
48 QPixmap pixmap(const QString &iconPath) noexcept
48 {
49 {
49 return QIcon{iconPath}.pixmap(QSize{16, 16});
50 return QIcon{iconPath}.pixmap(QSize{16, 16});
50 }
51 }
51
52
52 void initClosePixmapStyle(QCPItemPixmap &pixmap) noexcept
53 void initClosePixmapStyle(QCPItemPixmap &pixmap) noexcept
53 {
54 {
54 // Icon
55 // Icon
55 pixmap.setPixmap(
56 pixmap.setPixmap(
56 sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton).pixmap(QSize{16, 16}));
57 sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton).pixmap(QSize{16, 16}));
57
58
58 // Position
59 // Position
59 pixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
60 pixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
60 pixmap.topLeft->setCoords(1, 0);
61 pixmap.topLeft->setCoords(1, 0);
61 pixmap.setClipToAxisRect(false);
62 pixmap.setClipToAxisRect(false);
62
63
63 // Can be selected
64 // Can be selected
64 pixmap.setSelectable(true);
65 pixmap.setSelectable(true);
65 }
66 }
66
67
67 void initXAxisPixmapStyle(QCPItemPixmap &itemPixmap) noexcept
68 void initXAxisPixmapStyle(QCPItemPixmap &itemPixmap) noexcept
68 {
69 {
69 // Icon
70 // Icon
70 itemPixmap.setPixmap(pixmap(HIDE_AXIS_ICON_PATH));
71 itemPixmap.setPixmap(pixmap(HIDE_AXIS_ICON_PATH));
71
72
72 // Position
73 // Position
73 itemPixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
74 itemPixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
74 itemPixmap.topLeft->setCoords(0, 1);
75 itemPixmap.topLeft->setCoords(0, 1);
75 itemPixmap.setClipToAxisRect(false);
76 itemPixmap.setClipToAxisRect(false);
76
77
77 // Can be selected
78 // Can be selected
78 itemPixmap.setSelectable(true);
79 itemPixmap.setSelectable(true);
79 }
80 }
80
81
81 void initTitleTextStyle(QCPItemText &text) noexcept
82 void initTitleTextStyle(QCPItemText &text) noexcept
82 {
83 {
83 // Font and background styles
84 // Font and background styles
84 text.setColor(Qt::gray);
85 text.setColor(Qt::gray);
85 text.setBrush(Qt::white);
86 text.setBrush(Qt::white);
86
87
87 // Position
88 // Position
88 text.setPositionAlignment(Qt::AlignTop | Qt::AlignLeft);
89 text.setPositionAlignment(Qt::AlignTop | Qt::AlignLeft);
89 text.position->setType(QCPItemPosition::ptAxisRectRatio);
90 text.position->setType(QCPItemPosition::ptAxisRectRatio);
90 text.position->setCoords(0.5, 0);
91 text.position->setCoords(0.5, 0);
91 }
92 }
92
93
93 } // namespace
94 } // namespace
94
95
95 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
96 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
96 explicit VisualizationGraphRenderingDelegatePrivate(VisualizationGraphWidget &graphWidget)
97 explicit VisualizationGraphRenderingDelegatePrivate(VisualizationGraphWidget &graphWidget)
97 : m_Plot{graphWidget.plot()},
98 : m_Plot{graphWidget.plot()},
98 m_PointTracer{new QCPItemTracer{&m_Plot}},
99 m_PointTracer{new QCPItemTracer{&m_Plot}},
99 m_TracerTimer{},
100 m_TracerTimer{},
100 m_ClosePixmap{new QCPItemPixmap{&m_Plot}},
101 m_ClosePixmap{new QCPItemPixmap{&m_Plot}},
101 m_TitleText{new QCPItemText{&m_Plot}},
102 m_TitleText{new QCPItemText{&m_Plot}},
102 m_XAxisPixmap{new QCPItemPixmap{&m_Plot}},
103 m_XAxisPixmap{new QCPItemPixmap{&m_Plot}},
103 m_ShowXAxis{true},
104 m_ShowXAxis{true},
104 m_XAxisLabel{},
105 m_XAxisLabel{},
105 m_ColorScale{new QCPColorScale{&m_Plot}}
106 m_ColorScale{new QCPColorScale{&m_Plot}}
106 {
107 {
107 initPointTracerStyle(*m_PointTracer);
108 initPointTracerStyle(*m_PointTracer);
108
109
109 m_TracerTimer.setInterval(TOOLTIP_TIMEOUT);
110 m_TracerTimer.setInterval(TOOLTIP_TIMEOUT);
110 m_TracerTimer.setSingleShot(true);
111 m_TracerTimer.setSingleShot(true);
111
112
112 // Inits "close button" in plot overlay
113 // Inits "close button" in plot overlay
113 m_ClosePixmap->setLayer(OVERLAY_LAYER);
114 m_ClosePixmap->setLayer(OVERLAY_LAYER);
114 initClosePixmapStyle(*m_ClosePixmap);
115 initClosePixmapStyle(*m_ClosePixmap);
115
116
116 // Connects pixmap selection to graph widget closing
117 // Connects pixmap selection to graph widget closing
117 QObject::connect(m_ClosePixmap, &QCPItemPixmap::selectionChanged,
118 QObject::connect(m_ClosePixmap, &QCPItemPixmap::selectionChanged,
118 [&graphWidget](bool selected) {
119 [&graphWidget](bool selected) {
119 if (selected) {
120 if (selected) {
120 graphWidget.close();
121 graphWidget.close();
121 }
122 }
122 });
123 });
123
124
124 // Inits graph name in plot overlay
125 // Inits graph name in plot overlay
125 m_TitleText->setLayer(OVERLAY_LAYER);
126 m_TitleText->setLayer(OVERLAY_LAYER);
126 m_TitleText->setText(graphWidget.name());
127 m_TitleText->setText(graphWidget.name());
127 initTitleTextStyle(*m_TitleText);
128 initTitleTextStyle(*m_TitleText);
128
129
129 // Inits "show x-axis button" in plot overlay
130 // Inits "show x-axis button" in plot overlay
130 m_XAxisPixmap->setLayer(OVERLAY_LAYER);
131 m_XAxisPixmap->setLayer(OVERLAY_LAYER);
131 initXAxisPixmapStyle(*m_XAxisPixmap);
132 initXAxisPixmapStyle(*m_XAxisPixmap);
132
133
133 // Connects pixmap selection to graph x-axis showing/hiding
134 // Connects pixmap selection to graph x-axis showing/hiding
134 QObject::connect(m_XAxisPixmap, &QCPItemPixmap::selectionChanged, [this]() {
135 QObject::connect(m_XAxisPixmap, &QCPItemPixmap::selectionChanged, [this]() {
135 if (m_XAxisPixmap->selected()) {
136 if (m_XAxisPixmap->selected()) {
136 // Changes the selection state and refreshes the x-axis
137 // Changes the selection state and refreshes the x-axis
137 m_ShowXAxis = !m_ShowXAxis;
138 m_ShowXAxis = !m_ShowXAxis;
138 updateXAxisState();
139 updateXAxisState();
139 m_Plot.layer(AXES_LAYER)->replot();
140 m_Plot.layer(AXES_LAYER)->replot();
140
141
141 // Deselects the x-axis pixmap and updates icon
142 // Deselects the x-axis pixmap and updates icon
142 m_XAxisPixmap->setSelected(false);
143 m_XAxisPixmap->setSelected(false);
143 m_XAxisPixmap->setPixmap(
144 m_XAxisPixmap->setPixmap(
144 pixmap(m_ShowXAxis ? HIDE_AXIS_ICON_PATH : SHOW_AXIS_ICON_PATH));
145 pixmap(m_ShowXAxis ? HIDE_AXIS_ICON_PATH : SHOW_AXIS_ICON_PATH));
145 m_Plot.layer(OVERLAY_LAYER)->replot();
146 m_Plot.layer(OVERLAY_LAYER)->replot();
146 }
147 }
147 });
148 });
148 }
149 }
149
150
150 /// Updates state of x-axis according to the current selection of x-axis pixmap
151 /// Updates state of x-axis according to the current selection of x-axis pixmap
151 /// @remarks the method doesn't call plot refresh
152 /// @remarks the method doesn't call plot refresh
152 void updateXAxisState() noexcept
153 void updateXAxisState() noexcept
153 {
154 {
154 m_Plot.xAxis->setTickLabels(m_ShowXAxis);
155 m_Plot.xAxis->setTickLabels(m_ShowXAxis);
155 m_Plot.xAxis->setLabel(m_ShowXAxis ? m_XAxisLabel : QString{});
156 m_Plot.xAxis->setLabel(m_ShowXAxis ? m_XAxisLabel : QString{});
156 }
157 }
157
158
158 QCustomPlot &m_Plot;
159 QCustomPlot &m_Plot;
159 QCPItemTracer *m_PointTracer;
160 QCPItemTracer *m_PointTracer;
160 QTimer m_TracerTimer;
161 QTimer m_TracerTimer;
161 QCPItemPixmap *m_ClosePixmap; /// Graph's close button
162 QCPItemPixmap *m_ClosePixmap; /// Graph's close button
162 QCPItemText *m_TitleText; /// Graph's title
163 QCPItemText *m_TitleText; /// Graph's title
163 QCPItemPixmap *m_XAxisPixmap;
164 QCPItemPixmap *m_XAxisPixmap;
164 bool m_ShowXAxis; /// X-axis properties are shown or hidden
165 bool m_ShowXAxis; /// X-axis properties are shown or hidden
165 QString m_XAxisLabel;
166 QString m_XAxisLabel;
166 QCPColorScale *m_ColorScale; /// Color scale used for some types of graphs (as spectrograms)
167 QCPColorScale *m_ColorScale; /// Color scale used for some types of graphs (as spectrograms)
167 };
168 };
168
169
169 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(
170 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(
170 VisualizationGraphWidget &graphWidget)
171 VisualizationGraphWidget &graphWidget)
171 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(graphWidget)}
172 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(graphWidget)}
172 {
173 {
173 }
174 }
174
175
176 void VisualizationGraphRenderingDelegate::onMouseDoubleClick(QMouseEvent *event) noexcept
177 {
178 // Opens color scale editor if color scale is double clicked
179 if (auto colorScale
180 = dynamic_cast<QCPColorScale *>(impl->m_Plot.layoutElementAt(event->pos()))) {
181 ColorScaleEditor{}.exec();
182 }
183 }
184
175 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
185 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
176 {
186 {
177 // Cancels pending refresh
187 // Cancels pending refresh
178 impl->m_TracerTimer.disconnect();
188 impl->m_TracerTimer.disconnect();
179
189
180 // Reinits tracers
190 // Reinits tracers
181 impl->m_PointTracer->setGraph(nullptr);
191 impl->m_PointTracer->setGraph(nullptr);
182 impl->m_PointTracer->setVisible(false);
192 impl->m_PointTracer->setVisible(false);
183 impl->m_Plot.replot();
193 impl->m_Plot.replot();
184
194
185 // Gets the graph under the mouse position
195 // Gets the graph under the mouse position
186 auto eventPos = event->pos();
196 auto eventPos = event->pos();
187 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
197 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
188 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
198 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
189 auto graphData = graph->data();
199 auto graphData = graph->data();
190
200
191 // Gets the closest data point to the mouse
201 // Gets the closest data point to the mouse
192 auto graphDataIt = graphData->findBegin(mouseKey);
202 auto graphDataIt = graphData->findBegin(mouseKey);
193 if (graphDataIt != graphData->constEnd()) {
203 if (graphDataIt != graphData->constEnd()) {
194 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
204 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
195 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
205 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
196
206
197 // Displays point tracer
207 // Displays point tracer
198 impl->m_PointTracer->setGraph(graph);
208 impl->m_PointTracer->setGraph(graph);
199 impl->m_PointTracer->setGraphKey(graphDataIt->key);
209 impl->m_PointTracer->setGraphKey(graphDataIt->key);
200 impl->m_PointTracer->setLayer(
210 impl->m_PointTracer->setLayer(
201 impl->m_Plot.layer("main")); // Tracer is set on top of the plot's main layer
211 impl->m_Plot.layer("main")); // Tracer is set on top of the plot's main layer
202 impl->m_PointTracer->setVisible(true);
212 impl->m_PointTracer->setVisible(true);
203 impl->m_Plot.replot();
213 impl->m_Plot.replot();
204
214
205 // Starts timer to show tooltip after timeout
215 // Starts timer to show tooltip after timeout
206 auto showTooltip = [ tooltip = TOOLTIP_FORMAT.arg(key, value), eventPos, this ]()
216 auto showTooltip = [ tooltip = TOOLTIP_FORMAT.arg(key, value), eventPos, this ]()
207 {
217 {
208 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos) + TOOLTIP_OFFSET, tooltip,
218 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos) + TOOLTIP_OFFSET, tooltip,
209 &impl->m_Plot, TOOLTIP_RECT);
219 &impl->m_Plot, TOOLTIP_RECT);
210 };
220 };
211
221
212 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
222 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
213 impl->m_TracerTimer.start();
223 impl->m_TracerTimer.start();
214 }
224 }
215 }
225 }
216 }
226 }
217
227
218 void VisualizationGraphRenderingDelegate::setAxesProperties(
228 void VisualizationGraphRenderingDelegate::setAxesProperties(
219 std::shared_ptr<IDataSeries> dataSeries) noexcept
229 std::shared_ptr<IDataSeries> dataSeries) noexcept
220 {
230 {
221 // Stores x-axis label to be able to retrieve it when x-axis pixmap is unselected
231 // Stores x-axis label to be able to retrieve it when x-axis pixmap is unselected
222 impl->m_XAxisLabel = dataSeries->xAxisUnit().m_Name;
232 impl->m_XAxisLabel = dataSeries->xAxisUnit().m_Name;
223
233
224 auto axisHelper = IAxisHelperFactory::create(dataSeries);
234 auto axisHelper = IAxisHelperFactory::create(dataSeries);
225 axisHelper->setProperties(impl->m_Plot, *impl->m_ColorScale);
235 axisHelper->setProperties(impl->m_Plot, *impl->m_ColorScale);
226
236
227 // Updates x-axis state
237 // Updates x-axis state
228 impl->updateXAxisState();
238 impl->updateXAxisState();
229
239
230 impl->m_Plot.layer(AXES_LAYER)->replot();
240 impl->m_Plot.layer(AXES_LAYER)->replot();
231 }
241 }
232
242
233 void VisualizationGraphRenderingDelegate::setPlottablesProperties(
243 void VisualizationGraphRenderingDelegate::setPlottablesProperties(
234 std::shared_ptr<IDataSeries> dataSeries, PlottablesMap &plottables) noexcept
244 std::shared_ptr<IDataSeries> dataSeries, PlottablesMap &plottables) noexcept
235 {
245 {
236 auto plottablesHelper = IPlottablesHelperFactory::create(dataSeries);
246 auto plottablesHelper = IPlottablesHelperFactory::create(dataSeries);
237 plottablesHelper->setProperties(plottables);
247 plottablesHelper->setProperties(plottables);
238 }
248 }
239
249
240 void VisualizationGraphRenderingDelegate::showGraphOverlay(bool show) noexcept
250 void VisualizationGraphRenderingDelegate::showGraphOverlay(bool show) noexcept
241 {
251 {
242 auto overlay = impl->m_Plot.layer(OVERLAY_LAYER);
252 auto overlay = impl->m_Plot.layer(OVERLAY_LAYER);
243 overlay->setVisible(show);
253 overlay->setVisible(show);
244 overlay->replot();
254 overlay->replot();
245 }
255 }
@@ -1,597 +1,604
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/VisualizationZoneWidget.h"
7 #include "Visualization/VisualizationZoneWidget.h"
8 #include "ui_VisualizationGraphWidget.h"
8 #include "ui_VisualizationGraphWidget.h"
9
9
10 #include <Common/MimeTypesDef.h>
10 #include <Common/MimeTypesDef.h>
11 #include <Data/ArrayData.h>
11 #include <Data/ArrayData.h>
12 #include <Data/IDataSeries.h>
12 #include <Data/IDataSeries.h>
13 #include <DragAndDrop/DragDropHelper.h>
13 #include <DragAndDrop/DragDropHelper.h>
14 #include <Settings/SqpSettingsDefs.h>
14 #include <Settings/SqpSettingsDefs.h>
15 #include <SqpApplication.h>
15 #include <SqpApplication.h>
16 #include <Time/TimeController.h>
16 #include <Time/TimeController.h>
17 #include <Variable/Variable.h>
17 #include <Variable/Variable.h>
18 #include <Variable/VariableController.h>
18 #include <Variable/VariableController.h>
19
19
20 #include <unordered_map>
20 #include <unordered_map>
21
21
22 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
22 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
23
23
24 namespace {
24 namespace {
25
25
26 /// Key pressed to enable zoom on horizontal axis
26 /// Key pressed to enable zoom on horizontal axis
27 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
27 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
28
28
29 /// Key pressed to enable zoom on vertical axis
29 /// Key pressed to enable zoom on vertical axis
30 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
30 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
31
31
32 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
32 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
33 const auto PAN_SPEED = 5;
33 const auto PAN_SPEED = 5;
34
34
35 /// Key pressed to enable a calibration pan
35 /// Key pressed to enable a calibration pan
36 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
36 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
37
37
38 /// Minimum size for the zoom box, in percentage of the axis range
38 /// Minimum size for the zoom box, in percentage of the axis range
39 const auto ZOOM_BOX_MIN_SIZE = 0.8;
39 const auto ZOOM_BOX_MIN_SIZE = 0.8;
40
40
41 /// Format of the dates appearing in the label of a cursor
41 /// Format of the dates appearing in the label of a cursor
42 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
42 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
43
43
44 } // namespace
44 } // namespace
45
45
46 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
46 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
47
47
48 explicit VisualizationGraphWidgetPrivate(const QString &name)
48 explicit VisualizationGraphWidgetPrivate(const QString &name)
49 : m_Name{name},
49 : m_Name{name},
50 m_DoAcquisition{true},
50 m_DoAcquisition{true},
51 m_IsCalibration{false},
51 m_IsCalibration{false},
52 m_RenderingDelegate{nullptr}
52 m_RenderingDelegate{nullptr}
53 {
53 {
54 }
54 }
55
55
56 QString m_Name;
56 QString m_Name;
57 // 1 variable -> n qcpplot
57 // 1 variable -> n qcpplot
58 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
58 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
59 bool m_DoAcquisition;
59 bool m_DoAcquisition;
60 bool m_IsCalibration;
60 bool m_IsCalibration;
61 /// Delegate used to attach rendering features to the plot
61 /// Delegate used to attach rendering features to the plot
62 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
62 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
63
63
64 QCPItemRect *m_DrawingRect = nullptr;
64 QCPItemRect *m_DrawingRect = nullptr;
65 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
65 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
66 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
66 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
67
67
68 void configureDrawingRect()
68 void configureDrawingRect()
69 {
69 {
70 if (m_DrawingRect) {
70 if (m_DrawingRect) {
71 QPen p;
71 QPen p;
72 p.setWidth(2);
72 p.setWidth(2);
73 m_DrawingRect->setPen(p);
73 m_DrawingRect->setPen(p);
74 }
74 }
75 }
75 }
76
76
77 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
77 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
78 {
78 {
79 removeDrawingRect(plot);
79 removeDrawingRect(plot);
80
80
81 auto axisPos = posToAxisPos(pos, plot);
81 auto axisPos = posToAxisPos(pos, plot);
82
82
83 m_DrawingRect = new QCPItemRect{&plot};
83 m_DrawingRect = new QCPItemRect{&plot};
84 configureDrawingRect();
84 configureDrawingRect();
85
85
86 m_DrawingRect->topLeft->setCoords(axisPos);
86 m_DrawingRect->topLeft->setCoords(axisPos);
87 m_DrawingRect->bottomRight->setCoords(axisPos);
87 m_DrawingRect->bottomRight->setCoords(axisPos);
88 }
88 }
89
89
90 void removeDrawingRect(QCustomPlot &plot)
90 void removeDrawingRect(QCustomPlot &plot)
91 {
91 {
92 if (m_DrawingRect) {
92 if (m_DrawingRect) {
93 plot.removeItem(m_DrawingRect); // the item is deleted by QCustomPlot
93 plot.removeItem(m_DrawingRect); // the item is deleted by QCustomPlot
94 m_DrawingRect = nullptr;
94 m_DrawingRect = nullptr;
95 plot.replot(QCustomPlot::rpQueuedReplot);
95 plot.replot(QCustomPlot::rpQueuedReplot);
96 }
96 }
97 }
97 }
98
98
99 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
99 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
100 {
100 {
101 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
101 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
102 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
102 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
103 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
103 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
104 }
104 }
105
105
106 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
106 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
107 {
107 {
108 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
108 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
109 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
109 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
110
110
111 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
111 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
112 }
112 }
113 };
113 };
114
114
115 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
115 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
116 : VisualizationDragWidget{parent},
116 : VisualizationDragWidget{parent},
117 ui{new Ui::VisualizationGraphWidget},
117 ui{new Ui::VisualizationGraphWidget},
118 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
118 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
119 {
119 {
120 ui->setupUi(this);
120 ui->setupUi(this);
121
121
122 // 'Close' options : widget is deleted when closed
122 // 'Close' options : widget is deleted when closed
123 setAttribute(Qt::WA_DeleteOnClose);
123 setAttribute(Qt::WA_DeleteOnClose);
124
124
125 // Set qcpplot properties :
125 // Set qcpplot properties :
126 // - Drag (on x-axis) and zoom are enabled
126 // - Drag (on x-axis) and zoom are enabled
127 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
127 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
128 ui->widget->setInteractions(QCP::iRangeZoom | QCP::iSelectItems);
128 ui->widget->setInteractions(QCP::iRangeZoom | QCP::iSelectItems);
129
129
130 // The delegate must be initialized after the ui as it uses the plot
130 // The delegate must be initialized after the ui as it uses the plot
131 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
131 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
132
132
133 // Init the cursors
133 // Init the cursors
134 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
134 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
135 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
135 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
136 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
136 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
137 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
137 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
138
138
139 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
139 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
140 connect(ui->widget, &QCustomPlot::mouseRelease, this,
140 connect(ui->widget, &QCustomPlot::mouseRelease, this,
141 &VisualizationGraphWidget::onMouseRelease);
141 &VisualizationGraphWidget::onMouseRelease);
142 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
142 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
143 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
143 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
144 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
145 &VisualizationGraphWidget::onMouseDoubleClick);
144 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
146 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
145 &QCPAxis::rangeChanged),
147 &QCPAxis::rangeChanged),
146 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
148 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
147
149
148 // Activates menu when right clicking on the graph
150 // Activates menu when right clicking on the graph
149 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
151 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
150 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
152 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
151 &VisualizationGraphWidget::onGraphMenuRequested);
153 &VisualizationGraphWidget::onGraphMenuRequested);
152
154
153 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
155 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
154 &VariableController::onRequestDataLoading);
156 &VariableController::onRequestDataLoading);
155
157
156 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
158 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
157 &VisualizationGraphWidget::onUpdateVarDisplaying);
159 &VisualizationGraphWidget::onUpdateVarDisplaying);
158
160
159 #ifdef Q_OS_MAC
161 #ifdef Q_OS_MAC
160 plot().setPlottingHint(QCP::phFastPolylines, true);
162 plot().setPlottingHint(QCP::phFastPolylines, true);
161 #endif
163 #endif
162 }
164 }
163
165
164
166
165 VisualizationGraphWidget::~VisualizationGraphWidget()
167 VisualizationGraphWidget::~VisualizationGraphWidget()
166 {
168 {
167 delete ui;
169 delete ui;
168 }
170 }
169
171
170 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
172 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
171 {
173 {
172 auto parent = parentWidget();
174 auto parent = parentWidget();
173 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
175 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
174 parent = parent->parentWidget();
176 parent = parent->parentWidget();
175 }
177 }
176
178
177 return qobject_cast<VisualizationZoneWidget *>(parent);
179 return qobject_cast<VisualizationZoneWidget *>(parent);
178 }
180 }
179
181
180 void VisualizationGraphWidget::enableAcquisition(bool enable)
182 void VisualizationGraphWidget::enableAcquisition(bool enable)
181 {
183 {
182 impl->m_DoAcquisition = enable;
184 impl->m_DoAcquisition = enable;
183 }
185 }
184
186
185 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
187 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
186 {
188 {
187 // Uses delegate to create the qcpplot components according to the variable
189 // Uses delegate to create the qcpplot components according to the variable
188 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
190 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
189
191
190 if (auto dataSeries = variable->dataSeries()) {
192 if (auto dataSeries = variable->dataSeries()) {
191 // Set axes properties according to the units of the data series
193 // Set axes properties according to the units of the data series
192 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
194 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
193
195
194 // Sets rendering properties for the new plottables
196 // Sets rendering properties for the new plottables
195 // Warning: this method must be called after setAxesProperties(), as it can access to some
197 // Warning: this method must be called after setAxesProperties(), as it can access to some
196 // axes properties that have to be initialized
198 // axes properties that have to be initialized
197 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
199 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
198 }
200 }
199
201
200 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
202 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
201
203
202 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
204 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
203
205
204 this->enableAcquisition(false);
206 this->enableAcquisition(false);
205 this->setGraphRange(range);
207 this->setGraphRange(range);
206 this->enableAcquisition(true);
208 this->enableAcquisition(true);
207
209
208 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
210 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
209
211
210 emit variableAdded(variable);
212 emit variableAdded(variable);
211 }
213 }
212
214
213 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
215 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
214 {
216 {
215 // Each component associated to the variable :
217 // Each component associated to the variable :
216 // - is removed from qcpplot (which deletes it)
218 // - is removed from qcpplot (which deletes it)
217 // - is no longer referenced in the map
219 // - is no longer referenced in the map
218 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
220 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
219 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
221 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
220 emit variableAboutToBeRemoved(variable);
222 emit variableAboutToBeRemoved(variable);
221
223
222 auto &plottablesMap = variableIt->second;
224 auto &plottablesMap = variableIt->second;
223
225
224 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
226 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
225 plottableIt != plottableEnd;) {
227 plottableIt != plottableEnd;) {
226 ui->widget->removePlottable(plottableIt->second);
228 ui->widget->removePlottable(plottableIt->second);
227 plottableIt = plottablesMap.erase(plottableIt);
229 plottableIt = plottablesMap.erase(plottableIt);
228 }
230 }
229
231
230 impl->m_VariableToPlotMultiMap.erase(variableIt);
232 impl->m_VariableToPlotMultiMap.erase(variableIt);
231 }
233 }
232
234
233 // Updates graph
235 // Updates graph
234 ui->widget->replot();
236 ui->widget->replot();
235 }
237 }
236
238
237 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
239 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
238 {
240 {
239 auto variables = QList<std::shared_ptr<Variable> >{};
241 auto variables = QList<std::shared_ptr<Variable> >{};
240 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
242 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
241 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
243 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
242 variables << it->first;
244 variables << it->first;
243 }
245 }
244
246
245 return variables;
247 return variables;
246 }
248 }
247
249
248 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
250 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
249 {
251 {
250 if (!variable) {
252 if (!variable) {
251 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
253 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
252 return;
254 return;
253 }
255 }
254
256
255 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
257 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
256 }
258 }
257
259
258 SqpRange VisualizationGraphWidget::graphRange() const noexcept
260 SqpRange VisualizationGraphWidget::graphRange() const noexcept
259 {
261 {
260 auto graphRange = ui->widget->xAxis->range();
262 auto graphRange = ui->widget->xAxis->range();
261 return SqpRange{graphRange.lower, graphRange.upper};
263 return SqpRange{graphRange.lower, graphRange.upper};
262 }
264 }
263
265
264 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
266 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
265 {
267 {
266 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
268 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
267 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
269 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
268 ui->widget->replot();
270 ui->widget->replot();
269 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
271 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
270 }
272 }
271
273
272 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
274 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
273 {
275 {
274 if (visitor) {
276 if (visitor) {
275 visitor->visit(this);
277 visitor->visit(this);
276 }
278 }
277 else {
279 else {
278 qCCritical(LOG_VisualizationGraphWidget())
280 qCCritical(LOG_VisualizationGraphWidget())
279 << tr("Can't visit widget : the visitor is null");
281 << tr("Can't visit widget : the visitor is null");
280 }
282 }
281 }
283 }
282
284
283 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
285 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
284 {
286 {
285 /// @todo : for the moment, a graph can always accomodate a variable
287 /// @todo : for the moment, a graph can always accomodate a variable
286 Q_UNUSED(variable);
288 Q_UNUSED(variable);
287 return true;
289 return true;
288 }
290 }
289
291
290 bool VisualizationGraphWidget::contains(const Variable &variable) const
292 bool VisualizationGraphWidget::contains(const Variable &variable) const
291 {
293 {
292 // Finds the variable among the keys of the map
294 // Finds the variable among the keys of the map
293 auto variablePtr = &variable;
295 auto variablePtr = &variable;
294 auto findVariable
296 auto findVariable
295 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
297 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
296
298
297 auto end = impl->m_VariableToPlotMultiMap.cend();
299 auto end = impl->m_VariableToPlotMultiMap.cend();
298 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
300 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
299 return it != end;
301 return it != end;
300 }
302 }
301
303
302 QString VisualizationGraphWidget::name() const
304 QString VisualizationGraphWidget::name() const
303 {
305 {
304 return impl->m_Name;
306 return impl->m_Name;
305 }
307 }
306
308
307 QMimeData *VisualizationGraphWidget::mimeData() const
309 QMimeData *VisualizationGraphWidget::mimeData() const
308 {
310 {
309 auto mimeData = new QMimeData;
311 auto mimeData = new QMimeData;
310 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
312 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
311
313
312 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
314 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
313 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
315 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
314
316
315 return mimeData;
317 return mimeData;
316 }
318 }
317
319
318 bool VisualizationGraphWidget::isDragAllowed() const
320 bool VisualizationGraphWidget::isDragAllowed() const
319 {
321 {
320 return true;
322 return true;
321 }
323 }
322
324
323 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
325 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
324 {
326 {
325 if (highlighted) {
327 if (highlighted) {
326 plot().setBackground(QBrush(QColor("#BBD5EE")));
328 plot().setBackground(QBrush(QColor("#BBD5EE")));
327 }
329 }
328 else {
330 else {
329 plot().setBackground(QBrush(Qt::white));
331 plot().setBackground(QBrush(Qt::white));
330 }
332 }
331
333
332 plot().update();
334 plot().update();
333 }
335 }
334
336
335 void VisualizationGraphWidget::addVerticalCursor(double time)
337 void VisualizationGraphWidget::addVerticalCursor(double time)
336 {
338 {
337 impl->m_VerticalCursor->setPosition(time);
339 impl->m_VerticalCursor->setPosition(time);
338 impl->m_VerticalCursor->setVisible(true);
340 impl->m_VerticalCursor->setVisible(true);
339
341
340 auto text
342 auto text
341 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
343 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
342 impl->m_VerticalCursor->setLabelText(text);
344 impl->m_VerticalCursor->setLabelText(text);
343 }
345 }
344
346
345 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
347 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
346 {
348 {
347 impl->m_VerticalCursor->setAbsolutePosition(position);
349 impl->m_VerticalCursor->setAbsolutePosition(position);
348 impl->m_VerticalCursor->setVisible(true);
350 impl->m_VerticalCursor->setVisible(true);
349
351
350 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
352 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
351 auto text
353 auto text
352 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
354 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
353 impl->m_VerticalCursor->setLabelText(text);
355 impl->m_VerticalCursor->setLabelText(text);
354 }
356 }
355
357
356 void VisualizationGraphWidget::removeVerticalCursor()
358 void VisualizationGraphWidget::removeVerticalCursor()
357 {
359 {
358 impl->m_VerticalCursor->setVisible(false);
360 impl->m_VerticalCursor->setVisible(false);
359 plot().replot(QCustomPlot::rpQueuedReplot);
361 plot().replot(QCustomPlot::rpQueuedReplot);
360 }
362 }
361
363
362 void VisualizationGraphWidget::addHorizontalCursor(double value)
364 void VisualizationGraphWidget::addHorizontalCursor(double value)
363 {
365 {
364 impl->m_HorizontalCursor->setPosition(value);
366 impl->m_HorizontalCursor->setPosition(value);
365 impl->m_HorizontalCursor->setVisible(true);
367 impl->m_HorizontalCursor->setVisible(true);
366 impl->m_HorizontalCursor->setLabelText(QString::number(value));
368 impl->m_HorizontalCursor->setLabelText(QString::number(value));
367 }
369 }
368
370
369 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
371 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
370 {
372 {
371 impl->m_HorizontalCursor->setAbsolutePosition(position);
373 impl->m_HorizontalCursor->setAbsolutePosition(position);
372 impl->m_HorizontalCursor->setVisible(true);
374 impl->m_HorizontalCursor->setVisible(true);
373
375
374 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
376 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
375 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
377 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
376 }
378 }
377
379
378 void VisualizationGraphWidget::removeHorizontalCursor()
380 void VisualizationGraphWidget::removeHorizontalCursor()
379 {
381 {
380 impl->m_HorizontalCursor->setVisible(false);
382 impl->m_HorizontalCursor->setVisible(false);
381 plot().replot(QCustomPlot::rpQueuedReplot);
383 plot().replot(QCustomPlot::rpQueuedReplot);
382 }
384 }
383
385
384 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
386 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
385 {
387 {
386 Q_UNUSED(event);
388 Q_UNUSED(event);
387
389
388 // Prevents that all variables will be removed from graph when it will be closed
390 // Prevents that all variables will be removed from graph when it will be closed
389 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
391 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
390 emit variableAboutToBeRemoved(variableEntry.first);
392 emit variableAboutToBeRemoved(variableEntry.first);
391 }
393 }
392 }
394 }
393
395
394 void VisualizationGraphWidget::enterEvent(QEvent *event)
396 void VisualizationGraphWidget::enterEvent(QEvent *event)
395 {
397 {
396 Q_UNUSED(event);
398 Q_UNUSED(event);
397 impl->m_RenderingDelegate->showGraphOverlay(true);
399 impl->m_RenderingDelegate->showGraphOverlay(true);
398 }
400 }
399
401
400 void VisualizationGraphWidget::leaveEvent(QEvent *event)
402 void VisualizationGraphWidget::leaveEvent(QEvent *event)
401 {
403 {
402 Q_UNUSED(event);
404 Q_UNUSED(event);
403 impl->m_RenderingDelegate->showGraphOverlay(false);
405 impl->m_RenderingDelegate->showGraphOverlay(false);
404
406
405 if (auto parentZone = parentZoneWidget()) {
407 if (auto parentZone = parentZoneWidget()) {
406 parentZone->notifyMouseLeaveGraph(this);
408 parentZone->notifyMouseLeaveGraph(this);
407 }
409 }
408 else {
410 else {
409 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
411 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
410 }
412 }
411 }
413 }
412
414
413 QCustomPlot &VisualizationGraphWidget::plot() noexcept
415 QCustomPlot &VisualizationGraphWidget::plot() noexcept
414 {
416 {
415 return *ui->widget;
417 return *ui->widget;
416 }
418 }
417
419
418 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
420 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
419 {
421 {
420 QMenu graphMenu{};
422 QMenu graphMenu{};
421
423
422 // Iterates on variables (unique keys)
424 // Iterates on variables (unique keys)
423 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
425 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
424 end = impl->m_VariableToPlotMultiMap.cend();
426 end = impl->m_VariableToPlotMultiMap.cend();
425 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
427 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
426 // 'Remove variable' action
428 // 'Remove variable' action
427 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
429 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
428 [ this, var = it->first ]() { removeVariable(var); });
430 [ this, var = it->first ]() { removeVariable(var); });
429 }
431 }
430
432
431 if (!graphMenu.isEmpty()) {
433 if (!graphMenu.isEmpty()) {
432 graphMenu.exec(QCursor::pos());
434 graphMenu.exec(QCursor::pos());
433 }
435 }
434 }
436 }
435
437
436 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
438 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
437 {
439 {
438 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
440 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
439 << QThread::currentThread()->objectName() << "DoAcqui"
441 << QThread::currentThread()->objectName() << "DoAcqui"
440 << impl->m_DoAcquisition;
442 << impl->m_DoAcquisition;
441
443
442 auto graphRange = SqpRange{t1.lower, t1.upper};
444 auto graphRange = SqpRange{t1.lower, t1.upper};
443 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
445 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
444
446
445 if (impl->m_DoAcquisition) {
447 if (impl->m_DoAcquisition) {
446 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
448 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
447
449
448 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
450 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
449 end = impl->m_VariableToPlotMultiMap.end();
451 end = impl->m_VariableToPlotMultiMap.end();
450 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
452 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
451 variableUnderGraphVector.push_back(it->first);
453 variableUnderGraphVector.push_back(it->first);
452 }
454 }
453 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
455 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
454 !impl->m_IsCalibration);
456 !impl->m_IsCalibration);
455
457
456 if (!impl->m_IsCalibration) {
458 if (!impl->m_IsCalibration) {
457 qCDebug(LOG_VisualizationGraphWidget())
459 qCDebug(LOG_VisualizationGraphWidget())
458 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
460 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
459 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
461 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
460 emit synchronize(graphRange, oldGraphRange);
462 emit synchronize(graphRange, oldGraphRange);
461 }
463 }
462 }
464 }
463
465
464 auto pos = mapFromGlobal(QCursor::pos());
466 auto pos = mapFromGlobal(QCursor::pos());
465 auto axisPos = impl->posToAxisPos(pos, plot());
467 auto axisPos = impl->posToAxisPos(pos, plot());
466 if (auto parentZone = parentZoneWidget()) {
468 if (auto parentZone = parentZoneWidget()) {
467 if (impl->pointIsInAxisRect(axisPos, plot())) {
469 if (impl->pointIsInAxisRect(axisPos, plot())) {
468 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
470 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
469 }
471 }
470 else {
472 else {
471 parentZone->notifyMouseLeaveGraph(this);
473 parentZone->notifyMouseLeaveGraph(this);
472 }
474 }
473 }
475 }
474 else {
476 else {
475 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
477 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
476 }
478 }
477 }
479 }
478
480
481 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
482 {
483 impl->m_RenderingDelegate->onMouseDoubleClick(event);
484 }
485
479 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
486 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
480 {
487 {
481 // Handles plot rendering when mouse is moving
488 // Handles plot rendering when mouse is moving
482 impl->m_RenderingDelegate->onMouseMove(event);
489 impl->m_RenderingDelegate->onMouseMove(event);
483
490
484 auto axisPos = impl->posToAxisPos(event->pos(), plot());
491 auto axisPos = impl->posToAxisPos(event->pos(), plot());
485
492
486 if (impl->m_DrawingRect) {
493 if (impl->m_DrawingRect) {
487 impl->m_DrawingRect->bottomRight->setCoords(axisPos);
494 impl->m_DrawingRect->bottomRight->setCoords(axisPos);
488 }
495 }
489
496
490 if (auto parentZone = parentZoneWidget()) {
497 if (auto parentZone = parentZoneWidget()) {
491 if (impl->pointIsInAxisRect(axisPos, plot())) {
498 if (impl->pointIsInAxisRect(axisPos, plot())) {
492 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
499 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
493 }
500 }
494 else {
501 else {
495 parentZone->notifyMouseLeaveGraph(this);
502 parentZone->notifyMouseLeaveGraph(this);
496 }
503 }
497 }
504 }
498 else {
505 else {
499 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
506 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
500 }
507 }
501
508
502 VisualizationDragWidget::mouseMoveEvent(event);
509 VisualizationDragWidget::mouseMoveEvent(event);
503 }
510 }
504
511
505 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
512 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
506 {
513 {
507 auto value = event->angleDelta().x() + event->angleDelta().y();
514 auto value = event->angleDelta().x() + event->angleDelta().y();
508 if (value != 0) {
515 if (value != 0) {
509
516
510 auto direction = value > 0 ? 1.0 : -1.0;
517 auto direction = value > 0 ? 1.0 : -1.0;
511 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
518 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
512 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
519 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
513 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
520 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
514
521
515 auto zoomOrientations = QFlags<Qt::Orientation>{};
522 auto zoomOrientations = QFlags<Qt::Orientation>{};
516 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
523 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
517 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
524 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
518
525
519 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
526 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
520
527
521 if (!isZoomX && !isZoomY) {
528 if (!isZoomX && !isZoomY) {
522 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
529 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
523 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
530 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
524
531
525 axis->setRange(axis->range() + diff);
532 axis->setRange(axis->range() + diff);
526
533
527 if (plot().noAntialiasingOnDrag()) {
534 if (plot().noAntialiasingOnDrag()) {
528 plot().setNotAntialiasedElements(QCP::aeAll);
535 plot().setNotAntialiasedElements(QCP::aeAll);
529 }
536 }
530
537
531 plot().replot(QCustomPlot::rpQueuedReplot);
538 plot().replot(QCustomPlot::rpQueuedReplot);
532 }
539 }
533 }
540 }
534 }
541 }
535
542
536 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
543 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
537 {
544 {
538 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
545 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
539 impl->startDrawingRect(event->pos(), plot());
546 impl->startDrawingRect(event->pos(), plot());
540 }
547 }
541
548
542 VisualizationDragWidget::mousePressEvent(event);
549 VisualizationDragWidget::mousePressEvent(event);
543 }
550 }
544
551
545 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
552 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
546 {
553 {
547 if (impl->m_DrawingRect) {
554 if (impl->m_DrawingRect) {
548
555
549 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
556 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
550 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
557 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
551
558
552 auto newAxisXRange = QCPRange{impl->m_DrawingRect->topLeft->coords().x(),
559 auto newAxisXRange = QCPRange{impl->m_DrawingRect->topLeft->coords().x(),
553 impl->m_DrawingRect->bottomRight->coords().x()};
560 impl->m_DrawingRect->bottomRight->coords().x()};
554
561
555 auto newAxisYRange = QCPRange{impl->m_DrawingRect->topLeft->coords().y(),
562 auto newAxisYRange = QCPRange{impl->m_DrawingRect->topLeft->coords().y(),
556 impl->m_DrawingRect->bottomRight->coords().y()};
563 impl->m_DrawingRect->bottomRight->coords().y()};
557
564
558 impl->removeDrawingRect(plot());
565 impl->removeDrawingRect(plot());
559
566
560 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
567 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
561 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
568 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
562 axisX->setRange(newAxisXRange);
569 axisX->setRange(newAxisXRange);
563 axisY->setRange(newAxisYRange);
570 axisY->setRange(newAxisYRange);
564
571
565 plot().replot(QCustomPlot::rpQueuedReplot);
572 plot().replot(QCustomPlot::rpQueuedReplot);
566 }
573 }
567 }
574 }
568
575
569 impl->m_IsCalibration = false;
576 impl->m_IsCalibration = false;
570 }
577 }
571
578
572 void VisualizationGraphWidget::onDataCacheVariableUpdated()
579 void VisualizationGraphWidget::onDataCacheVariableUpdated()
573 {
580 {
574 auto graphRange = ui->widget->xAxis->range();
581 auto graphRange = ui->widget->xAxis->range();
575 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
582 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
576
583
577 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
584 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
578 auto variable = variableEntry.first;
585 auto variable = variableEntry.first;
579 qCDebug(LOG_VisualizationGraphWidget())
586 qCDebug(LOG_VisualizationGraphWidget())
580 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
587 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
581 qCDebug(LOG_VisualizationGraphWidget())
588 qCDebug(LOG_VisualizationGraphWidget())
582 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
589 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
583 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
590 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
584 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
591 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
585 variable->range());
592 variable->range());
586 }
593 }
587 }
594 }
588 }
595 }
589
596
590 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
597 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
591 const SqpRange &range)
598 const SqpRange &range)
592 {
599 {
593 auto it = impl->m_VariableToPlotMultiMap.find(variable);
600 auto it = impl->m_VariableToPlotMultiMap.find(variable);
594 if (it != impl->m_VariableToPlotMultiMap.end()) {
601 if (it != impl->m_VariableToPlotMultiMap.end()) {
595 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
602 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
596 }
603 }
597 }
604 }
General Comments 0
You need to be logged in to leave comments. Login now