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