##// END OF EJS Templates
Shifts tooltip to mouse
Alexandre Leroux -
r543:4cbf5bf3dd44
parent child
Show More
@@ -1,102 +1,105
1 #include "Visualization/VisualizationGraphRenderingDelegate.h"
1 #include "Visualization/VisualizationGraphRenderingDelegate.h"
2 #include "Visualization/qcustomplot.h"
2 #include "Visualization/qcustomplot.h"
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5
5
6 namespace {
6 namespace {
7
7
8 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
8 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
9
9
10 const auto TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
10 const auto TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
11
11
12 /// Offset used to shift the tooltip of the mouse
13 const auto TOOLTIP_OFFSET = QPoint{20, 20};
14
12 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
15 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
13 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
16 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
14
17
15 /// Timeout after which the tooltip is displayed
18 /// Timeout after which the tooltip is displayed
16 const auto TOOLTIP_TIMEOUT = 500;
19 const auto TOOLTIP_TIMEOUT = 500;
17
20
18 /// Formats a data value according to the axis on which it is present
21 /// Formats a data value according to the axis on which it is present
19 QString formatValue(double value, const QCPAxis &axis)
22 QString formatValue(double value, const QCPAxis &axis)
20 {
23 {
21 // If the axis is a time axis, formats the value as a date
24 // If the axis is a time axis, formats the value as a date
22 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
25 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
23 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
26 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
24 }
27 }
25 else {
28 else {
26 return QString::number(value);
29 return QString::number(value);
27 }
30 }
28 }
31 }
29
32
30 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
33 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
31 {
34 {
32 tracer.setInterpolating(false);
35 tracer.setInterpolating(false);
33 tracer.setStyle(QCPItemTracer::tsCircle);
36 tracer.setStyle(QCPItemTracer::tsCircle);
34 tracer.setSize(3);
37 tracer.setSize(3);
35 tracer.setPen(QPen(Qt::black));
38 tracer.setPen(QPen(Qt::black));
36 tracer.setBrush(Qt::black);
39 tracer.setBrush(Qt::black);
37 }
40 }
38
41
39 } // namespace
42 } // namespace
40
43
41 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
44 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
42 explicit VisualizationGraphRenderingDelegatePrivate(QCustomPlot &plot)
45 explicit VisualizationGraphRenderingDelegatePrivate(QCustomPlot &plot)
43 : m_Plot{plot}, m_PointTracer{new QCPItemTracer{&plot}}, m_TracerTimer{}
46 : m_Plot{plot}, m_PointTracer{new QCPItemTracer{&plot}}, m_TracerTimer{}
44 {
47 {
45 initPointTracerStyle(*m_PointTracer);
48 initPointTracerStyle(*m_PointTracer);
46
49
47 m_TracerTimer.setInterval(TOOLTIP_TIMEOUT);
50 m_TracerTimer.setInterval(TOOLTIP_TIMEOUT);
48 m_TracerTimer.setSingleShot(true);
51 m_TracerTimer.setSingleShot(true);
49 }
52 }
50
53
51 QCustomPlot &m_Plot;
54 QCustomPlot &m_Plot;
52 QCPItemTracer *m_PointTracer;
55 QCPItemTracer *m_PointTracer;
53 QTimer m_TracerTimer;
56 QTimer m_TracerTimer;
54 };
57 };
55
58
56 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(QCustomPlot &plot)
59 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(QCustomPlot &plot)
57 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(plot)}
60 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(plot)}
58 {
61 {
59 }
62 }
60
63
61 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
64 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
62 {
65 {
63 // Cancels pending refresh
66 // Cancels pending refresh
64 impl->m_TracerTimer.disconnect();
67 impl->m_TracerTimer.disconnect();
65
68
66 // Reinits tracers
69 // Reinits tracers
67 impl->m_PointTracer->setGraph(nullptr);
70 impl->m_PointTracer->setGraph(nullptr);
68 impl->m_PointTracer->setVisible(false);
71 impl->m_PointTracer->setVisible(false);
69 impl->m_Plot.replot();
72 impl->m_Plot.replot();
70
73
71 // Gets the graph under the mouse position
74 // Gets the graph under the mouse position
72 auto eventPos = event->pos();
75 auto eventPos = event->pos();
73 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
76 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
74 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
77 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
75 auto graphData = graph->data();
78 auto graphData = graph->data();
76
79
77 // Gets the closest data point to the mouse
80 // Gets the closest data point to the mouse
78 auto graphDataIt = graphData->findBegin(mouseKey);
81 auto graphDataIt = graphData->findBegin(mouseKey);
79 if (graphDataIt != graphData->constEnd()) {
82 if (graphDataIt != graphData->constEnd()) {
80 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
83 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
81 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
84 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
82
85
83 // Displays point tracer
86 // Displays point tracer
84 impl->m_PointTracer->setGraph(graph);
87 impl->m_PointTracer->setGraph(graph);
85 impl->m_PointTracer->setGraphKey(graphDataIt->key);
88 impl->m_PointTracer->setGraphKey(graphDataIt->key);
86 impl->m_PointTracer->setLayer(
89 impl->m_PointTracer->setLayer(
87 impl->m_Plot.layer("main")); // Tracer is set on top of the plot's main layer
90 impl->m_Plot.layer("main")); // Tracer is set on top of the plot's main layer
88 impl->m_PointTracer->setVisible(true);
91 impl->m_PointTracer->setVisible(true);
89 impl->m_Plot.replot();
92 impl->m_Plot.replot();
90
93
91 // Starts timer to show tooltip after timeout
94 // Starts timer to show tooltip after timeout
92 auto showTooltip = [ tooltip = TOOLTIP_FORMAT.arg(key, value), eventPos, this ]()
95 auto showTooltip = [ tooltip = TOOLTIP_FORMAT.arg(key, value), eventPos, this ]()
93 {
96 {
94 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos), tooltip, &impl->m_Plot,
97 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos) + TOOLTIP_OFFSET, tooltip,
95 TOOLTIP_RECT);
98 &impl->m_Plot, TOOLTIP_RECT);
96 };
99 };
97
100
98 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
101 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
99 impl->m_TracerTimer.start();
102 impl->m_TracerTimer.start();
100 }
103 }
101 }
104 }
102 }
105 }
General Comments 0
You need to be logged in to leave comments. Login now