@@ -70,6 +70,7 public: | |||||
70 | void setYRange(std::shared_ptr<Variable> variable); |
|
70 | void setYRange(std::shared_ptr<Variable> variable); | |
71 | SqpRange graphRange() const noexcept; |
|
71 | SqpRange graphRange() const noexcept; | |
72 | void setGraphRange(const SqpRange &range, bool calibration = false); |
|
72 | void setGraphRange(const SqpRange &range, bool calibration = false); | |
|
73 | void setAutoRangeOnVariableInitialization(bool value); | |||
73 |
|
74 | |||
74 | // Zones |
|
75 | // Zones | |
75 | /// Returns the ranges of all the selection zones on the graph |
|
76 | /// Returns the ranges of all the selection zones on the graph |
@@ -27,6 +27,9 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget") | |||||
27 | /// Fixed size of the validation column |
|
27 | /// Fixed size of the validation column | |
28 | const auto VALIDATION_COLUMN_SIZE = 35; |
|
28 | const auto VALIDATION_COLUMN_SIZE = 35; | |
29 |
|
29 | |||
|
30 | /// Percentage added to the range of a event when it is displayed | |||
|
31 | const auto EVENT_RANGE_MARGE = 30; // in % | |||
|
32 | ||||
30 | struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate { |
|
33 | struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate { | |
31 |
|
34 | |||
32 | CatalogueEventsModel *m_Model = nullptr; |
|
35 | CatalogueEventsModel *m_Model = nullptr; | |
@@ -185,99 +188,130 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate { | |||||
185 | } |
|
188 | } | |
186 | } |
|
189 | } | |
187 |
|
190 | |||
|
191 | QVector<SqpRange> getGraphRanges(const std::shared_ptr<DBEvent> &event) | |||
|
192 | { | |||
|
193 | // Retrieves the range of each product and the maximum size | |||
|
194 | QVector<SqpRange> graphRanges; | |||
|
195 | double maxDt = 0; | |||
|
196 | for (auto eventProduct : event->getEventProducts()) { | |||
|
197 | SqpRange eventRange; | |||
|
198 | eventRange.m_TStart = eventProduct.getTStart(); | |||
|
199 | eventRange.m_TEnd = eventProduct.getTEnd(); | |||
|
200 | graphRanges << eventRange; | |||
|
201 | ||||
|
202 | auto dt = eventRange.m_TEnd - eventRange.m_TStart; | |||
|
203 | if (dt > maxDt) { | |||
|
204 | maxDt = dt; | |||
|
205 | } | |||
|
206 | } | |||
|
207 | ||||
|
208 | // Adds the marge | |||
|
209 | maxDt *= (100.0 + EVENT_RANGE_MARGE) / 100.0; | |||
|
210 | ||||
|
211 | // Corrects the graph ranges so that they all have the same size | |||
|
212 | QVector<SqpRange> correctedGraphRanges; | |||
|
213 | for (auto range : graphRanges) { | |||
|
214 | auto dt = range.m_TEnd - range.m_TStart; | |||
|
215 | auto diff = qAbs((maxDt - dt) / 2.0); | |||
|
216 | ||||
|
217 | SqpRange correctedRange; | |||
|
218 | correctedRange.m_TStart = range.m_TStart - diff; | |||
|
219 | correctedRange.m_TEnd = range.m_TEnd + diff; | |||
|
220 | ||||
|
221 | correctedGraphRanges << correctedRange; | |||
|
222 | } | |||
|
223 | ||||
|
224 | return correctedGraphRanges; | |||
|
225 | } | |||
|
226 | ||||
188 | void updateForGraphMode(QTreeView *treeView) |
|
227 | void updateForGraphMode(QTreeView *treeView) | |
189 | { |
|
228 | { | |
190 | auto selectedRows = treeView->selectionModel()->selectedRows(); |
|
229 | auto selectedRows = treeView->selectionModel()->selectedRows(); | |
|
230 | if (selectedRows.count() != 1) { | |||
|
231 | qCWarning(LOG_CatalogueEventsWidget()) | |||
|
232 | << "updateGraphMode: not compatible with multiple events selected"; | |||
|
233 | return; | |||
|
234 | } | |||
191 |
|
235 | |||
192 | if (selectedRows.count() == 1) { |
|
236 | if (!m_VisualizationWidget) { | |
193 | auto event = m_Model->getEvent(selectedRows.first()); |
|
237 | qCWarning(LOG_CatalogueEventsWidget()) | |
194 | if (m_VisualizationWidget && event) { |
|
238 | << "updateGraphMode: visualization widget not found"; | |
195 | if (auto tab = m_VisualizationWidget->currentTabWidget()) { |
|
239 | return; | |
196 | if (auto zone = tab->getZoneWithName(m_ZoneForGraphMode)) { |
|
240 | } | |
197 |
|
241 | |||
198 | for (auto graph : m_CustomGraphs) { |
|
242 | auto event = m_Model->getEvent(selectedRows.first()); | |
199 | graph->close(); |
|
243 | if (!event) { | |
200 | auto variables = graph->variables().toVector(); |
|
244 | // A event product is probably selected | |
201 |
|
245 | qCInfo(LOG_CatalogueEventsWidget()) << "updateGraphMode: no events are selected"; | ||
202 | QMetaObject::invokeMethod( |
|
246 | return; | |
203 | &sqpApp->variableController(), "deleteVariables", |
|
247 | } | |
204 | Qt::QueuedConnection, |
|
248 | ||
205 | Q_ARG(QVector<std::shared_ptr<Variable> >, variables)); |
|
249 | auto tab = m_VisualizationWidget->currentTabWidget(); | |
206 | } |
|
250 | if (!tab) { | |
207 | m_CustomGraphs.clear(); |
|
251 | qCWarning(LOG_CatalogueEventsWidget()) | |
208 |
|
252 | << "updateGraphMode: no tab found in the visualization"; | ||
209 | QVector<SqpRange> graphRanges; |
|
253 | return; | |
210 | double maxDt = 0; |
|
254 | } | |
211 | for (auto eventProduct : event->getEventProducts()) { |
|
|||
212 | SqpRange eventRange; |
|
|||
213 | eventRange.m_TStart = eventProduct.getTStart(); |
|
|||
214 | eventRange.m_TEnd = eventProduct.getTEnd(); |
|
|||
215 | graphRanges << eventRange; |
|
|||
216 |
|
||||
217 | auto dt = eventRange.m_TEnd - eventRange.m_TStart; |
|
|||
218 | if (dt > maxDt) { |
|
|||
219 | maxDt = dt; |
|
|||
220 | } |
|
|||
221 | } |
|
|||
222 |
|
255 | |||
223 | QVector<SqpRange> correctedGraphRanges; |
|
256 | auto zone = tab->getZoneWithName(m_ZoneForGraphMode); | |
224 | for (auto range : graphRanges) { |
|
257 | if (!zone) { | |
225 | auto dt = range.m_TEnd - range.m_TStart; |
|
258 | qCWarning(LOG_CatalogueEventsWidget()) << "updateGraphMode: zone not found"; | |
226 | auto diff = qAbs((maxDt - dt) / 2.0); |
|
259 | return; | |
|
260 | } | |||
227 |
|
261 | |||
228 | SqpRange correctedRange; |
|
262 | // Close the previous graph and delete the asociated variables | |
229 | correctedRange.m_TStart = range.m_TStart - diff; |
|
263 | for (auto graph : m_CustomGraphs) { | |
230 | correctedRange.m_TEnd = range.m_TEnd + diff; |
|
264 | graph->close(); | |
|
265 | auto variables = graph->variables().toVector(); | |||
231 |
|
266 | |||
232 | correctedGraphRanges << correctedRange; |
|
267 | QMetaObject::invokeMethod(&sqpApp->variableController(), "deleteVariables", | |
233 | } |
|
268 | Qt::QueuedConnection, | |
|
269 | Q_ARG(QVector<std::shared_ptr<Variable> >, variables)); | |||
|
270 | } | |||
|
271 | m_CustomGraphs.clear(); | |||
234 |
|
272 | |||
235 | auto itRange = correctedGraphRanges.cbegin(); |
|
273 | // Calculates the range of each graph which will be created | |
236 | for (auto eventProduct : event->getEventProducts()) { |
|
274 | auto graphRange = getGraphRanges(event); | |
237 | auto productId = eventProduct.getProductId(); |
|
|||
238 |
|
275 | |||
239 | auto range = *itRange; |
|
276 | // Loops through the event products and create the graph | |
240 | ++itRange; |
|
277 | auto itRange = graphRange.cbegin(); | |
|
278 | for (auto eventProduct : event->getEventProducts()) { | |||
|
279 | auto productId = eventProduct.getProductId(); | |||
241 |
|
280 | |||
242 | auto context = new QObject{treeView}; |
|
281 | auto range = *itRange; | |
243 | QObject::connect( |
|
282 | ++itRange; | |
244 | &sqpApp->variableController(), &VariableController::variableAdded, |
|
|||
245 | context, |
|
|||
246 | [this, zone, context, range, productId](auto variable) { |
|
|||
247 |
|
283 | |||
248 | if (variable->metadata() |
|
284 | SqpRange productRange; | |
249 | .value(DataSourceItem::ID_DATA_KEY, "UnknownID") |
|
285 | productRange.m_TStart = eventProduct.getTStart(); | |
250 | .toString() |
|
286 | productRange.m_TEnd = eventProduct.getTEnd(); | |
251 | == productId) { |
|
|||
252 | auto graph = zone->createGraph(variable); |
|
|||
253 | m_CustomGraphs << graph; |
|
|||
254 |
|
287 | |||
255 | graph->setGraphRange(range, true); |
|
288 | auto context = new QObject{treeView}; | |
|
289 | QObject::connect( | |||
|
290 | &sqpApp->variableController(), &VariableController::variableAdded, context, | |||
|
291 | [this, zone, context, range, productRange, productId](auto variable) { | |||
256 |
|
292 | |||
257 | delete context; // removes the connection |
|
293 | if (variable->metadata().value(DataSourceItem::ID_DATA_KEY).toString() | |
258 |
|
|
294 | == productId) { | |
259 | }, |
|
295 | auto graph = zone->createGraph(variable); | |
260 | Qt::QueuedConnection); |
|
296 | graph->setAutoRangeOnVariableInitialization(false); | |
261 |
|
297 | |||
262 | QMetaObject::invokeMethod( |
|
298 | graph->addSelectionZones({productRange}); | |
263 | &sqpApp->dataSourceController(), "requestVariableFromProductIdKey", |
|
299 | m_CustomGraphs << graph; | |
264 | Qt::QueuedConnection, Q_ARG(QString, productId)); |
|
300 | ||
265 | } |
|
301 | graph->setGraphRange(range, true); | |
|
302 | ||||
|
303 | // Removes the graph from the graph list if it is closed manually | |||
|
304 | QObject::connect(graph, &VisualizationGraphWidget::destroyed, | |||
|
305 | [this, graph]() { m_CustomGraphs.removeAll(graph); }); | |||
|
306 | ||||
|
307 | delete context; // removes the connection | |||
266 | } |
|
308 | } | |
267 | } |
|
309 | }, | |
268 |
|
|
310 | Qt::QueuedConnection); | |
269 | qCWarning(LOG_CatalogueEventsWidget()) |
|
311 | ||
270 | << "updateGraphMode: no tab found in the visualization"; |
|
312 | QMetaObject::invokeMethod(&sqpApp->dataSourceController(), | |
271 | } |
|
313 | "requestVariableFromProductIdKey", Qt::QueuedConnection, | |
272 | } |
|
314 | Q_ARG(QString, productId)); | |
273 | else { |
|
|||
274 | qCWarning(LOG_CatalogueEventsWidget()) |
|
|||
275 | << "updateGraphMode: visualization widget not found"; |
|
|||
276 | } |
|
|||
277 | } |
|
|||
278 | else { |
|
|||
279 | qCWarning(LOG_CatalogueEventsWidget()) |
|
|||
280 | << "updateGraphMode: not compatible with multiple events selected"; |
|
|||
281 | } |
|
315 | } | |
282 | } |
|
316 | } | |
283 |
|
317 |
@@ -94,6 +94,8 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate { | |||||
94 |
|
94 | |||
95 | bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even |
|
95 | bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even | |
96 |
|
96 | |||
|
97 | bool m_VariableAutoRangeOnInit = true; | |||
|
98 | ||||
97 | void startDrawingRect(const QPoint &pos, QCustomPlot &plot) |
|
99 | void startDrawingRect(const QPoint &pos, QCustomPlot &plot) | |
98 | { |
|
100 | { | |
99 | removeDrawingRect(plot); |
|
101 | removeDrawingRect(plot); | |
@@ -314,7 +316,10 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, S | |||||
314 | if (auto var = varW.lock()) { |
|
316 | if (auto var = varW.lock()) { | |
315 | // If the variable is the first added in the graph, we load its range |
|
317 | // If the variable is the first added in the graph, we load its range | |
316 | auto firstVariableInGraph = range == INVALID_RANGE; |
|
318 | auto firstVariableInGraph = range == INVALID_RANGE; | |
317 |
auto loadedRange = |
|
319 | auto loadedRange = graphRange(); | |
|
320 | if (impl->m_VariableAutoRangeOnInit) { | |||
|
321 | loadedRange = firstVariableInGraph ? var->range() : range; | |||
|
322 | } | |||
318 | loadRange(var, loadedRange); |
|
323 | loadRange(var, loadedRange); | |
319 | setYRange(var); |
|
324 | setYRange(var); | |
320 | } |
|
325 | } | |
@@ -406,6 +411,11 void VisualizationGraphWidget::setGraphRange(const SqpRange &range, bool calibra | |||||
406 | qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END"); |
|
411 | qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END"); | |
407 | } |
|
412 | } | |
408 |
|
413 | |||
|
414 | void VisualizationGraphWidget::setAutoRangeOnVariableInitialization(bool value) | |||
|
415 | { | |||
|
416 | impl->m_VariableAutoRangeOnInit = value; | |||
|
417 | } | |||
|
418 | ||||
409 | QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const |
|
419 | QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const | |
410 | { |
|
420 | { | |
411 | QVector<SqpRange> ranges; |
|
421 | QVector<SqpRange> ranges; |
General Comments 0
You need to be logged in to leave comments.
Login now