##// END OF EJS Templates
Merge pull request 306 from SciQLop-fork develop...
perrinel -
r820:0b4649618604 merge
parent child
Show More
@@ -68,6 +68,12 public:
68 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
68 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
69 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
69 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
70
70
71 static QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &oldRange,
72 const SqpRange &nextRange);
73
74 static QVector<SqpRange> provideInCacheRangeList(const SqpRange &oldRange,
75 const SqpRange &nextRange);
76
71 signals:
77 signals:
72 void updated();
78 void updated();
73
79
@@ -83,7 +83,7 signals:
83 public slots:
83 public slots:
84 /// Request the data loading of the variable whithin range
84 /// Request the data loading of the variable whithin range
85 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
85 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
86 const SqpRange &oldRange, bool synchronise);
86 bool synchronise);
87 /**
87 /**
88 * Creates a new variable and adds it to the model
88 * Creates a new variable and adds it to the model
89 * @param name the name of the new variable
89 * @param name the name of the new variable
@@ -138,7 +138,6 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
138 impl->lockWrite();
138 impl->lockWrite();
139 if (cacheRange != impl->m_CacheRange) {
139 if (cacheRange != impl->m_CacheRange) {
140 impl->m_CacheRange = cacheRange;
140 impl->m_CacheRange = cacheRange;
141 impl->purgeDataSeries();
142 }
141 }
143 impl->unlock();
142 impl->unlock();
144 }
143 }
@@ -174,6 +173,7 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
174 impl->unlock();
173 impl->unlock();
175 }
174 }
176
175
176
177 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
177 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
178 {
178 {
179 impl->lockRead();
179 impl->lockRead();
@@ -285,7 +285,7 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const
285
285
286 if (impl->m_CacheRange != INVALID_RANGE) {
286 if (impl->m_CacheRange != INVALID_RANGE) {
287
287
288 if (this->intersect(range)) {
288 if (this->cacheIntersect(range)) {
289 if (range.m_TStart <= impl->m_CacheRange.m_TStart
289 if (range.m_TStart <= impl->m_CacheRange.m_TStart
290 && range.m_TEnd >= impl->m_CacheRange.m_TStart
290 && range.m_TEnd >= impl->m_CacheRange.m_TStart
291 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
291 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
@@ -313,3 +313,76 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const
313
313
314 return inCache;
314 return inCache;
315 }
315 }
316
317
318 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &oldRange,
319 const SqpRange &nextRange)
320 {
321
322 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
323 auto notInCache = QVector<SqpRange>{};
324 if (oldRange != INVALID_RANGE) {
325
326 if (!oldRange.contains(nextRange)) {
327 if (nextRange.m_TEnd <= oldRange.m_TStart || nextRange.m_TStart >= oldRange.m_TEnd) {
328 notInCache << nextRange;
329 }
330 else if (nextRange.m_TStart < oldRange.m_TStart
331 && nextRange.m_TEnd <= oldRange.m_TEnd) {
332 notInCache << SqpRange{nextRange.m_TStart, oldRange.m_TStart};
333 }
334 else if (nextRange.m_TStart < oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
335 notInCache << SqpRange{nextRange.m_TStart, oldRange.m_TStart}
336 << SqpRange{oldRange.m_TEnd, nextRange.m_TEnd};
337 }
338 else if (nextRange.m_TStart < oldRange.m_TEnd) {
339 notInCache << SqpRange{oldRange.m_TEnd, nextRange.m_TEnd};
340 }
341 else {
342 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
343 << QThread::currentThread();
344 }
345 }
346 }
347 else {
348 notInCache << nextRange;
349 }
350
351 return notInCache;
352 }
353
354 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &oldRange,
355 const SqpRange &nextRange)
356 {
357 // This code assume that cach is contigue. Can return 0 or 1 SqpRange
358
359 auto inCache = QVector<SqpRange>{};
360
361 if (oldRange != INVALID_RANGE) {
362
363 if (oldRange.intersect(nextRange)) {
364 if (nextRange.m_TStart <= oldRange.m_TStart && nextRange.m_TEnd >= oldRange.m_TStart
365 && nextRange.m_TEnd < oldRange.m_TEnd) {
366 inCache << SqpRange{oldRange.m_TStart, nextRange.m_TEnd};
367 }
368
369 else if (nextRange.m_TStart >= oldRange.m_TStart
370 && nextRange.m_TEnd <= oldRange.m_TEnd) {
371 inCache << nextRange;
372 }
373 else if (nextRange.m_TStart > oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
374 inCache << SqpRange{nextRange.m_TStart, oldRange.m_TEnd};
375 }
376 else if (nextRange.m_TStart <= oldRange.m_TStart
377 && nextRange.m_TEnd >= oldRange.m_TEnd) {
378 inCache << oldRange;
379 }
380 else {
381 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
382 << QThread::currentThread();
383 }
384 }
385 }
386
387 return inCache;
388 }
@@ -32,6 +32,10 struct VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate {
32 /// Remove the current request and execute the next one if exist
32 /// Remove the current request and execute the next one if exist
33 void updateToNextRequest(QUuid vIdentifier);
33 void updateToNextRequest(QUuid vIdentifier);
34
34
35 /// Remove and/or abort all AcqRequest in link with varRequestId
36 void cancelVarRequest(QUuid varRequestId);
37 void removeAcqRequest(QUuid acqRequestId);
38
35 QMutex m_WorkingMutex;
39 QMutex m_WorkingMutex;
36 QReadWriteLock m_Lock;
40 QReadWriteLock m_Lock;
37
41
@@ -67,7 +71,8 QUuid VariableAcquisitionWorker::pushVariableRequest(QUuid varRequestId, QUuid v
67
71
68 // Request creation
72 // Request creation
69 auto acqRequest = AcquisitionRequest{};
73 auto acqRequest = AcquisitionRequest{};
70 qCInfo(LOG_VariableAcquisitionWorker()) << tr("TpushVariableRequest ") << vIdentifier;
74 qCDebug(LOG_VariableAcquisitionWorker()) << tr("PushVariableRequest ") << vIdentifier
75 << varRequestId;
71 acqRequest.m_VarRequestId = varRequestId;
76 acqRequest.m_VarRequestId = varRequestId;
72 acqRequest.m_vIdentifier = vIdentifier;
77 acqRequest.m_vIdentifier = vIdentifier;
73 acqRequest.m_DataProviderParameters = parameters;
78 acqRequest.m_DataProviderParameters = parameters;
@@ -85,15 +90,19 QUuid VariableAcquisitionWorker::pushVariableRequest(QUuid varRequestId, QUuid v
85 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
90 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
86 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
91 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
87 // A current request already exists, we can replace the next one
92 // A current request already exists, we can replace the next one
88 auto nextAcqId = it->second.second;
93 auto oldAcqId = it->second.second;
89 auto acqIdentifierToAcqRequestMapIt = impl->m_AcqIdentifierToAcqRequestMap.find(nextAcqId);
94 auto acqIdentifierToAcqRequestMapIt = impl->m_AcqIdentifierToAcqRequestMap.find(oldAcqId);
90 if (acqIdentifierToAcqRequestMapIt != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
95 if (acqIdentifierToAcqRequestMapIt != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
91 auto request = acqIdentifierToAcqRequestMapIt->second;
96 auto oldAcqRequest = acqIdentifierToAcqRequestMapIt->second;
92 varRequestIdCanceled = request.m_VarRequestId;
97 varRequestIdCanceled = oldAcqRequest.m_VarRequestId;
93 }
98 }
94
99
95 it->second.second = acqRequest.m_AcqIdentifier;
100 it->second.second = acqRequest.m_AcqIdentifier;
96 impl->unlock();
101 impl->unlock();
102
103 // remove old acqIdentifier from the worker
104 impl->cancelVarRequest(varRequestIdCanceled);
105 // impl->m_AcqIdentifierToAcqRequestMap.erase(oldAcqId);
97 }
106 }
98 else {
107 else {
99 // First request for the variable, it must be stored and executed
108 // First request for the variable, it must be stored and executed
@@ -122,10 +131,7 void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier)
122 impl->unlock();
131 impl->unlock();
123
132
124 // Remove the current request from the worker
133 // Remove the current request from the worker
125
126 impl->lockWrite();
127 impl->updateToNextRequest(vIdentifier);
134 impl->updateToNextRequest(vIdentifier);
128 impl->unlock();
129
135
130 // notify the request aborting to the provider
136 // notify the request aborting to the provider
131 request.m_Provider->requestDataAborting(currentAcqId);
137 request.m_Provider->requestDataAborting(currentAcqId);
@@ -221,22 +227,28 void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier,
221 // if the counter is 0, we can return data then run the next request if it exists and
227 // if the counter is 0, we can return data then run the next request if it exists and
222 // removed the finished request
228 // removed the finished request
223 if (acqRequest.m_Size == acqRequest.m_Progression) {
229 if (acqRequest.m_Size == acqRequest.m_Progression) {
230 auto varId = acqRequest.m_vIdentifier;
231 auto rangeRequested = acqRequest.m_RangeRequested;
232 auto cacheRangeRequested = acqRequest.m_CacheRangeRequested;
224 // Return the data
233 // Return the data
225 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
234 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
226 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
235 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
227 emit dataProvided(acqRequest.m_vIdentifier, acqRequest.m_RangeRequested,
236 emit dataProvided(varId, rangeRequested, cacheRangeRequested, aIdToADPVit->second);
228 acqRequest.m_CacheRangeRequested, aIdToADPVit->second);
229 }
237 }
238 impl->unlock();
230
239
231 // Update to the next request
240 // Update to the next request
232 impl->updateToNextRequest(acqRequest.m_vIdentifier);
241 impl->updateToNextRequest(acqRequest.m_vIdentifier);
233 }
242 }
243 else {
244 impl->unlock();
245 }
234 }
246 }
235 else {
247 else {
248 impl->unlock();
236 qCWarning(LOG_VariableAcquisitionWorker())
249 qCWarning(LOG_VariableAcquisitionWorker())
237 << tr("Impossible to retrieve AcquisitionRequest for the incoming data.");
250 << tr("Impossible to retrieve AcquisitionRequest for the incoming data.");
238 }
251 }
239 impl->unlock();
240 }
252 }
241
253
242 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
254 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
@@ -296,27 +308,109 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariable
296 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::updateToNextRequest(
308 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::updateToNextRequest(
297 QUuid vIdentifier)
309 QUuid vIdentifier)
298 {
310 {
311 lockRead();
299 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
312 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
300 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
313 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
301 if (it->second.second.isNull()) {
314 if (it->second.second.isNull()) {
315 unlock();
302 // There is no next request, we can remove the variable request
316 // There is no next request, we can remove the variable request
303 removeVariableRequest(vIdentifier);
317 removeVariableRequest(vIdentifier);
304 }
318 }
305 else {
319 else {
306 auto acqIdentifierToRemove = it->second.first;
320 auto acqIdentifierToRemove = it->second.first;
307 // Move the next request to the current request
321 // Move the next request to the current request
308 it->second.first = it->second.second;
322 auto nextRequestId = it->second.second;
323 it->second.first = nextRequestId;
309 it->second.second = QUuid();
324 it->second.second = QUuid();
325 unlock();
310 // Remove AcquisitionRequest and results;
326 // Remove AcquisitionRequest and results;
327 lockWrite();
311 m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
328 m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
312 m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
329 m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
330 unlock();
313 // Execute the current request
331 // Execute the current request
314 QMetaObject::invokeMethod(q, "onExecuteRequest", Qt::QueuedConnection,
332 QMetaObject::invokeMethod(q, "onExecuteRequest", Qt::QueuedConnection,
315 Q_ARG(QUuid, it->second.first));
333 Q_ARG(QUuid, nextRequestId));
316 }
334 }
317 }
335 }
318 else {
336 else {
337 unlock();
319 qCCritical(LOG_VariableAcquisitionWorker())
338 qCCritical(LOG_VariableAcquisitionWorker())
320 << tr("Impossible to execute the acquisition on an unfound variable ");
339 << tr("Impossible to execute the acquisition on an unfound variable ");
321 }
340 }
322 }
341 }
342
343 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::cancelVarRequest(
344 QUuid varRequestId)
345 {
346 qCDebug(LOG_VariableAcquisitionWorker())
347 << "VariableAcquisitionWorkerPrivate::cancelVarRequest 0";
348 lockRead();
349 // get all AcqIdentifier in link with varRequestId
350 QVector<QUuid> acqIdsToRm;
351 auto cend = m_AcqIdentifierToAcqRequestMap.cend();
352 for (auto it = m_AcqIdentifierToAcqRequestMap.cbegin(); it != cend; ++it) {
353 if (it->second.m_VarRequestId == varRequestId) {
354 acqIdsToRm << it->first;
355 }
356 }
357 unlock();
358 // run aborting or removing of acqIdsToRm
359
360 for (auto acqId : acqIdsToRm) {
361 removeAcqRequest(acqId);
362 }
363 qCDebug(LOG_VariableAcquisitionWorker())
364 << "VariableAcquisitionWorkerPrivate::cancelVarRequest end";
365 }
366
367 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeAcqRequest(
368 QUuid acqRequestId)
369 {
370 qCDebug(LOG_VariableAcquisitionWorker())
371 << "VariableAcquisitionWorkerPrivate::removeAcqRequest";
372 QUuid vIdentifier;
373 std::shared_ptr<IDataProvider> provider;
374 lockRead();
375 auto acqIt = m_AcqIdentifierToAcqRequestMap.find(acqRequestId);
376 if (acqIt != m_AcqIdentifierToAcqRequestMap.cend()) {
377 vIdentifier = acqIt->second.m_vIdentifier;
378 provider = acqIt->second.m_Provider;
379
380 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
381 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
382 if (it->second.first == acqRequestId) {
383 // acqRequest is currently running -> let's aborting it
384 unlock();
385
386 // Remove the current request from the worker
387 updateToNextRequest(vIdentifier);
388
389 // notify the request aborting to the provider
390 provider->requestDataAborting(acqRequestId);
391 }
392 else if (it->second.second == acqRequestId) {
393 it->second.second = QUuid();
394 unlock();
395 }
396 else {
397 unlock();
398 }
399 }
400 else {
401 unlock();
402 }
403 }
404 else {
405 unlock();
406 }
407
408 lockWrite();
409
410 m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqRequestId);
411 m_AcqIdentifierToAcqRequestMap.erase(acqRequestId);
412
413 unlock();
414 qCDebug(LOG_VariableAcquisitionWorker())
415 << "VariableAcquisitionWorkerPrivate::removeAcqRequest END";
416 }
@@ -48,15 +48,17 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &
48 break;
48 break;
49 }
49 }
50 case AcquisitionZoomType::PanRight: {
50 case AcquisitionZoomType::PanRight: {
51 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
51 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
52 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
52 varRangeRequested.m_TStart += deltaRight;
53 varRangeRequested.m_TStart += deltaLeft;
53 varRangeRequested.m_TEnd += deltaRight;
54 varRangeRequested.m_TEnd += deltaRight;
54 break;
55 break;
55 }
56 }
56 case AcquisitionZoomType::PanLeft: {
57 case AcquisitionZoomType::PanLeft: {
57 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
58 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
59 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
58 varRangeRequested.m_TStart -= deltaLeft;
60 varRangeRequested.m_TStart -= deltaLeft;
59 varRangeRequested.m_TEnd -= deltaLeft;
61 varRangeRequested.m_TEnd -= deltaRight;
60 break;
62 break;
61 }
63 }
62 case AcquisitionZoomType::Unknown: {
64 case AcquisitionZoomType::Unknown: {
@@ -103,9 +105,6 struct VariableController::VariableControllerPrivate {
103 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
105 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
104 QUuid varRequestId);
106 QUuid varRequestId);
105
107
106 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
107 const SqpRange &dateTime);
108
109 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
108 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
110 std::shared_ptr<IDataSeries>
109 std::shared_ptr<IDataSeries>
111 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
110 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
@@ -117,6 +116,8 struct VariableController::VariableControllerPrivate {
117 void updateVariableRequest(QUuid varRequestId);
116 void updateVariableRequest(QUuid varRequestId);
118 void cancelVariableRequest(QUuid varRequestId);
117 void cancelVariableRequest(QUuid varRequestId);
119
118
119 SqpRange getLastRequestedRange(QUuid varId);
120
120 QMutex m_WorkingMutex;
121 QMutex m_WorkingMutex;
121 /// Variable model. The VariableController has the ownership
122 /// Variable model. The VariableController has the ownership
122 VariableModel *m_VariableModel;
123 VariableModel *m_VariableModel;
@@ -295,22 +296,24 VariableController::createVariable(const QString &name, const QVariantHash &meta
295
296
296 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
297 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
297 {
298 {
298 // TODO check synchronisation and Rescale
299 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
299 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
300 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
300 << QThread::currentThread()->objectName();
301 << QThread::currentThread()->objectName();
301 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
302 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
302 auto varRequestId = QUuid::createUuid();
303 auto variables = QVector<std::shared_ptr<Variable> >{};
303
304
304 for (const auto &selectedRow : qAsConst(selectedRows)) {
305 for (const auto &selectedRow : qAsConst(selectedRows)) {
305 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
306 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
306 selectedVariable->setRange(dateTime);
307 variables << selectedVariable;
307 impl->processRequest(selectedVariable, dateTime, varRequestId);
308
308
309 // notify that rescale operation has to be done
309 // notify that rescale operation has to be done
310 emit rangeChanged(selectedVariable, dateTime);
310 emit rangeChanged(selectedVariable, dateTime);
311 }
311 }
312 }
312 }
313 impl->updateVariableRequest(varRequestId);
313
314 if (!variables.isEmpty()) {
315 this->onRequestDataLoading(variables, dateTime, true);
316 }
314 }
317 }
315
318
316 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
319 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
@@ -455,8 +458,7 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
455 }
458 }
456
459
457 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
460 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
458 const SqpRange &range, const SqpRange &oldRange,
461 const SqpRange &range, bool synchronise)
459 bool synchronise)
460 {
462 {
461 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
463 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
462
464
@@ -549,19 +551,23 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const
549 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
551 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
550 auto zoomType = AcquisitionZoomType::Unknown;
552 auto zoomType = AcquisitionZoomType::Unknown;
551 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
553 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
554 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
552 zoomType = AcquisitionZoomType::ZoomOut;
555 zoomType = AcquisitionZoomType::ZoomOut;
553 }
556 }
554 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
557 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
558 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
555 zoomType = AcquisitionZoomType::PanRight;
559 zoomType = AcquisitionZoomType::PanRight;
556 }
560 }
557 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
561 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
562 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
558 zoomType = AcquisitionZoomType::PanLeft;
563 zoomType = AcquisitionZoomType::PanLeft;
559 }
564 }
560 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
565 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
566 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
561 zoomType = AcquisitionZoomType::ZoomIn;
567 zoomType = AcquisitionZoomType::ZoomIn;
562 }
568 }
563 else {
569 else {
564 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
570 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
565 }
571 }
566 return zoomType;
572 return zoomType;
567 }
573 }
@@ -570,59 +576,67 void VariableController::VariableControllerPrivate::processRequest(std::shared_p
570 const SqpRange &rangeRequested,
576 const SqpRange &rangeRequested,
571 QUuid varRequestId)
577 QUuid varRequestId)
572 {
578 {
573
574 // TODO: protect at
575 auto varRequest = VariableRequest{};
579 auto varRequest = VariableRequest{};
576 auto varId = m_VariableToIdentifierMap.at(var);
577
580
578 auto varStrategyRangesRequested
581 auto it = m_VariableToIdentifierMap.find(var);
579 = m_VariableCacheStrategy->computeRange(var->range(), rangeRequested);
582 if (it != m_VariableToIdentifierMap.cend()) {
580
583
581 auto notInCacheRangeList = QVector<SqpRange>{varStrategyRangesRequested.second};
584 auto varId = it->second;
582 auto inCacheRangeList = QVector<SqpRange>{};
583 if (m_VarIdToVarRequestIdQueueMap.find(varId) == m_VarIdToVarRequestIdQueueMap.cend()) {
584 notInCacheRangeList = var->provideNotInCacheRangeList(varStrategyRangesRequested.second);
585 inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second);
586 }
587
585
588 if (!notInCacheRangeList.empty()) {
586 auto oldRange = getLastRequestedRange(varId);
589 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
590 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
591
587
592 // store VarRequest
588 // check for update oldRange to the last request range.
593 storeVariableRequest(varId, varRequestId, varRequest);
589 if (oldRange == INVALID_RANGE) {
590 oldRange = var->range();
591 }
594
592
595 auto varProvider = m_VariableToProviderMap.at(var);
593 auto varStrategyRangesRequested
596 if (varProvider != nullptr) {
594 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
597 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
595
598 varRequestId, varId, varStrategyRangesRequested.first,
596 auto notInCacheRangeList
599 varStrategyRangesRequested.second,
597 = Variable::provideNotInCacheRangeList(oldRange, varStrategyRangesRequested.second);
600 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
598 auto inCacheRangeList
601 varProvider);
599 = Variable::provideInCacheRangeList(oldRange, varStrategyRangesRequested.second);
600
601 if (!notInCacheRangeList.empty()) {
602 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
603 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
604
605 // store VarRequest
606 storeVariableRequest(varId, varRequestId, varRequest);
607
608 auto varProvider = m_VariableToProviderMap.at(var);
609 if (varProvider != nullptr) {
610 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
611 varRequestId, varId, varStrategyRangesRequested.first,
612 varStrategyRangesRequested.second,
613 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
614 varProvider);
615
616 if (!varRequestIdCanceled.isNull()) {
617 qCInfo(LOG_VariableAcquisitionWorker()) << tr("varRequestIdCanceled: ")
618 << varRequestIdCanceled;
619 cancelVariableRequest(varRequestIdCanceled);
620 }
621 }
622 else {
623 qCCritical(LOG_VariableController())
624 << "Impossible to provide data with a null provider";
625 }
602
626
603 if (!varRequestIdCanceled.isNull()) {
627 if (!inCacheRangeList.empty()) {
604 qCDebug(LOG_VariableAcquisitionWorker()) << tr("vsarRequestIdCanceled: ")
628 emit q->updateVarDisplaying(var, inCacheRangeList.first());
605 << varRequestIdCanceled;
606 cancelVariableRequest(varRequestIdCanceled);
607 }
629 }
608 }
630 }
609 else {
631 else {
610 qCCritical(LOG_VariableController())
632 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
611 << "Impossible to provide data with a null provider";
633 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
612 }
634 // store VarRequest
613
635 storeVariableRequest(varId, varRequestId, varRequest);
614 if (!inCacheRangeList.empty()) {
636 acceptVariableRequest(
615 emit q->updateVarDisplaying(var, inCacheRangeList.first());
637 varId, var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
616 }
638 }
617 }
639 }
618 else {
619 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
620 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
621 // store VarRequest
622 storeVariableRequest(varId, varRequestId, varRequest);
623 acceptVariableRequest(varId,
624 var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
625 }
626 }
640 }
627
641
628 std::shared_ptr<Variable>
642 std::shared_ptr<Variable>
@@ -784,26 +798,22 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid
784 var->setRange(varRequest.m_RangeRequested);
798 var->setRange(varRequest.m_RangeRequested);
785 var->setCacheRange(varRequest.m_CacheRangeRequested);
799 var->setCacheRange(varRequest.m_CacheRangeRequested);
786 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
800 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
787 << varRequest.m_RangeRequested;
801 << varRequest.m_RangeRequested
788 qCDebug(LOG_VariableController()) << tr("2: onDataProvided")
789 << varRequest.m_CacheRangeRequested;
802 << varRequest.m_CacheRangeRequested;
803 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
804 << var->nbPoints()
805 << varRequest.m_DataSeries->nbPoints();
790 var->mergeDataSeries(varRequest.m_DataSeries);
806 var->mergeDataSeries(varRequest.m_DataSeries);
791 qCDebug(LOG_VariableController()) << tr("3: onDataProvided");
807 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
808 << var->nbPoints();
792
809
793 /// @todo MPL: confirm
794 // Variable update is notified only if there is no pending request for it
795 // if
796 // (m_VarIdToVarRequestIdQueueMap.count(varIdToVarRequestMapIt->first)
797 // == 0) {
798 emit var->updated();
810 emit var->updated();
799 // }
800 }
811 }
801 else {
812 else {
802 qCCritical(LOG_VariableController())
813 qCCritical(LOG_VariableController())
803 << tr("Impossible to update data to a null variable");
814 << tr("Impossible to update data to a null variable");
804 }
815 }
805 }
816 }
806
807 // cleaning varRequestId
817 // cleaning varRequestId
808 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
818 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
809 << m_VarRequestIdToVarIdVarRequestMap.size();
819 << m_VarRequestIdToVarIdVarRequestMap.size();
@@ -832,9 +842,48 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid
832 if (varRequestIdQueue.empty()) {
842 if (varRequestIdQueue.empty()) {
833 varIdToVarRequestIdQueueMapIt
843 varIdToVarRequestIdQueueMapIt
834 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
844 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
845
846 // Recompute if there is any next request based on the removed request.
835 }
847 }
836 else {
848 else {
837 ++varIdToVarRequestIdQueueMapIt;
849 ++varIdToVarRequestIdQueueMapIt;
838 }
850 }
839 }
851 }
840 }
852 }
853
854 SqpRange VariableController::VariableControllerPrivate::getLastRequestedRange(QUuid varId)
855 {
856 auto lastRangeRequested = SqpRange{INVALID_RANGE};
857 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
858 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
859 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
860 auto varRequestId = varRequestIdQueue.back();
861 auto varRequestIdToVarIdVarRequestMapIt
862 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
863 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
864 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
865 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
866 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
867 auto &varRequest = varIdToVarRequestMapIt->second;
868 lastRangeRequested = varRequest.m_RangeRequested;
869 }
870 else {
871 qCDebug(LOG_VariableController())
872 << tr("Impossible to getLastRequestedRange of a unknown variable id attached "
873 "to a variableRequestId")
874 << varRequestId << varId;
875 }
876 }
877 else {
878 qCCritical(LOG_VariableController())
879 << tr("Impossible to getLastRequestedRange of a unknown variableRequestId")
880 << varRequestId;
881 }
882 }
883 else {
884 qDebug(LOG_VariableController())
885 << tr("Impossible to getLastRequestedRange of a unknown variable id") << varId;
886 }
887
888 return lastRangeRequested;
889 }
@@ -105,8 +105,7 struct Move : public IOperation {
105 void exec(VariableController &variableController) const override
105 void exec(VariableController &variableController) const override
106 {
106 {
107 if (auto variable = variableController.variableModel()->variable(m_Index)) {
107 if (auto variable = variableController.variableModel()->variable(m_Index)) {
108 variableController.onRequestDataLoading({variable}, m_NewRange, variable->range(),
108 variableController.onRequestDataLoading({variable}, m_NewRange, !m_Shift);
109 !m_Shift);
110 }
109 }
111 }
110 }
112
111
@@ -171,20 +170,10 private slots:
171 void testSync();
170 void testSync();
172 };
171 };
173
172
174 void TestVariableSync::testSync_data()
173 namespace {
175 {
176 // ////////////// //
177 // Test structure //
178 // ////////////// //
179
180 QTest::addColumn<QUuid>("syncId");
181 QTest::addColumn<SqpRange>("initialRange");
182 QTest::addColumn<Iterations>("iterations");
183
184 // ////////// //
185 // Test cases //
186 // ////////// //
187
174
175 void testSyncCase1()
176 {
188 // Id used to synchronize variables in the controller
177 // Id used to synchronize variables in the controller
189 auto syncId = QUuid::createUuid();
178 auto syncId = QUuid::createUuid();
190
179
@@ -254,7 +243,86 void TestVariableSync::testSync_data()
254 // Zoom out
243 // Zoom out
255 moveVar0(range({12, 0}, {18, 0}), range({11, 0}, {17, 0}));
244 moveVar0(range({12, 0}, {18, 0}), range({11, 0}, {17, 0}));
256
245
257 QTest::newRow("sync1") << syncId << initialRange << std::move(iterations);
246 QTest::newRow("sync1") << syncId << initialRange << std::move(iterations) << 200;
247 }
248
249 void testSyncCase2()
250 {
251 // Id used to synchronize variables in the controller
252 auto syncId = QUuid::createUuid();
253
254 /// Generates a range according to a start time and a end time (the date is the same)
255 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
256 return DateUtils::secondsSinceEpoch(
257 QDateTime{{year, month, day}, QTime{hours, minutes, seconds}, Qt::UTC});
258 };
259
260 auto initialRange = SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)};
261
262 Iterations iterations{};
263 // Creates variables var0 and var1
264 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
265 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
266
267 // Adds variables into the sync group (ranges don't need to be tested here)
268 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
269 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
270
271
272 // Moves var0 through several operations:
273 // - range of var0 changes
274 // - range or var1 changes according to the previous shift (one hour)
275 auto moveVar0 = [&iterations](const auto &var0NewRange) {
276 iterations.push_back(
277 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var0NewRange}}});
278 };
279 moveVar0(SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)});
280 moveVar0(SqpRange{dateTime(2017, 1, 1, 14, 0, 0), dateTime(2017, 1, 1, 15, 0, 0)});
281 moveVar0(SqpRange{dateTime(2017, 1, 1, 8, 0, 0), dateTime(2017, 1, 1, 9, 0, 0)});
282 // moveVar0(SqpRange{dateTime(2017, 1, 1, 7, 30, 0), dateTime(2017, 1, 1, 9, 30, 0)});
283 moveVar0(SqpRange{dateTime(2017, 1, 1, 2, 0, 0), dateTime(2017, 1, 1, 4, 0, 0)});
284 moveVar0(SqpRange{dateTime(2017, 1, 1, 6, 0, 0), dateTime(2017, 1, 1, 8, 0, 0)});
285
286 moveVar0(SqpRange{dateTime(2017, 1, 10, 6, 0, 0), dateTime(2017, 1, 15, 8, 0, 0)});
287 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 1, 25, 8, 0, 0)});
288 moveVar0(SqpRange{dateTime(2017, 1, 2, 6, 0, 0), dateTime(2017, 1, 8, 8, 0, 0)});
289
290 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
291 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
292 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
293 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
294 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
295 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
296 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
297 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
298 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
299 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
300 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
301 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
302
303
304 QTest::newRow("sync2") << syncId << initialRange << iterations << 4000;
305 // QTest::newRow("sync3") << syncId << initialRange << iterations << 5000;
306 }
307 }
308
309 void TestVariableSync::testSync_data()
310 {
311 // ////////////// //
312 // Test structure //
313 // ////////////// //
314
315 QTest::addColumn<QUuid>("syncId");
316 QTest::addColumn<SqpRange>("initialRange");
317 QTest::addColumn<Iterations>("iterations");
318 QTest::addColumn<int>("operationDelay");
319
320 // ////////// //
321 // Test cases //
322 // ////////// //
323
324 testSyncCase1();
325 testSyncCase2();
258 }
326 }
259
327
260 void TestVariableSync::testSync()
328 void TestVariableSync::testSync()
@@ -271,15 +339,8 void TestVariableSync::testSync()
271 // Synchronization group used
339 // Synchronization group used
272 variableController.onAddSynchronizationGroupId(syncId);
340 variableController.onAddSynchronizationGroupId(syncId);
273
341
274 // For each iteration:
342 auto validateRanges = [&variableController](const auto &expectedRanges) {
275 // - execute operation
343 for (const auto &expectedRangeEntry : expectedRanges) {
276 // - compare the variables' state to the expected states
277 QFETCH(Iterations, iterations);
278 for (const auto &iteration : iterations) {
279 iteration.m_Operation->exec(variableController);
280 QTest::qWait(OPERATION_DELAY);
281
282 for (const auto &expectedRangeEntry : iteration.m_ExpectedRanges) {
283 auto variableIndex = expectedRangeEntry.first;
344 auto variableIndex = expectedRangeEntry.first;
284 auto expectedRange = expectedRangeEntry.second;
345 auto expectedRange = expectedRangeEntry.second;
285
346
@@ -297,12 +358,31 void TestVariableSync::testSync()
297
358
298 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
359 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
299 auto expectedValues = values(range);
360 auto expectedValues = values(range);
361 qInfo() << std::distance(it.first, it.second) << expectedValues.size();
300 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
362 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
301 [](const auto &dataSeriesIt, const auto &expectedValue) {
363 [](const auto &dataSeriesIt, const auto &expectedValue) {
302 return dataSeriesIt.value() == expectedValue;
364 return dataSeriesIt.value() == expectedValue;
303 }));
365 }));
304 }
366 }
367 };
368
369 // For each iteration:
370 // - execute operation
371 // - compare the variables' state to the expected states
372 QFETCH(Iterations, iterations);
373 QFETCH(int, operationDelay);
374 for (const auto &iteration : iterations) {
375 iteration.m_Operation->exec(variableController);
376 QTest::qWait(operationDelay);
377
378 validateRanges(iteration.m_ExpectedRanges);
379 }
380
381 for (const auto &iteration : iterations) {
382 iteration.m_Operation->exec(variableController);
305 }
383 }
384 QTest::qWait(operationDelay);
385 validateRanges(iterations.back().m_ExpectedRanges);
306 }
386 }
307
387
308 QTEST_MAIN(TestVariableSync)
388 QTEST_MAIN(TestVariableSync)
@@ -39,7 +39,6 public:
39 /// Removes a variable from the graph
39 /// Removes a variable from the graph
40 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
40 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
41
41
42 void setRange(std::shared_ptr<Variable> variable, const SqpRange &range);
43 void setYRange(const SqpRange &range);
42 void setYRange(const SqpRange &range);
44 SqpRange graphRange() const noexcept;
43 SqpRange graphRange() const noexcept;
45 void setGraphRange(const SqpRange &range);
44 void setGraphRange(const SqpRange &range);
@@ -54,7 +53,7 public:
54 signals:
53 signals:
55 void synchronize(const SqpRange &range, const SqpRange &oldRange);
54 void synchronize(const SqpRange &range, const SqpRange &oldRange);
56 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
55 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
57 const SqpRange &oldRange, bool synchronise);
56 bool synchronise);
58
57
59 /// Signal emitted when the variable is about to be removed from the graph
58 /// Signal emitted when the variable is about to be removed from the graph
60 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
59 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
@@ -119,14 +119,11 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, S
119
119
120 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
120 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
121
121
122 auto varRange = variable->range();
123
124 this->enableAcquisition(false);
122 this->enableAcquisition(false);
125 this->setGraphRange(range);
123 this->setGraphRange(range);
126 this->enableAcquisition(true);
124 this->enableAcquisition(true);
127
125
128 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, varRange,
126 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
129 false);
130
127
131 emit variableAdded(variable);
128 emit variableAdded(variable);
132 }
129 }
@@ -155,17 +152,6 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable
155 ui->widget->replot();
152 ui->widget->replot();
156 }
153 }
157
154
158 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable, const SqpRange &range)
159 {
160 // Note: in case of different axes that depends on variable, we could start with a code like
161 // that:
162 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
163 // for (auto it = componentsIt.first; it != componentsIt.second;) {
164 // }
165 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
166 ui->widget->replot();
167 }
168
169 void VisualizationGraphWidget::setYRange(const SqpRange &range)
155 void VisualizationGraphWidget::setYRange(const SqpRange &range)
170 {
156 {
171 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
157 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
@@ -282,7 +268,7 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange
282 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
268 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
283 variableUnderGraphVector.push_back(it->first);
269 variableUnderGraphVector.push_back(it->first);
284 }
270 }
285 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange, oldGraphRange,
271 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
286 !impl->m_IsCalibration);
272 !impl->m_IsCalibration);
287
273
288 if (!impl->m_IsCalibration) {
274 if (!impl->m_IsCalibration) {
@@ -153,8 +153,9 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
153 }
153 }
154 case AcquisitionZoomType::PanRight: {
154 case AcquisitionZoomType::PanRight: {
155 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
155 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
156 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
156 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
157 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
157 graphChildRange.m_TStart += deltaRight;
158 graphChildRange.m_TStart += deltaLeft;
158 graphChildRange.m_TEnd += deltaRight;
159 graphChildRange.m_TEnd += deltaRight;
159 qCDebug(LOG_VisualizationZoneWidget())
160 qCDebug(LOG_VisualizationZoneWidget())
160 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
161 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
@@ -163,8 +164,9 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
163 case AcquisitionZoomType::PanLeft: {
164 case AcquisitionZoomType::PanLeft: {
164 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
165 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
166 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
167 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
166 graphChildRange.m_TStart -= deltaLeft;
168 graphChildRange.m_TStart -= deltaLeft;
167 graphChildRange.m_TEnd -= deltaLeft;
169 graphChildRange.m_TEnd -= deltaRight;
168 break;
170 break;
169 }
171 }
170 case AcquisitionZoomType::Unknown: {
172 case AcquisitionZoomType::Unknown: {
@@ -59,7 +59,9 void RescaleAxeOperation::visit(VisualizationGraphWidget *graphWidget)
59 if (graphWidget) {
59 if (graphWidget) {
60 // If the widget contains the variable, rescale it
60 // If the widget contains the variable, rescale it
61 if (impl->m_Variable && graphWidget->contains(*impl->m_Variable)) {
61 if (impl->m_Variable && graphWidget->contains(*impl->m_Variable)) {
62 graphWidget->setRange(impl->m_Variable, impl->m_Range);
62 graphWidget->enableAcquisition(false);
63 graphWidget->setGraphRange(impl->m_Range);
64 graphWidget->enableAcquisition(true);
63 }
65 }
64 }
66 }
65 else {
67 else {
@@ -123,8 +123,7 void TestAmdaAcquisition::testAcquisition()
123
123
124 auto nextSqpR
124 auto nextSqpR
125 = SqpRange{DateUtils::secondsSinceEpoch(tStart), DateUtils::secondsSinceEpoch(tEnd)};
125 = SqpRange{DateUtils::secondsSinceEpoch(tStart), DateUtils::secondsSinceEpoch(tEnd)};
126 vc.onRequestDataLoading(QVector<std::shared_ptr<Variable> >{} << var, nextSqpR,
126 vc.onRequestDataLoading(QVector<std::shared_ptr<Variable> >{} << var, nextSqpR, true);
127 var->range(), true);
128
127
129 QEventLoop loop;
128 QEventLoop loop;
130 QTimer::singleShot(timeToWaitMs, &loop, &QEventLoop::quit);
129 QTimer::singleShot(timeToWaitMs, &loop, &QEventLoop::quit);
@@ -26,6 +26,11 public:
26 void requestDataAborting(QUuid acqIdentifier) override;
26 void requestDataAborting(QUuid acqIdentifier) override;
27
27
28
28
29 /// Provide data
30 std::shared_ptr<IDataSeries> provideDataSeries(const SqpRange &dataRangeRequested,
31 const QVariantHash &data);
32
33
29 private:
34 private:
30 std::shared_ptr<IDataSeries>
35 std::shared_ptr<IDataSeries>
31 retrieveData(QUuid acqIdentifier, const SqpRange &dataRangeRequested, const QVariantHash &data);
36 retrieveData(QUuid acqIdentifier, const SqpRange &dataRangeRequested, const QVariantHash &data);
@@ -145,8 +145,9 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid acqIdentifier,
145 progress = currentProgress;
145 progress = currentProgress;
146
146
147 emit dataProvidedProgress(acqIdentifier, progress);
147 emit dataProvidedProgress(acqIdentifier, progress);
148 qCInfo(LOG_CosinusProvider()) << "TORM: CosinusProvider::retrieveData"
148 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::retrieveData"
149 << QThread::currentThread()->objectName() << progress;
149 << QThread::currentThread()->objectName()
150 << progress;
150 // NOTE: Try to use multithread if possible
151 // NOTE: Try to use multithread if possible
151 }
152 }
152 }
153 }
@@ -179,7 +180,6 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
179 for (const auto &dateTime : qAsConst(times)) {
180 for (const auto &dateTime : qAsConst(times)) {
180 if (m_VariableToEnableProvider[acqIdentifier]) {
181 if (m_VariableToEnableProvider[acqIdentifier]) {
181 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime, parameters.m_Data);
182 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime, parameters.m_Data);
182 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::dataProvided";
183 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
183 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
184 }
184 }
185 }
185 }
@@ -187,7 +187,6 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
187
187
188 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
188 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
189 {
189 {
190 // TODO: Add Mutex
191 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
190 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
192 << QThread::currentThread()->objectName();
191 << QThread::currentThread()->objectName();
193 auto it = m_VariableToEnableProvider.find(acqIdentifier);
192 auto it = m_VariableToEnableProvider.find(acqIdentifier);
@@ -195,7 +194,18 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
195 it.value() = false;
194 it.value() = false;
196 }
195 }
197 else {
196 else {
198 qCWarning(LOG_CosinusProvider())
197 qCDebug(LOG_CosinusProvider())
199 << tr("Aborting progression of inexistant identifier detected !!!");
198 << tr("Aborting progression of inexistant identifier detected !!!");
200 }
199 }
201 }
200 }
201
202 std::shared_ptr<IDataSeries> CosinusProvider::provideDataSeries(const SqpRange &dataRangeRequested,
203 const QVariantHash &data)
204 {
205 auto uid = QUuid::createUuid();
206 m_VariableToEnableProvider[uid] = true;
207 auto dataSeries = this->retrieveData(uid, dataRangeRequested, data);
208
209 m_VariableToEnableProvider.remove(uid);
210 return dataSeries;
211 }
@@ -24,9 +24,6 const auto TESTS_RESOURCES_PATH = QFileInfo{
24 /// Format of dates in data files
24 /// Format of dates in data files
25 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
25 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
26
26
27 /// Delay after each operation on the variable before validating it (in ms)
28 const auto OPERATION_DELAY = 250;
29
30 /**
27 /**
31 * Verifies that the data in the candidate series are identical to the data in the reference series
28 * Verifies that the data in the candidate series are identical to the data in the reference series
32 * in a specific range
29 * in a specific range
@@ -45,6 +42,9 bool checkDataSeries(std::shared_ptr<IDataSeries> candidate, const SqpRange &ran
45
42
46 auto referenceIt = reference->xAxisRange(range.m_TStart, range.m_TEnd);
43 auto referenceIt = reference->xAxisRange(range.m_TStart, range.m_TEnd);
47
44
45 qInfo() << "candidateSize" << std::distance(candidate->cbegin(), candidate->cend());
46 qInfo() << "refSize" << std::distance(referenceIt.first, referenceIt.second);
47
48 return std::equal(candidate->cbegin(), candidate->cend(), referenceIt.first, referenceIt.second,
48 return std::equal(candidate->cbegin(), candidate->cend(), referenceIt.first, referenceIt.second,
49 [](const auto &it1, const auto &it2) {
49 [](const auto &it1, const auto &it2) {
50 // - milliseconds precision for time
50 // - milliseconds precision for time
@@ -54,29 +54,6 bool checkDataSeries(std::shared_ptr<IDataSeries> candidate, const SqpRange &ran
54 });
54 });
55 }
55 }
56
56
57 /// Generates the data series from the reading of a data stream
58 std::shared_ptr<IDataSeries> readDataStream(QTextStream &stream)
59 {
60 std::vector<double> xAxisData, valuesData;
61
62 QString line{};
63 while (stream.readLineInto(&line)) {
64 // Separates date (x-axis data) to value data
65 auto splitLine = line.split('\t');
66 if (splitLine.size() == 2) {
67 // Converts datetime to double
68 auto dateTime = QDateTime::fromString(splitLine[0], DATETIME_FORMAT);
69 dateTime.setTimeSpec(Qt::UTC);
70 xAxisData.push_back(DateUtils::secondsSinceEpoch(dateTime));
71
72 valuesData.push_back(splitLine[1].toDouble());
73 }
74 }
75
76 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
77 Unit{{}, true}, Unit{});
78 }
79
80 } // namespace
57 } // namespace
81
58
82 /**
59 /**
@@ -99,8 +76,9 void TestCosinusAcquisition::testAcquisition_data()
99 // Test structure //
76 // Test structure //
100 // ////////////// //
77 // ////////////// //
101
78
102 QTest::addColumn<QString>("dataFilename"); // File containing expected data of acquisitions
79 QTest::addColumn<SqpRange>("referenceRange"); // Range for generating reference series
103 QTest::addColumn<SqpRange>("initialRange"); // First acquisition
80 QTest::addColumn<SqpRange>("initialRange"); // First acquisition
81 QTest::addColumn<int>("operationDelay"); // Acquisitions to make
104 QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
82 QTest::addColumn<std::vector<SqpRange> >("operations"); // Acquisitions to make
105
83
106 // ////////// //
84 // ////////// //
@@ -113,8 +91,8 void TestCosinusAcquisition::testAcquisition_data()
113 };
91 };
114
92
115 QTest::newRow("cosinus")
93 QTest::newRow("cosinus")
116 << "Cosinus_100Hz_20170101_1200_20170101_1300.txt"
94 << SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)}
117 << SqpRange{dateTime(2017, 1, 1, 12, 30, 0), dateTime(2017, 1, 1, 12, 35, 1)}
95 << SqpRange{dateTime(2017, 1, 1, 12, 30, 0), dateTime(2017, 1, 1, 12, 35, 1)} << 250
118 << std::vector<SqpRange>{
96 << std::vector<SqpRange>{
119 // Pan (jump) left
97 // Pan (jump) left
120 SqpRange{dateTime(2017, 1, 1, 12, 45, 0), dateTime(2017, 1, 1, 12, 50, 0)},
98 SqpRange{dateTime(2017, 1, 1, 12, 45, 0), dateTime(2017, 1, 1, 12, 50, 0)},
@@ -130,55 +108,76 void TestCosinusAcquisition::testAcquisition_data()
130 SqpRange{dateTime(2017, 1, 1, 12, 17, 30), dateTime(2017, 1, 1, 12, 19, 30)},
108 SqpRange{dateTime(2017, 1, 1, 12, 17, 30), dateTime(2017, 1, 1, 12, 19, 30)},
131 // Zoom out
109 // Zoom out
132 SqpRange{dateTime(2017, 1, 1, 12, 12, 30), dateTime(2017, 1, 1, 12, 24, 30)}};
110 SqpRange{dateTime(2017, 1, 1, 12, 12, 30), dateTime(2017, 1, 1, 12, 24, 30)}};
111
112 QTest::newRow("cosinus_big")
113 << SqpRange{dateTime(2017, 1, 1, 1, 0, 0), dateTime(2017, 1, 5, 13, 0, 0)}
114 << SqpRange{dateTime(2017, 1, 2, 6, 30, 0), dateTime(2017, 1, 2, 18, 30, 0)} << 5000
115 << std::vector<SqpRange>{
116 // Pan (jump) left
117 SqpRange{dateTime(2017, 1, 1, 13, 30, 0), dateTime(2017, 1, 1, 18, 30, 0)},
118 // Pan (jump) right
119 SqpRange{dateTime(2017, 1, 3, 4, 30, 0), dateTime(2017, 1, 3, 10, 30, 0)},
120 // Pan (overlay) right
121 SqpRange{dateTime(2017, 1, 3, 8, 30, 0), dateTime(2017, 1, 3, 12, 30, 0)},
122 // Pan (overlay) left
123 SqpRange{dateTime(2017, 1, 2, 8, 30, 0), dateTime(2017, 1, 3, 10, 30, 0)},
124 // Pan (overlay) left
125 SqpRange{dateTime(2017, 1, 1, 12, 30, 0), dateTime(2017, 1, 3, 5, 30, 0)},
126 // Zoom in
127 SqpRange{dateTime(2017, 1, 2, 2, 30, 0), dateTime(2017, 1, 2, 8, 30, 0)},
128 // Zoom out
129 SqpRange{dateTime(2017, 1, 1, 14, 30, 0), dateTime(2017, 1, 3, 12, 30, 0)}};
133 }
130 }
134
131
135 void TestCosinusAcquisition::testAcquisition()
132 void TestCosinusAcquisition::testAcquisition()
136 {
133 {
137 // Retrieves data file
134 // Retrieves reference range
138 QFETCH(QString, dataFilename);
135 QFETCH(SqpRange, referenceRange);
139
136 CosinusProvider referenceProvider{};
140 auto dataFilePath = QFileInfo{TESTS_RESOURCES_PATH, dataFilename}.absoluteFilePath();
137 auto dataSeries = referenceProvider.provideDataSeries(
141 QFile dataFile{dataFilePath};
138 referenceRange, {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 100.}});
142
139
143 if (dataFile.open(QFile::ReadOnly)) {
140 auto end = dataSeries->cend() - 1;
144 // Generates data series to compare with
141 qInfo() << dataSeries->nbPoints() << dataSeries->cbegin()->x() << end->x();
145 QTextStream dataStream{&dataFile};
142
146 auto dataSeries = readDataStream(dataStream);
143 /// Lambda used to validate a variable at each step
147
144 auto validateVariable
148 /// Lambda used to validate a variable at each step
145 = [dataSeries](std::shared_ptr<Variable> variable, const SqpRange &range) {
149 auto validateVariable = [dataSeries](std::shared_ptr<Variable> variable,
146 // Checks that the variable's range has changed
150 const SqpRange &range) {
147 QCOMPARE(variable->range(), range);
151 // Checks that the variable's range has changed
148
152 QCOMPARE(variable->range(), range);
149 // Checks the variable's data series
153
150 QVERIFY(checkDataSeries(variable->dataSeries(), variable->cacheRange(), dataSeries));
154 // Checks the variable's data series
151 };
155 QVERIFY(checkDataSeries(variable->dataSeries(), variable->cacheRange(), dataSeries));
152
156 };
153 // Creates variable
157
154 QFETCH(SqpRange, initialRange);
158 // Creates variable
155 sqpApp->timeController().onTimeToUpdate(initialRange);
159 QFETCH(SqpRange, initialRange);
156 auto provider = std::make_shared<CosinusProvider>();
160 sqpApp->timeController().onTimeToUpdate(initialRange);
157 auto variable = sqpApp->variableController().createVariable(
161 auto provider = std::make_shared<CosinusProvider>();
158 "MMS", {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 100.}}, provider);
162 auto variable = sqpApp->variableController().createVariable(
159
163 "MMS", {{COSINUS_TYPE_KEY, "scalar"}, {COSINUS_FREQUENCY_KEY, 100.}}, provider);
160 QFETCH(int, operationDelay);
164
161 QTest::qWait(operationDelay);
165 QTest::qWait(OPERATION_DELAY);
162 validateVariable(variable, initialRange);
166 validateVariable(variable, initialRange);
163
167
164 // Makes operations on the variable
168 // Makes operations on the variable
165 QFETCH(std::vector<SqpRange>, operations);
169 QFETCH(std::vector<SqpRange>, operations);
166 for (const auto &operation : operations) {
170 for (const auto &operation : operations) {
167 // Asks request on the variable and waits during its execution
171 // Asks request on the variable and waits during its execution
168 sqpApp->variableController().onRequestDataLoading({variable}, operation, true);
172 sqpApp->variableController().onRequestDataLoading({variable}, operation,
169
173 variable->range(), true);
170 QTest::qWait(operationDelay);
174
171 validateVariable(variable, operation);
175 QTest::qWait(OPERATION_DELAY);
176 validateVariable(variable, operation);
177 }
178 }
172 }
179 else {
173
180 QFAIL("Can't read input data file");
174
175 for (const auto &operation : operations) {
176 // Asks request on the variable and waits during its execution
177 sqpApp->variableController().onRequestDataLoading({variable}, operation, true);
181 }
178 }
179 QTest::qWait(operationDelay);
180 validateVariable(variable, operations.back());
182 }
181 }
183
182
184 int main(int argc, char *argv[])
183 int main(int argc, char *argv[])
General Comments 0
You need to be logged in to leave comments. Login now