##// END OF EJS Templates
Separate the initialization of the properties of the graph of the update of the units of the graph....
Alexandre Leroux -
r1308:41b7c6aab8be
parent child
Show More
@@ -1,42 +1,44
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 Variable;
12 class VisualizationGraphWidget;
13 class VisualizationGraphWidget;
13
14
14 class VisualizationGraphRenderingDelegate {
15 class VisualizationGraphRenderingDelegate {
15 public:
16 public:
16 /// Ctor
17 /// Ctor
17 /// @param graphWidget the graph widget to which the delegate is associated
18 /// @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
19 /// @remarks the graph widget must exist throughout the life cycle of the delegate
19 explicit VisualizationGraphRenderingDelegate(VisualizationGraphWidget &graphWidget);
20 explicit VisualizationGraphRenderingDelegate(VisualizationGraphWidget &graphWidget);
20
21
21 void onMouseDoubleClick(QMouseEvent *event) noexcept;
22 void onMouseDoubleClick(QMouseEvent *event) noexcept;
22 void onMouseMove(QMouseEvent *event) noexcept;
23 void onMouseMove(QMouseEvent *event) noexcept;
23 /// Updates rendering when data of plot changed
24 /// Updates rendering when data of plot changed
24 void onPlotUpdated() noexcept;
25 void onPlotUpdated() noexcept;
25
26
26 /// Sets properties of the plot's axes from the data series passed as parameter
27 /// Sets units of the plot's axes according to the properties of the variable passed as
27 void setAxesProperties(std::shared_ptr<IDataSeries> dataSeries) noexcept;
28 /// parameter
29 void setAxesUnits(const Variable &variable) noexcept;
28
30
29 /// Sets rendering properties of the plottables passed as parameter, from the data series that
31 /// Sets graph properties of the plottables passed as parameter, from the variable that
30 /// generated these
32 /// generated these
31 void setPlottablesProperties(std::shared_ptr<IDataSeries> dataSeries,
33 void setGraphProperties(const Variable &variable, PlottablesMap &plottables) noexcept;
32 PlottablesMap &plottables) noexcept;
34
33
35
34 /// Shows or hides graph overlay (name, close button, etc.)
36 /// Shows or hides graph overlay (name, close button, etc.)
35 void showGraphOverlay(bool show) noexcept;
37 void showGraphOverlay(bool show) noexcept;
36
38
37 private:
39 private:
38 class VisualizationGraphRenderingDelegatePrivate;
40 class VisualizationGraphRenderingDelegatePrivate;
39 spimpl::unique_impl_ptr<VisualizationGraphRenderingDelegatePrivate> impl;
41 spimpl::unique_impl_ptr<VisualizationGraphRenderingDelegatePrivate> impl;
40 };
42 };
41
43
42 #endif // SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
44 #endif // SCIQLOP_VISUALIZATIONGRAPHRENDERINGDELEGATE_H
@@ -1,332 +1,338
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/ColorScaleEditor.h"
4 #include "Visualization/PlottablesRenderingUtils.h"
4 #include "Visualization/PlottablesRenderingUtils.h"
5 #include "Visualization/SqpColorScale.h"
5 #include "Visualization/SqpColorScale.h"
6 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationGraphWidget.h"
7 #include "Visualization/qcustomplot.h"
7 #include "Visualization/qcustomplot.h"
8
8
9 #include <Common/DateUtils.h>
9 #include <Common/DateUtils.h>
10
10
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <Variable/Variable.h>
12
13
13 #include <SqpApplication.h>
14 #include <SqpApplication.h>
14
15
15 namespace {
16 namespace {
16
17
17 /// Name of the axes layer in QCustomPlot
18 /// Name of the axes layer in QCustomPlot
18 const auto AXES_LAYER = QStringLiteral("axes");
19 const auto AXES_LAYER = QStringLiteral("axes");
19
20
20 /// Icon used to show x-axis properties
21 /// Icon used to show x-axis properties
21 const auto HIDE_AXIS_ICON_PATH = QStringLiteral(":/icones/down.png");
22 const auto HIDE_AXIS_ICON_PATH = QStringLiteral(":/icones/down.png");
22
23
23 /// Name of the overlay layer in QCustomPlot
24 /// Name of the overlay layer in QCustomPlot
24 const auto OVERLAY_LAYER = QStringLiteral("overlay");
25 const auto OVERLAY_LAYER = QStringLiteral("overlay");
25
26
26 /// Pixmap used to show x-axis properties
27 /// Pixmap used to show x-axis properties
27 const auto SHOW_AXIS_ICON_PATH = QStringLiteral(":/icones/up.png");
28 const auto SHOW_AXIS_ICON_PATH = QStringLiteral(":/icones/up.png");
28
29
29 /// Tooltip format for graphs
30 /// Tooltip format for graphs
30 const auto GRAPH_TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
31 const auto GRAPH_TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
31
32
32 /// Tooltip format for colormaps
33 /// Tooltip format for colormaps
33 const auto COLORMAP_TOOLTIP_FORMAT = QStringLiteral("x: %1\ny: %2\nvalue: %3");
34 const auto COLORMAP_TOOLTIP_FORMAT = QStringLiteral("x: %1\ny: %2\nvalue: %3");
34
35
35 /// Offset used to shift the tooltip of the mouse
36 /// Offset used to shift the tooltip of the mouse
36 const auto TOOLTIP_OFFSET = QPoint{20, 20};
37 const auto TOOLTIP_OFFSET = QPoint{20, 20};
37
38
38 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
39 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
39 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
40 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
40
41
41 /// Timeout after which the tooltip is displayed
42 /// Timeout after which the tooltip is displayed
42 const auto TOOLTIP_TIMEOUT = 500;
43 const auto TOOLTIP_TIMEOUT = 500;
43
44
44 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
45 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
45 {
46 {
46 tracer.setInterpolating(false);
47 tracer.setInterpolating(false);
47 tracer.setStyle(QCPItemTracer::tsCircle);
48 tracer.setStyle(QCPItemTracer::tsCircle);
48 tracer.setSize(3);
49 tracer.setSize(3);
49 tracer.setPen(QPen(Qt::black));
50 tracer.setPen(QPen(Qt::black));
50 tracer.setBrush(Qt::black);
51 tracer.setBrush(Qt::black);
51 tracer.setSelectable(false);
52 tracer.setSelectable(false);
52 }
53 }
53
54
54 QPixmap pixmap(const QString &iconPath) noexcept
55 QPixmap pixmap(const QString &iconPath) noexcept
55 {
56 {
56 return QIcon{iconPath}.pixmap(QSize{16, 16});
57 return QIcon{iconPath}.pixmap(QSize{16, 16});
57 }
58 }
58
59
59 void initClosePixmapStyle(QCPItemPixmap &pixmap) noexcept
60 void initClosePixmapStyle(QCPItemPixmap &pixmap) noexcept
60 {
61 {
61 // Icon
62 // Icon
62 pixmap.setPixmap(
63 pixmap.setPixmap(
63 sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton).pixmap(QSize{16, 16}));
64 sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton).pixmap(QSize{16, 16}));
64
65
65 // Position
66 // Position
66 pixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
67 pixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
67 pixmap.topLeft->setCoords(1, 0);
68 pixmap.topLeft->setCoords(1, 0);
68 pixmap.setClipToAxisRect(false);
69 pixmap.setClipToAxisRect(false);
69
70
70 // Can be selected
71 // Can be selected
71 pixmap.setSelectable(true);
72 pixmap.setSelectable(true);
72 }
73 }
73
74
74 void initXAxisPixmapStyle(QCPItemPixmap &itemPixmap) noexcept
75 void initXAxisPixmapStyle(QCPItemPixmap &itemPixmap) noexcept
75 {
76 {
76 // Icon
77 // Icon
77 itemPixmap.setPixmap(pixmap(HIDE_AXIS_ICON_PATH));
78 itemPixmap.setPixmap(pixmap(HIDE_AXIS_ICON_PATH));
78
79
79 // Position
80 // Position
80 itemPixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
81 itemPixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
81 itemPixmap.topLeft->setCoords(0, 1);
82 itemPixmap.topLeft->setCoords(0, 1);
82 itemPixmap.setClipToAxisRect(false);
83 itemPixmap.setClipToAxisRect(false);
83
84
84 // Can be selected
85 // Can be selected
85 itemPixmap.setSelectable(true);
86 itemPixmap.setSelectable(true);
86 }
87 }
87
88
88 void initTitleTextStyle(QCPItemText &text) noexcept
89 void initTitleTextStyle(QCPItemText &text) noexcept
89 {
90 {
90 // Font and background styles
91 // Font and background styles
91 text.setColor(Qt::gray);
92 text.setColor(Qt::gray);
92 text.setBrush(Qt::white);
93 text.setBrush(Qt::white);
93
94
94 // Position
95 // Position
95 text.setPositionAlignment(Qt::AlignTop | Qt::AlignLeft);
96 text.setPositionAlignment(Qt::AlignTop | Qt::AlignLeft);
96 text.position->setType(QCPItemPosition::ptAxisRectRatio);
97 text.position->setType(QCPItemPosition::ptAxisRectRatio);
97 text.position->setCoords(0.5, 0);
98 text.position->setCoords(0.5, 0);
98 text.setSelectable(false);
99 text.setSelectable(false);
99 }
100 }
100
101
101 /**
102 /**
102 * Returns the cell index (x or y) of a colormap according to the coordinate passed in parameter.
103 * Returns the cell index (x or y) of a colormap according to the coordinate passed in parameter.
103 * This method handles the fact that a colormap axis can be logarithmic or linear.
104 * This method handles the fact that a colormap axis can be logarithmic or linear.
104 * @param colormap the colormap for which to calculate the index
105 * @param colormap the colormap for which to calculate the index
105 * @param coord the coord to convert to cell index
106 * @param coord the coord to convert to cell index
106 * @param xCoord calculates the x index if true, calculates y index if false
107 * @param xCoord calculates the x index if true, calculates y index if false
107 * @return the cell index
108 * @return the cell index
108 */
109 */
109 int colorMapCellIndex(const QCPColorMap &colormap, double coord, bool xCoord)
110 int colorMapCellIndex(const QCPColorMap &colormap, double coord, bool xCoord)
110 {
111 {
111 // Determines the axis of the colormap according to xCoord, and whether it is logarithmic or not
112 // Determines the axis of the colormap according to xCoord, and whether it is logarithmic or not
112 auto isLogarithmic = (xCoord ? colormap.keyAxis() : colormap.valueAxis())->scaleType()
113 auto isLogarithmic = (xCoord ? colormap.keyAxis() : colormap.valueAxis())->scaleType()
113 == QCPAxis::stLogarithmic;
114 == QCPAxis::stLogarithmic;
114
115
115 if (isLogarithmic) {
116 if (isLogarithmic) {
116 // For a logarithmic axis we can't use the conversion method of colormap, so we calculate
117 // For a logarithmic axis we can't use the conversion method of colormap, so we calculate
117 // the index manually based on the position of the coordinate on the axis
118 // the index manually based on the position of the coordinate on the axis
118
119
119 // Gets the axis range and the number of values between range bounds to calculate the step
120 // Gets the axis range and the number of values between range bounds to calculate the step
120 // between each value of the range
121 // between each value of the range
121 auto range = xCoord ? colormap.data()->keyRange() : colormap.data()->valueRange();
122 auto range = xCoord ? colormap.data()->keyRange() : colormap.data()->valueRange();
122 auto nbValues = (xCoord ? colormap.data()->keySize() : colormap.data()->valueSize()) - 1;
123 auto nbValues = (xCoord ? colormap.data()->keySize() : colormap.data()->valueSize()) - 1;
123 auto valueStep
124 auto valueStep
124 = (std::log10(range.upper) - std::log10(range.lower)) / static_cast<double>(nbValues);
125 = (std::log10(range.upper) - std::log10(range.lower)) / static_cast<double>(nbValues);
125
126
126 // According to the coord position, calculates the closest index in the range
127 // According to the coord position, calculates the closest index in the range
127 return std::round((std::log10(coord) - std::log10(range.lower)) / valueStep);
128 return std::round((std::log10(coord) - std::log10(range.lower)) / valueStep);
128 }
129 }
129 else {
130 else {
130 // For a linear axis, we use the conversion method of colormap
131 // For a linear axis, we use the conversion method of colormap
131 int index;
132 int index;
132 if (xCoord) {
133 if (xCoord) {
133 colormap.data()->coordToCell(coord, 0., &index, nullptr);
134 colormap.data()->coordToCell(coord, 0., &index, nullptr);
134 }
135 }
135 else {
136 else {
136 colormap.data()->coordToCell(0., coord, nullptr, &index);
137 colormap.data()->coordToCell(0., coord, nullptr, &index);
137 }
138 }
138
139
139 return index;
140 return index;
140 }
141 }
141 }
142 }
142
143
143 } // namespace
144 } // namespace
144
145
145 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
146 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
146 explicit VisualizationGraphRenderingDelegatePrivate(VisualizationGraphWidget &graphWidget)
147 explicit VisualizationGraphRenderingDelegatePrivate(VisualizationGraphWidget &graphWidget)
147 : m_Plot{graphWidget.plot()},
148 : m_Plot{graphWidget.plot()},
148 m_PointTracer{new QCPItemTracer{&m_Plot}},
149 m_PointTracer{new QCPItemTracer{&m_Plot}},
149 m_TracerTimer{},
150 m_TracerTimer{},
150 m_ClosePixmap{new QCPItemPixmap{&m_Plot}},
151 m_ClosePixmap{new QCPItemPixmap{&m_Plot}},
151 m_TitleText{new QCPItemText{&m_Plot}},
152 m_TitleText{new QCPItemText{&m_Plot}},
152 m_XAxisPixmap{new QCPItemPixmap{&m_Plot}},
153 m_XAxisPixmap{new QCPItemPixmap{&m_Plot}},
153 m_ShowXAxis{true},
154 m_ShowXAxis{true},
154 m_XAxisLabel{},
155 m_XAxisLabel{},
155 m_ColorScale{SqpColorScale{m_Plot}}
156 m_ColorScale{SqpColorScale{m_Plot}}
156 {
157 {
157 initPointTracerStyle(*m_PointTracer);
158 initPointTracerStyle(*m_PointTracer);
158
159
159 m_TracerTimer.setInterval(TOOLTIP_TIMEOUT);
160 m_TracerTimer.setInterval(TOOLTIP_TIMEOUT);
160 m_TracerTimer.setSingleShot(true);
161 m_TracerTimer.setSingleShot(true);
161
162
162 // Inits "close button" in plot overlay
163 // Inits "close button" in plot overlay
163 m_ClosePixmap->setLayer(OVERLAY_LAYER);
164 m_ClosePixmap->setLayer(OVERLAY_LAYER);
164 initClosePixmapStyle(*m_ClosePixmap);
165 initClosePixmapStyle(*m_ClosePixmap);
165
166
166 // Connects pixmap selection to graph widget closing
167 // Connects pixmap selection to graph widget closing
167 QObject::connect(&m_Plot, &QCustomPlot::itemClick,
168 QObject::connect(&m_Plot, &QCustomPlot::itemClick,
168 [&graphWidget, this](auto item, auto mouseEvent) {
169 [&graphWidget, this](auto item, auto mouseEvent) {
169 if (item == m_ClosePixmap) {
170 if (item == m_ClosePixmap) {
170 graphWidget.close();
171 graphWidget.close();
171 }
172 }
172 });
173 });
173
174
174 // Inits graph name in plot overlay
175 // Inits graph name in plot overlay
175 m_TitleText->setLayer(OVERLAY_LAYER);
176 m_TitleText->setLayer(OVERLAY_LAYER);
176 m_TitleText->setText(graphWidget.name());
177 m_TitleText->setText(graphWidget.name());
177 initTitleTextStyle(*m_TitleText);
178 initTitleTextStyle(*m_TitleText);
178
179
179 // Inits "show x-axis button" in plot overlay
180 // Inits "show x-axis button" in plot overlay
180 m_XAxisPixmap->setLayer(OVERLAY_LAYER);
181 m_XAxisPixmap->setLayer(OVERLAY_LAYER);
181 initXAxisPixmapStyle(*m_XAxisPixmap);
182 initXAxisPixmapStyle(*m_XAxisPixmap);
182
183
183 // Connects pixmap selection to graph x-axis showing/hiding
184 // Connects pixmap selection to graph x-axis showing/hiding
184 QObject::connect(&m_Plot, &QCustomPlot::itemClick, [this](auto item, auto mouseEvent) {
185 QObject::connect(&m_Plot, &QCustomPlot::itemClick, [this](auto item, auto mouseEvent) {
185 if (m_XAxisPixmap == item) {
186 if (m_XAxisPixmap == item) {
186 // Changes the selection state and refreshes the x-axis
187 // Changes the selection state and refreshes the x-axis
187 m_ShowXAxis = !m_ShowXAxis;
188 m_ShowXAxis = !m_ShowXAxis;
188 this->updateXAxisState();
189 this->updateXAxisState();
189 m_Plot.layer(AXES_LAYER)->replot();
190 m_Plot.layer(AXES_LAYER)->replot();
190
191
191 // Deselects the x-axis pixmap and updates icon
192 // Deselects the x-axis pixmap and updates icon
192 m_XAxisPixmap->setPixmap(
193 m_XAxisPixmap->setPixmap(
193 pixmap(m_ShowXAxis ? HIDE_AXIS_ICON_PATH : SHOW_AXIS_ICON_PATH));
194 pixmap(m_ShowXAxis ? HIDE_AXIS_ICON_PATH : SHOW_AXIS_ICON_PATH));
194 m_Plot.layer(OVERLAY_LAYER)->replot();
195 m_Plot.layer(OVERLAY_LAYER)->replot();
195 }
196 }
196 });
197 });
197 }
198 }
198
199
199 /// Updates state of x-axis according to the current selection of x-axis pixmap
200 /// Updates state of x-axis according to the current selection of x-axis pixmap
200 /// @remarks the method doesn't call plot refresh
201 /// @remarks the method doesn't call plot refresh
201 void updateXAxisState() noexcept
202 void updateXAxisState() noexcept
202 {
203 {
203 m_Plot.xAxis->setTickLabels(m_ShowXAxis);
204 m_Plot.xAxis->setTickLabels(m_ShowXAxis);
204 m_Plot.xAxis->setLabel(m_ShowXAxis ? m_XAxisLabel : QString{});
205 m_Plot.xAxis->setLabel(m_ShowXAxis ? m_XAxisLabel : QString{});
205 }
206 }
206
207
207 QCustomPlot &m_Plot;
208 QCustomPlot &m_Plot;
208 QCPItemTracer *m_PointTracer;
209 QCPItemTracer *m_PointTracer;
209 QTimer m_TracerTimer;
210 QTimer m_TracerTimer;
210 QCPItemPixmap *m_ClosePixmap; /// Graph's close button
211 QCPItemPixmap *m_ClosePixmap; /// Graph's close button
211 QCPItemText *m_TitleText; /// Graph's title
212 QCPItemText *m_TitleText; /// Graph's title
212 QCPItemPixmap *m_XAxisPixmap;
213 QCPItemPixmap *m_XAxisPixmap;
213 bool m_ShowXAxis; /// X-axis properties are shown or hidden
214 bool m_ShowXAxis; /// X-axis properties are shown or hidden
214 QString m_XAxisLabel;
215 QString m_XAxisLabel;
215 SqpColorScale m_ColorScale; /// Color scale used for some types of graphs (as spectrograms)
216 SqpColorScale m_ColorScale; /// Color scale used for some types of graphs (as spectrograms)
216 };
217 };
217
218
218 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(
219 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(
219 VisualizationGraphWidget &graphWidget)
220 VisualizationGraphWidget &graphWidget)
220 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(graphWidget)}
221 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(graphWidget)}
221 {
222 {
222 }
223 }
223
224
224 void VisualizationGraphRenderingDelegate::onMouseDoubleClick(QMouseEvent *event) noexcept
225 void VisualizationGraphRenderingDelegate::onMouseDoubleClick(QMouseEvent *event) noexcept
225 {
226 {
226 // Opens color scale editor if color scale is double clicked
227 // Opens color scale editor if color scale is double clicked
227 auto colorScale = static_cast<QCPColorScale *>(impl->m_Plot.layoutElementAt(event->pos()));
228 auto colorScale = static_cast<QCPColorScale *>(impl->m_Plot.layoutElementAt(event->pos()));
228 if (impl->m_ColorScale.m_Scale == colorScale) {
229 if (impl->m_ColorScale.m_Scale == colorScale) {
229 if (ColorScaleEditor{impl->m_ColorScale}.exec() == QDialog::Accepted) {
230 if (ColorScaleEditor{impl->m_ColorScale}.exec() == QDialog::Accepted) {
230 impl->m_Plot.replot();
231 impl->m_Plot.replot();
231 }
232 }
232 }
233 }
233 }
234 }
234
235
235 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
236 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
236 {
237 {
237 // Cancels pending refresh
238 // Cancels pending refresh
238 impl->m_TracerTimer.disconnect();
239 impl->m_TracerTimer.disconnect();
239
240
240 // Reinits tracers
241 // Reinits tracers
241 impl->m_PointTracer->setGraph(nullptr);
242 impl->m_PointTracer->setGraph(nullptr);
242 impl->m_PointTracer->setVisible(false);
243 impl->m_PointTracer->setVisible(false);
243 impl->m_Plot.replot();
244 impl->m_Plot.replot();
244
245
245 QString tooltip{};
246 QString tooltip{};
246
247
247 // Gets the graph under the mouse position
248 // Gets the graph under the mouse position
248 auto eventPos = event->pos();
249 auto eventPos = event->pos();
249 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
250 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
250 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
251 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
251 auto graphData = graph->data();
252 auto graphData = graph->data();
252
253
253 // Gets the closest data point to the mouse
254 // Gets the closest data point to the mouse
254 auto graphDataIt = graphData->findBegin(mouseKey);
255 auto graphDataIt = graphData->findBegin(mouseKey);
255 if (graphDataIt != graphData->constEnd()) {
256 if (graphDataIt != graphData->constEnd()) {
256 // Sets tooltip
257 // Sets tooltip
257 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
258 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
258 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
259 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
259 tooltip = GRAPH_TOOLTIP_FORMAT.arg(key, value);
260 tooltip = GRAPH_TOOLTIP_FORMAT.arg(key, value);
260
261
261 // Displays point tracer
262 // Displays point tracer
262 impl->m_PointTracer->setGraph(graph);
263 impl->m_PointTracer->setGraph(graph);
263 impl->m_PointTracer->setGraphKey(graphDataIt->key);
264 impl->m_PointTracer->setGraphKey(graphDataIt->key);
264 impl->m_PointTracer->setLayer(
265 impl->m_PointTracer->setLayer(
265 impl->m_Plot.layer("main")); // Tracer is set on top of the plot's main layer
266 impl->m_Plot.layer("main")); // Tracer is set on top of the plot's main layer
266 impl->m_PointTracer->setVisible(true);
267 impl->m_PointTracer->setVisible(true);
267 impl->m_Plot.replot();
268 impl->m_Plot.replot();
268 }
269 }
269 }
270 }
270 else if (auto colorMap = qobject_cast<QCPColorMap *>(impl->m_Plot.plottableAt(eventPos))) {
271 else if (auto colorMap = qobject_cast<QCPColorMap *>(impl->m_Plot.plottableAt(eventPos))) {
271 // Gets x and y coords
272 // Gets x and y coords
272 auto x = colorMap->keyAxis()->pixelToCoord(eventPos.x());
273 auto x = colorMap->keyAxis()->pixelToCoord(eventPos.x());
273 auto y = colorMap->valueAxis()->pixelToCoord(eventPos.y());
274 auto y = colorMap->valueAxis()->pixelToCoord(eventPos.y());
274
275
275 // Calculates x and y cell indexes, and retrieves the underlying value
276 // Calculates x and y cell indexes, and retrieves the underlying value
276 auto xCellIndex = colorMapCellIndex(*colorMap, x, true);
277 auto xCellIndex = colorMapCellIndex(*colorMap, x, true);
277 auto yCellIndex = colorMapCellIndex(*colorMap, y, false);
278 auto yCellIndex = colorMapCellIndex(*colorMap, y, false);
278 auto value = colorMap->data()->cell(xCellIndex, yCellIndex);
279 auto value = colorMap->data()->cell(xCellIndex, yCellIndex);
279
280
280 // Sets tooltips
281 // Sets tooltips
281 tooltip = COLORMAP_TOOLTIP_FORMAT.arg(formatValue(x, *colorMap->keyAxis()),
282 tooltip = COLORMAP_TOOLTIP_FORMAT.arg(formatValue(x, *colorMap->keyAxis()),
282 formatValue(y, *colorMap->valueAxis()),
283 formatValue(y, *colorMap->valueAxis()),
283 formatValue(value, *colorMap->colorScale()->axis()));
284 formatValue(value, *colorMap->colorScale()->axis()));
284 }
285 }
285
286
286 if (!tooltip.isEmpty()) {
287 if (!tooltip.isEmpty()) {
287 // Starts timer to show tooltip after timeout
288 // Starts timer to show tooltip after timeout
288 auto showTooltip = [tooltip, eventPos, this]() {
289 auto showTooltip = [tooltip, eventPos, this]() {
289 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos) + TOOLTIP_OFFSET, tooltip,
290 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos) + TOOLTIP_OFFSET, tooltip,
290 &impl->m_Plot, TOOLTIP_RECT);
291 &impl->m_Plot, TOOLTIP_RECT);
291 };
292 };
292
293
293 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
294 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
294 impl->m_TracerTimer.start();
295 impl->m_TracerTimer.start();
295 }
296 }
296 }
297 }
297
298
298 void VisualizationGraphRenderingDelegate::onPlotUpdated() noexcept
299 void VisualizationGraphRenderingDelegate::onPlotUpdated() noexcept
299 {
300 {
300 // Updates color scale bounds
301 // Updates color scale bounds
301 impl->m_ColorScale.updateDataRange();
302 impl->m_ColorScale.updateDataRange();
302 impl->m_Plot.replot();
303 impl->m_Plot.replot();
303 }
304 }
304
305
305 void VisualizationGraphRenderingDelegate::setAxesProperties(
306 void VisualizationGraphRenderingDelegate::setAxesUnits(const Variable &variable) noexcept
306 std::shared_ptr<IDataSeries> dataSeries) noexcept
307 {
307 {
308 // Stores x-axis label to be able to retrieve it when x-axis pixmap is unselected
309 impl->m_XAxisLabel = dataSeries->xAxisUnit().m_Name;
310
308
311 auto axisHelper = IAxisHelperFactory::create(dataSeries);
309 auto axisHelper = IAxisHelperFactory::create(variable);
312 axisHelper->setProperties(impl->m_Plot, impl->m_ColorScale);
310 axisHelper->setUnits(impl->m_Plot, impl->m_ColorScale);
311
312 // Stores x-axis label to be able to retrieve it when x-axis pixmap is unselected
313 impl->m_XAxisLabel = impl->m_Plot.xAxis->label();
313
314
314 // Updates x-axis state
315 // Updates x-axis state
315 impl->updateXAxisState();
316 impl->updateXAxisState();
316
317
317 impl->m_Plot.layer(AXES_LAYER)->replot();
318 impl->m_Plot.layer(AXES_LAYER)->replot();
318 }
319 }
319
320
320 void VisualizationGraphRenderingDelegate::setPlottablesProperties(
321 void VisualizationGraphRenderingDelegate::setGraphProperties(const Variable &variable,
321 std::shared_ptr<IDataSeries> dataSeries, PlottablesMap &plottables) noexcept
322 PlottablesMap &plottables) noexcept
322 {
323 {
323 auto plottablesHelper = IPlottablesHelperFactory::create(dataSeries);
324 // Axes' properties
325 auto axisHelper = IAxisHelperFactory::create(variable);
326 axisHelper->setProperties(impl->m_Plot, impl->m_ColorScale);
327
328 // Plottables' properties
329 auto plottablesHelper = IPlottablesHelperFactory::create(variable);
324 plottablesHelper->setProperties(plottables);
330 plottablesHelper->setProperties(plottables);
325 }
331 }
326
332
327 void VisualizationGraphRenderingDelegate::showGraphOverlay(bool show) noexcept
333 void VisualizationGraphRenderingDelegate::showGraphOverlay(bool show) noexcept
328 {
334 {
329 auto overlay = impl->m_Plot.layer(OVERLAY_LAYER);
335 auto overlay = impl->m_Plot.layer(OVERLAY_LAYER);
330 overlay->setVisible(show);
336 overlay->setVisible(show);
331 overlay->replot();
337 overlay->replot();
332 }
338 }
General Comments 0
You need to be logged in to leave comments. Login now