##// END OF EJS Templates
Calls plot refresh when the editor is closed
Alexandre Leroux -
r1013:121d1ac0be46
parent child
Show More
@@ -1,256 +1,258
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
12
13 #include <SqpApplication.h>
13 #include <SqpApplication.h>
14
14
15 namespace {
15 namespace {
16
16
17 /// Name of the axes layer in QCustomPlot
17 /// Name of the axes layer in QCustomPlot
18 const auto AXES_LAYER = QStringLiteral("axes");
18 const auto AXES_LAYER = QStringLiteral("axes");
19
19
20 /// Icon used to show x-axis properties
20 /// Icon used to show x-axis properties
21 const auto HIDE_AXIS_ICON_PATH = QStringLiteral(":/icones/down.png");
21 const auto HIDE_AXIS_ICON_PATH = QStringLiteral(":/icones/down.png");
22
22
23 /// Name of the overlay layer in QCustomPlot
23 /// Name of the overlay layer in QCustomPlot
24 const auto OVERLAY_LAYER = QStringLiteral("overlay");
24 const auto OVERLAY_LAYER = QStringLiteral("overlay");
25
25
26 /// Pixmap used to show x-axis properties
26 /// Pixmap used to show x-axis properties
27 const auto SHOW_AXIS_ICON_PATH = QStringLiteral(":/icones/up.png");
27 const auto SHOW_AXIS_ICON_PATH = QStringLiteral(":/icones/up.png");
28
28
29 const auto TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
29 const auto TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
30
30
31 /// Offset used to shift the tooltip of the mouse
31 /// Offset used to shift the tooltip of the mouse
32 const auto TOOLTIP_OFFSET = QPoint{20, 20};
32 const auto TOOLTIP_OFFSET = QPoint{20, 20};
33
33
34 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
34 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
35 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
35 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
36
36
37 /// Timeout after which the tooltip is displayed
37 /// Timeout after which the tooltip is displayed
38 const auto TOOLTIP_TIMEOUT = 500;
38 const auto TOOLTIP_TIMEOUT = 500;
39
39
40 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
40 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
41 {
41 {
42 tracer.setInterpolating(false);
42 tracer.setInterpolating(false);
43 tracer.setStyle(QCPItemTracer::tsCircle);
43 tracer.setStyle(QCPItemTracer::tsCircle);
44 tracer.setSize(3);
44 tracer.setSize(3);
45 tracer.setPen(QPen(Qt::black));
45 tracer.setPen(QPen(Qt::black));
46 tracer.setBrush(Qt::black);
46 tracer.setBrush(Qt::black);
47 }
47 }
48
48
49 QPixmap pixmap(const QString &iconPath) noexcept
49 QPixmap pixmap(const QString &iconPath) noexcept
50 {
50 {
51 return QIcon{iconPath}.pixmap(QSize{16, 16});
51 return QIcon{iconPath}.pixmap(QSize{16, 16});
52 }
52 }
53
53
54 void initClosePixmapStyle(QCPItemPixmap &pixmap) noexcept
54 void initClosePixmapStyle(QCPItemPixmap &pixmap) noexcept
55 {
55 {
56 // Icon
56 // Icon
57 pixmap.setPixmap(
57 pixmap.setPixmap(
58 sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton).pixmap(QSize{16, 16}));
58 sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton).pixmap(QSize{16, 16}));
59
59
60 // Position
60 // Position
61 pixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
61 pixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
62 pixmap.topLeft->setCoords(1, 0);
62 pixmap.topLeft->setCoords(1, 0);
63 pixmap.setClipToAxisRect(false);
63 pixmap.setClipToAxisRect(false);
64
64
65 // Can be selected
65 // Can be selected
66 pixmap.setSelectable(true);
66 pixmap.setSelectable(true);
67 }
67 }
68
68
69 void initXAxisPixmapStyle(QCPItemPixmap &itemPixmap) noexcept
69 void initXAxisPixmapStyle(QCPItemPixmap &itemPixmap) noexcept
70 {
70 {
71 // Icon
71 // Icon
72 itemPixmap.setPixmap(pixmap(HIDE_AXIS_ICON_PATH));
72 itemPixmap.setPixmap(pixmap(HIDE_AXIS_ICON_PATH));
73
73
74 // Position
74 // Position
75 itemPixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
75 itemPixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
76 itemPixmap.topLeft->setCoords(0, 1);
76 itemPixmap.topLeft->setCoords(0, 1);
77 itemPixmap.setClipToAxisRect(false);
77 itemPixmap.setClipToAxisRect(false);
78
78
79 // Can be selected
79 // Can be selected
80 itemPixmap.setSelectable(true);
80 itemPixmap.setSelectable(true);
81 }
81 }
82
82
83 void initTitleTextStyle(QCPItemText &text) noexcept
83 void initTitleTextStyle(QCPItemText &text) noexcept
84 {
84 {
85 // Font and background styles
85 // Font and background styles
86 text.setColor(Qt::gray);
86 text.setColor(Qt::gray);
87 text.setBrush(Qt::white);
87 text.setBrush(Qt::white);
88
88
89 // Position
89 // Position
90 text.setPositionAlignment(Qt::AlignTop | Qt::AlignLeft);
90 text.setPositionAlignment(Qt::AlignTop | Qt::AlignLeft);
91 text.position->setType(QCPItemPosition::ptAxisRectRatio);
91 text.position->setType(QCPItemPosition::ptAxisRectRatio);
92 text.position->setCoords(0.5, 0);
92 text.position->setCoords(0.5, 0);
93 }
93 }
94
94
95 } // namespace
95 } // namespace
96
96
97 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
97 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
98 explicit VisualizationGraphRenderingDelegatePrivate(VisualizationGraphWidget &graphWidget)
98 explicit VisualizationGraphRenderingDelegatePrivate(VisualizationGraphWidget &graphWidget)
99 : m_Plot{graphWidget.plot()},
99 : m_Plot{graphWidget.plot()},
100 m_PointTracer{new QCPItemTracer{&m_Plot}},
100 m_PointTracer{new QCPItemTracer{&m_Plot}},
101 m_TracerTimer{},
101 m_TracerTimer{},
102 m_ClosePixmap{new QCPItemPixmap{&m_Plot}},
102 m_ClosePixmap{new QCPItemPixmap{&m_Plot}},
103 m_TitleText{new QCPItemText{&m_Plot}},
103 m_TitleText{new QCPItemText{&m_Plot}},
104 m_XAxisPixmap{new QCPItemPixmap{&m_Plot}},
104 m_XAxisPixmap{new QCPItemPixmap{&m_Plot}},
105 m_ShowXAxis{true},
105 m_ShowXAxis{true},
106 m_XAxisLabel{},
106 m_XAxisLabel{},
107 m_ColorScale{SqpColorScale{m_Plot}}
107 m_ColorScale{SqpColorScale{m_Plot}}
108 {
108 {
109 initPointTracerStyle(*m_PointTracer);
109 initPointTracerStyle(*m_PointTracer);
110
110
111 m_TracerTimer.setInterval(TOOLTIP_TIMEOUT);
111 m_TracerTimer.setInterval(TOOLTIP_TIMEOUT);
112 m_TracerTimer.setSingleShot(true);
112 m_TracerTimer.setSingleShot(true);
113
113
114 // Inits "close button" in plot overlay
114 // Inits "close button" in plot overlay
115 m_ClosePixmap->setLayer(OVERLAY_LAYER);
115 m_ClosePixmap->setLayer(OVERLAY_LAYER);
116 initClosePixmapStyle(*m_ClosePixmap);
116 initClosePixmapStyle(*m_ClosePixmap);
117
117
118 // Connects pixmap selection to graph widget closing
118 // Connects pixmap selection to graph widget closing
119 QObject::connect(m_ClosePixmap, &QCPItemPixmap::selectionChanged,
119 QObject::connect(m_ClosePixmap, &QCPItemPixmap::selectionChanged,
120 [&graphWidget](bool selected) {
120 [&graphWidget](bool selected) {
121 if (selected) {
121 if (selected) {
122 graphWidget.close();
122 graphWidget.close();
123 }
123 }
124 });
124 });
125
125
126 // Inits graph name in plot overlay
126 // Inits graph name in plot overlay
127 m_TitleText->setLayer(OVERLAY_LAYER);
127 m_TitleText->setLayer(OVERLAY_LAYER);
128 m_TitleText->setText(graphWidget.name());
128 m_TitleText->setText(graphWidget.name());
129 initTitleTextStyle(*m_TitleText);
129 initTitleTextStyle(*m_TitleText);
130
130
131 // Inits "show x-axis button" in plot overlay
131 // Inits "show x-axis button" in plot overlay
132 m_XAxisPixmap->setLayer(OVERLAY_LAYER);
132 m_XAxisPixmap->setLayer(OVERLAY_LAYER);
133 initXAxisPixmapStyle(*m_XAxisPixmap);
133 initXAxisPixmapStyle(*m_XAxisPixmap);
134
134
135 // Connects pixmap selection to graph x-axis showing/hiding
135 // Connects pixmap selection to graph x-axis showing/hiding
136 QObject::connect(m_XAxisPixmap, &QCPItemPixmap::selectionChanged, [this]() {
136 QObject::connect(m_XAxisPixmap, &QCPItemPixmap::selectionChanged, [this]() {
137 if (m_XAxisPixmap->selected()) {
137 if (m_XAxisPixmap->selected()) {
138 // Changes the selection state and refreshes the x-axis
138 // Changes the selection state and refreshes the x-axis
139 m_ShowXAxis = !m_ShowXAxis;
139 m_ShowXAxis = !m_ShowXAxis;
140 updateXAxisState();
140 updateXAxisState();
141 m_Plot.layer(AXES_LAYER)->replot();
141 m_Plot.layer(AXES_LAYER)->replot();
142
142
143 // Deselects the x-axis pixmap and updates icon
143 // Deselects the x-axis pixmap and updates icon
144 m_XAxisPixmap->setSelected(false);
144 m_XAxisPixmap->setSelected(false);
145 m_XAxisPixmap->setPixmap(
145 m_XAxisPixmap->setPixmap(
146 pixmap(m_ShowXAxis ? HIDE_AXIS_ICON_PATH : SHOW_AXIS_ICON_PATH));
146 pixmap(m_ShowXAxis ? HIDE_AXIS_ICON_PATH : SHOW_AXIS_ICON_PATH));
147 m_Plot.layer(OVERLAY_LAYER)->replot();
147 m_Plot.layer(OVERLAY_LAYER)->replot();
148 }
148 }
149 });
149 });
150 }
150 }
151
151
152 /// Updates state of x-axis according to the current selection of x-axis pixmap
152 /// Updates state of x-axis according to the current selection of x-axis pixmap
153 /// @remarks the method doesn't call plot refresh
153 /// @remarks the method doesn't call plot refresh
154 void updateXAxisState() noexcept
154 void updateXAxisState() noexcept
155 {
155 {
156 m_Plot.xAxis->setTickLabels(m_ShowXAxis);
156 m_Plot.xAxis->setTickLabels(m_ShowXAxis);
157 m_Plot.xAxis->setLabel(m_ShowXAxis ? m_XAxisLabel : QString{});
157 m_Plot.xAxis->setLabel(m_ShowXAxis ? m_XAxisLabel : QString{});
158 }
158 }
159
159
160 QCustomPlot &m_Plot;
160 QCustomPlot &m_Plot;
161 QCPItemTracer *m_PointTracer;
161 QCPItemTracer *m_PointTracer;
162 QTimer m_TracerTimer;
162 QTimer m_TracerTimer;
163 QCPItemPixmap *m_ClosePixmap; /// Graph's close button
163 QCPItemPixmap *m_ClosePixmap; /// Graph's close button
164 QCPItemText *m_TitleText; /// Graph's title
164 QCPItemText *m_TitleText; /// Graph's title
165 QCPItemPixmap *m_XAxisPixmap;
165 QCPItemPixmap *m_XAxisPixmap;
166 bool m_ShowXAxis; /// X-axis properties are shown or hidden
166 bool m_ShowXAxis; /// X-axis properties are shown or hidden
167 QString m_XAxisLabel;
167 QString m_XAxisLabel;
168 SqpColorScale m_ColorScale; /// Color scale used for some types of graphs (as spectrograms)
168 SqpColorScale m_ColorScale; /// Color scale used for some types of graphs (as spectrograms)
169 };
169 };
170
170
171 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(
171 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(
172 VisualizationGraphWidget &graphWidget)
172 VisualizationGraphWidget &graphWidget)
173 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(graphWidget)}
173 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(graphWidget)}
174 {
174 {
175 }
175 }
176
176
177 void VisualizationGraphRenderingDelegate::onMouseDoubleClick(QMouseEvent *event) noexcept
177 void VisualizationGraphRenderingDelegate::onMouseDoubleClick(QMouseEvent *event) noexcept
178 {
178 {
179 // Opens color scale editor if color scale is double clicked
179 // Opens color scale editor if color scale is double clicked
180 if (auto colorScale
180 auto colorScale = dynamic_cast<QCPColorScale *>(impl->m_Plot.layoutElementAt(event->pos()));
181 = dynamic_cast<QCPColorScale *>(impl->m_Plot.layoutElementAt(event->pos()))) {
181 if (impl->m_ColorScale.m_Scale == colorScale) {
182 ColorScaleEditor{}.exec();
182 if (ColorScaleEditor{impl->m_ColorScale}.exec() == QDialog::Accepted) {
183 impl->m_Plot.replot();
184 }
183 }
185 }
184 }
186 }
185
187
186 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
188 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
187 {
189 {
188 // Cancels pending refresh
190 // Cancels pending refresh
189 impl->m_TracerTimer.disconnect();
191 impl->m_TracerTimer.disconnect();
190
192
191 // Reinits tracers
193 // Reinits tracers
192 impl->m_PointTracer->setGraph(nullptr);
194 impl->m_PointTracer->setGraph(nullptr);
193 impl->m_PointTracer->setVisible(false);
195 impl->m_PointTracer->setVisible(false);
194 impl->m_Plot.replot();
196 impl->m_Plot.replot();
195
197
196 // Gets the graph under the mouse position
198 // Gets the graph under the mouse position
197 auto eventPos = event->pos();
199 auto eventPos = event->pos();
198 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
200 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
199 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
201 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
200 auto graphData = graph->data();
202 auto graphData = graph->data();
201
203
202 // Gets the closest data point to the mouse
204 // Gets the closest data point to the mouse
203 auto graphDataIt = graphData->findBegin(mouseKey);
205 auto graphDataIt = graphData->findBegin(mouseKey);
204 if (graphDataIt != graphData->constEnd()) {
206 if (graphDataIt != graphData->constEnd()) {
205 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
207 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
206 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
208 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
207
209
208 // Displays point tracer
210 // Displays point tracer
209 impl->m_PointTracer->setGraph(graph);
211 impl->m_PointTracer->setGraph(graph);
210 impl->m_PointTracer->setGraphKey(graphDataIt->key);
212 impl->m_PointTracer->setGraphKey(graphDataIt->key);
211 impl->m_PointTracer->setLayer(
213 impl->m_PointTracer->setLayer(
212 impl->m_Plot.layer("main")); // Tracer is set on top of the plot's main layer
214 impl->m_Plot.layer("main")); // Tracer is set on top of the plot's main layer
213 impl->m_PointTracer->setVisible(true);
215 impl->m_PointTracer->setVisible(true);
214 impl->m_Plot.replot();
216 impl->m_Plot.replot();
215
217
216 // Starts timer to show tooltip after timeout
218 // Starts timer to show tooltip after timeout
217 auto showTooltip = [ tooltip = TOOLTIP_FORMAT.arg(key, value), eventPos, this ]()
219 auto showTooltip = [ tooltip = TOOLTIP_FORMAT.arg(key, value), eventPos, this ]()
218 {
220 {
219 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos) + TOOLTIP_OFFSET, tooltip,
221 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos) + TOOLTIP_OFFSET, tooltip,
220 &impl->m_Plot, TOOLTIP_RECT);
222 &impl->m_Plot, TOOLTIP_RECT);
221 };
223 };
222
224
223 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
225 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
224 impl->m_TracerTimer.start();
226 impl->m_TracerTimer.start();
225 }
227 }
226 }
228 }
227 }
229 }
228
230
229 void VisualizationGraphRenderingDelegate::setAxesProperties(
231 void VisualizationGraphRenderingDelegate::setAxesProperties(
230 std::shared_ptr<IDataSeries> dataSeries) noexcept
232 std::shared_ptr<IDataSeries> dataSeries) noexcept
231 {
233 {
232 // Stores x-axis label to be able to retrieve it when x-axis pixmap is unselected
234 // Stores x-axis label to be able to retrieve it when x-axis pixmap is unselected
233 impl->m_XAxisLabel = dataSeries->xAxisUnit().m_Name;
235 impl->m_XAxisLabel = dataSeries->xAxisUnit().m_Name;
234
236
235 auto axisHelper = IAxisHelperFactory::create(dataSeries);
237 auto axisHelper = IAxisHelperFactory::create(dataSeries);
236 axisHelper->setProperties(impl->m_Plot, impl->m_ColorScale);
238 axisHelper->setProperties(impl->m_Plot, impl->m_ColorScale);
237
239
238 // Updates x-axis state
240 // Updates x-axis state
239 impl->updateXAxisState();
241 impl->updateXAxisState();
240
242
241 impl->m_Plot.layer(AXES_LAYER)->replot();
243 impl->m_Plot.layer(AXES_LAYER)->replot();
242 }
244 }
243
245
244 void VisualizationGraphRenderingDelegate::setPlottablesProperties(
246 void VisualizationGraphRenderingDelegate::setPlottablesProperties(
245 std::shared_ptr<IDataSeries> dataSeries, PlottablesMap &plottables) noexcept
247 std::shared_ptr<IDataSeries> dataSeries, PlottablesMap &plottables) noexcept
246 {
248 {
247 auto plottablesHelper = IPlottablesHelperFactory::create(dataSeries);
249 auto plottablesHelper = IPlottablesHelperFactory::create(dataSeries);
248 plottablesHelper->setProperties(plottables);
250 plottablesHelper->setProperties(plottables);
249 }
251 }
250
252
251 void VisualizationGraphRenderingDelegate::showGraphOverlay(bool show) noexcept
253 void VisualizationGraphRenderingDelegate::showGraphOverlay(bool show) noexcept
252 {
254 {
253 auto overlay = impl->m_Plot.layer(OVERLAY_LAYER);
255 auto overlay = impl->m_Plot.layer(OVERLAY_LAYER);
254 overlay->setVisible(show);
256 overlay->setVisible(show);
255 overlay->replot();
257 overlay->replot();
256 }
258 }
General Comments 0
You need to be logged in to leave comments. Login now