##// END OF EJS Templates
Fix bug in synchro for operation (jump + rescaling)
perrinel -
r814:1fc2e26b3db5
parent child
Show More
@@ -1,890 +1,896
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableAcquisitionWorker.h>
2 #include <Variable/VariableAcquisitionWorker.h>
3 #include <Variable/VariableCacheStrategy.h>
3 #include <Variable/VariableCacheStrategy.h>
4 #include <Variable/VariableCacheStrategyFactory.h>
4 #include <Variable/VariableCacheStrategyFactory.h>
5 #include <Variable/VariableController.h>
5 #include <Variable/VariableController.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7 #include <Variable/VariableSynchronizationGroup.h>
7 #include <Variable/VariableSynchronizationGroup.h>
8
8
9 #include <Data/DataProviderParameters.h>
9 #include <Data/DataProviderParameters.h>
10 #include <Data/IDataProvider.h>
10 #include <Data/IDataProvider.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <Data/VariableRequest.h>
12 #include <Data/VariableRequest.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14
14
15 #include <QMutex>
15 #include <QMutex>
16 #include <QThread>
16 #include <QThread>
17 #include <QUuid>
17 #include <QUuid>
18 #include <QtCore/QItemSelectionModel>
18 #include <QtCore/QItemSelectionModel>
19
19
20 #include <deque>
20 #include <deque>
21 #include <set>
21 #include <set>
22 #include <unordered_map>
22 #include <unordered_map>
23
23
24 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
24 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
25
25
26 namespace {
26 namespace {
27
27
28 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
28 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
29 const SqpRange &oldGraphRange)
29 const SqpRange &oldGraphRange)
30 {
30 {
31 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
31 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
32
32
33 auto varRangeRequested = varRange;
33 auto varRangeRequested = varRange;
34 switch (zoomType) {
34 switch (zoomType) {
35 case AcquisitionZoomType::ZoomIn: {
35 case AcquisitionZoomType::ZoomIn: {
36 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
36 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
37 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
37 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
38 varRangeRequested.m_TStart += deltaLeft;
38 varRangeRequested.m_TStart += deltaLeft;
39 varRangeRequested.m_TEnd -= deltaRight;
39 varRangeRequested.m_TEnd -= deltaRight;
40 break;
40 break;
41 }
41 }
42
42
43 case AcquisitionZoomType::ZoomOut: {
43 case AcquisitionZoomType::ZoomOut: {
44 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
44 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
45 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
45 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
46 varRangeRequested.m_TStart -= deltaLeft;
46 varRangeRequested.m_TStart -= deltaLeft;
47 varRangeRequested.m_TEnd += deltaRight;
47 varRangeRequested.m_TEnd += deltaRight;
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: {
63 qCCritical(LOG_VariableController())
65 qCCritical(LOG_VariableController())
64 << VariableController::tr("Impossible to synchronize: zoom type unknown");
66 << VariableController::tr("Impossible to synchronize: zoom type unknown");
65 break;
67 break;
66 }
68 }
67 default:
69 default:
68 qCCritical(LOG_VariableController()) << VariableController::tr(
70 qCCritical(LOG_VariableController()) << VariableController::tr(
69 "Impossible to synchronize: zoom type not take into account");
71 "Impossible to synchronize: zoom type not take into account");
70 // No action
72 // No action
71 break;
73 break;
72 }
74 }
73
75
74 return varRangeRequested;
76 return varRangeRequested;
75 }
77 }
76 }
78 }
77
79
78 struct VariableController::VariableControllerPrivate {
80 struct VariableController::VariableControllerPrivate {
79 explicit VariableControllerPrivate(VariableController *parent)
81 explicit VariableControllerPrivate(VariableController *parent)
80 : m_WorkingMutex{},
82 : m_WorkingMutex{},
81 m_VariableModel{new VariableModel{parent}},
83 m_VariableModel{new VariableModel{parent}},
82 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
84 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
83 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
85 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
84 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
86 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
85 CacheStrategy::SingleThreshold)},
87 CacheStrategy::SingleThreshold)},
86 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
88 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
87 q{parent}
89 q{parent}
88 {
90 {
89
91
90 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
92 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
91 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
93 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
92 }
94 }
93
95
94
96
95 virtual ~VariableControllerPrivate()
97 virtual ~VariableControllerPrivate()
96 {
98 {
97 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
99 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
98 m_VariableAcquisitionWorkerThread.quit();
100 m_VariableAcquisitionWorkerThread.quit();
99 m_VariableAcquisitionWorkerThread.wait();
101 m_VariableAcquisitionWorkerThread.wait();
100 }
102 }
101
103
102
104
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,
108 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
107 const SqpRange &dateTime);
109 const SqpRange &dateTime);
108
110
109 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
111 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
110 std::shared_ptr<IDataSeries>
112 std::shared_ptr<IDataSeries>
111 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
113 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
112
114
113 void registerProvider(std::shared_ptr<IDataProvider> provider);
115 void registerProvider(std::shared_ptr<IDataProvider> provider);
114
116
115 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
117 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
116 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
118 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
117 void updateVariableRequest(QUuid varRequestId);
119 void updateVariableRequest(QUuid varRequestId);
118 void cancelVariableRequest(QUuid varRequestId);
120 void cancelVariableRequest(QUuid varRequestId);
119
121
120 SqpRange getLastRequestedRange(QUuid varId);
122 SqpRange getLastRequestedRange(QUuid varId);
121
123
122 QMutex m_WorkingMutex;
124 QMutex m_WorkingMutex;
123 /// Variable model. The VariableController has the ownership
125 /// Variable model. The VariableController has the ownership
124 VariableModel *m_VariableModel;
126 VariableModel *m_VariableModel;
125 QItemSelectionModel *m_VariableSelectionModel;
127 QItemSelectionModel *m_VariableSelectionModel;
126
128
127
129
128 TimeController *m_TimeController{nullptr};
130 TimeController *m_TimeController{nullptr};
129 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
131 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
130 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
132 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
131 QThread m_VariableAcquisitionWorkerThread;
133 QThread m_VariableAcquisitionWorkerThread;
132
134
133 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
135 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
134 m_VariableToProviderMap;
136 m_VariableToProviderMap;
135 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
137 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
136 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
138 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
137 m_GroupIdToVariableSynchronizationGroupMap;
139 m_GroupIdToVariableSynchronizationGroupMap;
138 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
140 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
139 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
141 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
140
142
141 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
143 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
142
144
143 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
145 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
144
146
145
147
146 VariableController *q;
148 VariableController *q;
147 };
149 };
148
150
149
151
150 VariableController::VariableController(QObject *parent)
152 VariableController::VariableController(QObject *parent)
151 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
153 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
152 {
154 {
153 qCDebug(LOG_VariableController()) << tr("VariableController construction")
155 qCDebug(LOG_VariableController()) << tr("VariableController construction")
154 << QThread::currentThread();
156 << QThread::currentThread();
155
157
156 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
158 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
157 &VariableController::onAbortProgressRequested);
159 &VariableController::onAbortProgressRequested);
158
160
159 connect(impl->m_VariableAcquisitionWorker.get(),
161 connect(impl->m_VariableAcquisitionWorker.get(),
160 &VariableAcquisitionWorker::variableCanceledRequested, this,
162 &VariableAcquisitionWorker::variableCanceledRequested, this,
161 &VariableController::onAbortAcquisitionRequested);
163 &VariableController::onAbortAcquisitionRequested);
162
164
163 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
165 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
164 &VariableController::onDataProvided);
166 &VariableController::onDataProvided);
165 connect(impl->m_VariableAcquisitionWorker.get(),
167 connect(impl->m_VariableAcquisitionWorker.get(),
166 &VariableAcquisitionWorker::variableRequestInProgress, this,
168 &VariableAcquisitionWorker::variableRequestInProgress, this,
167 &VariableController::onVariableRetrieveDataInProgress);
169 &VariableController::onVariableRetrieveDataInProgress);
168
170
169
171
170 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
172 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
171 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
173 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
172 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
174 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
173 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
175 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
174
176
175
177
176 impl->m_VariableAcquisitionWorkerThread.start();
178 impl->m_VariableAcquisitionWorkerThread.start();
177 }
179 }
178
180
179 VariableController::~VariableController()
181 VariableController::~VariableController()
180 {
182 {
181 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
183 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
182 << QThread::currentThread();
184 << QThread::currentThread();
183 this->waitForFinish();
185 this->waitForFinish();
184 }
186 }
185
187
186 VariableModel *VariableController::variableModel() noexcept
188 VariableModel *VariableController::variableModel() noexcept
187 {
189 {
188 return impl->m_VariableModel;
190 return impl->m_VariableModel;
189 }
191 }
190
192
191 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
193 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
192 {
194 {
193 return impl->m_VariableSelectionModel;
195 return impl->m_VariableSelectionModel;
194 }
196 }
195
197
196 void VariableController::setTimeController(TimeController *timeController) noexcept
198 void VariableController::setTimeController(TimeController *timeController) noexcept
197 {
199 {
198 impl->m_TimeController = timeController;
200 impl->m_TimeController = timeController;
199 }
201 }
200
202
201 std::shared_ptr<Variable>
203 std::shared_ptr<Variable>
202 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
204 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
203 {
205 {
204 if (impl->m_VariableModel->containsVariable(variable)) {
206 if (impl->m_VariableModel->containsVariable(variable)) {
205 // Clones variable
207 // Clones variable
206 auto duplicate = variable->clone();
208 auto duplicate = variable->clone();
207
209
208 // Adds clone to model
210 // Adds clone to model
209 impl->m_VariableModel->addVariable(duplicate);
211 impl->m_VariableModel->addVariable(duplicate);
210
212
211 // Generates clone identifier
213 // Generates clone identifier
212 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
214 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
213
215
214 // Registers provider
216 // Registers provider
215 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
217 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
216 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
218 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
217
219
218 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
220 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
219 if (duplicateProvider) {
221 if (duplicateProvider) {
220 impl->registerProvider(duplicateProvider);
222 impl->registerProvider(duplicateProvider);
221 }
223 }
222
224
223 return duplicate;
225 return duplicate;
224 }
226 }
225 else {
227 else {
226 qCCritical(LOG_VariableController())
228 qCCritical(LOG_VariableController())
227 << tr("Can't create duplicate of variable %1: variable not registered in the model")
229 << tr("Can't create duplicate of variable %1: variable not registered in the model")
228 .arg(variable->name());
230 .arg(variable->name());
229 return nullptr;
231 return nullptr;
230 }
232 }
231 }
233 }
232
234
233 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
235 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
234 {
236 {
235 if (!variable) {
237 if (!variable) {
236 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
238 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
237 return;
239 return;
238 }
240 }
239
241
240 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
242 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
241 // make some treatments before the deletion
243 // make some treatments before the deletion
242 emit variableAboutToBeDeleted(variable);
244 emit variableAboutToBeDeleted(variable);
243
245
244 // Deletes identifier
246 // Deletes identifier
245 impl->m_VariableToIdentifierMap.erase(variable);
247 impl->m_VariableToIdentifierMap.erase(variable);
246
248
247 // Deletes provider
249 // Deletes provider
248 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
250 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
249 qCDebug(LOG_VariableController())
251 qCDebug(LOG_VariableController())
250 << tr("Number of providers deleted for variable %1: %2")
252 << tr("Number of providers deleted for variable %1: %2")
251 .arg(variable->name(), QString::number(nbProvidersDeleted));
253 .arg(variable->name(), QString::number(nbProvidersDeleted));
252
254
253
255
254 // Deletes from model
256 // Deletes from model
255 impl->m_VariableModel->deleteVariable(variable);
257 impl->m_VariableModel->deleteVariable(variable);
256 }
258 }
257
259
258 void VariableController::deleteVariables(
260 void VariableController::deleteVariables(
259 const QVector<std::shared_ptr<Variable> > &variables) noexcept
261 const QVector<std::shared_ptr<Variable> > &variables) noexcept
260 {
262 {
261 for (auto variable : qAsConst(variables)) {
263 for (auto variable : qAsConst(variables)) {
262 deleteVariable(variable);
264 deleteVariable(variable);
263 }
265 }
264 }
266 }
265
267
266 std::shared_ptr<Variable>
268 std::shared_ptr<Variable>
267 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
269 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
268 std::shared_ptr<IDataProvider> provider) noexcept
270 std::shared_ptr<IDataProvider> provider) noexcept
269 {
271 {
270 if (!impl->m_TimeController) {
272 if (!impl->m_TimeController) {
271 qCCritical(LOG_VariableController())
273 qCCritical(LOG_VariableController())
272 << tr("Impossible to create variable: The time controller is null");
274 << tr("Impossible to create variable: The time controller is null");
273 return nullptr;
275 return nullptr;
274 }
276 }
275
277
276 auto range = impl->m_TimeController->dateTime();
278 auto range = impl->m_TimeController->dateTime();
277
279
278 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
280 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
279 auto identifier = QUuid::createUuid();
281 auto identifier = QUuid::createUuid();
280
282
281 // store the provider
283 // store the provider
282 impl->registerProvider(provider);
284 impl->registerProvider(provider);
283
285
284 // Associate the provider
286 // Associate the provider
285 impl->m_VariableToProviderMap[newVariable] = provider;
287 impl->m_VariableToProviderMap[newVariable] = provider;
286 qCInfo(LOG_VariableController()) << "createVariable: " << identifier;
288 qCInfo(LOG_VariableController()) << "createVariable: " << identifier;
287 impl->m_VariableToIdentifierMap[newVariable] = identifier;
289 impl->m_VariableToIdentifierMap[newVariable] = identifier;
288
290
289
291
290 auto varRequestId = QUuid::createUuid();
292 auto varRequestId = QUuid::createUuid();
291 impl->processRequest(newVariable, range, varRequestId);
293 impl->processRequest(newVariable, range, varRequestId);
292 impl->updateVariableRequest(varRequestId);
294 impl->updateVariableRequest(varRequestId);
293
295
294 return newVariable;
296 return newVariable;
295 }
297 }
296 }
298 }
297
299
298 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
300 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
299 {
301 {
300 // TODO check synchronisation and Rescale
302 // TODO check synchronisation and Rescale
301 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
303 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
302 << QThread::currentThread()->objectName();
304 << QThread::currentThread()->objectName();
303 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
305 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
304 auto varRequestId = QUuid::createUuid();
306 auto varRequestId = QUuid::createUuid();
305
307
306 for (const auto &selectedRow : qAsConst(selectedRows)) {
308 for (const auto &selectedRow : qAsConst(selectedRows)) {
307 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
309 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
308 selectedVariable->setRange(dateTime);
310 selectedVariable->setRange(dateTime);
309 impl->processRequest(selectedVariable, dateTime, varRequestId);
311 impl->processRequest(selectedVariable, dateTime, varRequestId);
310
312
311 // notify that rescale operation has to be done
313 // notify that rescale operation has to be done
312 emit rangeChanged(selectedVariable, dateTime);
314 emit rangeChanged(selectedVariable, dateTime);
313 }
315 }
314 }
316 }
315 impl->updateVariableRequest(varRequestId);
317 impl->updateVariableRequest(varRequestId);
316 }
318 }
317
319
318 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
320 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
319 const SqpRange &cacheRangeRequested,
321 const SqpRange &cacheRangeRequested,
320 QVector<AcquisitionDataPacket> dataAcquired)
322 QVector<AcquisitionDataPacket> dataAcquired)
321 {
323 {
322 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
324 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
323 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
325 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
324 if (!varRequestId.isNull()) {
326 if (!varRequestId.isNull()) {
325 impl->updateVariableRequest(varRequestId);
327 impl->updateVariableRequest(varRequestId);
326 }
328 }
327 }
329 }
328
330
329 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
331 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
330 {
332 {
331 qCDebug(LOG_VariableController())
333 qCDebug(LOG_VariableController())
332 << "TORM: variableController::onVariableRetrieveDataInProgress"
334 << "TORM: variableController::onVariableRetrieveDataInProgress"
333 << QThread::currentThread()->objectName() << progress;
335 << QThread::currentThread()->objectName() << progress;
334 if (auto var = impl->findVariable(identifier)) {
336 if (auto var = impl->findVariable(identifier)) {
335 impl->m_VariableModel->setDataProgress(var, progress);
337 impl->m_VariableModel->setDataProgress(var, progress);
336 }
338 }
337 else {
339 else {
338 qCCritical(LOG_VariableController())
340 qCCritical(LOG_VariableController())
339 << tr("Impossible to notify progression of a null variable");
341 << tr("Impossible to notify progression of a null variable");
340 }
342 }
341 }
343 }
342
344
343 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
345 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
344 {
346 {
345 auto it = impl->m_VariableToIdentifierMap.find(variable);
347 auto it = impl->m_VariableToIdentifierMap.find(variable);
346 if (it != impl->m_VariableToIdentifierMap.cend()) {
348 if (it != impl->m_VariableToIdentifierMap.cend()) {
347 impl->m_VariableAcquisitionWorker->abortProgressRequested(it->second);
349 impl->m_VariableAcquisitionWorker->abortProgressRequested(it->second);
348
350
349 QUuid varRequestId;
351 QUuid varRequestId;
350 auto varIdToVarRequestIdQueueMapIt = impl->m_VarIdToVarRequestIdQueueMap.find(it->second);
352 auto varIdToVarRequestIdQueueMapIt = impl->m_VarIdToVarRequestIdQueueMap.find(it->second);
351 if (varIdToVarRequestIdQueueMapIt != impl->m_VarIdToVarRequestIdQueueMap.cend()) {
353 if (varIdToVarRequestIdQueueMapIt != impl->m_VarIdToVarRequestIdQueueMap.cend()) {
352 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
354 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
353 varRequestId = varRequestIdQueue.front();
355 varRequestId = varRequestIdQueue.front();
354 impl->cancelVariableRequest(varRequestId);
356 impl->cancelVariableRequest(varRequestId);
355
357
356 // Finish the progression for the request
358 // Finish the progression for the request
357 impl->m_VariableModel->setDataProgress(variable, 0.0);
359 impl->m_VariableModel->setDataProgress(variable, 0.0);
358 }
360 }
359 else {
361 else {
360 qCWarning(LOG_VariableController())
362 qCWarning(LOG_VariableController())
361 << tr("Aborting progression of inexistant variable request detected !!!")
363 << tr("Aborting progression of inexistant variable request detected !!!")
362 << QThread::currentThread()->objectName();
364 << QThread::currentThread()->objectName();
363 }
365 }
364 }
366 }
365 else {
367 else {
366 qCWarning(LOG_VariableController())
368 qCWarning(LOG_VariableController())
367 << tr("Aborting progression of inexistant variable detected !!!")
369 << tr("Aborting progression of inexistant variable detected !!!")
368 << QThread::currentThread()->objectName();
370 << QThread::currentThread()->objectName();
369 }
371 }
370 }
372 }
371
373
372 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
374 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
373 {
375 {
374 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
376 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
375 << QThread::currentThread()->objectName() << vIdentifier;
377 << QThread::currentThread()->objectName() << vIdentifier;
376
378
377 if (auto var = impl->findVariable(vIdentifier)) {
379 if (auto var = impl->findVariable(vIdentifier)) {
378 this->onAbortProgressRequested(var);
380 this->onAbortProgressRequested(var);
379 }
381 }
380 else {
382 else {
381 qCCritical(LOG_VariableController())
383 qCCritical(LOG_VariableController())
382 << tr("Impossible to abort Acquisition Requestof a null variable");
384 << tr("Impossible to abort Acquisition Requestof a null variable");
383 }
385 }
384 }
386 }
385
387
386 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
388 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
387 {
389 {
388 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
390 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
389 << QThread::currentThread()->objectName()
391 << QThread::currentThread()->objectName()
390 << synchronizationGroupId;
392 << synchronizationGroupId;
391 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
393 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
392 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
394 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
393 std::make_pair(synchronizationGroupId, vSynchroGroup));
395 std::make_pair(synchronizationGroupId, vSynchroGroup));
394 }
396 }
395
397
396 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
398 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
397 {
399 {
398 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
400 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
399 }
401 }
400
402
401 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
403 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
402 QUuid synchronizationGroupId)
404 QUuid synchronizationGroupId)
403
405
404 {
406 {
405 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
407 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
406 << synchronizationGroupId;
408 << synchronizationGroupId;
407 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
409 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
408 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
410 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
409 auto groupIdToVSGIt
411 auto groupIdToVSGIt
410 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
412 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
411 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
413 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
412 impl->m_VariableIdGroupIdMap.insert(
414 impl->m_VariableIdGroupIdMap.insert(
413 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
415 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
414 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
416 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
415 }
417 }
416 else {
418 else {
417 qCCritical(LOG_VariableController())
419 qCCritical(LOG_VariableController())
418 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
420 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
419 << variable->name();
421 << variable->name();
420 }
422 }
421 }
423 }
422 else {
424 else {
423 qCCritical(LOG_VariableController())
425 qCCritical(LOG_VariableController())
424 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
426 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
425 }
427 }
426 }
428 }
427
429
428 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
430 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
429 QUuid synchronizationGroupId)
431 QUuid synchronizationGroupId)
430 {
432 {
431 // Gets variable id
433 // Gets variable id
432 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
434 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
433 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
435 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
434 qCCritical(LOG_VariableController())
436 qCCritical(LOG_VariableController())
435 << tr("Can't desynchronize variable %1: variable identifier not found")
437 << tr("Can't desynchronize variable %1: variable identifier not found")
436 .arg(variable->name());
438 .arg(variable->name());
437 return;
439 return;
438 }
440 }
439
441
440 // Gets synchronization group
442 // Gets synchronization group
441 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
443 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
442 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
444 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
443 qCCritical(LOG_VariableController())
445 qCCritical(LOG_VariableController())
444 << tr("Can't desynchronize variable %1: unknown synchronization group")
446 << tr("Can't desynchronize variable %1: unknown synchronization group")
445 .arg(variable->name());
447 .arg(variable->name());
446 return;
448 return;
447 }
449 }
448
450
449 auto variableId = variableIt->second;
451 auto variableId = variableIt->second;
450
452
451 // Removes variable from synchronization group
453 // Removes variable from synchronization group
452 auto synchronizationGroup = groupIt->second;
454 auto synchronizationGroup = groupIt->second;
453 synchronizationGroup->removeVariableId(variableId);
455 synchronizationGroup->removeVariableId(variableId);
454
456
455 // Removes link between variable and synchronization group
457 // Removes link between variable and synchronization group
456 impl->m_VariableIdGroupIdMap.erase(variableId);
458 impl->m_VariableIdGroupIdMap.erase(variableId);
457 }
459 }
458
460
459 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
461 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
460 const SqpRange &range, const SqpRange &oldRange,
462 const SqpRange &range, const SqpRange &oldRange,
461 bool synchronise)
463 bool synchronise)
462 {
464 {
463 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
465 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
464
466
465 // we want to load data of the variable for the dateTime.
467 // we want to load data of the variable for the dateTime.
466 // First we check if the cache contains some of them.
468 // First we check if the cache contains some of them.
467 // For the other, we ask the provider to give them.
469 // For the other, we ask the provider to give them.
468
470
469 auto varRequestId = QUuid::createUuid();
471 auto varRequestId = QUuid::createUuid();
470 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
472 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
471 << QThread::currentThread()->objectName() << varRequestId;
473 << QThread::currentThread()->objectName() << varRequestId;
472
474
473 for (const auto &var : variables) {
475 for (const auto &var : variables) {
474 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
476 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
475 impl->processRequest(var, range, varRequestId);
477 impl->processRequest(var, range, varRequestId);
476 }
478 }
477
479
478 if (synchronise) {
480 if (synchronise) {
479 // Get the group ids
481 // Get the group ids
480 qCDebug(LOG_VariableController())
482 qCDebug(LOG_VariableController())
481 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
483 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
482 auto groupIds = std::set<QUuid>{};
484 auto groupIds = std::set<QUuid>{};
483 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
485 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
484 for (const auto &var : variables) {
486 for (const auto &var : variables) {
485 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
487 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
486 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
488 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
487 auto vId = varToVarIdIt->second;
489 auto vId = varToVarIdIt->second;
488 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
490 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
489 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
491 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
490 auto gId = varIdToGroupIdIt->second;
492 auto gId = varIdToGroupIdIt->second;
491 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
493 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
492 if (groupIds.find(gId) == groupIds.cend()) {
494 if (groupIds.find(gId) == groupIds.cend()) {
493 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
495 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
494 groupIds.insert(gId);
496 groupIds.insert(gId);
495 }
497 }
496 }
498 }
497 }
499 }
498 }
500 }
499
501
500 // We assume here all group ids exist
502 // We assume here all group ids exist
501 for (const auto &gId : groupIds) {
503 for (const auto &gId : groupIds) {
502 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
504 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
503 auto vSyncIds = vSynchronizationGroup->getIds();
505 auto vSyncIds = vSynchronizationGroup->getIds();
504 qCDebug(LOG_VariableController()) << "Var in synchro group ";
506 qCDebug(LOG_VariableController()) << "Var in synchro group ";
505 for (auto vId : vSyncIds) {
507 for (auto vId : vSyncIds) {
506 auto var = impl->findVariable(vId);
508 auto var = impl->findVariable(vId);
507
509
508 // Don't process already processed var
510 // Don't process already processed var
509 if (!variables.contains(var)) {
511 if (!variables.contains(var)) {
510 if (var != nullptr) {
512 if (var != nullptr) {
511 qCDebug(LOG_VariableController()) << "processRequest synchro for"
513 qCDebug(LOG_VariableController()) << "processRequest synchro for"
512 << var->name();
514 << var->name();
513 auto vSyncRangeRequested = computeSynchroRangeRequested(
515 auto vSyncRangeRequested = computeSynchroRangeRequested(
514 var->range(), range, groupIdToOldRangeMap.at(gId));
516 var->range(), range, groupIdToOldRangeMap.at(gId));
515 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
517 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
516 impl->processRequest(var, vSyncRangeRequested, varRequestId);
518 impl->processRequest(var, vSyncRangeRequested, varRequestId);
517 }
519 }
518 else {
520 else {
519 qCCritical(LOG_VariableController())
521 qCCritical(LOG_VariableController())
520
522
521 << tr("Impossible to synchronize a null variable");
523 << tr("Impossible to synchronize a null variable");
522 }
524 }
523 }
525 }
524 }
526 }
525 }
527 }
526 }
528 }
527
529
528 impl->updateVariableRequest(varRequestId);
530 impl->updateVariableRequest(varRequestId);
529 }
531 }
530
532
531
533
532 void VariableController::initialize()
534 void VariableController::initialize()
533 {
535 {
534 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
536 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
535 impl->m_WorkingMutex.lock();
537 impl->m_WorkingMutex.lock();
536 qCDebug(LOG_VariableController()) << tr("VariableController init END");
538 qCDebug(LOG_VariableController()) << tr("VariableController init END");
537 }
539 }
538
540
539 void VariableController::finalize()
541 void VariableController::finalize()
540 {
542 {
541 impl->m_WorkingMutex.unlock();
543 impl->m_WorkingMutex.unlock();
542 }
544 }
543
545
544 void VariableController::waitForFinish()
546 void VariableController::waitForFinish()
545 {
547 {
546 QMutexLocker locker{&impl->m_WorkingMutex};
548 QMutexLocker locker{&impl->m_WorkingMutex};
547 }
549 }
548
550
549 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
551 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
550 {
552 {
551 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
553 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
552 auto zoomType = AcquisitionZoomType::Unknown;
554 auto zoomType = AcquisitionZoomType::Unknown;
553 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
555 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
556 qCCritical(LOG_VariableController()) << "zoomtype: ZoomOut";
554 zoomType = AcquisitionZoomType::ZoomOut;
557 zoomType = AcquisitionZoomType::ZoomOut;
555 }
558 }
556 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
559 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
560 qCCritical(LOG_VariableController()) << "zoomtype: PanRight";
557 zoomType = AcquisitionZoomType::PanRight;
561 zoomType = AcquisitionZoomType::PanRight;
558 }
562 }
559 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
563 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
564 qCCritical(LOG_VariableController()) << "zoomtype: PanLeft";
560 zoomType = AcquisitionZoomType::PanLeft;
565 zoomType = AcquisitionZoomType::PanLeft;
561 }
566 }
562 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
567 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
568 qCCritical(LOG_VariableController()) << "zoomtype: ZoomIn";
563 zoomType = AcquisitionZoomType::ZoomIn;
569 zoomType = AcquisitionZoomType::ZoomIn;
564 }
570 }
565 else {
571 else {
566 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
572 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
567 }
573 }
568 return zoomType;
574 return zoomType;
569 }
575 }
570
576
571 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
577 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
572 const SqpRange &rangeRequested,
578 const SqpRange &rangeRequested,
573 QUuid varRequestId)
579 QUuid varRequestId)
574 {
580 {
575 auto varRequest = VariableRequest{};
581 auto varRequest = VariableRequest{};
576
582
577 auto it = m_VariableToIdentifierMap.find(var);
583 auto it = m_VariableToIdentifierMap.find(var);
578 if (it != m_VariableToIdentifierMap.cend()) {
584 if (it != m_VariableToIdentifierMap.cend()) {
579
585
580 auto varId = it->second;
586 auto varId = it->second;
581
587
582 auto oldRange = getLastRequestedRange(varId);
588 auto oldRange = getLastRequestedRange(varId);
583
589
584 // check for update oldRange to the last request range.
590 // check for update oldRange to the last request range.
585 if (oldRange == INVALID_RANGE) {
591 if (oldRange == INVALID_RANGE) {
586 oldRange = var->range();
592 oldRange = var->range();
587 }
593 }
588
594
589 auto varStrategyRangesRequested
595 auto varStrategyRangesRequested
590 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
596 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
591
597
592 auto notInCacheRangeList = QVector<SqpRange>{varStrategyRangesRequested.second};
598 auto notInCacheRangeList = QVector<SqpRange>{varStrategyRangesRequested.second};
593 auto inCacheRangeList = QVector<SqpRange>{};
599 auto inCacheRangeList = QVector<SqpRange>{};
594 if (m_VarIdToVarRequestIdQueueMap.find(varId) == m_VarIdToVarRequestIdQueueMap.cend()) {
600 if (m_VarIdToVarRequestIdQueueMap.find(varId) == m_VarIdToVarRequestIdQueueMap.cend()) {
595 notInCacheRangeList
601 notInCacheRangeList
596 = var->provideNotInCacheRangeList(varStrategyRangesRequested.second);
602 = var->provideNotInCacheRangeList(varStrategyRangesRequested.second);
597 inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second);
603 inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second);
598 }
604 }
599
605
600 if (!notInCacheRangeList.empty()) {
606 if (!notInCacheRangeList.empty()) {
601 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
607 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
602 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
608 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
603
609
604 // store VarRequest
610 // store VarRequest
605 storeVariableRequest(varId, varRequestId, varRequest);
611 storeVariableRequest(varId, varRequestId, varRequest);
606
612
607 auto varProvider = m_VariableToProviderMap.at(var);
613 auto varProvider = m_VariableToProviderMap.at(var);
608 if (varProvider != nullptr) {
614 if (varProvider != nullptr) {
609 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
615 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
610 varRequestId, varId, varStrategyRangesRequested.first,
616 varRequestId, varId, varStrategyRangesRequested.first,
611 varStrategyRangesRequested.second,
617 varStrategyRangesRequested.second,
612 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
618 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
613 varProvider);
619 varProvider);
614
620
615 if (!varRequestIdCanceled.isNull()) {
621 if (!varRequestIdCanceled.isNull()) {
616 qCDebug(LOG_VariableAcquisitionWorker()) << tr("vsarRequestIdCanceled: ")
622 qCDebug(LOG_VariableAcquisitionWorker()) << tr("vsarRequestIdCanceled: ")
617 << varRequestIdCanceled;
623 << varRequestIdCanceled;
618 cancelVariableRequest(varRequestIdCanceled);
624 cancelVariableRequest(varRequestIdCanceled);
619 }
625 }
620 }
626 }
621 else {
627 else {
622 qCCritical(LOG_VariableController())
628 qCCritical(LOG_VariableController())
623 << "Impossible to provide data with a null provider";
629 << "Impossible to provide data with a null provider";
624 }
630 }
625
631
626 if (!inCacheRangeList.empty()) {
632 if (!inCacheRangeList.empty()) {
627 emit q->updateVarDisplaying(var, inCacheRangeList.first());
633 emit q->updateVarDisplaying(var, inCacheRangeList.first());
628 }
634 }
629 }
635 }
630 else {
636 else {
631 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
637 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
632 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
638 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
633 // store VarRequest
639 // store VarRequest
634 storeVariableRequest(varId, varRequestId, varRequest);
640 storeVariableRequest(varId, varRequestId, varRequest);
635 acceptVariableRequest(
641 acceptVariableRequest(
636 varId, var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
642 varId, var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
637 }
643 }
638 }
644 }
639 }
645 }
640
646
641 std::shared_ptr<Variable>
647 std::shared_ptr<Variable>
642 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
648 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
643 {
649 {
644 std::shared_ptr<Variable> var;
650 std::shared_ptr<Variable> var;
645 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
651 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
646
652
647 auto end = m_VariableToIdentifierMap.cend();
653 auto end = m_VariableToIdentifierMap.cend();
648 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
654 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
649 if (it != end) {
655 if (it != end) {
650 var = it->first;
656 var = it->first;
651 }
657 }
652 else {
658 else {
653 qCCritical(LOG_VariableController())
659 qCCritical(LOG_VariableController())
654 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
660 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
655 }
661 }
656
662
657 return var;
663 return var;
658 }
664 }
659
665
660 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
666 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
661 const QVector<AcquisitionDataPacket> acqDataPacketVector)
667 const QVector<AcquisitionDataPacket> acqDataPacketVector)
662 {
668 {
663 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
669 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
664 << acqDataPacketVector.size();
670 << acqDataPacketVector.size();
665 std::shared_ptr<IDataSeries> dataSeries;
671 std::shared_ptr<IDataSeries> dataSeries;
666 if (!acqDataPacketVector.isEmpty()) {
672 if (!acqDataPacketVector.isEmpty()) {
667 dataSeries = acqDataPacketVector[0].m_DateSeries;
673 dataSeries = acqDataPacketVector[0].m_DateSeries;
668 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
674 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
669 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
675 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
670 }
676 }
671 }
677 }
672 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
678 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
673 << acqDataPacketVector.size();
679 << acqDataPacketVector.size();
674 return dataSeries;
680 return dataSeries;
675 }
681 }
676
682
677 void VariableController::VariableControllerPrivate::registerProvider(
683 void VariableController::VariableControllerPrivate::registerProvider(
678 std::shared_ptr<IDataProvider> provider)
684 std::shared_ptr<IDataProvider> provider)
679 {
685 {
680 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
686 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
681 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
687 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
682 << provider->objectName();
688 << provider->objectName();
683 m_ProviderSet.insert(provider);
689 m_ProviderSet.insert(provider);
684 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
690 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
685 &VariableAcquisitionWorker::onVariableDataAcquired);
691 &VariableAcquisitionWorker::onVariableDataAcquired);
686 connect(provider.get(), &IDataProvider::dataProvidedProgress,
692 connect(provider.get(), &IDataProvider::dataProvidedProgress,
687 m_VariableAcquisitionWorker.get(),
693 m_VariableAcquisitionWorker.get(),
688 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
694 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
689 connect(provider.get(), &IDataProvider::dataProvidedFailed,
695 connect(provider.get(), &IDataProvider::dataProvidedFailed,
690 m_VariableAcquisitionWorker.get(),
696 m_VariableAcquisitionWorker.get(),
691 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
697 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
692 }
698 }
693 else {
699 else {
694 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
700 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
695 }
701 }
696 }
702 }
697
703
698 void VariableController::VariableControllerPrivate::storeVariableRequest(
704 void VariableController::VariableControllerPrivate::storeVariableRequest(
699 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
705 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
700 {
706 {
701 // First request for the variable. we can create an entry for it
707 // First request for the variable. we can create an entry for it
702 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
708 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
703 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
709 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
704 auto varRequestIdQueue = std::deque<QUuid>{};
710 auto varRequestIdQueue = std::deque<QUuid>{};
705 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
711 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
706 varRequestIdQueue.push_back(varRequestId);
712 varRequestIdQueue.push_back(varRequestId);
707 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
713 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
708 }
714 }
709 else {
715 else {
710 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
716 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
711 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
717 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
712 varRequestIdQueue.push_back(varRequestId);
718 varRequestIdQueue.push_back(varRequestId);
713 }
719 }
714
720
715 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
721 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
716 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
722 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
717 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
723 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
718 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
724 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
719 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
725 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
720 m_VarRequestIdToVarIdVarRequestMap.insert(
726 m_VarRequestIdToVarIdVarRequestMap.insert(
721 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
727 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
722 }
728 }
723 else {
729 else {
724 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
730 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
725 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
731 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
726 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
732 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
727 }
733 }
728 }
734 }
729
735
730 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
736 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
731 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
737 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
732 {
738 {
733 QUuid varRequestId;
739 QUuid varRequestId;
734 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
740 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
735 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
741 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
736 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
742 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
737 varRequestId = varRequestIdQueue.front();
743 varRequestId = varRequestIdQueue.front();
738 auto varRequestIdToVarIdVarRequestMapIt
744 auto varRequestIdToVarIdVarRequestMapIt
739 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
745 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
740 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
746 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
741 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
747 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
742 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
748 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
743 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
749 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
744 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
750 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
745 auto &varRequest = varIdToVarRequestMapIt->second;
751 auto &varRequest = varIdToVarRequestMapIt->second;
746 varRequest.m_DataSeries = dataSeries;
752 varRequest.m_DataSeries = dataSeries;
747 varRequest.m_CanUpdate = true;
753 varRequest.m_CanUpdate = true;
748 }
754 }
749 else {
755 else {
750 qCDebug(LOG_VariableController())
756 qCDebug(LOG_VariableController())
751 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
757 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
752 "to a variableRequestId")
758 "to a variableRequestId")
753 << varRequestId << varId;
759 << varRequestId << varId;
754 }
760 }
755 }
761 }
756 else {
762 else {
757 qCCritical(LOG_VariableController())
763 qCCritical(LOG_VariableController())
758 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
764 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
759 << varRequestId;
765 << varRequestId;
760 }
766 }
761
767
762 varRequestIdQueue.pop_front();
768 varRequestIdQueue.pop_front();
763 if (varRequestIdQueue.empty()) {
769 if (varRequestIdQueue.empty()) {
764 qCDebug(LOG_VariableController())
770 qCDebug(LOG_VariableController())
765 << tr("TORM Erase REQUEST because it has been accepted") << varId;
771 << tr("TORM Erase REQUEST because it has been accepted") << varId;
766 m_VarIdToVarRequestIdQueueMap.erase(varId);
772 m_VarIdToVarRequestIdQueueMap.erase(varId);
767 }
773 }
768 }
774 }
769 else {
775 else {
770 qCCritical(LOG_VariableController())
776 qCCritical(LOG_VariableController())
771 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
777 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
772 }
778 }
773
779
774 return varRequestId;
780 return varRequestId;
775 }
781 }
776
782
777 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
783 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
778 {
784 {
779
785
780 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
786 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
781 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
787 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
782 bool processVariableUpdate = true;
788 bool processVariableUpdate = true;
783 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
789 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
784 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
790 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
785 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
791 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
786 ++varIdToVarRequestMapIt) {
792 ++varIdToVarRequestMapIt) {
787 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
793 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
788 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
794 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
789 << processVariableUpdate;
795 << processVariableUpdate;
790 }
796 }
791
797
792 if (processVariableUpdate) {
798 if (processVariableUpdate) {
793 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
799 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
794 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
800 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
795 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
801 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
796 auto &varRequest = varIdToVarRequestMapIt->second;
802 auto &varRequest = varIdToVarRequestMapIt->second;
797 var->setRange(varRequest.m_RangeRequested);
803 var->setRange(varRequest.m_RangeRequested);
798 var->setCacheRange(varRequest.m_CacheRangeRequested);
804 var->setCacheRange(varRequest.m_CacheRangeRequested);
799 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
805 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
800 << varRequest.m_RangeRequested;
806 << varRequest.m_RangeRequested;
801 qCDebug(LOG_VariableController()) << tr("2: onDataProvided")
807 qCDebug(LOG_VariableController()) << tr("2: onDataProvided")
802 << varRequest.m_CacheRangeRequested;
808 << varRequest.m_CacheRangeRequested;
803 var->mergeDataSeries(varRequest.m_DataSeries);
809 var->mergeDataSeries(varRequest.m_DataSeries);
804 qCDebug(LOG_VariableController()) << tr("3: onDataProvided");
810 qCDebug(LOG_VariableController()) << tr("3: onDataProvided");
805
811
806 /// @todo MPL: confirm
812 /// @todo MPL: confirm
807 // Variable update is notified only if there is no pending request for it
813 // Variable update is notified only if there is no pending request for it
808 // if
814 // if
809 // (m_VarIdToVarRequestIdQueueMap.count(varIdToVarRequestMapIt->first)
815 // (m_VarIdToVarRequestIdQueueMap.count(varIdToVarRequestMapIt->first)
810 // == 0) {
816 // == 0) {
811 emit var->updated();
817 emit var->updated();
812 // }
818 // }
813 }
819 }
814 else {
820 else {
815 qCCritical(LOG_VariableController())
821 qCCritical(LOG_VariableController())
816 << tr("Impossible to update data to a null variable");
822 << tr("Impossible to update data to a null variable");
817 }
823 }
818 }
824 }
819
825
820 // cleaning varRequestId
826 // cleaning varRequestId
821 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
827 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
822 << m_VarRequestIdToVarIdVarRequestMap.size();
828 << m_VarRequestIdToVarIdVarRequestMap.size();
823 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
829 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
824 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
830 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
825 << m_VarRequestIdToVarIdVarRequestMap.size();
831 << m_VarRequestIdToVarIdVarRequestMap.size();
826 }
832 }
827 }
833 }
828 else {
834 else {
829 qCCritical(LOG_VariableController())
835 qCCritical(LOG_VariableController())
830 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
836 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
831 }
837 }
832 }
838 }
833
839
834 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
840 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
835 {
841 {
836 // cleaning varRequestId
842 // cleaning varRequestId
837 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
843 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
838
844
839 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
845 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
840 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
846 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
841 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
847 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
842 varRequestIdQueue.erase(
848 varRequestIdQueue.erase(
843 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
849 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
844 varRequestIdQueue.end());
850 varRequestIdQueue.end());
845 if (varRequestIdQueue.empty()) {
851 if (varRequestIdQueue.empty()) {
846 varIdToVarRequestIdQueueMapIt
852 varIdToVarRequestIdQueueMapIt
847 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
853 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
848 }
854 }
849 else {
855 else {
850 ++varIdToVarRequestIdQueueMapIt;
856 ++varIdToVarRequestIdQueueMapIt;
851 }
857 }
852 }
858 }
853 }
859 }
854
860
855 SqpRange VariableController::VariableControllerPrivate::getLastRequestedRange(QUuid varId)
861 SqpRange VariableController::VariableControllerPrivate::getLastRequestedRange(QUuid varId)
856 {
862 {
857 auto lastRangeRequested = SqpRange{INVALID_RANGE};
863 auto lastRangeRequested = SqpRange{INVALID_RANGE};
858 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
864 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
859 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
865 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
860 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
866 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
861 auto varRequestId = varRequestIdQueue.back();
867 auto varRequestId = varRequestIdQueue.back();
862 auto varRequestIdToVarIdVarRequestMapIt
868 auto varRequestIdToVarIdVarRequestMapIt
863 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
869 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
864 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
870 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
865 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
871 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
866 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
872 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
867 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
873 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
868 auto &varRequest = varIdToVarRequestMapIt->second;
874 auto &varRequest = varIdToVarRequestMapIt->second;
869 lastRangeRequested = varRequest.m_RangeRequested;
875 lastRangeRequested = varRequest.m_RangeRequested;
870 }
876 }
871 else {
877 else {
872 qCDebug(LOG_VariableController())
878 qCDebug(LOG_VariableController())
873 << tr("Impossible to getLastRequestedRange of a unknown variable id attached "
879 << tr("Impossible to getLastRequestedRange of a unknown variable id attached "
874 "to a variableRequestId")
880 "to a variableRequestId")
875 << varRequestId << varId;
881 << varRequestId << varId;
876 }
882 }
877 }
883 }
878 else {
884 else {
879 qCCritical(LOG_VariableController())
885 qCCritical(LOG_VariableController())
880 << tr("Impossible to getLastRequestedRange of a unknown variableRequestId")
886 << tr("Impossible to getLastRequestedRange of a unknown variableRequestId")
881 << varRequestId;
887 << varRequestId;
882 }
888 }
883 }
889 }
884 else {
890 else {
885 qDebug(LOG_VariableController())
891 qDebug(LOG_VariableController())
886 << tr("Impossible to getLastRequestedRange of a unknown variable id") << varId;
892 << tr("Impossible to getLastRequestedRange of a unknown variable id") << varId;
887 }
893 }
888
894
889 return lastRangeRequested;
895 return lastRangeRequested;
890 }
896 }
@@ -1,310 +1,391
1 #include <QObject>
1 #include <QObject>
2 #include <QtTest>
2 #include <QtTest>
3
3
4 #include <memory>
4 #include <memory>
5
5
6 #include <Data/DataProviderParameters.h>
6 #include <Data/DataProviderParameters.h>
7 #include <Data/IDataProvider.h>
7 #include <Data/IDataProvider.h>
8 #include <Data/ScalarSeries.h>
8 #include <Data/ScalarSeries.h>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10 #include <Variable/Variable.h>
10 #include <Variable/Variable.h>
11 #include <Variable/VariableController.h>
11 #include <Variable/VariableController.h>
12 #include <Variable/VariableModel.h>
12 #include <Variable/VariableModel.h>
13
13
14 namespace {
14 namespace {
15
15
16 /// Delay after each operation on the variable before validating it (in ms)
16 /// Delay after each operation on the variable before validating it (in ms)
17 const auto OPERATION_DELAY = 100;
17 const auto OPERATION_DELAY = 100;
18
18
19 /**
19 /**
20 * Generates values according to a range. The value generated for a time t is the number of seconds
20 * Generates values according to a range. The value generated for a time t is the number of seconds
21 * of difference between t and a reference value (which is midnight -> 00:00:00)
21 * of difference between t and a reference value (which is midnight -> 00:00:00)
22 *
22 *
23 * Example: For a range between 00:00:10 and 00:00:20, the generated values are
23 * Example: For a range between 00:00:10 and 00:00:20, the generated values are
24 * {10,11,12,13,14,15,16,17,18,19,20}
24 * {10,11,12,13,14,15,16,17,18,19,20}
25 */
25 */
26 std::vector<double> values(const SqpRange &range)
26 std::vector<double> values(const SqpRange &range)
27 {
27 {
28 QTime referenceTime{0, 0};
28 QTime referenceTime{0, 0};
29
29
30 std::vector<double> result{};
30 std::vector<double> result{};
31
31
32 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
32 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
33 auto time = DateUtils::dateTime(i).time();
33 auto time = DateUtils::dateTime(i).time();
34 result.push_back(referenceTime.secsTo(time));
34 result.push_back(referenceTime.secsTo(time));
35 }
35 }
36
36
37 return result;
37 return result;
38 }
38 }
39
39
40 /// Provider used for the tests
40 /// Provider used for the tests
41 class TestProvider : public IDataProvider {
41 class TestProvider : public IDataProvider {
42 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
42 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
43
43
44 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
44 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
45 {
45 {
46 const auto &ranges = parameters.m_Times;
46 const auto &ranges = parameters.m_Times;
47
47
48 for (const auto &range : ranges) {
48 for (const auto &range : ranges) {
49 // Generates data series
49 // Generates data series
50 auto valuesData = values(range);
50 auto valuesData = values(range);
51
51
52 std::vector<double> xAxisData{};
52 std::vector<double> xAxisData{};
53 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
53 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
54 xAxisData.push_back(i);
54 xAxisData.push_back(i);
55 }
55 }
56
56
57 auto dataSeries = std::make_shared<ScalarSeries>(
57 auto dataSeries = std::make_shared<ScalarSeries>(
58 std::move(xAxisData), std::move(valuesData), Unit{"t", true}, Unit{});
58 std::move(xAxisData), std::move(valuesData), Unit{"t", true}, Unit{});
59
59
60 emit dataProvided(acqIdentifier, dataSeries, range);
60 emit dataProvided(acqIdentifier, dataSeries, range);
61 }
61 }
62 }
62 }
63
63
64 void requestDataAborting(QUuid acqIdentifier) override
64 void requestDataAborting(QUuid acqIdentifier) override
65 {
65 {
66 // Does nothing
66 // Does nothing
67 }
67 }
68 };
68 };
69
69
70 /**
70 /**
71 * Interface representing an operation performed on a variable controller.
71 * Interface representing an operation performed on a variable controller.
72 * This interface is used in tests to apply a set of operations and check the status of the
72 * This interface is used in tests to apply a set of operations and check the status of the
73 * controller after each operation
73 * controller after each operation
74 */
74 */
75 struct IOperation {
75 struct IOperation {
76 virtual ~IOperation() = default;
76 virtual ~IOperation() = default;
77 /// Executes the operation on the variable controller
77 /// Executes the operation on the variable controller
78 virtual void exec(VariableController &variableController) const = 0;
78 virtual void exec(VariableController &variableController) const = 0;
79 };
79 };
80
80
81 /**
81 /**
82 *Variable creation operation in the controller
82 *Variable creation operation in the controller
83 */
83 */
84 struct Create : public IOperation {
84 struct Create : public IOperation {
85 explicit Create(int index) : m_Index{index} {}
85 explicit Create(int index) : m_Index{index} {}
86
86
87 void exec(VariableController &variableController) const override
87 void exec(VariableController &variableController) const override
88 {
88 {
89 auto variable = variableController.createVariable(QString::number(m_Index), {},
89 auto variable = variableController.createVariable(QString::number(m_Index), {},
90 std::make_unique<TestProvider>());
90 std::make_unique<TestProvider>());
91 }
91 }
92
92
93 int m_Index; ///< The index of the variable to create in the controller
93 int m_Index; ///< The index of the variable to create in the controller
94 };
94 };
95
95
96 /**
96 /**
97 * Variable move/shift operation in the controller
97 * Variable move/shift operation in the controller
98 */
98 */
99 struct Move : public IOperation {
99 struct Move : public IOperation {
100 explicit Move(int index, const SqpRange &newRange, bool shift = false)
100 explicit Move(int index, const SqpRange &newRange, bool shift = false)
101 : m_Index{index}, m_NewRange{newRange}, m_Shift{shift}
101 : m_Index{index}, m_NewRange{newRange}, m_Shift{shift}
102 {
102 {
103 }
103 }
104
104
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, variable->range(),
109 !m_Shift);
109 !m_Shift);
110 }
110 }
111 }
111 }
112
112
113 int m_Index; ///< The index of the variable to move
113 int m_Index; ///< The index of the variable to move
114 SqpRange m_NewRange; ///< The new range of the variable
114 SqpRange m_NewRange; ///< The new range of the variable
115 bool m_Shift; ///< Performs a shift (
115 bool m_Shift; ///< Performs a shift (
116 };
116 };
117
117
118 /**
118 /**
119 * Variable synchronization/desynchronization operation in the controller
119 * Variable synchronization/desynchronization operation in the controller
120 */
120 */
121 struct Synchronize : public IOperation {
121 struct Synchronize : public IOperation {
122 explicit Synchronize(int index, QUuid syncId, bool synchronize = true)
122 explicit Synchronize(int index, QUuid syncId, bool synchronize = true)
123 : m_Index{index}, m_SyncId{syncId}, m_Synchronize{synchronize}
123 : m_Index{index}, m_SyncId{syncId}, m_Synchronize{synchronize}
124 {
124 {
125 }
125 }
126
126
127 void exec(VariableController &variableController) const override
127 void exec(VariableController &variableController) const override
128 {
128 {
129 if (auto variable = variableController.variableModel()->variable(m_Index)) {
129 if (auto variable = variableController.variableModel()->variable(m_Index)) {
130 if (m_Synchronize) {
130 if (m_Synchronize) {
131 variableController.onAddSynchronized(variable, m_SyncId);
131 variableController.onAddSynchronized(variable, m_SyncId);
132 }
132 }
133 else {
133 else {
134 variableController.desynchronize(variable, m_SyncId);
134 variableController.desynchronize(variable, m_SyncId);
135 }
135 }
136 }
136 }
137 }
137 }
138
138
139 int m_Index; ///< The index of the variable to sync/desync
139 int m_Index; ///< The index of the variable to sync/desync
140 QUuid m_SyncId; ///< The synchronization group of the variable
140 QUuid m_SyncId; ///< The synchronization group of the variable
141 bool m_Synchronize; ///< Performs sync or desync operation
141 bool m_Synchronize; ///< Performs sync or desync operation
142 };
142 };
143
143
144 /**
144 /**
145 * Test Iteration
145 * Test Iteration
146 *
146 *
147 * A test iteration includes an operation to be performed, and a set of expected ranges after each
147 * A test iteration includes an operation to be performed, and a set of expected ranges after each
148 * operation. Each range is tested after the operation to ensure that:
148 * operation. Each range is tested after the operation to ensure that:
149 * - the range of the variable is the expected range
149 * - the range of the variable is the expected range
150 * - the data of the variable are those generated for the expected range
150 * - the data of the variable are those generated for the expected range
151 */
151 */
152 struct Iteration {
152 struct Iteration {
153 std::shared_ptr<IOperation> m_Operation; ///< Operation to perform
153 std::shared_ptr<IOperation> m_Operation; ///< Operation to perform
154 std::map<int, SqpRange> m_ExpectedRanges; ///< Expected ranges (by variable index)
154 std::map<int, SqpRange> m_ExpectedRanges; ///< Expected ranges (by variable index)
155 };
155 };
156
156
157 using Iterations = std::vector<Iteration>;
157 using Iterations = std::vector<Iteration>;
158
158
159 } // namespace
159 } // namespace
160
160
161 Q_DECLARE_METATYPE(Iterations)
161 Q_DECLARE_METATYPE(Iterations)
162
162
163 class TestVariableSync : public QObject {
163 class TestVariableSync : public QObject {
164 Q_OBJECT
164 Q_OBJECT
165
165
166 private slots:
166 private slots:
167 /// Input data for @sa testSync()
167 /// Input data for @sa testSync()
168 void testSync_data();
168 void testSync_data();
169
169
170 /// Tests synchronization between variables through several operations
170 /// Tests synchronization between variables through several operations
171 void testSync();
171 void testSync();
172 };
172 };
173
173
174 void TestVariableSync::testSync_data()
174 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
175
176 void testSyncCase1()
177 {
188 // Id used to synchronize variables in the controller
178 // Id used to synchronize variables in the controller
189 auto syncId = QUuid::createUuid();
179 auto syncId = QUuid::createUuid();
190
180
191 /// Generates a range according to a start time and a end time (the date is the same)
181 /// Generates a range according to a start time and a end time (the date is the same)
192 auto range = [](const QTime &startTime, const QTime &endTime) {
182 auto range = [](const QTime &startTime, const QTime &endTime) {
193 return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}),
183 return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}),
194 DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})};
184 DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})};
195 };
185 };
196
186
197 auto initialRange = range({12, 0}, {13, 0});
187 auto initialRange = range({12, 0}, {13, 0});
198
188
199 Iterations iterations{};
189 Iterations iterations{};
200 // Creates variables var0, var1 and var2
190 // Creates variables var0, var1 and var2
201 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
191 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
202 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
192 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
203 iterations.push_back(
193 iterations.push_back(
204 {std::make_shared<Create>(2), {{0, initialRange}, {1, initialRange}, {2, initialRange}}});
194 {std::make_shared<Create>(2), {{0, initialRange}, {1, initialRange}, {2, initialRange}}});
205
195
206 // Adds variables into the sync group (ranges don't need to be tested here)
196 // Adds variables into the sync group (ranges don't need to be tested here)
207 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
197 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
208 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
198 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
209 iterations.push_back({std::make_shared<Synchronize>(2, syncId)});
199 iterations.push_back({std::make_shared<Synchronize>(2, syncId)});
210
200
211 // Moves var0: ranges of var0, var1 and var2 change
201 // Moves var0: ranges of var0, var1 and var2 change
212 auto newRange = range({12, 30}, {13, 30});
202 auto newRange = range({12, 30}, {13, 30});
213 iterations.push_back(
203 iterations.push_back(
214 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
204 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
215
205
216 // Moves var1: ranges of var0, var1 and var2 change
206 // Moves var1: ranges of var0, var1 and var2 change
217 newRange = range({13, 0}, {14, 0});
207 newRange = range({13, 0}, {14, 0});
218 iterations.push_back(
208 iterations.push_back(
219 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
209 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
220
210
221 // Moves var2: ranges of var0, var1 and var2 change
211 // Moves var2: ranges of var0, var1 and var2 change
222 newRange = range({13, 30}, {14, 30});
212 newRange = range({13, 30}, {14, 30});
223 iterations.push_back(
213 iterations.push_back(
224 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
214 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
225
215
226 // Desyncs var2 and moves var0:
216 // Desyncs var2 and moves var0:
227 // - ranges of var0 and var1 change
217 // - ranges of var0 and var1 change
228 // - range of var2 doesn't change anymore
218 // - range of var2 doesn't change anymore
229 auto var2Range = newRange;
219 auto var2Range = newRange;
230 newRange = range({13, 45}, {14, 45});
220 newRange = range({13, 45}, {14, 45});
231 iterations.push_back({std::make_shared<Synchronize>(2, syncId, false)});
221 iterations.push_back({std::make_shared<Synchronize>(2, syncId, false)});
232 iterations.push_back(
222 iterations.push_back(
233 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, var2Range}}});
223 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, var2Range}}});
234
224
235 // Shifts var0: although var1 is synchronized with var0, its range doesn't change
225 // Shifts var0: although var1 is synchronized with var0, its range doesn't change
236 auto var1Range = newRange;
226 auto var1Range = newRange;
237 newRange = range({14, 45}, {15, 45});
227 newRange = range({14, 45}, {15, 45});
238 iterations.push_back({std::make_shared<Move>(0, newRange, true),
228 iterations.push_back({std::make_shared<Move>(0, newRange, true),
239 {{0, newRange}, {1, var1Range}, {2, var2Range}}});
229 {{0, newRange}, {1, var1Range}, {2, var2Range}}});
240
230
241 // Moves var0 through several operations:
231 // Moves var0 through several operations:
242 // - range of var0 changes
232 // - range of var0 changes
243 // - range or var1 changes according to the previous shift (one hour)
233 // - range or var1 changes according to the previous shift (one hour)
244 auto moveVar0 = [&iterations](const auto &var0NewRange, const auto &var1ExpectedRange) {
234 auto moveVar0 = [&iterations](const auto &var0NewRange, const auto &var1ExpectedRange) {
245 iterations.push_back(
235 iterations.push_back(
246 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}});
236 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}});
247 };
237 };
248 // Pan left
238 // Pan left
249 moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30}));
239 moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30}));
250 // Pan right
240 // Pan right
251 moveVar0(range({16, 0}, {17, 0}), range({15, 0}, {16, 0}));
241 moveVar0(range({16, 0}, {17, 0}), range({15, 0}, {16, 0}));
252 // Zoom in
242 // Zoom in
253 moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45}));
243 moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45}));
254 // Zoom out
244 // Zoom out
255 moveVar0(range({12, 0}, {18, 0}), range({11, 0}, {17, 0}));
245 moveVar0(range({12, 0}, {18, 0}), range({11, 0}, {17, 0}));
256
246
257 QTest::newRow("sync1") << syncId << initialRange << std::move(iterations);
247 QTest::newRow("sync1") << syncId << initialRange << std::move(iterations) << 200;
248 }
249
250 void testSyncCase2()
251 {
252 // Id used to synchronize variables in the controller
253 auto syncId = QUuid::createUuid();
254
255 /// Generates a range according to a start time and a end time (the date is the same)
256 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
257 return DateUtils::secondsSinceEpoch(
258 QDateTime{{year, month, day}, QTime{hours, minutes, seconds}, Qt::UTC});
259 };
260
261 auto initialRange = SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)};
262
263 Iterations iterations{};
264 // Creates variables var0 and var1
265 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
266 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
267
268 // Adds variables into the sync group (ranges don't need to be tested here)
269 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
270 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
271
272
273 // Moves var0 through several operations:
274 // - range of var0 changes
275 // - range or var1 changes according to the previous shift (one hour)
276 auto moveVar0 = [&iterations](const auto &var0NewRange) {
277 iterations.push_back(
278 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var0NewRange}}});
279 };
280 moveVar0(SqpRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)});
281 moveVar0(SqpRange{dateTime(2017, 1, 1, 14, 0, 0), dateTime(2017, 1, 1, 15, 0, 0)});
282 moveVar0(SqpRange{dateTime(2017, 1, 1, 8, 0, 0), dateTime(2017, 1, 1, 9, 0, 0)});
283 // moveVar0(SqpRange{dateTime(2017, 1, 1, 7, 30, 0), dateTime(2017, 1, 1, 9, 30, 0)});
284 moveVar0(SqpRange{dateTime(2017, 1, 1, 2, 0, 0), dateTime(2017, 1, 1, 4, 0, 0)});
285 moveVar0(SqpRange{dateTime(2017, 1, 1, 6, 0, 0), dateTime(2017, 1, 1, 8, 0, 0)});
286
287 moveVar0(SqpRange{dateTime(2017, 1, 10, 6, 0, 0), dateTime(2017, 1, 15, 8, 0, 0)});
288 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 1, 25, 8, 0, 0)});
289 moveVar0(SqpRange{dateTime(2017, 1, 2, 6, 0, 0), dateTime(2017, 1, 8, 8, 0, 0)});
290
291 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
292 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
293 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
294 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
295 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
296 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
297 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
298 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
299 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
300 moveVar0(SqpRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)});
301 moveVar0(SqpRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)});
302 moveVar0(SqpRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)});
303
304
305 QTest::newRow("sync2") << syncId << initialRange << iterations << 4000;
306 // QTest::newRow("sync3") << syncId << initialRange << iterations << 5000;
307 }
308 }
309
310 void TestVariableSync::testSync_data()
311 {
312 // ////////////// //
313 // Test structure //
314 // ////////////// //
315
316 QTest::addColumn<QUuid>("syncId");
317 QTest::addColumn<SqpRange>("initialRange");
318 QTest::addColumn<Iterations>("iterations");
319 QTest::addColumn<int>("operationDelay");
320
321 // ////////// //
322 // Test cases //
323 // ////////// //
324
325 testSyncCase1();
326 testSyncCase2();
258 }
327 }
259
328
260 void TestVariableSync::testSync()
329 void TestVariableSync::testSync()
261 {
330 {
262 // Inits controllers
331 // Inits controllers
263 TimeController timeController{};
332 TimeController timeController{};
264 VariableController variableController{};
333 VariableController variableController{};
265 variableController.setTimeController(&timeController);
334 variableController.setTimeController(&timeController);
266
335
267 QFETCH(QUuid, syncId);
336 QFETCH(QUuid, syncId);
268 QFETCH(SqpRange, initialRange);
337 QFETCH(SqpRange, initialRange);
269 timeController.onTimeToUpdate(initialRange);
338 timeController.onTimeToUpdate(initialRange);
270
339
271 // Synchronization group used
340 // Synchronization group used
272 variableController.onAddSynchronizationGroupId(syncId);
341 variableController.onAddSynchronizationGroupId(syncId);
273
342
274 // For each iteration:
343 auto validateRanges = [&variableController](const auto &expectedRanges) {
275 // - execute operation
344 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;
345 auto variableIndex = expectedRangeEntry.first;
284 auto expectedRange = expectedRangeEntry.second;
346 auto expectedRange = expectedRangeEntry.second;
285
347
286 // Gets the variable in the controller
348 // Gets the variable in the controller
287 auto variable = variableController.variableModel()->variable(variableIndex);
349 auto variable = variableController.variableModel()->variable(variableIndex);
288
350
289 // Compares variable's range to the expected range
351 // Compares variable's range to the expected range
290 QVERIFY(variable != nullptr);
352 QVERIFY(variable != nullptr);
291 auto range = variable->range();
353 auto range = variable->range();
292 QCOMPARE(range, expectedRange);
354 QCOMPARE(range, expectedRange);
293
355
294 // Compares variable's data with values expected for its range
356 // Compares variable's data with values expected for its range
295 auto dataSeries = variable->dataSeries();
357 auto dataSeries = variable->dataSeries();
296 QVERIFY(dataSeries != nullptr);
358 QVERIFY(dataSeries != nullptr);
297
359
298 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
360 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
299 auto expectedValues = values(range);
361 auto expectedValues = values(range);
362 qInfo() << std::distance(it.first, it.second) << expectedValues.size();
300 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
363 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
301 [](const auto &dataSeriesIt, const auto &expectedValue) {
364 [](const auto &dataSeriesIt, const auto &expectedValue) {
302 return dataSeriesIt.value() == expectedValue;
365 return dataSeriesIt.value() == expectedValue;
303 }));
366 }));
304 }
367 }
368 };
369
370 // For each iteration:
371 // - execute operation
372 // - compare the variables' state to the expected states
373 QFETCH(Iterations, iterations);
374 QFETCH(int, operationDelay);
375 for (const auto &iteration : iterations) {
376 iteration.m_Operation->exec(variableController);
377 QTest::qWait(operationDelay);
378
379 validateRanges(iteration.m_ExpectedRanges);
380 }
381
382 for (const auto &iteration : iterations) {
383 iteration.m_Operation->exec(variableController);
305 }
384 }
385 QTest::qWait(operationDelay);
386 validateRanges(iterations.back().m_ExpectedRanges);
306 }
387 }
307
388
308 QTEST_MAIN(TestVariableSync)
389 QTEST_MAIN(TestVariableSync)
309
390
310 #include "TestVariableSync.moc"
391 #include "TestVariableSync.moc"
@@ -1,302 +1,304
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "ui_VisualizationZoneWidget.h"
6 #include "ui_VisualizationZoneWidget.h"
7
7
8 #include <Data/SqpRange.h>
8 #include <Data/SqpRange.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11
11
12 #include <QUuid>
12 #include <QUuid>
13 #include <SqpApplication.h>
13 #include <SqpApplication.h>
14 #include <cmath>
14 #include <cmath>
15
15
16 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
16 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
17
17
18 namespace {
18 namespace {
19
19
20 /// Minimum height for graph added in zones (in pixels)
20 /// Minimum height for graph added in zones (in pixels)
21 const auto GRAPH_MINIMUM_HEIGHT = 300;
21 const auto GRAPH_MINIMUM_HEIGHT = 300;
22
22
23 /// Generates a default name for a new graph, according to the number of graphs already displayed in
23 /// Generates a default name for a new graph, according to the number of graphs already displayed in
24 /// the zone
24 /// the zone
25 QString defaultGraphName(const QLayout &layout)
25 QString defaultGraphName(const QLayout &layout)
26 {
26 {
27 auto count = 0;
27 auto count = 0;
28 for (auto i = 0; i < layout.count(); ++i) {
28 for (auto i = 0; i < layout.count(); ++i) {
29 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
29 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
30 count++;
30 count++;
31 }
31 }
32 }
32 }
33
33
34 return QObject::tr("Graph %1").arg(count + 1);
34 return QObject::tr("Graph %1").arg(count + 1);
35 }
35 }
36
36
37 /**
37 /**
38 * Applies a function to all graphs of the zone represented by its layout
38 * Applies a function to all graphs of the zone represented by its layout
39 * @param layout the layout that contains graphs
39 * @param layout the layout that contains graphs
40 * @param fun the function to apply to each graph
40 * @param fun the function to apply to each graph
41 */
41 */
42 template <typename Fun>
42 template <typename Fun>
43 void processGraphs(QLayout &layout, Fun fun)
43 void processGraphs(QLayout &layout, Fun fun)
44 {
44 {
45 for (auto i = 0; i < layout.count(); ++i) {
45 for (auto i = 0; i < layout.count(); ++i) {
46 if (auto item = layout.itemAt(i)) {
46 if (auto item = layout.itemAt(i)) {
47 if (auto visualizationGraphWidget
47 if (auto visualizationGraphWidget
48 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
48 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
49 fun(*visualizationGraphWidget);
49 fun(*visualizationGraphWidget);
50 }
50 }
51 }
51 }
52 }
52 }
53 }
53 }
54
54
55 } // namespace
55 } // namespace
56
56
57 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
57 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
58
58
59 explicit VisualizationZoneWidgetPrivate()
59 explicit VisualizationZoneWidgetPrivate()
60 : m_SynchronisationGroupId{QUuid::createUuid()},
60 : m_SynchronisationGroupId{QUuid::createUuid()},
61 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
61 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
62 {
62 {
63 }
63 }
64 QUuid m_SynchronisationGroupId;
64 QUuid m_SynchronisationGroupId;
65 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
65 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
66 };
66 };
67
67
68 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
68 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
69 : QWidget{parent},
69 : QWidget{parent},
70 ui{new Ui::VisualizationZoneWidget},
70 ui{new Ui::VisualizationZoneWidget},
71 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
71 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
72 {
72 {
73 ui->setupUi(this);
73 ui->setupUi(this);
74
74
75 ui->zoneNameLabel->setText(name);
75 ui->zoneNameLabel->setText(name);
76
76
77 // 'Close' options : widget is deleted when closed
77 // 'Close' options : widget is deleted when closed
78 setAttribute(Qt::WA_DeleteOnClose);
78 setAttribute(Qt::WA_DeleteOnClose);
79 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
79 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
80 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
80 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
81
81
82 // Synchronisation id
82 // Synchronisation id
83 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
83 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
84 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
84 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
85 }
85 }
86
86
87 VisualizationZoneWidget::~VisualizationZoneWidget()
87 VisualizationZoneWidget::~VisualizationZoneWidget()
88 {
88 {
89 delete ui;
89 delete ui;
90 }
90 }
91
91
92 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
92 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
93 {
93 {
94 // Synchronize new graph with others in the zone
94 // Synchronize new graph with others in the zone
95 impl->m_Synchronizer->addGraph(*graphWidget);
95 impl->m_Synchronizer->addGraph(*graphWidget);
96
96
97 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
97 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
98 }
98 }
99
99
100 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
100 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
101 {
101 {
102 auto graphWidget = new VisualizationGraphWidget{
102 auto graphWidget = new VisualizationGraphWidget{
103 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
103 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
104
104
105
105
106 // Set graph properties
106 // Set graph properties
107 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
107 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
108 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
108 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
109
109
110
110
111 // Lambda to synchronize zone widget
111 // Lambda to synchronize zone widget
112 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
112 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
113 const SqpRange &oldGraphRange) {
113 const SqpRange &oldGraphRange) {
114
114
115 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
115 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
116 auto frameLayout = ui->visualizationZoneFrame->layout();
116 auto frameLayout = ui->visualizationZoneFrame->layout();
117 for (auto i = 0; i < frameLayout->count(); ++i) {
117 for (auto i = 0; i < frameLayout->count(); ++i) {
118 auto graphChild
118 auto graphChild
119 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
119 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
120 if (graphChild && (graphChild != graphWidget)) {
120 if (graphChild && (graphChild != graphWidget)) {
121
121
122 auto graphChildRange = graphChild->graphRange();
122 auto graphChildRange = graphChild->graphRange();
123 switch (zoomType) {
123 switch (zoomType) {
124 case AcquisitionZoomType::ZoomIn: {
124 case AcquisitionZoomType::ZoomIn: {
125 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
125 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
126 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
126 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
127 graphChildRange.m_TStart += deltaLeft;
127 graphChildRange.m_TStart += deltaLeft;
128 graphChildRange.m_TEnd -= deltaRight;
128 graphChildRange.m_TEnd -= deltaRight;
129 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
129 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
130 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
130 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
131 << deltaLeft;
131 << deltaLeft;
132 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
132 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
133 << deltaRight;
133 << deltaRight;
134 qCDebug(LOG_VisualizationZoneWidget())
134 qCDebug(LOG_VisualizationZoneWidget())
135 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
135 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
136
136
137 break;
137 break;
138 }
138 }
139
139
140 case AcquisitionZoomType::ZoomOut: {
140 case AcquisitionZoomType::ZoomOut: {
141 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
141 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
142 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
142 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
143 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
143 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
144 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
144 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
145 << deltaLeft;
145 << deltaLeft;
146 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
146 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
147 << deltaRight;
147 << deltaRight;
148 qCDebug(LOG_VisualizationZoneWidget())
148 qCDebug(LOG_VisualizationZoneWidget())
149 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
149 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
150 graphChildRange.m_TStart -= deltaLeft;
150 graphChildRange.m_TStart -= deltaLeft;
151 graphChildRange.m_TEnd += deltaRight;
151 graphChildRange.m_TEnd += deltaRight;
152 break;
152 break;
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;
161 break;
162 break;
162 }
163 }
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: {
171 qCDebug(LOG_VisualizationZoneWidget())
173 qCDebug(LOG_VisualizationZoneWidget())
172 << tr("Impossible to synchronize: zoom type unknown");
174 << tr("Impossible to synchronize: zoom type unknown");
173 break;
175 break;
174 }
176 }
175 default:
177 default:
176 qCCritical(LOG_VisualizationZoneWidget())
178 qCCritical(LOG_VisualizationZoneWidget())
177 << tr("Impossible to synchronize: zoom type not take into account");
179 << tr("Impossible to synchronize: zoom type not take into account");
178 // No action
180 // No action
179 break;
181 break;
180 }
182 }
181 graphChild->enableAcquisition(false);
183 graphChild->enableAcquisition(false);
182 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
184 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
183 << graphChild->graphRange();
185 << graphChild->graphRange();
184 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
186 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
185 << graphChildRange;
187 << graphChildRange;
186 qCDebug(LOG_VisualizationZoneWidget())
188 qCDebug(LOG_VisualizationZoneWidget())
187 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
189 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
188 graphChild->setGraphRange(graphChildRange);
190 graphChild->setGraphRange(graphChildRange);
189 graphChild->enableAcquisition(true);
191 graphChild->enableAcquisition(true);
190 }
192 }
191 }
193 }
192 };
194 };
193
195
194 // connection for synchronization
196 // connection for synchronization
195 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
197 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
196 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
198 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
197 &VisualizationZoneWidget::onVariableAdded);
199 &VisualizationZoneWidget::onVariableAdded);
198 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
200 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
199 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
201 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
200
202
201 auto range = SqpRange{};
203 auto range = SqpRange{};
202
204
203 // Apply visitor to graph children
205 // Apply visitor to graph children
204 auto layout = ui->visualizationZoneFrame->layout();
206 auto layout = ui->visualizationZoneFrame->layout();
205 if (layout->count() > 0) {
207 if (layout->count() > 0) {
206 // Case of a new graph in a existant zone
208 // Case of a new graph in a existant zone
207 if (auto visualizationGraphWidget
209 if (auto visualizationGraphWidget
208 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
210 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
209 range = visualizationGraphWidget->graphRange();
211 range = visualizationGraphWidget->graphRange();
210 }
212 }
211 }
213 }
212 else {
214 else {
213 // Case of a new graph as the first of the zone
215 // Case of a new graph as the first of the zone
214 range = variable->range();
216 range = variable->range();
215 }
217 }
216
218
217 this->addGraph(graphWidget);
219 this->addGraph(graphWidget);
218
220
219 graphWidget->addVariable(variable, range);
221 graphWidget->addVariable(variable, range);
220
222
221 // get y using variable range
223 // get y using variable range
222 if (auto dataSeries = variable->dataSeries()) {
224 if (auto dataSeries = variable->dataSeries()) {
223 dataSeries->lockRead();
225 dataSeries->lockRead();
224 auto valuesBounds
226 auto valuesBounds
225 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
227 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
226 auto end = dataSeries->cend();
228 auto end = dataSeries->cend();
227 if (valuesBounds.first != end && valuesBounds.second != end) {
229 if (valuesBounds.first != end && valuesBounds.second != end) {
228 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
230 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
229
231
230 auto minValue = rangeValue(valuesBounds.first->minValue());
232 auto minValue = rangeValue(valuesBounds.first->minValue());
231 auto maxValue = rangeValue(valuesBounds.second->maxValue());
233 auto maxValue = rangeValue(valuesBounds.second->maxValue());
232
234
233 graphWidget->setYRange(SqpRange{minValue, maxValue});
235 graphWidget->setYRange(SqpRange{minValue, maxValue});
234 }
236 }
235 dataSeries->unlock();
237 dataSeries->unlock();
236 }
238 }
237
239
238 return graphWidget;
240 return graphWidget;
239 }
241 }
240
242
241 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
243 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
242 {
244 {
243 if (visitor) {
245 if (visitor) {
244 visitor->visitEnter(this);
246 visitor->visitEnter(this);
245
247
246 // Apply visitor to graph children: widgets different from graphs are not visited (no
248 // Apply visitor to graph children: widgets different from graphs are not visited (no
247 // action)
249 // action)
248 processGraphs(
250 processGraphs(
249 *ui->visualizationZoneFrame->layout(),
251 *ui->visualizationZoneFrame->layout(),
250 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
252 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
251
253
252 visitor->visitLeave(this);
254 visitor->visitLeave(this);
253 }
255 }
254 else {
256 else {
255 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
257 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
256 }
258 }
257 }
259 }
258
260
259 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
261 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
260 {
262 {
261 // A tab can always accomodate a variable
263 // A tab can always accomodate a variable
262 Q_UNUSED(variable);
264 Q_UNUSED(variable);
263 return true;
265 return true;
264 }
266 }
265
267
266 bool VisualizationZoneWidget::contains(const Variable &variable) const
268 bool VisualizationZoneWidget::contains(const Variable &variable) const
267 {
269 {
268 Q_UNUSED(variable);
270 Q_UNUSED(variable);
269 return false;
271 return false;
270 }
272 }
271
273
272 QString VisualizationZoneWidget::name() const
274 QString VisualizationZoneWidget::name() const
273 {
275 {
274 return ui->zoneNameLabel->text();
276 return ui->zoneNameLabel->text();
275 }
277 }
276
278
277 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
279 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
278 {
280 {
279 // Closes graphs in the zone
281 // Closes graphs in the zone
280 processGraphs(*ui->visualizationZoneFrame->layout(),
282 processGraphs(*ui->visualizationZoneFrame->layout(),
281 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
283 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
282
284
283 // Delete synchronization group from variable controller
285 // Delete synchronization group from variable controller
284 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
286 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
285 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
287 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
286
288
287 QWidget::closeEvent(event);
289 QWidget::closeEvent(event);
288 }
290 }
289
291
290 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
292 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
291 {
293 {
292 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
294 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
293 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
295 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
294 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
296 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
295 }
297 }
296
298
297 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
299 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
298 {
300 {
299 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
301 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
300 Q_ARG(std::shared_ptr<Variable>, variable),
302 Q_ARG(std::shared_ptr<Variable>, variable),
301 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
303 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
302 }
304 }
General Comments 3
Under Review
author

Auto status change to "Under Review"

Approved
author

Status change > Approved

You need to be logged in to leave comments. Login now