##// END OF EJS Templates
Next range of a variable synchronized is now computed using:...
perrinel -
r627:4e5df98215ef
parent child
Show More
@@ -1,238 +1,238
1 1 #include "Variable/VariableAcquisitionWorker.h"
2 2
3 3 #include "Variable/Variable.h"
4 4
5 5 #include <Data/AcquisitionRequest.h>
6 6 #include <Data/SqpRange.h>
7 7
8 8 #include <unordered_map>
9 9 #include <utility>
10 10
11 11 #include <QMutex>
12 12 #include <QReadWriteLock>
13 13 #include <QThread>
14 14
15 15 Q_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker, "VariableAcquisitionWorker")
16 16
17 17 struct VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate {
18 18
19 19 explicit VariableAcquisitionWorkerPrivate() : m_Lock{QReadWriteLock::Recursive} {}
20 20
21 21 void lockRead() { m_Lock.lockForRead(); }
22 22 void lockWrite() { m_Lock.lockForWrite(); }
23 23 void unlock() { m_Lock.unlock(); }
24 24
25 25 void removeVariableRequest(QUuid vIdentifier);
26 26
27 27 QMutex m_WorkingMutex;
28 28 QReadWriteLock m_Lock;
29 29
30 30 std::map<QUuid, QVector<AcquisitionDataPacket> > m_AcqIdentifierToAcqDataPacketVectorMap;
31 31 std::map<QUuid, AcquisitionRequest> m_AcqIdentifierToAcqRequestMap;
32 32 std::map<QUuid, std::pair<QUuid, QUuid> > m_VIdentifierToCurrrentAcqIdNextIdPairMap;
33 33 };
34 34
35 35
36 36 VariableAcquisitionWorker::VariableAcquisitionWorker(QObject *parent)
37 37 : QObject{parent}, impl{spimpl::make_unique_impl<VariableAcquisitionWorkerPrivate>()}
38 38 {
39 39 }
40 40
41 41 VariableAcquisitionWorker::~VariableAcquisitionWorker()
42 42 {
43 43 qCInfo(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker destruction")
44 44 << QThread::currentThread();
45 45 this->waitForFinish();
46 46 }
47 47
48 48
49 49 QUuid VariableAcquisitionWorker::pushVariableRequest(QUuid varRequestId, QUuid vIdentifier,
50 50 SqpRange rangeRequested,
51 51 SqpRange cacheRangeRequested,
52 52 DataProviderParameters parameters,
53 53 std::shared_ptr<IDataProvider> provider)
54 54 {
55 qCInfo(LOG_VariableAcquisitionWorker())
55 qCDebug(LOG_VariableAcquisitionWorker())
56 56 << tr("TORM VariableAcquisitionWorker::pushVariableRequest ") << cacheRangeRequested;
57 57 auto varRequestIdCanceled = QUuid();
58 58
59 59 // Request creation
60 60 auto acqRequest = AcquisitionRequest{};
61 61 acqRequest.m_VarRequestId = varRequestId;
62 62 acqRequest.m_vIdentifier = vIdentifier;
63 63 acqRequest.m_DataProviderParameters = parameters;
64 64 acqRequest.m_RangeRequested = rangeRequested;
65 65 acqRequest.m_CacheRangeRequested = cacheRangeRequested;
66 66 acqRequest.m_Size = parameters.m_Times.size();
67 67 acqRequest.m_Provider = provider;
68 68
69 69
70 70 // Register request
71 71 impl->lockWrite();
72 72 impl->m_AcqIdentifierToAcqRequestMap.insert(
73 73 std::make_pair(acqRequest.m_AcqIdentifier, acqRequest));
74 74
75 75 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
76 76 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
77 77 // A current request already exists, we can replace the next one
78 78 auto nextAcqId = it->second.second;
79 79 auto acqIdentifierToAcqRequestMapIt = impl->m_AcqIdentifierToAcqRequestMap.find(nextAcqId);
80 80 if (acqIdentifierToAcqRequestMapIt != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
81 81 auto request = acqIdentifierToAcqRequestMapIt->second;
82 82 varRequestIdCanceled = request.m_VarRequestId;
83 83 }
84 84
85 85 it->second.second = acqRequest.m_AcqIdentifier;
86 86 impl->unlock();
87 87 }
88 88 else {
89 89 // First request for the variable, it must be stored and executed
90 90 impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.insert(
91 91 std::make_pair(vIdentifier, std::make_pair(acqRequest.m_AcqIdentifier, QUuid())));
92 92 impl->unlock();
93 93
94 94 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
95 95 Q_ARG(QUuid, acqRequest.m_AcqIdentifier));
96 96 }
97 97
98 98 return varRequestIdCanceled;
99 99 }
100 100
101 101 void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier)
102 102 {
103 103 // TODO
104 104 }
105 105
106 106 void VariableAcquisitionWorker::onVariableRetrieveDataInProgress(QUuid acqIdentifier,
107 107 double progress)
108 108 {
109 109 // TODO
110 110 }
111 111
112 112 void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier,
113 113 std::shared_ptr<IDataSeries> dataSeries,
114 114 SqpRange dataRangeAcquired)
115 115 {
116 116 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onVariableDataAcquired on range ")
117 117 << acqIdentifier << dataRangeAcquired;
118 118 impl->lockWrite();
119 119 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
120 120 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
121 121 // Store the result
122 122 auto dataPacket = AcquisitionDataPacket{};
123 123 dataPacket.m_Range = dataRangeAcquired;
124 124 dataPacket.m_DateSeries = dataSeries;
125 125
126 126 auto aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
127 127 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
128 128 // A current request result already exists, we can update it
129 129 aIdToADPVit->second.push_back(dataPacket);
130 130 }
131 131 else {
132 132 // First request result for the variable, it must be stored
133 133 impl->m_AcqIdentifierToAcqDataPacketVectorMap.insert(
134 134 std::make_pair(acqIdentifier, QVector<AcquisitionDataPacket>() << dataPacket));
135 135 }
136 136
137 137
138 138 // Decrement the counter of the request
139 139 auto &acqRequest = aIdToARit->second;
140 140 acqRequest.m_Size = acqRequest.m_Size - 1;
141 141
142 142 // if the counter is 0, we can return data then run the next request if it exists and
143 143 // removed the finished request
144 144 if (acqRequest.m_Size == 0) {
145 145 // Return the data
146 146 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
147 147 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
148 148 emit dataProvided(acqRequest.m_vIdentifier, acqRequest.m_RangeRequested,
149 149 acqRequest.m_CacheRangeRequested, aIdToADPVit->second);
150 150 }
151 151
152 152 // Execute the next one
153 153 auto it
154 154 = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(acqRequest.m_vIdentifier);
155 155
156 156 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
157 157 if (it->second.second.isNull()) {
158 158 // There is no next request, we can remove the variable request
159 159 impl->removeVariableRequest(acqRequest.m_vIdentifier);
160 160 }
161 161 else {
162 162 auto acqIdentifierToRemove = it->second.first;
163 163 // Move the next request to the current request
164 164 it->second.first = it->second.second;
165 165 it->second.second = QUuid();
166 166 // Remove AcquisitionRequest and results;
167 167 impl->m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
168 168 impl->m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
169 169 // Execute the current request
170 170 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
171 171 Q_ARG(QUuid, it->second.first));
172 172 }
173 173 }
174 174 else {
175 175 qCCritical(LOG_VariableAcquisitionWorker())
176 176 << tr("Impossible to execute the acquisition on an unfound variable ");
177 177 }
178 178 }
179 179 }
180 180 else {
181 181 qCCritical(LOG_VariableAcquisitionWorker())
182 182 << tr("Impossible to retrieve AcquisitionRequest for the incoming data");
183 183 }
184 184 impl->unlock();
185 185 }
186 186
187 187 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
188 188 {
189 qCInfo(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread();
189 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread();
190 190 impl->lockRead();
191 191 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
192 192 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
193 193 auto request = it->second;
194 194 impl->unlock();
195 195 request.m_Provider->requestDataLoading(acqIdentifier, request.m_DataProviderParameters);
196 196 }
197 197 else {
198 198 impl->unlock();
199 199 // TODO log no acqIdentifier recognized
200 200 }
201 201 }
202 202
203 203 void VariableAcquisitionWorker::initialize()
204 204 {
205 205 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init")
206 206 << QThread::currentThread();
207 207 impl->m_WorkingMutex.lock();
208 208 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init END");
209 209 }
210 210
211 211 void VariableAcquisitionWorker::finalize()
212 212 {
213 213 impl->m_WorkingMutex.unlock();
214 214 }
215 215
216 216 void VariableAcquisitionWorker::waitForFinish()
217 217 {
218 218 QMutexLocker locker{&impl->m_WorkingMutex};
219 219 }
220 220
221 221 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariableRequest(
222 222 QUuid vIdentifier)
223 223 {
224 224 lockWrite();
225 225 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
226 226
227 227 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
228 228 // A current request already exists, we can replace the next one
229 229
230 230 m_AcqIdentifierToAcqRequestMap.erase(it->second.first);
231 231 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.first);
232 232
233 233 m_AcqIdentifierToAcqRequestMap.erase(it->second.second);
234 234 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.second);
235 235 }
236 236 m_VIdentifierToCurrrentAcqIdNextIdPairMap.erase(vIdentifier);
237 237 unlock();
238 238 }
@@ -1,734 +1,738
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableAcquisitionWorker.h>
3 #include <Variable/VariableCacheController.h>
4 3 #include <Variable/VariableCacheStrategy.h>
5 4 #include <Variable/VariableController.h>
6 5 #include <Variable/VariableModel.h>
7 6 #include <Variable/VariableSynchronizationGroup.h>
8 7
9 8 #include <Data/DataProviderParameters.h>
10 9 #include <Data/IDataProvider.h>
11 10 #include <Data/IDataSeries.h>
12 11 #include <Data/VariableRequest.h>
13 12 #include <Time/TimeController.h>
14 13
15 14 #include <QMutex>
16 15 #include <QThread>
17 16 #include <QUuid>
18 17 #include <QtCore/QItemSelectionModel>
19 18
20 19 #include <deque>
21 20 #include <set>
22 21 #include <unordered_map>
23 22
24 23 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
25 24
26 25 namespace {
27 26
28 27 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
29 28 const SqpRange &oldGraphRange)
30 29 {
31 30 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
32 31
33 32 auto varRangeRequested = varRange;
34 33 switch (zoomType) {
35 34 case AcquisitionZoomType::ZoomIn: {
36 35 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
37 36 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
38 37 varRangeRequested.m_TStart += deltaLeft;
39 38 varRangeRequested.m_TEnd -= deltaRight;
40 39 break;
41 40 }
42 41
43 42 case AcquisitionZoomType::ZoomOut: {
44 43 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
45 44 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
46 45 varRangeRequested.m_TStart -= deltaLeft;
47 46 varRangeRequested.m_TEnd += deltaRight;
48 47 break;
49 48 }
50 49 case AcquisitionZoomType::PanRight: {
51 50 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
52 51 varRangeRequested.m_TStart += deltaRight;
53 52 varRangeRequested.m_TEnd += deltaRight;
54 53 break;
55 54 }
56 55 case AcquisitionZoomType::PanLeft: {
57 56 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
58 57 varRangeRequested.m_TStart -= deltaLeft;
59 58 varRangeRequested.m_TEnd -= deltaLeft;
60 59 break;
61 60 }
62 61 case AcquisitionZoomType::Unknown: {
63 62 qCCritical(LOG_VariableController())
64 63 << VariableController::tr("Impossible to synchronize: zoom type unknown");
65 64 break;
66 65 }
67 66 default:
68 67 qCCritical(LOG_VariableController()) << VariableController::tr(
69 68 "Impossible to synchronize: zoom type not take into account");
70 69 // No action
71 70 break;
72 71 }
73 72
74 73 return varRangeRequested;
75 74 }
76 75 }
77 76
78 77 struct VariableController::VariableControllerPrivate {
79 78 explicit VariableControllerPrivate(VariableController *parent)
80 79 : m_WorkingMutex{},
81 80 m_VariableModel{new VariableModel{parent}},
82 81 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
83 m_VariableCacheController{std::make_unique<VariableCacheController>()},
84 82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
85 83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
86 84 q{parent}
87 85 {
88 86
89 87 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
90 88 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
91 89 }
92 90
93 91
94 92 virtual ~VariableControllerPrivate()
95 93 {
96 94 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
97 95 m_VariableAcquisitionWorkerThread.quit();
98 96 m_VariableAcquisitionWorkerThread.wait();
99 97 }
100 98
101 99
102 100 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
103 101 QUuid varRequestId);
104 102
105 103 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
106 104 const SqpRange &dateTime);
107 105
108 106 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
109 107 std::shared_ptr<IDataSeries>
110 108 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
111 109
112 110 void registerProvider(std::shared_ptr<IDataProvider> provider);
113 111
114 112 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
115 113 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
116 114 void updateVariableRequest(QUuid varRequestId);
117 115 void cancelVariableRequest(QUuid varRequestId);
118 116
119 117 QMutex m_WorkingMutex;
120 118 /// Variable model. The VariableController has the ownership
121 119 VariableModel *m_VariableModel;
122 120 QItemSelectionModel *m_VariableSelectionModel;
123 121
124 122
125 123 TimeController *m_TimeController{nullptr};
126 std::unique_ptr<VariableCacheController> m_VariableCacheController;
127 124 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
128 125 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
129 126 QThread m_VariableAcquisitionWorkerThread;
130 127
131 128 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
132 129 m_VariableToProviderMap;
133 130 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
134 131 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
135 132 m_GroupIdToVariableSynchronizationGroupMap;
136 133 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
137 134 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
138 135
139 136 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
140 137
141 138 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
142 139
143 140
144 141 VariableController *q;
145 142 };
146 143
147 144
148 145 VariableController::VariableController(QObject *parent)
149 146 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
150 147 {
151 148 qCDebug(LOG_VariableController()) << tr("VariableController construction")
152 149 << QThread::currentThread();
153 150
154 151 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
155 152 &VariableController::onAbortProgressRequested);
156 153
157 154 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
158 155 &VariableController::onDataProvided);
159 156 connect(impl->m_VariableAcquisitionWorker.get(),
160 157 &VariableAcquisitionWorker::variableRequestInProgress, this,
161 158 &VariableController::onVariableRetrieveDataInProgress);
162 159
163 160 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
164 161 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
165 162 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
166 163 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
167 164
168 165
169 166 impl->m_VariableAcquisitionWorkerThread.start();
170 167 }
171 168
172 169 VariableController::~VariableController()
173 170 {
174 171 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
175 172 << QThread::currentThread();
176 173 this->waitForFinish();
177 174 }
178 175
179 176 VariableModel *VariableController::variableModel() noexcept
180 177 {
181 178 return impl->m_VariableModel;
182 179 }
183 180
184 181 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
185 182 {
186 183 return impl->m_VariableSelectionModel;
187 184 }
188 185
189 186 void VariableController::setTimeController(TimeController *timeController) noexcept
190 187 {
191 188 impl->m_TimeController = timeController;
192 189 }
193 190
194 191 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
195 192 {
196 193 if (!variable) {
197 194 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
198 195 return;
199 196 }
200 197
201 198 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
202 199 // make some treatments before the deletion
203 200 emit variableAboutToBeDeleted(variable);
204 201
205 202 // Deletes identifier
206 203 impl->m_VariableToIdentifierMap.erase(variable);
207 204
208 205 // Deletes provider
209 206 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
210 207 qCDebug(LOG_VariableController())
211 208 << tr("Number of providers deleted for variable %1: %2")
212 209 .arg(variable->name(), QString::number(nbProvidersDeleted));
213 210
214 // Clears cache
215 impl->m_VariableCacheController->clear(variable);
216 211
217 212 // Deletes from model
218 213 impl->m_VariableModel->deleteVariable(variable);
219 214 }
220 215
221 216 void VariableController::deleteVariables(
222 217 const QVector<std::shared_ptr<Variable> > &variables) noexcept
223 218 {
224 219 for (auto variable : qAsConst(variables)) {
225 220 deleteVariable(variable);
226 221 }
227 222 }
228 223
229 224 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
230 225 {
231 226 }
232 227
233 228 std::shared_ptr<Variable>
234 229 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
235 230 std::shared_ptr<IDataProvider> provider) noexcept
236 231 {
237 232 if (!impl->m_TimeController) {
238 233 qCCritical(LOG_VariableController())
239 234 << tr("Impossible to create variable: The time controller is null");
240 235 return nullptr;
241 236 }
242 237
243 238 auto range = impl->m_TimeController->dateTime();
244 239
245 240 if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) {
246 241 auto identifier = QUuid::createUuid();
247 242
248 243 // store the provider
249 244 impl->registerProvider(provider);
250 245
251 246 // Associate the provider
252 247 impl->m_VariableToProviderMap[newVariable] = provider;
253 248 impl->m_VariableToIdentifierMap[newVariable] = identifier;
254 249
255 250
256 251 auto varRequestId = QUuid::createUuid();
257 252 qCInfo(LOG_VariableController()) << "processRequest for" << name << varRequestId;
258 253 impl->processRequest(newVariable, range, varRequestId);
259 254 impl->updateVariableRequest(varRequestId);
260 255
261 256 return newVariable;
262 257 }
263 258 }
264 259
265 260 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
266 261 {
267 262 // TODO check synchronisation and Rescale
268 263 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
269 264 << QThread::currentThread()->objectName();
270 265 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
271 266 auto varRequestId = QUuid::createUuid();
272 267
273 268 for (const auto &selectedRow : qAsConst(selectedRows)) {
274 269 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
275 270 selectedVariable->setRange(dateTime);
276 271 impl->processRequest(selectedVariable, dateTime, varRequestId);
277 272
278 273 // notify that rescale operation has to be done
279 274 emit rangeChanged(selectedVariable, dateTime);
280 275 }
281 276 }
282 277 impl->updateVariableRequest(varRequestId);
283 278 }
284 279
285 280 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
286 281 const SqpRange &cacheRangeRequested,
287 282 QVector<AcquisitionDataPacket> dataAcquired)
288 283 {
289 284 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
290 285 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
291 286 if (!varRequestId.isNull()) {
292 287 impl->updateVariableRequest(varRequestId);
293 288 }
294 289 }
295 290
296 291 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
297 292 {
298 293 if (auto var = impl->findVariable(identifier)) {
299 294 impl->m_VariableModel->setDataProgress(var, progress);
300 295 }
301 296 else {
302 297 qCCritical(LOG_VariableController())
303 298 << tr("Impossible to notify progression of a null variable");
304 299 }
305 300 }
306 301
307 302 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
308 303 {
309 304 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
310 305 << QThread::currentThread()->objectName();
311 306
312 307 auto it = impl->m_VariableToIdentifierMap.find(variable);
313 308 if (it != impl->m_VariableToIdentifierMap.cend()) {
314 309 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
315 310 }
316 311 else {
317 312 qCWarning(LOG_VariableController())
318 313 << tr("Aborting progression of inexistant variable detected !!!")
319 314 << QThread::currentThread()->objectName();
320 315 }
321 316 }
322 317
323 318 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
324 319 {
325 320 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
326 321 << QThread::currentThread()->objectName()
327 322 << synchronizationGroupId;
328 323 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
329 324 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
330 325 std::make_pair(synchronizationGroupId, vSynchroGroup));
331 326 }
332 327
333 328 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
334 329 {
335 330 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
336 331 }
337 332
338 333 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
339 334 QUuid synchronizationGroupId)
340 335
341 336 {
342 337 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
343 338 << synchronizationGroupId;
344 339 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
345 340 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
346 341 auto groupIdToVSGIt
347 342 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
348 343 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
349 344 impl->m_VariableIdGroupIdMap.insert(
350 345 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
351 346 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
352 347 }
353 348 else {
354 349 qCCritical(LOG_VariableController())
355 350 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
356 351 << variable->name();
357 352 }
358 353 }
359 354 else {
360 355 qCCritical(LOG_VariableController())
361 356 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
362 357 }
363 358 }
364 359
365 360
366 361 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
367 362 const SqpRange &range, const SqpRange &oldRange,
368 363 bool synchronise)
369 364 {
370 365 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
371 366
372 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
373 << QThread::currentThread()->objectName();
374 367 // we want to load data of the variable for the dateTime.
375 368 // First we check if the cache contains some of them.
376 369 // For the other, we ask the provider to give them.
377 370
378 371 auto varRequestId = QUuid::createUuid();
372 qCInfo(LOG_VariableController()) << "VariableController::onRequestDataLoading"
373 << QThread::currentThread()->objectName() << varRequestId;
379 374
380 375 for (const auto &var : variables) {
381 qCInfo(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
376 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
382 377 impl->processRequest(var, range, varRequestId);
383 378 }
384 379
385 380 if (synchronise) {
386 381 // Get the group ids
387 382 qCDebug(LOG_VariableController())
388 383 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
389 auto groupIds = std::set<QUuid>();
384 auto groupIds = std::set<QUuid>{};
385 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
390 386 for (const auto &var : variables) {
391 387 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
392 388 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
393 389 auto vId = varToVarIdIt->second;
394 390 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
395 391 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
396 392 auto gId = varIdToGroupIdIt->second;
393 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
397 394 if (groupIds.find(gId) == groupIds.cend()) {
398 395 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
399 396 groupIds.insert(gId);
400 397 }
401 398 }
402 399 }
403 400 }
404 401
405 402 // We assume here all group ids exist
406 403 for (const auto &gId : groupIds) {
407 404 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
408 405 auto vSyncIds = vSynchronizationGroup->getIds();
409 406 qCDebug(LOG_VariableController()) << "Var in synchro group ";
410 407 for (auto vId : vSyncIds) {
411 408 auto var = impl->findVariable(vId);
412 409
413 410 // Don't process already processed var
414 411 if (!variables.contains(var)) {
415 412 if (var != nullptr) {
416 413 qCDebug(LOG_VariableController()) << "processRequest synchro for"
417 414 << var->name();
418 auto vSyncRangeRequested
419 = computeSynchroRangeRequested(var->range(), range, oldRange);
415 auto vSyncRangeRequested = computeSynchroRangeRequested(
416 var->range(), range, groupIdToOldRangeMap.at(gId));
417 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
420 418 impl->processRequest(var, vSyncRangeRequested, varRequestId);
421 419 }
422 420 else {
423 421 qCCritical(LOG_VariableController())
424 422
425 423 << tr("Impossible to synchronize a null variable");
426 424 }
427 425 }
428 426 }
429 427 }
430 428 }
431 429
432 430 impl->updateVariableRequest(varRequestId);
433 431 }
434 432
435 433
436 434 void VariableController::initialize()
437 435 {
438 436 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
439 437 impl->m_WorkingMutex.lock();
440 438 qCDebug(LOG_VariableController()) << tr("VariableController init END");
441 439 }
442 440
443 441 void VariableController::finalize()
444 442 {
445 443 impl->m_WorkingMutex.unlock();
446 444 }
447 445
448 446 void VariableController::waitForFinish()
449 447 {
450 448 QMutexLocker locker{&impl->m_WorkingMutex};
451 449 }
452 450
453 451 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
454 452 {
455 453 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
456 454 auto zoomType = AcquisitionZoomType::Unknown;
457 455 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
458 456 zoomType = AcquisitionZoomType::ZoomOut;
459 457 }
460 458 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
461 459 zoomType = AcquisitionZoomType::PanRight;
462 460 }
463 461 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
464 462 zoomType = AcquisitionZoomType::PanLeft;
465 463 }
466 464 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
467 465 zoomType = AcquisitionZoomType::ZoomIn;
468 466 }
469 467 else {
470 468 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
471 469 }
472 470 return zoomType;
473 471 }
474 472
475 473 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
476 474 const SqpRange &rangeRequested,
477 475 QUuid varRequestId)
478 476 {
479 477
480 478 // TODO: protect at
481 479 auto varRequest = VariableRequest{};
482 480 auto varId = m_VariableToIdentifierMap.at(var);
483 481
484
485 482 auto varStrategyRangesRequested
486 483 = m_VariableCacheStrategy->computeStrategyRanges(var->range(), rangeRequested);
487 484 auto notInCacheRangeList = var->provideNotInCacheRangeList(varStrategyRangesRequested.second);
488 485 auto inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second);
489 486
490 487 if (!notInCacheRangeList.empty()) {
491 488 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
492 489 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
490 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest RR ") << rangeRequested;
491 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest R ")
492 << varStrategyRangesRequested.first;
493 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest CR ")
494 << varStrategyRangesRequested.second;
493 495 // store VarRequest
494 496 storeVariableRequest(varId, varRequestId, varRequest);
495 497
496 498 auto varProvider = m_VariableToProviderMap.at(var);
497 499 if (varProvider != nullptr) {
498 500 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
499 501 varRequestId, varId, varStrategyRangesRequested.first,
500 502 varStrategyRangesRequested.second,
501 503 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
502 504 varProvider);
503 505
504 506 if (!varRequestIdCanceled.isNull()) {
507 qCInfo(LOG_VariableAcquisitionWorker()) << tr("varRequestIdCanceled: ")
508 << varRequestIdCanceled;
505 509 cancelVariableRequest(varRequestIdCanceled);
506 510 }
507 511 }
508 512 else {
509 513 qCCritical(LOG_VariableController())
510 514 << "Impossible to provide data with a null provider";
511 515 }
512 516
513 517 if (!inCacheRangeList.empty()) {
514 518 emit q->updateVarDisplaying(var, inCacheRangeList.first());
515 519 }
516 520 }
517 521 else {
518 522
519 523 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
520 524 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
521 525 // store VarRequest
522 526 storeVariableRequest(varId, varRequestId, varRequest);
523 527 acceptVariableRequest(varId,
524 528 var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
525 529 }
526 530 }
527 531
528 532 std::shared_ptr<Variable>
529 533 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
530 534 {
531 535 std::shared_ptr<Variable> var;
532 536 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
533 537
534 538 auto end = m_VariableToIdentifierMap.cend();
535 539 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
536 540 if (it != end) {
537 541 var = it->first;
538 542 }
539 543 else {
540 544 qCCritical(LOG_VariableController())
541 545 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
542 546 }
543 547
544 548 return var;
545 549 }
546 550
547 551 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
548 552 const QVector<AcquisitionDataPacket> acqDataPacketVector)
549 553 {
550 554 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
551 555 << acqDataPacketVector.size();
552 556 std::shared_ptr<IDataSeries> dataSeries;
553 557 if (!acqDataPacketVector.isEmpty()) {
554 558 dataSeries = acqDataPacketVector[0].m_DateSeries;
555 559 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
556 560 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
557 561 }
558 562 }
559 563 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
560 564 << acqDataPacketVector.size();
561 565 return dataSeries;
562 566 }
563 567
564 568 void VariableController::VariableControllerPrivate::registerProvider(
565 569 std::shared_ptr<IDataProvider> provider)
566 570 {
567 571 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
568 572 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
569 573 << provider->objectName();
570 574 m_ProviderSet.insert(provider);
571 575 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
572 576 &VariableAcquisitionWorker::onVariableDataAcquired);
573 577 connect(provider.get(), &IDataProvider::dataProvidedProgress,
574 578 m_VariableAcquisitionWorker.get(),
575 579 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
576 580 }
577 581 else {
578 582 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
579 583 }
580 584 }
581 585
582 586 void VariableController::VariableControllerPrivate::storeVariableRequest(
583 587 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
584 588 {
585 589 // First request for the variable. we can create an entry for it
586 590 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
587 591 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
588 592 auto varRequestIdQueue = std::deque<QUuid>{};
589 593 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
590 594 varRequestIdQueue.push_back(varRequestId);
591 595 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
592 596 }
593 597 else {
594 598 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
595 599 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
596 600 varRequestIdQueue.push_back(varRequestId);
597 601 }
598 602
599 603 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
600 604 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
601 605 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
602 606 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
603 607 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
604 608 m_VarRequestIdToVarIdVarRequestMap.insert(
605 609 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
606 610 }
607 611 else {
608 612 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
609 613 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
610 614 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
611 615 }
612 616 }
613 617
614 618 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
615 619 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
616 620 {
617 621 QUuid varRequestId;
618 622 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
619 623 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
620 624 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
621 625 varRequestId = varRequestIdQueue.front();
622 626 auto varRequestIdToVarIdVarRequestMapIt
623 627 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
624 628 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
625 629 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
626 630 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
627 631 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
628 632 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
629 633 auto &varRequest = varIdToVarRequestMapIt->second;
630 634 varRequest.m_DataSeries = dataSeries;
631 635 varRequest.m_CanUpdate = true;
632 636 }
633 637 else {
634 638 qCDebug(LOG_VariableController())
635 639 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
636 640 "to a variableRequestId")
637 641 << varRequestId << varId;
638 642 }
639 643 }
640 644 else {
641 645 qCCritical(LOG_VariableController())
642 646 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
643 647 << varRequestId;
644 648 }
645 649
646 650 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in QUEUE ?")
647 651 << varRequestIdQueue.size();
648 652 varRequestIdQueue.pop_front();
649 653 qCDebug(LOG_VariableController()) << tr("2: erase REQUEST in QUEUE ?")
650 654 << varRequestIdQueue.size();
651 655 if (varRequestIdQueue.empty()) {
652 656 m_VarIdToVarRequestIdQueueMap.erase(varId);
653 657 }
654 658 }
655 659 else {
656 660 qCCritical(LOG_VariableController())
657 661 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
658 662 }
659 663
660 664 return varRequestId;
661 665 }
662 666
663 667 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
664 668 {
665 669
666 670 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
667 671 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
668 672 bool processVariableUpdate = true;
669 673 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
670 674 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
671 675 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
672 676 ++varIdToVarRequestMapIt) {
673 677 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
674 678 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
675 679 << processVariableUpdate;
676 680 }
677 681
678 682 if (processVariableUpdate) {
679 683 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
680 684 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
681 685 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
682 686 auto &varRequest = varIdToVarRequestMapIt->second;
683 687 var->setRange(varRequest.m_RangeRequested);
684 688 var->setCacheRange(varRequest.m_CacheRangeRequested);
685 qCInfo(LOG_VariableController()) << tr("1: onDataProvided")
686 << varRequest.m_RangeRequested;
687 qCInfo(LOG_VariableController()) << tr("2: onDataProvided")
688 << varRequest.m_CacheRangeRequested;
689 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
690 << varRequest.m_RangeRequested;
691 qCDebug(LOG_VariableController()) << tr("2: onDataProvided")
692 << varRequest.m_CacheRangeRequested;
689 693 var->mergeDataSeries(varRequest.m_DataSeries);
690 qCInfo(LOG_VariableController()) << tr("3: onDataProvided")
691 << varRequest.m_DataSeries->range();
694 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
695 << varRequest.m_DataSeries->range();
692 696 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
693 697 emit var->updated();
694 698 }
695 699 else {
696 700 qCCritical(LOG_VariableController())
697 701 << tr("Impossible to update data to a null variable");
698 702 }
699 703 }
700 704
701 705 // cleaning varRequestId
702 706 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
703 707 << m_VarRequestIdToVarIdVarRequestMap.size();
704 708 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
705 709 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
706 710 << m_VarRequestIdToVarIdVarRequestMap.size();
707 711 }
708 712 }
709 713 else {
710 714 qCCritical(LOG_VariableController())
711 715 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
712 716 }
713 717 }
714 718
715 719 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
716 720 {
717 721 // cleaning varRequestId
718 722 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
719 723
720 724 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
721 725 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
722 726 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
723 727 varRequestIdQueue.erase(
724 728 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
725 729 varRequestIdQueue.end());
726 730 if (varRequestIdQueue.empty()) {
727 731 varIdToVarRequestIdQueueMapIt
728 732 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
729 733 }
730 734 else {
731 735 ++varIdToVarRequestIdQueueMapIt;
732 736 }
733 737 }
734 738 }
@@ -1,257 +1,257
1 1 #include "Visualization/VisualizationZoneWidget.h"
2 2
3 3
4 4 #include "Visualization/IVisualizationWidgetVisitor.h"
5 5 #include "Visualization/VisualizationGraphWidget.h"
6 6 #include "ui_VisualizationZoneWidget.h"
7 7
8 8 #include <Data/SqpRange.h>
9 9 #include <Variable/Variable.h>
10 10 #include <Variable/VariableController.h>
11 11
12 12 #include <QUuid>
13 13 #include <SqpApplication.h>
14 14 #include <cmath>
15 15
16 16 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
17 17
18 18 namespace {
19 19
20 20 /// Minimum height for graph added in zones (in pixels)
21 21 const auto GRAPH_MINIMUM_HEIGHT = 300;
22 22
23 23 /// Generates a default name for a new graph, according to the number of graphs already displayed in
24 24 /// the zone
25 25 QString defaultGraphName(const QLayout &layout)
26 26 {
27 27 auto count = 0;
28 28 for (auto i = 0; i < layout.count(); ++i) {
29 29 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
30 30 count++;
31 31 }
32 32 }
33 33
34 34 return QObject::tr("Graph %1").arg(count + 1);
35 35 }
36 36
37 37 } // namespace
38 38
39 39 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
40 40
41 41 explicit VisualizationZoneWidgetPrivate() : m_SynchronisationGroupId{QUuid::createUuid()} {}
42 42 QUuid m_SynchronisationGroupId;
43 43 };
44 44
45 45 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
46 46 : QWidget{parent},
47 47 ui{new Ui::VisualizationZoneWidget},
48 48 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
49 49 {
50 50 ui->setupUi(this);
51 51
52 52 ui->zoneNameLabel->setText(name);
53 53
54 54 // 'Close' options : widget is deleted when closed
55 55 setAttribute(Qt::WA_DeleteOnClose);
56 56 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
57 57 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
58 58
59 59 // Synchronisation id
60 60 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
61 61 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
62 62 }
63 63
64 64 VisualizationZoneWidget::~VisualizationZoneWidget()
65 65 {
66 66 delete ui;
67 67 }
68 68
69 69 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
70 70 {
71 71 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
72 72 }
73 73
74 74 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
75 75 {
76 76 auto graphWidget = new VisualizationGraphWidget{
77 77 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
78 78
79 79
80 80 // Set graph properties
81 81 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
82 82 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
83 83
84 84
85 85 // Lambda to synchronize zone widget
86 86 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
87 87 const SqpRange &oldGraphRange) {
88 88
89 89 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
90 90 auto frameLayout = ui->visualizationZoneFrame->layout();
91 91 for (auto i = 0; i < frameLayout->count(); ++i) {
92 92 auto graphChild
93 93 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
94 94 if (graphChild && (graphChild != graphWidget)) {
95 95
96 96 auto graphChildRange = graphChild->graphRange();
97 97 switch (zoomType) {
98 98 case AcquisitionZoomType::ZoomIn: {
99 99 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
100 100 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
101 101 graphChildRange.m_TStart += deltaLeft;
102 102 graphChildRange.m_TEnd -= deltaRight;
103 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
104 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
105 << deltaLeft;
106 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
107 << deltaRight;
108 qCCritical(LOG_VisualizationZoneWidget())
103 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
104 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
105 << deltaLeft;
106 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
107 << deltaRight;
108 qCDebug(LOG_VisualizationZoneWidget())
109 109 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
110 110
111 111 break;
112 112 }
113 113
114 114 case AcquisitionZoomType::ZoomOut: {
115 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
115 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
116 116 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
117 117 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
118 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
119 << deltaLeft;
120 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
121 << deltaRight;
122 qCCritical(LOG_VisualizationZoneWidget())
118 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
119 << deltaLeft;
120 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
121 << deltaRight;
122 qCDebug(LOG_VisualizationZoneWidget())
123 123 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
124 124 graphChildRange.m_TStart -= deltaLeft;
125 125 graphChildRange.m_TEnd += deltaRight;
126 126 break;
127 127 }
128 128 case AcquisitionZoomType::PanRight: {
129 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
129 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
130 130 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
131 131 graphChildRange.m_TStart += deltaRight;
132 132 graphChildRange.m_TEnd += deltaRight;
133 qCCritical(LOG_VisualizationZoneWidget())
133 qCDebug(LOG_VisualizationZoneWidget())
134 134 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
135 135 break;
136 136 }
137 137 case AcquisitionZoomType::PanLeft: {
138 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
138 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
139 139 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
140 140 graphChildRange.m_TStart -= deltaLeft;
141 141 graphChildRange.m_TEnd -= deltaLeft;
142 142 break;
143 143 }
144 144 case AcquisitionZoomType::Unknown: {
145 qCCritical(LOG_VisualizationZoneWidget())
145 qCDebug(LOG_VisualizationZoneWidget())
146 146 << tr("Impossible to synchronize: zoom type unknown");
147 147 break;
148 148 }
149 149 default:
150 150 qCCritical(LOG_VisualizationZoneWidget())
151 151 << tr("Impossible to synchronize: zoom type not take into account");
152 152 // No action
153 153 break;
154 154 }
155 155 graphChild->enableAcquisition(false);
156 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
157 << graphChild->graphRange();
158 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
159 << graphChildRange;
160 qCCritical(LOG_VisualizationZoneWidget())
156 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
157 << graphChild->graphRange();
158 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
159 << graphChildRange;
160 qCDebug(LOG_VisualizationZoneWidget())
161 161 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
162 162 graphChild->setGraphRange(graphChildRange);
163 163 graphChild->enableAcquisition(true);
164 164 }
165 165 }
166 166 };
167 167
168 168 // connection for synchronization
169 169 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
170 170 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
171 171 &VisualizationZoneWidget::onVariableAdded);
172 172
173 173 auto range = SqpRange{};
174 174
175 175 // Apply visitor to graph children
176 176 auto layout = ui->visualizationZoneFrame->layout();
177 177 if (layout->count() > 0) {
178 178 // Case of a new graph in a existant zone
179 179 if (auto visualizationGraphWidget
180 180 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
181 181 range = visualizationGraphWidget->graphRange();
182 182 }
183 183 }
184 184 else {
185 185 // Case of a new graph as the first of the zone
186 186 range = variable->range();
187 187 }
188 188
189 189 this->addGraph(graphWidget);
190 190
191 191 graphWidget->addVariable(variable, range);
192 192
193 193 // get y using variable range
194 194 if (auto dataSeries = variable->dataSeries()) {
195 195 auto valuesBounds = dataSeries->valuesBounds(range.m_TStart, range.m_TEnd);
196 196 auto end = dataSeries->cend();
197 197 if (valuesBounds.first != end && valuesBounds.second != end) {
198 198 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
199 199
200 200 auto minValue = rangeValue(valuesBounds.first->minValue());
201 201 auto maxValue = rangeValue(valuesBounds.second->maxValue());
202 202
203 203 graphWidget->setYRange(SqpRange{minValue, maxValue});
204 204 }
205 205 }
206 206
207 207 return graphWidget;
208 208 }
209 209
210 210 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
211 211 {
212 212 if (visitor) {
213 213 visitor->visitEnter(this);
214 214
215 215 // Apply visitor to graph children
216 216 auto layout = ui->visualizationZoneFrame->layout();
217 217 for (auto i = 0; i < layout->count(); ++i) {
218 218 if (auto item = layout->itemAt(i)) {
219 219 // Widgets different from graphs are not visited (no action)
220 220 if (auto visualizationGraphWidget
221 221 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
222 222 visualizationGraphWidget->accept(visitor);
223 223 }
224 224 }
225 225 }
226 226
227 227 visitor->visitLeave(this);
228 228 }
229 229 else {
230 230 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
231 231 }
232 232 }
233 233
234 234 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
235 235 {
236 236 // A tab can always accomodate a variable
237 237 Q_UNUSED(variable);
238 238 return true;
239 239 }
240 240
241 241 bool VisualizationZoneWidget::contains(const Variable &variable) const
242 242 {
243 243 Q_UNUSED(variable);
244 244 return false;
245 245 }
246 246
247 247 QString VisualizationZoneWidget::name() const
248 248 {
249 249 return ui->zoneNameLabel->text();
250 250 }
251 251
252 252 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
253 253 {
254 254 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
255 255 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
256 256 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
257 257 }
@@ -1,197 +1,197
1 1 #include "AmdaProvider.h"
2 2 #include "AmdaResultParser.h"
3 3
4 4 #include "SqpApplication.h"
5 5 #include <Data/DataSeries.h>
6 6 #include <Data/IDataSeries.h>
7 7 #include <Data/ScalarSeries.h>
8 8 #include <Time/TimeController.h>
9 9 #include <Variable/Variable.h>
10 10 #include <Variable/VariableController.h>
11 11
12 12 #include <QObject>
13 13 #include <QtTest>
14 14
15 15 #include <memory>
16 16
17 17 // TEST with REF:
18 18 // AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00
19 19 // imf(0) - Type : Local Parameter @ CDPP/AMDA -
20 20 // Name : bx_gse - Units : nT - Size : 1 -
21 21 // Frame : GSE - Mission : ACE -
22 22 // Instrument : MFI - Dataset : mfi_final-prelim
23 23 // REFERENCE DOWNLOAD FILE =
24 24 // http://amda.irap.omp.eu/php/rest/getParameter.php?startTime=2012-01-01T12:00:00&stopTime=2012-01-03T12:00:00&parameterID=imf(0)&outputFormat=ASCII&timeFormat=ISO8601&gzip=0
25 25
26 26 namespace {
27 27
28 28 /// Path for the tests
29 29 const auto TESTS_RESOURCES_PATH
30 30 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaAcquisition"}.absoluteFilePath();
31 31
32 32 const auto TESTS_AMDA_REF_FILE = QString{"AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00.txt"};
33 33
34 34 template <typename T>
35 35 bool compareDataSeries(std::shared_ptr<IDataSeries> candidate, SqpRange candidateCacheRange,
36 36 std::shared_ptr<IDataSeries> reference)
37 37 {
38 38 auto compareLambda = [](const auto &it1, const auto &it2) {
39 39 return (it1.x() == it2.x()) && (it1.value() == it2.value());
40 40 };
41 41
42 42 auto candidateDS = std::dynamic_pointer_cast<T>(candidate);
43 43 auto referenceDS = std::dynamic_pointer_cast<T>(reference);
44 44
45 45 if (candidateDS && referenceDS) {
46 46
47 47 auto itRefs
48 48 = referenceDS->xAxisRange(candidateCacheRange.m_TStart, candidateCacheRange.m_TEnd);
49 49 qDebug() << " DISTANCE" << std::distance(candidateDS->cbegin(), candidateDS->cend())
50 50 << std::distance(itRefs.first, itRefs.second);
51 51
52 52 // auto xcValue = candidateDS->valuesData()->data();
53 53 // auto dist = std::distance(itRefs.first, itRefs.second);
54 54 // auto it = itRefs.first;
55 55 // for (auto i = 0; i < dist - 1; ++i) {
56 56 // ++it;
57 57 // qInfo() << "END:" << it->value();
58 58 // }
59 59 // qDebug() << "END:" << it->value() << xcValue.last();
60 60
61 61 return std::equal(candidateDS->cbegin(), candidateDS->cend(), itRefs.first, itRefs.second,
62 62 compareLambda);
63 63 }
64 64 else {
65 65 return false;
66 66 }
67 67 }
68 68 }
69 69
70 70 class TestAmdaAcquisition : public QObject {
71 71 Q_OBJECT
72 72
73 73 private slots:
74 74 void testAcquisition();
75 75 };
76 76
77 77 void TestAmdaAcquisition::testAcquisition()
78 78 {
79 79 // READ the ref file:
80 80 auto filePath = QFileInfo{TESTS_RESOURCES_PATH, TESTS_AMDA_REF_FILE}.absoluteFilePath();
81 81 auto results = AmdaResultParser::readTxt(filePath, AmdaResultParser::ValueType::SCALAR);
82 82
83 83 auto provider = std::make_shared<AmdaProvider>();
84 84 auto timeController = std::make_unique<TimeController>();
85 85
86 86 auto varRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 3, 0, 0}};
87 87 auto varRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 0, 0}};
88 88
89 89 auto sqpR = SqpRange{DateUtils::secondsSinceEpoch(varRS), DateUtils::secondsSinceEpoch(varRE)};
90 90
91 91 timeController->onTimeToUpdate(sqpR);
92 92
93 93 QVariantHash metaData;
94 94 metaData.insert("dataType", "scalar");
95 95 metaData.insert("xml:id", "imf(0)");
96 96
97 97 VariableController vc;
98 98 vc.setTimeController(timeController.get());
99 99
100 100 auto var = vc.createVariable("bx_gse", metaData, provider);
101 101
102 102 // 1 : Variable creation
103 103 QCOMPARE(var->range().m_TStart, sqpR.m_TStart);
104 104 QCOMPARE(var->range().m_TEnd, sqpR.m_TEnd);
105 105
106 106 qDebug() << " 1: TIMECONTROLLER" << timeController->dateTime();
107 107 qDebug() << " 1: RANGE " << var->range();
108 108 qDebug() << " 1: CACHERANGE" << var->cacheRange();
109 109
110 110 // wait for 10 sec before asking next request toi permit asynchrone process to finish.
111 111 auto timeToWaitMs = 10000;
112 112
113 113 QEventLoop loop;
114 114 QTimer::singleShot(timeToWaitMs, &loop, &QEventLoop::quit);
115 115 loop.exec();
116 116
117 117 // Tests on acquisition operation
118 118
119 119 int count = 1;
120 120
121 121 auto requestDataLoading = [&vc, var, timeToWaitMs, results, &count](auto tStart, auto tEnd) {
122 122 ++count;
123 123
124 124 auto nextSqpR
125 125 = SqpRange{DateUtils::secondsSinceEpoch(tStart), DateUtils::secondsSinceEpoch(tEnd)};
126 126 vc.onRequestDataLoading(QVector<std::shared_ptr<Variable> >{} << var, nextSqpR,
127 127 var->range(), true);
128 128
129 129 QEventLoop loop;
130 130 QTimer::singleShot(timeToWaitMs, &loop, &QEventLoop::quit);
131 131 loop.exec();
132 132
133 qDebug() << count << "RANGE " << var->range();
134 qDebug() << count << "CACHERANGE" << var->cacheRange();
133 qInfo() << count << "RANGE " << var->range();
134 qInfo() << count << "CACHERANGE" << var->cacheRange();
135 135
136 136 QCOMPARE(var->range().m_TStart, nextSqpR.m_TStart);
137 137 QCOMPARE(var->range().m_TEnd, nextSqpR.m_TEnd);
138 138
139 139 // Verify dataserie
140 140 QVERIFY(compareDataSeries<ScalarSeries>(var->dataSeries(), var->cacheRange(), results));
141 141
142 142 };
143 143
144 144 // 2 : pan (jump) left for one hour
145 145 auto nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 1, 0, 0}};
146 146 auto nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 2, 0, 0}};
147 // requestDataLoading(nextVarRS, nextVarRE);
147 requestDataLoading(nextVarRS, nextVarRE);
148 148
149 149
150 150 // 3 : pan (jump) right for one hour
151 151 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 0, 0}};
152 152 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 0, 0}};
153 153 requestDataLoading(nextVarRS, nextVarRE);
154 154
155 155 // 4 : pan (overlay) right for 30 min
156 156 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 30, 0}};
157 157 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 30, 0}};
158 158 // requestDataLoading(nextVarRS, nextVarRE);
159 159
160 160 // 5 : pan (overlay) left for 30 min
161 161 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 0, 0}};
162 162 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 0, 0}};
163 163 // requestDataLoading(nextVarRS, nextVarRE);
164 164
165 165 // 6 : pan (overlay) left for 30 min - BIS
166 166 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 30, 0}};
167 167 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 30, 0}};
168 168 // requestDataLoading(nextVarRS, nextVarRE);
169 169
170 170 // 7 : Zoom in Inside 20 min range
171 171 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 50, 0}};
172 172 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 10, 0}};
173 173 // requestDataLoading(nextVarRS, nextVarRE);
174 174
175 175 // 8 : Zoom out Inside 2 hours range
176 176 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 0, 0}};
177 177 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 0, 0}};
178 178 // requestDataLoading(nextVarRS, nextVarRE);
179 179
180 180
181 181 // Close the app after 10 sec
182 182 QTimer::singleShot(timeToWaitMs, &loop, &QEventLoop::quit);
183 183 loop.exec();
184 184 }
185 185
186 186 int main(int argc, char *argv[])
187 187 {
188 188 SqpApplication app(argc, argv);
189 189 app.setAttribute(Qt::AA_Use96Dpi, true);
190 190 TestAmdaAcquisition tc;
191 191 QTEST_SET_MAIN_SOURCE_PATH
192 192 return QTest::qExec(&tc, argc, argv);
193 193 }
194 194
195 195 // QTEST_MAIN(TestAmdaAcquisition)
196 196
197 197 #include "TestAmdaAcquisition.moc"
General Comments 0
You need to be logged in to leave comments. Login now