##// END OF EJS Templates
Handles rendering of plottables (3)...
Alexandre Leroux -
r919:6c44d229ea1f
parent child
Show More
@@ -1,35 +1,39
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 onMouseMove(QMouseEvent *event) noexcept;
21 void onMouseMove(QMouseEvent *event) noexcept;
22
22
23 /// Sets properties of the plot's axes from the data series passed as parameter
23 /// Sets properties of the plot's axes from the data series passed as parameter
24 void setAxesProperties(std::shared_ptr<IDataSeries> dataSeries) noexcept;
24 void setAxesProperties(std::shared_ptr<IDataSeries> dataSeries) noexcept;
25
25
26 /// Sets rendering properties of the plottables passed as parameter, from the data series that
27 /// generated these
28 void setPlottablesProperties(std::shared_ptr<IDataSeries> dataSeries,
29 PlottablesMap &plottables) noexcept;
26
30
27 /// Shows or hides graph overlay (name, close button, etc.)
31 /// Shows or hides graph overlay (name, close button, etc.)
28 void showGraphOverlay(bool show) noexcept;
32 void showGraphOverlay(bool show) noexcept;
29
33
30 private:
34 private:
31 class VisualizationGraphRenderingDelegatePrivate;
35 class VisualizationGraphRenderingDelegatePrivate;
32 spimpl::unique_impl_ptr<VisualizationGraphRenderingDelegatePrivate> impl;
36 spimpl::unique_impl_ptr<VisualizationGraphRenderingDelegatePrivate> impl;
33 };
37 };
34
38
35 #endif // SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
39 #endif // SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
@@ -1,235 +1,243
1 #include "Visualization/VisualizationGraphRenderingDelegate.h"
1 #include "Visualization/VisualizationGraphRenderingDelegate.h"
2 #include "Visualization/AxisRenderingUtils.h"
2 #include "Visualization/AxisRenderingUtils.h"
3 #include "Visualization/PlottablesRenderingUtils.h"
3 #include "Visualization/VisualizationGraphWidget.h"
4 #include "Visualization/VisualizationGraphWidget.h"
4 #include "Visualization/qcustomplot.h"
5 #include "Visualization/qcustomplot.h"
5
6
6 #include <Common/DateUtils.h>
7 #include <Common/DateUtils.h>
7
8
8 #include <Data/IDataSeries.h>
9 #include <Data/IDataSeries.h>
9
10
10 #include <SqpApplication.h>
11 #include <SqpApplication.h>
11
12
12 namespace {
13 namespace {
13
14
14 /// Name of the axes layer in QCustomPlot
15 /// Name of the axes layer in QCustomPlot
15 const auto AXES_LAYER = QStringLiteral("axes");
16 const auto AXES_LAYER = QStringLiteral("axes");
16
17
17 /// Icon used to show x-axis properties
18 /// Icon used to show x-axis properties
18 const auto HIDE_AXIS_ICON_PATH = QStringLiteral(":/icones/down.png");
19 const auto HIDE_AXIS_ICON_PATH = QStringLiteral(":/icones/down.png");
19
20
20 /// Name of the overlay layer in QCustomPlot
21 /// Name of the overlay layer in QCustomPlot
21 const auto OVERLAY_LAYER = QStringLiteral("overlay");
22 const auto OVERLAY_LAYER = QStringLiteral("overlay");
22
23
23 /// Pixmap used to show x-axis properties
24 /// Pixmap used to show x-axis properties
24 const auto SHOW_AXIS_ICON_PATH = QStringLiteral(":/icones/up.png");
25 const auto SHOW_AXIS_ICON_PATH = QStringLiteral(":/icones/up.png");
25
26
26 const auto TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
27 const auto TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
27
28
28 /// Offset used to shift the tooltip of the mouse
29 /// Offset used to shift the tooltip of the mouse
29 const auto TOOLTIP_OFFSET = QPoint{20, 20};
30 const auto TOOLTIP_OFFSET = QPoint{20, 20};
30
31
31 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
32 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
32 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
33 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
33
34
34 /// Timeout after which the tooltip is displayed
35 /// Timeout after which the tooltip is displayed
35 const auto TOOLTIP_TIMEOUT = 500;
36 const auto TOOLTIP_TIMEOUT = 500;
36
37
37 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
38 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
38 {
39 {
39 tracer.setInterpolating(false);
40 tracer.setInterpolating(false);
40 tracer.setStyle(QCPItemTracer::tsCircle);
41 tracer.setStyle(QCPItemTracer::tsCircle);
41 tracer.setSize(3);
42 tracer.setSize(3);
42 tracer.setPen(QPen(Qt::black));
43 tracer.setPen(QPen(Qt::black));
43 tracer.setBrush(Qt::black);
44 tracer.setBrush(Qt::black);
44 }
45 }
45
46
46 QPixmap pixmap(const QString &iconPath) noexcept
47 QPixmap pixmap(const QString &iconPath) noexcept
47 {
48 {
48 return QIcon{iconPath}.pixmap(QSize{16, 16});
49 return QIcon{iconPath}.pixmap(QSize{16, 16});
49 }
50 }
50
51
51 void initClosePixmapStyle(QCPItemPixmap &pixmap) noexcept
52 void initClosePixmapStyle(QCPItemPixmap &pixmap) noexcept
52 {
53 {
53 // Icon
54 // Icon
54 pixmap.setPixmap(
55 pixmap.setPixmap(
55 sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton).pixmap(QSize{16, 16}));
56 sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton).pixmap(QSize{16, 16}));
56
57
57 // Position
58 // Position
58 pixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
59 pixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
59 pixmap.topLeft->setCoords(1, 0);
60 pixmap.topLeft->setCoords(1, 0);
60 pixmap.setClipToAxisRect(false);
61 pixmap.setClipToAxisRect(false);
61
62
62 // Can be selected
63 // Can be selected
63 pixmap.setSelectable(true);
64 pixmap.setSelectable(true);
64 }
65 }
65
66
66 void initXAxisPixmapStyle(QCPItemPixmap &itemPixmap) noexcept
67 void initXAxisPixmapStyle(QCPItemPixmap &itemPixmap) noexcept
67 {
68 {
68 // Icon
69 // Icon
69 itemPixmap.setPixmap(pixmap(HIDE_AXIS_ICON_PATH));
70 itemPixmap.setPixmap(pixmap(HIDE_AXIS_ICON_PATH));
70
71
71 // Position
72 // Position
72 itemPixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
73 itemPixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
73 itemPixmap.topLeft->setCoords(0, 1);
74 itemPixmap.topLeft->setCoords(0, 1);
74 itemPixmap.setClipToAxisRect(false);
75 itemPixmap.setClipToAxisRect(false);
75
76
76 // Can be selected
77 // Can be selected
77 itemPixmap.setSelectable(true);
78 itemPixmap.setSelectable(true);
78 }
79 }
79
80
80 void initTitleTextStyle(QCPItemText &text) noexcept
81 void initTitleTextStyle(QCPItemText &text) noexcept
81 {
82 {
82 // Font and background styles
83 // Font and background styles
83 text.setColor(Qt::gray);
84 text.setColor(Qt::gray);
84 text.setBrush(Qt::white);
85 text.setBrush(Qt::white);
85
86
86 // Position
87 // Position
87 text.setPositionAlignment(Qt::AlignTop | Qt::AlignLeft);
88 text.setPositionAlignment(Qt::AlignTop | Qt::AlignLeft);
88 text.position->setType(QCPItemPosition::ptAxisRectRatio);
89 text.position->setType(QCPItemPosition::ptAxisRectRatio);
89 text.position->setCoords(0.5, 0);
90 text.position->setCoords(0.5, 0);
90 }
91 }
91
92
92 } // namespace
93 } // namespace
93
94
94 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
95 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
95 explicit VisualizationGraphRenderingDelegatePrivate(VisualizationGraphWidget &graphWidget)
96 explicit VisualizationGraphRenderingDelegatePrivate(VisualizationGraphWidget &graphWidget)
96 : m_Plot{graphWidget.plot()},
97 : m_Plot{graphWidget.plot()},
97 m_PointTracer{new QCPItemTracer{&m_Plot}},
98 m_PointTracer{new QCPItemTracer{&m_Plot}},
98 m_TracerTimer{},
99 m_TracerTimer{},
99 m_ClosePixmap{new QCPItemPixmap{&m_Plot}},
100 m_ClosePixmap{new QCPItemPixmap{&m_Plot}},
100 m_TitleText{new QCPItemText{&m_Plot}},
101 m_TitleText{new QCPItemText{&m_Plot}},
101 m_XAxisPixmap{new QCPItemPixmap{&m_Plot}},
102 m_XAxisPixmap{new QCPItemPixmap{&m_Plot}},
102 m_ShowXAxis{true},
103 m_ShowXAxis{true},
103 m_XAxisLabel{}
104 m_XAxisLabel{}
104 {
105 {
105 initPointTracerStyle(*m_PointTracer);
106 initPointTracerStyle(*m_PointTracer);
106
107
107 m_TracerTimer.setInterval(TOOLTIP_TIMEOUT);
108 m_TracerTimer.setInterval(TOOLTIP_TIMEOUT);
108 m_TracerTimer.setSingleShot(true);
109 m_TracerTimer.setSingleShot(true);
109
110
110 // Inits "close button" in plot overlay
111 // Inits "close button" in plot overlay
111 m_ClosePixmap->setLayer(OVERLAY_LAYER);
112 m_ClosePixmap->setLayer(OVERLAY_LAYER);
112 initClosePixmapStyle(*m_ClosePixmap);
113 initClosePixmapStyle(*m_ClosePixmap);
113
114
114 // Connects pixmap selection to graph widget closing
115 // Connects pixmap selection to graph widget closing
115 QObject::connect(m_ClosePixmap, &QCPItemPixmap::selectionChanged,
116 QObject::connect(m_ClosePixmap, &QCPItemPixmap::selectionChanged,
116 [&graphWidget](bool selected) {
117 [&graphWidget](bool selected) {
117 if (selected) {
118 if (selected) {
118 graphWidget.close();
119 graphWidget.close();
119 }
120 }
120 });
121 });
121
122
122 // Inits graph name in plot overlay
123 // Inits graph name in plot overlay
123 m_TitleText->setLayer(OVERLAY_LAYER);
124 m_TitleText->setLayer(OVERLAY_LAYER);
124 m_TitleText->setText(graphWidget.name());
125 m_TitleText->setText(graphWidget.name());
125 initTitleTextStyle(*m_TitleText);
126 initTitleTextStyle(*m_TitleText);
126
127
127 // Inits "show x-axis button" in plot overlay
128 // Inits "show x-axis button" in plot overlay
128 m_XAxisPixmap->setLayer(OVERLAY_LAYER);
129 m_XAxisPixmap->setLayer(OVERLAY_LAYER);
129 initXAxisPixmapStyle(*m_XAxisPixmap);
130 initXAxisPixmapStyle(*m_XAxisPixmap);
130
131
131 // Connects pixmap selection to graph x-axis showing/hiding
132 // Connects pixmap selection to graph x-axis showing/hiding
132 QObject::connect(m_XAxisPixmap, &QCPItemPixmap::selectionChanged, [this]() {
133 QObject::connect(m_XAxisPixmap, &QCPItemPixmap::selectionChanged, [this]() {
133 if (m_XAxisPixmap->selected()) {
134 if (m_XAxisPixmap->selected()) {
134 // Changes the selection state and refreshes the x-axis
135 // Changes the selection state and refreshes the x-axis
135 m_ShowXAxis = !m_ShowXAxis;
136 m_ShowXAxis = !m_ShowXAxis;
136 updateXAxisState();
137 updateXAxisState();
137 m_Plot.layer(AXES_LAYER)->replot();
138 m_Plot.layer(AXES_LAYER)->replot();
138
139
139 // Deselects the x-axis pixmap and updates icon
140 // Deselects the x-axis pixmap and updates icon
140 m_XAxisPixmap->setSelected(false);
141 m_XAxisPixmap->setSelected(false);
141 m_XAxisPixmap->setPixmap(
142 m_XAxisPixmap->setPixmap(
142 pixmap(m_ShowXAxis ? HIDE_AXIS_ICON_PATH : SHOW_AXIS_ICON_PATH));
143 pixmap(m_ShowXAxis ? HIDE_AXIS_ICON_PATH : SHOW_AXIS_ICON_PATH));
143 m_Plot.layer(OVERLAY_LAYER)->replot();
144 m_Plot.layer(OVERLAY_LAYER)->replot();
144 }
145 }
145 });
146 });
146 }
147 }
147
148
148 /// Updates state of x-axis according to the current selection of x-axis pixmap
149 /// Updates state of x-axis according to the current selection of x-axis pixmap
149 /// @remarks the method doesn't call plot refresh
150 /// @remarks the method doesn't call plot refresh
150 void updateXAxisState() noexcept
151 void updateXAxisState() noexcept
151 {
152 {
152 m_Plot.xAxis->setTickLabels(m_ShowXAxis);
153 m_Plot.xAxis->setTickLabels(m_ShowXAxis);
153 m_Plot.xAxis->setLabel(m_ShowXAxis ? m_XAxisLabel : QString{});
154 m_Plot.xAxis->setLabel(m_ShowXAxis ? m_XAxisLabel : QString{});
154 }
155 }
155
156
156 QCustomPlot &m_Plot;
157 QCustomPlot &m_Plot;
157 QCPItemTracer *m_PointTracer;
158 QCPItemTracer *m_PointTracer;
158 QTimer m_TracerTimer;
159 QTimer m_TracerTimer;
159 QCPItemPixmap *m_ClosePixmap; /// Graph's close button
160 QCPItemPixmap *m_ClosePixmap; /// Graph's close button
160 QCPItemText *m_TitleText; /// Graph's title
161 QCPItemText *m_TitleText; /// Graph's title
161 QCPItemPixmap *m_XAxisPixmap;
162 QCPItemPixmap *m_XAxisPixmap;
162 bool m_ShowXAxis; /// X-axis properties are shown or hidden
163 bool m_ShowXAxis; /// X-axis properties are shown or hidden
163 QString m_XAxisLabel;
164 QString m_XAxisLabel;
164 };
165 };
165
166
166 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(
167 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(
167 VisualizationGraphWidget &graphWidget)
168 VisualizationGraphWidget &graphWidget)
168 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(graphWidget)}
169 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(graphWidget)}
169 {
170 {
170 }
171 }
171
172
172 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
173 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
173 {
174 {
174 // Cancels pending refresh
175 // Cancels pending refresh
175 impl->m_TracerTimer.disconnect();
176 impl->m_TracerTimer.disconnect();
176
177
177 // Reinits tracers
178 // Reinits tracers
178 impl->m_PointTracer->setGraph(nullptr);
179 impl->m_PointTracer->setGraph(nullptr);
179 impl->m_PointTracer->setVisible(false);
180 impl->m_PointTracer->setVisible(false);
180 impl->m_Plot.replot();
181 impl->m_Plot.replot();
181
182
182 // Gets the graph under the mouse position
183 // Gets the graph under the mouse position
183 auto eventPos = event->pos();
184 auto eventPos = event->pos();
184 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
185 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
185 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
186 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
186 auto graphData = graph->data();
187 auto graphData = graph->data();
187
188
188 // Gets the closest data point to the mouse
189 // Gets the closest data point to the mouse
189 auto graphDataIt = graphData->findBegin(mouseKey);
190 auto graphDataIt = graphData->findBegin(mouseKey);
190 if (graphDataIt != graphData->constEnd()) {
191 if (graphDataIt != graphData->constEnd()) {
191 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
192 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
192 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
193 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
193
194
194 // Displays point tracer
195 // Displays point tracer
195 impl->m_PointTracer->setGraph(graph);
196 impl->m_PointTracer->setGraph(graph);
196 impl->m_PointTracer->setGraphKey(graphDataIt->key);
197 impl->m_PointTracer->setGraphKey(graphDataIt->key);
197 impl->m_PointTracer->setLayer(
198 impl->m_PointTracer->setLayer(
198 impl->m_Plot.layer("main")); // Tracer is set on top of the plot's main layer
199 impl->m_Plot.layer("main")); // Tracer is set on top of the plot's main layer
199 impl->m_PointTracer->setVisible(true);
200 impl->m_PointTracer->setVisible(true);
200 impl->m_Plot.replot();
201 impl->m_Plot.replot();
201
202
202 // Starts timer to show tooltip after timeout
203 // Starts timer to show tooltip after timeout
203 auto showTooltip = [ tooltip = TOOLTIP_FORMAT.arg(key, value), eventPos, this ]()
204 auto showTooltip = [ tooltip = TOOLTIP_FORMAT.arg(key, value), eventPos, this ]()
204 {
205 {
205 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos) + TOOLTIP_OFFSET, tooltip,
206 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos) + TOOLTIP_OFFSET, tooltip,
206 &impl->m_Plot, TOOLTIP_RECT);
207 &impl->m_Plot, TOOLTIP_RECT);
207 };
208 };
208
209
209 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
210 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
210 impl->m_TracerTimer.start();
211 impl->m_TracerTimer.start();
211 }
212 }
212 }
213 }
213 }
214 }
214
215
215 void VisualizationGraphRenderingDelegate::setAxesProperties(
216 void VisualizationGraphRenderingDelegate::setAxesProperties(
216 std::shared_ptr<IDataSeries> dataSeries) noexcept
217 std::shared_ptr<IDataSeries> dataSeries) noexcept
217 {
218 {
218 // Stores x-axis label to be able to retrieve it when x-axis pixmap is unselected
219 // Stores x-axis label to be able to retrieve it when x-axis pixmap is unselected
219 impl->m_XAxisLabel = dataSeries->xAxisUnit().m_Name;
220 impl->m_XAxisLabel = dataSeries->xAxisUnit().m_Name;
220
221
221 auto axisHelper = IAxisHelperFactory::create(dataSeries);
222 auto axisHelper = IAxisHelperFactory::create(dataSeries);
222 axisHelper->setProperties(impl->m_Plot, *impl->m_ColorScale);
223 axisHelper->setProperties(impl->m_Plot, *impl->m_ColorScale);
223
224
224 // Updates x-axis state
225 // Updates x-axis state
225 impl->updateXAxisState();
226 impl->updateXAxisState();
226
227
227 impl->m_Plot.layer(AXES_LAYER)->replot();
228 impl->m_Plot.layer(AXES_LAYER)->replot();
228 }
229 }
229
230
231 void VisualizationGraphRenderingDelegate::setPlottablesProperties(
232 std::shared_ptr<IDataSeries> dataSeries, PlottablesMap &plottables) noexcept
233 {
234 auto plottablesHelper = IPlottablesHelperFactory::create(dataSeries);
235 plottablesHelper->setProperties(plottables);
236 }
237
230 void VisualizationGraphRenderingDelegate::showGraphOverlay(bool show) noexcept
238 void VisualizationGraphRenderingDelegate::showGraphOverlay(bool show) noexcept
231 {
239 {
232 auto overlay = impl->m_Plot.layer(OVERLAY_LAYER);
240 auto overlay = impl->m_Plot.layer(OVERLAY_LAYER);
233 overlay->setVisible(show);
241 overlay->setVisible(show);
234 overlay->replot();
242 overlay->replot();
235 }
243 }
@@ -1,397 +1,402
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationDefs.h"
3 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationGraphHelper.h"
4 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
8
8
9 #include <Common/MimeTypesDef.h>
9 #include <Common/MimeTypesDef.h>
10 #include <Data/ArrayData.h>
10 #include <Data/ArrayData.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <DragAndDrop/DragDropHelper.h>
12 #include <DragAndDrop/DragDropHelper.h>
13 #include <Settings/SqpSettingsDefs.h>
13 #include <Settings/SqpSettingsDefs.h>
14 #include <SqpApplication.h>
14 #include <SqpApplication.h>
15 #include <Time/TimeController.h>
15 #include <Time/TimeController.h>
16 #include <Variable/Variable.h>
16 #include <Variable/Variable.h>
17 #include <Variable/VariableController.h>
17 #include <Variable/VariableController.h>
18
18
19 #include <unordered_map>
19 #include <unordered_map>
20
20
21 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
21 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
22
22
23 namespace {
23 namespace {
24
24
25 /// Key pressed to enable zoom on horizontal axis
25 /// Key pressed to enable zoom on horizontal axis
26 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
26 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
27
27
28 /// Key pressed to enable zoom on vertical axis
28 /// Key pressed to enable zoom on vertical axis
29 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
29 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
30
30
31 } // namespace
31 } // namespace
32
32
33 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
33 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
34
34
35 explicit VisualizationGraphWidgetPrivate(const QString &name)
35 explicit VisualizationGraphWidgetPrivate(const QString &name)
36 : m_Name{name},
36 : m_Name{name},
37 m_DoAcquisition{true},
37 m_DoAcquisition{true},
38 m_IsCalibration{false},
38 m_IsCalibration{false},
39 m_RenderingDelegate{nullptr}
39 m_RenderingDelegate{nullptr}
40 {
40 {
41 }
41 }
42
42
43 QString m_Name;
43 QString m_Name;
44 // 1 variable -> n qcpplot
44 // 1 variable -> n qcpplot
45 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
45 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
46 bool m_DoAcquisition;
46 bool m_DoAcquisition;
47 bool m_IsCalibration;
47 bool m_IsCalibration;
48 /// Delegate used to attach rendering features to the plot
48 /// Delegate used to attach rendering features to the plot
49 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
49 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
50 };
50 };
51
51
52 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
52 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
53 : VisualizationDragWidget{parent},
53 : VisualizationDragWidget{parent},
54 ui{new Ui::VisualizationGraphWidget},
54 ui{new Ui::VisualizationGraphWidget},
55 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
55 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
56 {
56 {
57 ui->setupUi(this);
57 ui->setupUi(this);
58
58
59 // 'Close' options : widget is deleted when closed
59 // 'Close' options : widget is deleted when closed
60 setAttribute(Qt::WA_DeleteOnClose);
60 setAttribute(Qt::WA_DeleteOnClose);
61
61
62 // Set qcpplot properties :
62 // Set qcpplot properties :
63 // - Drag (on x-axis) and zoom are enabled
63 // - Drag (on x-axis) and zoom are enabled
64 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
64 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
65 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
65 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
66 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
66 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
67
67
68 // The delegate must be initialized after the ui as it uses the plot
68 // The delegate must be initialized after the ui as it uses the plot
69 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
69 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
70
70
71 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
71 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
72 connect(ui->widget, &QCustomPlot::mouseRelease, this,
72 connect(ui->widget, &QCustomPlot::mouseRelease, this,
73 &VisualizationGraphWidget::onMouseRelease);
73 &VisualizationGraphWidget::onMouseRelease);
74 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
74 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
75 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
75 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
76 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
76 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
77 &QCPAxis::rangeChanged),
77 &QCPAxis::rangeChanged),
78 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
78 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
79
79
80 // Activates menu when right clicking on the graph
80 // Activates menu when right clicking on the graph
81 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
81 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
82 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
82 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
83 &VisualizationGraphWidget::onGraphMenuRequested);
83 &VisualizationGraphWidget::onGraphMenuRequested);
84
84
85 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
85 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
86 &VariableController::onRequestDataLoading);
86 &VariableController::onRequestDataLoading);
87
87
88 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
88 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
89 &VisualizationGraphWidget::onUpdateVarDisplaying);
89 &VisualizationGraphWidget::onUpdateVarDisplaying);
90 }
90 }
91
91
92
92
93 VisualizationGraphWidget::~VisualizationGraphWidget()
93 VisualizationGraphWidget::~VisualizationGraphWidget()
94 {
94 {
95 delete ui;
95 delete ui;
96 }
96 }
97
97
98 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
98 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
99 {
99 {
100 auto parent = parentWidget();
100 auto parent = parentWidget();
101 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
101 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
102 parent = parent->parentWidget();
102 parent = parent->parentWidget();
103 }
103 }
104
104
105 return qobject_cast<VisualizationZoneWidget *>(parent);
105 return qobject_cast<VisualizationZoneWidget *>(parent);
106 }
106 }
107
107
108 void VisualizationGraphWidget::enableAcquisition(bool enable)
108 void VisualizationGraphWidget::enableAcquisition(bool enable)
109 {
109 {
110 impl->m_DoAcquisition = enable;
110 impl->m_DoAcquisition = enable;
111 }
111 }
112
112
113 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
113 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
114 {
114 {
115 // Uses delegate to create the qcpplot components according to the variable
115 // Uses delegate to create the qcpplot components according to the variable
116 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
116 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
117
117
118 if (auto dataSeries = variable->dataSeries()) {
118 if (auto dataSeries = variable->dataSeries()) {
119 // Set axes properties according to the units of the data series
119 // Set axes properties according to the units of the data series
120 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
120 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
121
122 // Sets rendering properties for the new plottables
123 // Warning: this method must be called after setAxesProperties(), as it can access to some
124 // axes properties that have to be initialized
125 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
121 }
126 }
122
127
123 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
128 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
124
129
125 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
130 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
126
131
127 this->enableAcquisition(false);
132 this->enableAcquisition(false);
128 this->setGraphRange(range);
133 this->setGraphRange(range);
129 this->enableAcquisition(true);
134 this->enableAcquisition(true);
130
135
131 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
136 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
132
137
133 emit variableAdded(variable);
138 emit variableAdded(variable);
134 }
139 }
135
140
136 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
141 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
137 {
142 {
138 // Each component associated to the variable :
143 // Each component associated to the variable :
139 // - is removed from qcpplot (which deletes it)
144 // - is removed from qcpplot (which deletes it)
140 // - is no longer referenced in the map
145 // - is no longer referenced in the map
141 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
146 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
142 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
147 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
143 emit variableAboutToBeRemoved(variable);
148 emit variableAboutToBeRemoved(variable);
144
149
145 auto &plottablesMap = variableIt->second;
150 auto &plottablesMap = variableIt->second;
146
151
147 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
152 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
148 plottableIt != plottableEnd;) {
153 plottableIt != plottableEnd;) {
149 ui->widget->removePlottable(plottableIt->second);
154 ui->widget->removePlottable(plottableIt->second);
150 plottableIt = plottablesMap.erase(plottableIt);
155 plottableIt = plottablesMap.erase(plottableIt);
151 }
156 }
152
157
153 impl->m_VariableToPlotMultiMap.erase(variableIt);
158 impl->m_VariableToPlotMultiMap.erase(variableIt);
154 }
159 }
155
160
156 // Updates graph
161 // Updates graph
157 ui->widget->replot();
162 ui->widget->replot();
158 }
163 }
159
164
160 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
165 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
161 {
166 {
162 auto variables = QList<std::shared_ptr<Variable> >{};
167 auto variables = QList<std::shared_ptr<Variable> >{};
163 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
168 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
164 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
169 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
165 variables << it->first;
170 variables << it->first;
166 }
171 }
167
172
168 return variables;
173 return variables;
169 }
174 }
170
175
171 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
176 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
172 {
177 {
173 if (!variable) {
178 if (!variable) {
174 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
179 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
175 return;
180 return;
176 }
181 }
177
182
178 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
183 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
179 }
184 }
180
185
181 SqpRange VisualizationGraphWidget::graphRange() const noexcept
186 SqpRange VisualizationGraphWidget::graphRange() const noexcept
182 {
187 {
183 auto graphRange = ui->widget->xAxis->range();
188 auto graphRange = ui->widget->xAxis->range();
184 return SqpRange{graphRange.lower, graphRange.upper};
189 return SqpRange{graphRange.lower, graphRange.upper};
185 }
190 }
186
191
187 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
192 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
188 {
193 {
189 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
194 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
190 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
195 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
191 ui->widget->replot();
196 ui->widget->replot();
192 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
197 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
193 }
198 }
194
199
195 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
200 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
196 {
201 {
197 if (visitor) {
202 if (visitor) {
198 visitor->visit(this);
203 visitor->visit(this);
199 }
204 }
200 else {
205 else {
201 qCCritical(LOG_VisualizationGraphWidget())
206 qCCritical(LOG_VisualizationGraphWidget())
202 << tr("Can't visit widget : the visitor is null");
207 << tr("Can't visit widget : the visitor is null");
203 }
208 }
204 }
209 }
205
210
206 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
211 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
207 {
212 {
208 /// @todo : for the moment, a graph can always accomodate a variable
213 /// @todo : for the moment, a graph can always accomodate a variable
209 Q_UNUSED(variable);
214 Q_UNUSED(variable);
210 return true;
215 return true;
211 }
216 }
212
217
213 bool VisualizationGraphWidget::contains(const Variable &variable) const
218 bool VisualizationGraphWidget::contains(const Variable &variable) const
214 {
219 {
215 // Finds the variable among the keys of the map
220 // Finds the variable among the keys of the map
216 auto variablePtr = &variable;
221 auto variablePtr = &variable;
217 auto findVariable
222 auto findVariable
218 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
223 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
219
224
220 auto end = impl->m_VariableToPlotMultiMap.cend();
225 auto end = impl->m_VariableToPlotMultiMap.cend();
221 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
226 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
222 return it != end;
227 return it != end;
223 }
228 }
224
229
225 QString VisualizationGraphWidget::name() const
230 QString VisualizationGraphWidget::name() const
226 {
231 {
227 return impl->m_Name;
232 return impl->m_Name;
228 }
233 }
229
234
230 QMimeData *VisualizationGraphWidget::mimeData() const
235 QMimeData *VisualizationGraphWidget::mimeData() const
231 {
236 {
232 auto mimeData = new QMimeData;
237 auto mimeData = new QMimeData;
233 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
238 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
234
239
235 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
240 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
236 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
241 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
237
242
238 return mimeData;
243 return mimeData;
239 }
244 }
240
245
241 bool VisualizationGraphWidget::isDragAllowed() const
246 bool VisualizationGraphWidget::isDragAllowed() const
242 {
247 {
243 return true;
248 return true;
244 }
249 }
245
250
246 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
251 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
247 {
252 {
248 if (highlighted) {
253 if (highlighted) {
249 plot().setBackground(QBrush(QColor("#BBD5EE")));
254 plot().setBackground(QBrush(QColor("#BBD5EE")));
250 }
255 }
251 else {
256 else {
252 plot().setBackground(QBrush(Qt::white));
257 plot().setBackground(QBrush(Qt::white));
253 }
258 }
254
259
255 plot().update();
260 plot().update();
256 }
261 }
257
262
258 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
263 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
259 {
264 {
260 Q_UNUSED(event);
265 Q_UNUSED(event);
261
266
262 // Prevents that all variables will be removed from graph when it will be closed
267 // Prevents that all variables will be removed from graph when it will be closed
263 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
268 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
264 emit variableAboutToBeRemoved(variableEntry.first);
269 emit variableAboutToBeRemoved(variableEntry.first);
265 }
270 }
266 }
271 }
267
272
268 void VisualizationGraphWidget::enterEvent(QEvent *event)
273 void VisualizationGraphWidget::enterEvent(QEvent *event)
269 {
274 {
270 Q_UNUSED(event);
275 Q_UNUSED(event);
271 impl->m_RenderingDelegate->showGraphOverlay(true);
276 impl->m_RenderingDelegate->showGraphOverlay(true);
272 }
277 }
273
278
274 void VisualizationGraphWidget::leaveEvent(QEvent *event)
279 void VisualizationGraphWidget::leaveEvent(QEvent *event)
275 {
280 {
276 Q_UNUSED(event);
281 Q_UNUSED(event);
277 impl->m_RenderingDelegate->showGraphOverlay(false);
282 impl->m_RenderingDelegate->showGraphOverlay(false);
278 }
283 }
279
284
280 QCustomPlot &VisualizationGraphWidget::plot() noexcept
285 QCustomPlot &VisualizationGraphWidget::plot() noexcept
281 {
286 {
282 return *ui->widget;
287 return *ui->widget;
283 }
288 }
284
289
285 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
290 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
286 {
291 {
287 QMenu graphMenu{};
292 QMenu graphMenu{};
288
293
289 // Iterates on variables (unique keys)
294 // Iterates on variables (unique keys)
290 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
295 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
291 end = impl->m_VariableToPlotMultiMap.cend();
296 end = impl->m_VariableToPlotMultiMap.cend();
292 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
297 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
293 // 'Remove variable' action
298 // 'Remove variable' action
294 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
299 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
295 [ this, var = it->first ]() { removeVariable(var); });
300 [ this, var = it->first ]() { removeVariable(var); });
296 }
301 }
297
302
298 if (!graphMenu.isEmpty()) {
303 if (!graphMenu.isEmpty()) {
299 graphMenu.exec(QCursor::pos());
304 graphMenu.exec(QCursor::pos());
300 }
305 }
301 }
306 }
302
307
303 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
308 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
304 {
309 {
305 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
310 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
306 << QThread::currentThread()->objectName() << "DoAcqui"
311 << QThread::currentThread()->objectName() << "DoAcqui"
307 << impl->m_DoAcquisition;
312 << impl->m_DoAcquisition;
308
313
309 auto graphRange = SqpRange{t1.lower, t1.upper};
314 auto graphRange = SqpRange{t1.lower, t1.upper};
310 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
315 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
311
316
312 if (impl->m_DoAcquisition) {
317 if (impl->m_DoAcquisition) {
313 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
318 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
314
319
315 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
320 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
316 end = impl->m_VariableToPlotMultiMap.end();
321 end = impl->m_VariableToPlotMultiMap.end();
317 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
322 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
318 variableUnderGraphVector.push_back(it->first);
323 variableUnderGraphVector.push_back(it->first);
319 }
324 }
320 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
325 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
321 !impl->m_IsCalibration);
326 !impl->m_IsCalibration);
322
327
323 if (!impl->m_IsCalibration) {
328 if (!impl->m_IsCalibration) {
324 qCDebug(LOG_VisualizationGraphWidget())
329 qCDebug(LOG_VisualizationGraphWidget())
325 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
330 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
326 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
331 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
327 emit synchronize(graphRange, oldGraphRange);
332 emit synchronize(graphRange, oldGraphRange);
328 }
333 }
329 }
334 }
330 }
335 }
331
336
332 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
337 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
333 {
338 {
334 // Handles plot rendering when mouse is moving
339 // Handles plot rendering when mouse is moving
335 impl->m_RenderingDelegate->onMouseMove(event);
340 impl->m_RenderingDelegate->onMouseMove(event);
336
341
337 VisualizationDragWidget::mouseMoveEvent(event);
342 VisualizationDragWidget::mouseMoveEvent(event);
338 }
343 }
339
344
340 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
345 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
341 {
346 {
342 auto zoomOrientations = QFlags<Qt::Orientation>{};
347 auto zoomOrientations = QFlags<Qt::Orientation>{};
343
348
344 // Lambda that enables a zoom orientation if the key modifier related to this orientation
349 // Lambda that enables a zoom orientation if the key modifier related to this orientation
345 // has
350 // has
346 // been pressed
351 // been pressed
347 auto enableOrientation
352 auto enableOrientation
348 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
353 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
349 auto orientationEnabled = event->modifiers().testFlag(modifier);
354 auto orientationEnabled = event->modifiers().testFlag(modifier);
350 zoomOrientations.setFlag(orientation, orientationEnabled);
355 zoomOrientations.setFlag(orientation, orientationEnabled);
351 };
356 };
352 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
357 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
353 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
358 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
354
359
355 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
360 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
356 }
361 }
357
362
358 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
363 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
359 {
364 {
360 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
365 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
361
366
362 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
367 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
363
368
364 VisualizationDragWidget::mousePressEvent(event);
369 VisualizationDragWidget::mousePressEvent(event);
365 }
370 }
366
371
367 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
372 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
368 {
373 {
369 impl->m_IsCalibration = false;
374 impl->m_IsCalibration = false;
370 }
375 }
371
376
372 void VisualizationGraphWidget::onDataCacheVariableUpdated()
377 void VisualizationGraphWidget::onDataCacheVariableUpdated()
373 {
378 {
374 auto graphRange = ui->widget->xAxis->range();
379 auto graphRange = ui->widget->xAxis->range();
375 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
380 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
376
381
377 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
382 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
378 auto variable = variableEntry.first;
383 auto variable = variableEntry.first;
379 qCDebug(LOG_VisualizationGraphWidget())
384 qCDebug(LOG_VisualizationGraphWidget())
380 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
385 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
381 qCDebug(LOG_VisualizationGraphWidget())
386 qCDebug(LOG_VisualizationGraphWidget())
382 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
387 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
383 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
388 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
384 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
389 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
385 variable->range());
390 variable->range());
386 }
391 }
387 }
392 }
388 }
393 }
389
394
390 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
395 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
391 const SqpRange &range)
396 const SqpRange &range)
392 {
397 {
393 auto it = impl->m_VariableToPlotMultiMap.find(variable);
398 auto it = impl->m_VariableToPlotMultiMap.find(variable);
394 if (it != impl->m_VariableToPlotMultiMap.end()) {
399 if (it != impl->m_VariableToPlotMultiMap.end()) {
395 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
400 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
396 }
401 }
397 }
402 }
General Comments 0
You need to be logged in to leave comments. Login now