##// END OF EJS Templates
Uses SciQlop color scale in graphs
Alexandre Leroux -
r1050:761051f0c06c
parent child
Show More
@@ -1,37 +1,37
1 1 #ifndef SCIQLOP_AXISRENDERINGUTILS_H
2 2 #define SCIQLOP_AXISRENDERINGUTILS_H
3 3
4 4 #include <memory>
5 5
6 6 #include <QtCore/QLoggingCategory>
7 7 #include <QtCore/QString>
8 8
9 9 Q_DECLARE_LOGGING_CATEGORY(LOG_AxisRenderingUtils)
10 10
11 11 class IDataSeries;
12 12 class QCPAxis;
13 class QCPColorScale;
14 13 class QCustomPlot;
14 class SqpColorScale;
15 15
16 16 /// Formats a data value according to the axis on which it is present
17 17 QString formatValue(double value, const QCPAxis &axis);
18 18
19 19 /**
20 20 * Helper used to handle axes rendering
21 21 */
22 22 struct IAxisHelper {
23 23 virtual ~IAxisHelper() noexcept = default;
24 24
25 25 /// Set properties of the plot's axes and the color scale associated to plot passed as
26 26 /// parameters
27 27 /// @param plot the plot for which to set axe properties
28 28 /// @param colorScale the color scale for which to set properties
29 virtual void setProperties(QCustomPlot &plot, QCPColorScale &colorScale) = 0;
29 virtual void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) = 0;
30 30 };
31 31
32 32 struct IAxisHelperFactory {
33 33 /// Creates IAxisHelper according to a data series
34 34 static std::unique_ptr<IAxisHelper> create(std::shared_ptr<IDataSeries> dataSeries) noexcept;
35 35 };
36 36
37 37 #endif // SCIQLOP_AXISRENDERINGUTILS_H
@@ -1,174 +1,173
1 1 #include "Visualization/AxisRenderingUtils.h"
2 2
3 3 #include <Data/ScalarSeries.h>
4 4 #include <Data/SpectrogramSeries.h>
5 5 #include <Data/VectorSeries.h>
6 6
7 #include <Visualization/SqpColorScale.h>
7 8 #include <Visualization/qcustomplot.h>
8 9
9 10 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
10 11
11 12 namespace {
12 13
13 14 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
14 15
15 16 /// Format for datetimes on a axis
16 17 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
17 18
18 19 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
19 20 /// non-time data
20 21 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
21 22 {
22 23 if (isTimeAxis) {
23 24 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
24 25 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
25 26 dateTicker->setDateTimeSpec(Qt::UTC);
26 27
27 28 return dateTicker;
28 29 }
29 30 else if (scaleType == QCPAxis::stLogarithmic) {
30 31 return QSharedPointer<QCPAxisTickerLog>::create();
31 32 }
32 33 else {
33 34 // default ticker
34 35 return QSharedPointer<QCPAxisTicker>::create();
35 36 }
36 37 }
37 38
38 39 /**
39 40 * Sets properties of the axis passed as parameter
40 41 * @param axis the axis to set
41 42 * @param unit the unit to set for the axis
42 43 * @param scaleType the scale type to set for the axis
43 44 */
44 45 void setAxisProperties(QCPAxis &axis, const Unit &unit,
45 46 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
46 47 {
47 48 // label (unit name)
48 49 axis.setLabel(unit.m_Name);
49 50
50 51 // scale type
51 52 axis.setScaleType(scaleType);
52 53 if (scaleType == QCPAxis::stLogarithmic) {
53 54 // Scientific notation
54 55 axis.setNumberPrecision(0);
55 56 axis.setNumberFormat("eb");
56 57 }
57 58
58 59 // ticker (depending on the type of unit)
59 60 axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
60 61 }
61 62
62 63 /**
63 64 * Delegate used to set axes properties
64 65 */
65 66 template <typename T, typename Enabled = void>
66 67 struct AxisSetter {
67 static void setProperties(T &, QCustomPlot &, QCPColorScale &)
68 static void setProperties(T &, QCustomPlot &, SqpColorScale &)
68 69 {
69 70 // Default implementation does nothing
70 71 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
71 72 }
72 73 };
73 74
74 75 /**
75 76 * Specialization of AxisSetter for scalars and vectors
76 77 * @sa ScalarSeries
77 78 * @sa VectorSeries
78 79 */
79 80 template <typename T>
80 81 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
81 82 or std::is_base_of<VectorSeries, T>::value> > {
82 static void setProperties(T &dataSeries, QCustomPlot &plot, QCPColorScale &)
83 static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
83 84 {
84 85 dataSeries.lockRead();
85 86 auto xAxisUnit = dataSeries.xAxisUnit();
86 87 auto valuesUnit = dataSeries.valuesUnit();
87 88 dataSeries.unlock();
88 89
89 90 setAxisProperties(*plot.xAxis, xAxisUnit);
90 91 setAxisProperties(*plot.yAxis, valuesUnit);
91 92 }
92 93 };
93 94
94 95 /**
95 96 * Specialization of AxisSetter for spectrograms
96 97 * @sa SpectrogramSeries
97 98 */
98 99 template <typename T>
99 100 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
100 static void setProperties(T &dataSeries, QCustomPlot &plot, QCPColorScale &colorScale)
101 static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
101 102 {
102 103 dataSeries.lockRead();
103 104 auto xAxisUnit = dataSeries.xAxisUnit();
104 105 auto yAxisUnit = dataSeries.yAxisUnit();
105 106 auto valuesUnit = dataSeries.valuesUnit();
106 107 dataSeries.unlock();
107 108
108 109 setAxisProperties(*plot.xAxis, xAxisUnit);
109 110 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
110 111
111 112 // Displays color scale in plot
112 113 plot.plotLayout()->insertRow(0);
113 plot.plotLayout()->addElement(0, 0, &colorScale);
114 colorScale.setType(QCPAxis::atTop);
115 colorScale.setMinimumMargins(QMargins{0, 0, 0, 0});
114 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
115 colorScale.m_Scale->setType(QCPAxis::atTop);
116 colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
116 117
117 118 // Aligns color scale with axes
118 119 auto marginGroups = plot.axisRect()->marginGroups();
119 120 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
120 colorScale.setMarginGroup(it.key(), it.value());
121 colorScale.m_Scale->setMarginGroup(it.key(), it.value());
121 122 }
122 123
123 124 // Set color scale properties
124 setAxisProperties(*colorScale.axis(), valuesUnit, QCPAxis::stLogarithmic);
125 /// @todo ALX: temp data range, remove it when widget to set data range is implemented
126 colorScale.setDataRange(QCPRange{8.32e2, 1.77e7});
125 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
127 126 }
128 127 };
129 128
130 129 /**
131 130 * Default implementation of IAxisHelper, which takes data series to set axes properties
132 131 * @tparam T the data series' type
133 132 */
134 133 template <typename T>
135 134 struct AxisHelper : public IAxisHelper {
136 135 explicit AxisHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
137 136
138 void setProperties(QCustomPlot &plot, QCPColorScale &colorScale) override
137 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
139 138 {
140 139 AxisSetter<T>::setProperties(m_DataSeries, plot, colorScale);
141 140 }
142 141
143 142 T &m_DataSeries;
144 143 };
145 144
146 145 } // namespace
147 146
148 147 QString formatValue(double value, const QCPAxis &axis)
149 148 {
150 149 // If the axis is a time axis, formats the value as a date
151 150 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
152 151 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
153 152 }
154 153 else {
155 154 return QString::number(value);
156 155 }
157 156 }
158 157
159 158 std::unique_ptr<IAxisHelper>
160 159 IAxisHelperFactory::create(std::shared_ptr<IDataSeries> dataSeries) noexcept
161 160 {
162 161 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
163 162 return std::make_unique<AxisHelper<ScalarSeries> >(*scalarSeries);
164 163 }
165 164 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
166 165 return std::make_unique<AxisHelper<SpectrogramSeries> >(*spectrogramSeries);
167 166 }
168 167 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
169 168 return std::make_unique<AxisHelper<VectorSeries> >(*vectorSeries);
170 169 }
171 170 else {
172 171 return std::make_unique<AxisHelper<IDataSeries> >(*dataSeries);
173 172 }
174 173 }
@@ -1,127 +1,122
1 1 #include "Visualization/PlottablesRenderingUtils.h"
2 2
3 3 #include <Common/ColorUtils.h>
4 4
5 5 #include <Data/ScalarSeries.h>
6 6 #include <Data/SpectrogramSeries.h>
7 7 #include <Data/VectorSeries.h>
8 8
9 9 #include <Visualization/qcustomplot.h>
10 10
11 11 Q_LOGGING_CATEGORY(LOG_PlottablesRenderingUtils, "PlottablesRenderingUtils")
12 12
13 13 namespace {
14 14
15 /// Default gradient used for colormap
16 const auto DEFAULT_COLORMAP_GRADIENT = QCPColorGradient::gpJet;
17
18 15 /**
19 16 * Delegate used to set plottables properties
20 17 */
21 18 template <typename T, typename Enabled = void>
22 19 struct PlottablesSetter {
23 20 static void setProperties(T &, PlottablesMap &)
24 21 {
25 22 // Default implementation does nothing
26 23 qCCritical(LOG_PlottablesRenderingUtils())
27 24 << "Can't set plottables properties: unmanaged type of data";
28 25 }
29 26 };
30 27
31 28 /**
32 29 * Specialization of PlottablesSetter for scalars and vectors
33 30 * @sa ScalarSeries
34 31 * @sa VectorSeries
35 32 */
36 33 template <typename T>
37 34 struct PlottablesSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
38 35 or std::is_base_of<VectorSeries, T>::value> > {
39 36 static void setProperties(T &dataSeries, PlottablesMap &plottables)
40 37 {
41 38 // Gets the number of components of the data series
42 39 dataSeries.lockRead();
43 40 auto componentCount = dataSeries.valuesData()->componentCount();
44 41 dataSeries.unlock();
45 42
46 43 // Generates colors for each component
47 44 auto colors = ColorUtils::colors(Qt::blue, Qt::red, componentCount);
48 45
49 46 // For each component of the data series, creates a QCPGraph to add to the plot
50 47 for (auto i = 0; i < componentCount; ++i) {
51 48 auto graph = plottables.at(i);
52 49 graph->setPen(QPen{colors.at(i)});
53 50 }
54 51 }
55 52 };
56 53
57 54 /**
58 55 * Specialization of PlottablesSetter for spectrograms
59 56 * @sa SpectrogramSeries
60 57 */
61 58 template <typename T>
62 59 struct PlottablesSetter<T,
63 60 typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
64 61 static void setProperties(T &, PlottablesMap &plottables)
65 62 {
66 63 // Checks that for a spectrogram there is only one plottable, that is a colormap
67 64 if (plottables.size() != 1) {
68 65 return;
69 66 }
70 67
71 68 if (auto colormap = dynamic_cast<QCPColorMap *>(plottables.begin()->second)) {
72 69 colormap->setInterpolate(false); // No value interpolation
73 70 colormap->setTightBoundary(true);
74 71
75 72 // Finds color scale in the colormap's plot to associate with it
76 73 auto plot = colormap->parentPlot();
77 74 auto plotElements = plot->plotLayout()->elements(false);
78 75 for (auto plotElement : plotElements) {
79 76 if (auto colorScale = dynamic_cast<QCPColorScale *>(plotElement)) {
80 77 colormap->setColorScale(colorScale);
81 78 }
82 79 }
83 80
84 // Sets gradient used for color scale
85 colormap->setGradient(DEFAULT_COLORMAP_GRADIENT);
86 81 colormap->rescaleDataRange();
87 82 }
88 83 else {
89 84 qCCritical(LOG_PlottablesRenderingUtils()) << "Can't get colormap of the spectrogram";
90 85 }
91 86 }
92 87 };
93 88
94 89 /**
95 90 * Default implementation of IPlottablesHelper, which takes data series to set plottables properties
96 91 * @tparam T the data series' type
97 92 */
98 93 template <typename T>
99 94 struct PlottablesHelper : public IPlottablesHelper {
100 95 explicit PlottablesHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
101 96
102 97 void setProperties(PlottablesMap &plottables) override
103 98 {
104 99 PlottablesSetter<T>::setProperties(m_DataSeries, plottables);
105 100 }
106 101
107 102 T &m_DataSeries;
108 103 };
109 104
110 105 } // namespace
111 106
112 107 std::unique_ptr<IPlottablesHelper>
113 108 IPlottablesHelperFactory::create(std::shared_ptr<IDataSeries> dataSeries) noexcept
114 109 {
115 110 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
116 111 return std::make_unique<PlottablesHelper<ScalarSeries> >(*scalarSeries);
117 112 }
118 113 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
119 114 return std::make_unique<PlottablesHelper<SpectrogramSeries> >(*spectrogramSeries);
120 115 }
121 116 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
122 117 return std::make_unique<PlottablesHelper<VectorSeries> >(*vectorSeries);
123 118 }
124 119 else {
125 120 return std::make_unique<PlottablesHelper<IDataSeries> >(*dataSeries);
126 121 }
127 122 }
@@ -1,255 +1,256
1 1 #include "Visualization/VisualizationGraphRenderingDelegate.h"
2 2 #include "Visualization/AxisRenderingUtils.h"
3 3 #include "Visualization/ColorScaleEditor.h"
4 4 #include "Visualization/PlottablesRenderingUtils.h"
5 #include "Visualization/SqpColorScale.h"
5 6 #include "Visualization/VisualizationGraphWidget.h"
6 7 #include "Visualization/qcustomplot.h"
7 8
8 9 #include <Common/DateUtils.h>
9 10
10 11 #include <Data/IDataSeries.h>
11 12
12 13 #include <SqpApplication.h>
13 14
14 15 namespace {
15 16
16 17 /// Name of the axes layer in QCustomPlot
17 18 const auto AXES_LAYER = QStringLiteral("axes");
18 19
19 20 /// Icon used to show x-axis properties
20 21 const auto HIDE_AXIS_ICON_PATH = QStringLiteral(":/icones/down.png");
21 22
22 23 /// Name of the overlay layer in QCustomPlot
23 24 const auto OVERLAY_LAYER = QStringLiteral("overlay");
24 25
25 26 /// Pixmap used to show x-axis properties
26 27 const auto SHOW_AXIS_ICON_PATH = QStringLiteral(":/icones/up.png");
27 28
28 29 const auto TOOLTIP_FORMAT = QStringLiteral("key: %1\nvalue: %2");
29 30
30 31 /// Offset used to shift the tooltip of the mouse
31 32 const auto TOOLTIP_OFFSET = QPoint{20, 20};
32 33
33 34 /// Tooltip display rectangle (the tooltip is hidden when the mouse leaves this rectangle)
34 35 const auto TOOLTIP_RECT = QRect{10, 10, 10, 10};
35 36
36 37 /// Timeout after which the tooltip is displayed
37 38 const auto TOOLTIP_TIMEOUT = 500;
38 39
39 40 void initPointTracerStyle(QCPItemTracer &tracer) noexcept
40 41 {
41 42 tracer.setInterpolating(false);
42 43 tracer.setStyle(QCPItemTracer::tsCircle);
43 44 tracer.setSize(3);
44 45 tracer.setPen(QPen(Qt::black));
45 46 tracer.setBrush(Qt::black);
46 47 }
47 48
48 49 QPixmap pixmap(const QString &iconPath) noexcept
49 50 {
50 51 return QIcon{iconPath}.pixmap(QSize{16, 16});
51 52 }
52 53
53 54 void initClosePixmapStyle(QCPItemPixmap &pixmap) noexcept
54 55 {
55 56 // Icon
56 57 pixmap.setPixmap(
57 58 sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton).pixmap(QSize{16, 16}));
58 59
59 60 // Position
60 61 pixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
61 62 pixmap.topLeft->setCoords(1, 0);
62 63 pixmap.setClipToAxisRect(false);
63 64
64 65 // Can be selected
65 66 pixmap.setSelectable(true);
66 67 }
67 68
68 69 void initXAxisPixmapStyle(QCPItemPixmap &itemPixmap) noexcept
69 70 {
70 71 // Icon
71 72 itemPixmap.setPixmap(pixmap(HIDE_AXIS_ICON_PATH));
72 73
73 74 // Position
74 75 itemPixmap.topLeft->setType(QCPItemPosition::ptAxisRectRatio);
75 76 itemPixmap.topLeft->setCoords(0, 1);
76 77 itemPixmap.setClipToAxisRect(false);
77 78
78 79 // Can be selected
79 80 itemPixmap.setSelectable(true);
80 81 }
81 82
82 83 void initTitleTextStyle(QCPItemText &text) noexcept
83 84 {
84 85 // Font and background styles
85 86 text.setColor(Qt::gray);
86 87 text.setBrush(Qt::white);
87 88
88 89 // Position
89 90 text.setPositionAlignment(Qt::AlignTop | Qt::AlignLeft);
90 91 text.position->setType(QCPItemPosition::ptAxisRectRatio);
91 92 text.position->setCoords(0.5, 0);
92 93 }
93 94
94 95 } // namespace
95 96
96 97 struct VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegatePrivate {
97 98 explicit VisualizationGraphRenderingDelegatePrivate(VisualizationGraphWidget &graphWidget)
98 99 : m_Plot{graphWidget.plot()},
99 100 m_PointTracer{new QCPItemTracer{&m_Plot}},
100 101 m_TracerTimer{},
101 102 m_ClosePixmap{new QCPItemPixmap{&m_Plot}},
102 103 m_TitleText{new QCPItemText{&m_Plot}},
103 104 m_XAxisPixmap{new QCPItemPixmap{&m_Plot}},
104 105 m_ShowXAxis{true},
105 106 m_XAxisLabel{},
106 m_ColorScale{new QCPColorScale{&m_Plot}}
107 m_ColorScale{SqpColorScale{m_Plot}}
107 108 {
108 109 initPointTracerStyle(*m_PointTracer);
109 110
110 111 m_TracerTimer.setInterval(TOOLTIP_TIMEOUT);
111 112 m_TracerTimer.setSingleShot(true);
112 113
113 114 // Inits "close button" in plot overlay
114 115 m_ClosePixmap->setLayer(OVERLAY_LAYER);
115 116 initClosePixmapStyle(*m_ClosePixmap);
116 117
117 118 // Connects pixmap selection to graph widget closing
118 119 QObject::connect(m_ClosePixmap, &QCPItemPixmap::selectionChanged,
119 120 [&graphWidget](bool selected) {
120 121 if (selected) {
121 122 graphWidget.close();
122 123 }
123 124 });
124 125
125 126 // Inits graph name in plot overlay
126 127 m_TitleText->setLayer(OVERLAY_LAYER);
127 128 m_TitleText->setText(graphWidget.name());
128 129 initTitleTextStyle(*m_TitleText);
129 130
130 131 // Inits "show x-axis button" in plot overlay
131 132 m_XAxisPixmap->setLayer(OVERLAY_LAYER);
132 133 initXAxisPixmapStyle(*m_XAxisPixmap);
133 134
134 135 // Connects pixmap selection to graph x-axis showing/hiding
135 136 QObject::connect(m_XAxisPixmap, &QCPItemPixmap::selectionChanged, [this]() {
136 137 if (m_XAxisPixmap->selected()) {
137 138 // Changes the selection state and refreshes the x-axis
138 139 m_ShowXAxis = !m_ShowXAxis;
139 140 updateXAxisState();
140 141 m_Plot.layer(AXES_LAYER)->replot();
141 142
142 143 // Deselects the x-axis pixmap and updates icon
143 144 m_XAxisPixmap->setSelected(false);
144 145 m_XAxisPixmap->setPixmap(
145 146 pixmap(m_ShowXAxis ? HIDE_AXIS_ICON_PATH : SHOW_AXIS_ICON_PATH));
146 147 m_Plot.layer(OVERLAY_LAYER)->replot();
147 148 }
148 149 });
149 150 }
150 151
151 152 /// Updates state of x-axis according to the current selection of x-axis pixmap
152 153 /// @remarks the method doesn't call plot refresh
153 154 void updateXAxisState() noexcept
154 155 {
155 156 m_Plot.xAxis->setTickLabels(m_ShowXAxis);
156 157 m_Plot.xAxis->setLabel(m_ShowXAxis ? m_XAxisLabel : QString{});
157 158 }
158 159
159 160 QCustomPlot &m_Plot;
160 161 QCPItemTracer *m_PointTracer;
161 162 QTimer m_TracerTimer;
162 163 QCPItemPixmap *m_ClosePixmap; /// Graph's close button
163 164 QCPItemText *m_TitleText; /// Graph's title
164 165 QCPItemPixmap *m_XAxisPixmap;
165 166 bool m_ShowXAxis; /// X-axis properties are shown or hidden
166 167 QString m_XAxisLabel;
167 QCPColorScale *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)
168 169 };
169 170
170 171 VisualizationGraphRenderingDelegate::VisualizationGraphRenderingDelegate(
171 172 VisualizationGraphWidget &graphWidget)
172 173 : impl{spimpl::make_unique_impl<VisualizationGraphRenderingDelegatePrivate>(graphWidget)}
173 174 {
174 175 }
175 176
176 177 void VisualizationGraphRenderingDelegate::onMouseDoubleClick(QMouseEvent *event) noexcept
177 178 {
178 179 // Opens color scale editor if color scale is double clicked
179 180 if (auto colorScale
180 181 = dynamic_cast<QCPColorScale *>(impl->m_Plot.layoutElementAt(event->pos()))) {
181 182 ColorScaleEditor{}.exec();
182 183 }
183 184 }
184 185
185 186 void VisualizationGraphRenderingDelegate::onMouseMove(QMouseEvent *event) noexcept
186 187 {
187 188 // Cancels pending refresh
188 189 impl->m_TracerTimer.disconnect();
189 190
190 191 // Reinits tracers
191 192 impl->m_PointTracer->setGraph(nullptr);
192 193 impl->m_PointTracer->setVisible(false);
193 194 impl->m_Plot.replot();
194 195
195 196 // Gets the graph under the mouse position
196 197 auto eventPos = event->pos();
197 198 if (auto graph = qobject_cast<QCPGraph *>(impl->m_Plot.plottableAt(eventPos))) {
198 199 auto mouseKey = graph->keyAxis()->pixelToCoord(eventPos.x());
199 200 auto graphData = graph->data();
200 201
201 202 // Gets the closest data point to the mouse
202 203 auto graphDataIt = graphData->findBegin(mouseKey);
203 204 if (graphDataIt != graphData->constEnd()) {
204 205 auto key = formatValue(graphDataIt->key, *graph->keyAxis());
205 206 auto value = formatValue(graphDataIt->value, *graph->valueAxis());
206 207
207 208 // Displays point tracer
208 209 impl->m_PointTracer->setGraph(graph);
209 210 impl->m_PointTracer->setGraphKey(graphDataIt->key);
210 211 impl->m_PointTracer->setLayer(
211 212 impl->m_Plot.layer("main")); // Tracer is set on top of the plot's main layer
212 213 impl->m_PointTracer->setVisible(true);
213 214 impl->m_Plot.replot();
214 215
215 216 // Starts timer to show tooltip after timeout
216 217 auto showTooltip = [ tooltip = TOOLTIP_FORMAT.arg(key, value), eventPos, this ]()
217 218 {
218 219 QToolTip::showText(impl->m_Plot.mapToGlobal(eventPos) + TOOLTIP_OFFSET, tooltip,
219 220 &impl->m_Plot, TOOLTIP_RECT);
220 221 };
221 222
222 223 QObject::connect(&impl->m_TracerTimer, &QTimer::timeout, showTooltip);
223 224 impl->m_TracerTimer.start();
224 225 }
225 226 }
226 227 }
227 228
228 229 void VisualizationGraphRenderingDelegate::setAxesProperties(
229 230 std::shared_ptr<IDataSeries> dataSeries) noexcept
230 231 {
231 232 // Stores x-axis label to be able to retrieve it when x-axis pixmap is unselected
232 233 impl->m_XAxisLabel = dataSeries->xAxisUnit().m_Name;
233 234
234 235 auto axisHelper = IAxisHelperFactory::create(dataSeries);
235 axisHelper->setProperties(impl->m_Plot, *impl->m_ColorScale);
236 axisHelper->setProperties(impl->m_Plot, impl->m_ColorScale);
236 237
237 238 // Updates x-axis state
238 239 impl->updateXAxisState();
239 240
240 241 impl->m_Plot.layer(AXES_LAYER)->replot();
241 242 }
242 243
243 244 void VisualizationGraphRenderingDelegate::setPlottablesProperties(
244 245 std::shared_ptr<IDataSeries> dataSeries, PlottablesMap &plottables) noexcept
245 246 {
246 247 auto plottablesHelper = IPlottablesHelperFactory::create(dataSeries);
247 248 plottablesHelper->setProperties(plottables);
248 249 }
249 250
250 251 void VisualizationGraphRenderingDelegate::showGraphOverlay(bool show) noexcept
251 252 {
252 253 auto overlay = impl->m_Plot.layer(OVERLAY_LAYER);
253 254 overlay->setVisible(show);
254 255 overlay->replot();
255 256 }
General Comments 0
You need to be logged in to leave comments. Login now