##// END OF EJS Templates
Creates graph when dropping a product in the visu
trabillard -
r1288:5bae3c800f05
parent child
Show More
@@ -1,142 +1,144
1 1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
2 2 #define SCIQLOP_VARIABLECONTROLLER_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/AcquisitionDataPacket.h>
7 7 #include <Data/SqpRange.h>
8 8
9 9 #include <QLoggingCategory>
10 10 #include <QObject>
11 11 #include <QUuid>
12 12
13 13 #include <Common/spimpl.h>
14 14
15 15 class IDataProvider;
16 16 class QItemSelectionModel;
17 17 class TimeController;
18 18 class Variable;
19 19 class VariableModel;
20 20
21 21 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
22 22
23 23
24 24 /**
25 25 * Possible types of zoom operation
26 26 */
27 27 enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
28 28
29 29
30 30 /**
31 31 * @brief The VariableController class aims to handle the variables in SciQlop.
32 32 */
33 33 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
34 34 Q_OBJECT
35 35 public:
36 36 explicit VariableController(QObject *parent = 0);
37 37 virtual ~VariableController();
38 38
39 39 VariableModel *variableModel() noexcept;
40 40 QItemSelectionModel *variableSelectionModel() noexcept;
41 41
42 42 void setTimeController(TimeController *timeController) noexcept;
43 43
44 44 /**
45 45 * Clones the variable passed in parameter and adds the duplicate to the controller
46 46 * @param variable the variable to duplicate
47 47 * @return the duplicate created, nullptr if the variable couldn't be created
48 48 */
49 49 std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept;
50 50
51 51 /**
52 52 * Deletes from the controller the variable passed in parameter.
53 53 *
54 54 * Delete a variable includes:
55 55 * - the deletion of the various references to the variable in SciQlop
56 56 * - the deletion of the model variable
57 57 * - the deletion of the provider associated with the variable
58 58 * - removing the cache associated with the variable
59 59 *
60 60 * @param variable the variable to delete from the controller.
61 61 */
62 62 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
63 63
64 64 /**
65 65 * Deletes from the controller the variables passed in parameter.
66 66 * @param variables the variables to delete from the controller.
67 67 * @sa deleteVariable()
68 68 */
69 69 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
70 70
71 71 /// Returns the MIME data associated to a list of variables
72 72 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
73 73
74 74 /// Returns the list of variables contained in a MIME data
75 75 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
76 76
77 77 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
78 78 signals:
79 79 /// Signal emitted when a variable is about to be deleted from the controller
80 80 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
81 81
82 82 /// Signal emitted when a data acquisition is requested on a range for a variable
83 83 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
84 84
85 85 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
86 86 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
87 87
88 88 /// Signal emitted when all acquisitions related to the variables have been completed (whether
89 89 /// validated, canceled, or failed)
90 90 void acquisitionFinished();
91 91
92 void variableAdded(const std::shared_ptr<Variable> &variable);
93
92 94 public slots:
93 95 /// Request the data loading of the variable whithin range
94 96 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
95 97 bool synchronise);
96 98 /**
97 99 * Creates a new variable and adds it to the model
98 100 * @param name the name of the new variable
99 101 * @param metadata the metadata of the new variable
100 102 * @param provider the data provider for the new variable
101 103 * @return the pointer to the new variable or nullptr if the creation failed
102 104 */
103 105 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
104 106 std::shared_ptr<IDataProvider> provider) noexcept;
105 107
106 108 /// Update the temporal parameters of every selected variable to dateTime
107 109 void onDateTimeOnSelection(const SqpRange &dateTime);
108 110
109 111 /// Update the temporal parameters of the specified variable
110 112 void onUpdateDateTime(std::shared_ptr<Variable> variable, const SqpRange &dateTime);
111 113
112 114
113 115 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
114 116 const SqpRange &cacheRangeRequested,
115 117 QVector<AcquisitionDataPacket> dataAcquired);
116 118
117 119 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
118 120
119 121 /// Cancel the current request for the variable
120 122 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
121 123 void onAbortAcquisitionRequested(QUuid vIdentifier);
122 124
123 125 // synchronization group methods
124 126 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
125 127 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
126 128 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
127 129
128 130 /// Desynchronizes the variable of the group whose identifier is passed in parameter
129 131 /// @remarks the method does nothing if the variable is not part of the group
130 132 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
131 133
132 134 void initialize();
133 135 void finalize();
134 136
135 137 private:
136 138 void waitForFinish();
137 139
138 140 class VariableControllerPrivate;
139 141 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
140 142 };
141 143
142 144 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,1102 +1,1104
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableAcquisitionWorker.h>
3 3 #include <Variable/VariableCacheStrategy.h>
4 4 #include <Variable/VariableCacheStrategyFactory.h>
5 5 #include <Variable/VariableController.h>
6 6 #include <Variable/VariableModel.h>
7 7 #include <Variable/VariableSynchronizationGroup.h>
8 8
9 9 #include <Data/DataProviderParameters.h>
10 10 #include <Data/IDataProvider.h>
11 11 #include <Data/IDataSeries.h>
12 12 #include <Data/VariableRequest.h>
13 13 #include <Time/TimeController.h>
14 14
15 15 #include <QDataStream>
16 16 #include <QMutex>
17 17 #include <QThread>
18 18 #include <QUuid>
19 19 #include <QtCore/QItemSelectionModel>
20 20
21 21 #include <deque>
22 22 #include <set>
23 23 #include <unordered_map>
24 24
25 25 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
26 26
27 27 namespace {
28 28
29 29 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
30 30 const SqpRange &oldGraphRange)
31 31 {
32 32 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
33 33
34 34 auto varRangeRequested = varRange;
35 35 switch (zoomType) {
36 36 case AcquisitionZoomType::ZoomIn: {
37 37 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
38 38 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
39 39 varRangeRequested.m_TStart += deltaLeft;
40 40 varRangeRequested.m_TEnd -= deltaRight;
41 41 break;
42 42 }
43 43
44 44 case AcquisitionZoomType::ZoomOut: {
45 45 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
46 46 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
47 47 varRangeRequested.m_TStart -= deltaLeft;
48 48 varRangeRequested.m_TEnd += deltaRight;
49 49 break;
50 50 }
51 51 case AcquisitionZoomType::PanRight: {
52 52 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
53 53 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
54 54 varRangeRequested.m_TStart += deltaLeft;
55 55 varRangeRequested.m_TEnd += deltaRight;
56 56 break;
57 57 }
58 58 case AcquisitionZoomType::PanLeft: {
59 59 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
60 60 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
61 61 varRangeRequested.m_TStart -= deltaLeft;
62 62 varRangeRequested.m_TEnd -= deltaRight;
63 63 break;
64 64 }
65 65 case AcquisitionZoomType::Unknown: {
66 66 qCCritical(LOG_VariableController())
67 67 << VariableController::tr("Impossible to synchronize: zoom type unknown");
68 68 break;
69 69 }
70 70 default:
71 71 qCCritical(LOG_VariableController()) << VariableController::tr(
72 72 "Impossible to synchronize: zoom type not take into account");
73 73 // No action
74 74 break;
75 75 }
76 76
77 77 return varRangeRequested;
78 78 }
79 79 }
80 80
81 81 enum class VariableRequestHandlerState { OFF, RUNNING, PENDING };
82 82
83 83 struct VariableRequestHandler {
84 84
85 85 VariableRequestHandler()
86 86 {
87 87 m_CanUpdate = false;
88 88 m_State = VariableRequestHandlerState::OFF;
89 89 }
90 90
91 91 QUuid m_VarId;
92 92 VariableRequest m_RunningVarRequest;
93 93 VariableRequest m_PendingVarRequest;
94 94 VariableRequestHandlerState m_State;
95 95 bool m_CanUpdate;
96 96 };
97 97
98 98 struct VariableController::VariableControllerPrivate {
99 99 explicit VariableControllerPrivate(VariableController *parent)
100 100 : m_WorkingMutex{},
101 101 m_VariableModel{new VariableModel{parent}},
102 102 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
103 103 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
104 104 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
105 105 CacheStrategy::SingleThreshold)},
106 106 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
107 107 q{parent}
108 108 {
109 109
110 110 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
111 111 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
112 112 }
113 113
114 114
115 115 virtual ~VariableControllerPrivate()
116 116 {
117 117 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
118 118 m_VariableAcquisitionWorkerThread.quit();
119 119 m_VariableAcquisitionWorkerThread.wait();
120 120 }
121 121
122 122
123 123 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
124 124 QUuid varRequestId);
125 125
126 126 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
127 127 std::shared_ptr<IDataSeries>
128 128 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
129 129
130 130 void registerProvider(std::shared_ptr<IDataProvider> provider);
131 131
132 132 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
133 133 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
134 134 void updateVariables(QUuid varRequestId);
135 135 void updateVariableRequest(QUuid varRequestId);
136 136 void cancelVariableRequest(QUuid varRequestId);
137 137 void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest);
138 138
139 139 template <typename VariableIterator>
140 140 void desynchronize(VariableIterator variableIt, const QUuid &syncGroupId);
141 141
142 142 QMutex m_WorkingMutex;
143 143 /// Variable model. The VariableController has the ownership
144 144 VariableModel *m_VariableModel;
145 145 QItemSelectionModel *m_VariableSelectionModel;
146 146
147 147
148 148 TimeController *m_TimeController{nullptr};
149 149 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
150 150 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
151 151 QThread m_VariableAcquisitionWorkerThread;
152 152
153 153 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
154 154 m_VariableToProviderMap;
155 155 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
156 156 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
157 157 m_GroupIdToVariableSynchronizationGroupMap;
158 158 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
159 159 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
160 160
161 161 std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds;
162 162 std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler;
163 163
164 164 VariableController *q;
165 165 };
166 166
167 167
168 168 VariableController::VariableController(QObject *parent)
169 169 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
170 170 {
171 171 qCDebug(LOG_VariableController()) << tr("VariableController construction")
172 172 << QThread::currentThread();
173 173
174 174 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
175 175 &VariableController::onAbortProgressRequested);
176 176
177 177 connect(impl->m_VariableAcquisitionWorker.get(),
178 178 &VariableAcquisitionWorker::variableCanceledRequested, this,
179 179 &VariableController::onAbortAcquisitionRequested);
180 180
181 181 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
182 182 &VariableController::onDataProvided);
183 183 connect(impl->m_VariableAcquisitionWorker.get(),
184 184 &VariableAcquisitionWorker::variableRequestInProgress, this,
185 185 &VariableController::onVariableRetrieveDataInProgress);
186 186
187 187
188 188 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
189 189 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
190 190 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
191 191 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
192 192
193 193 connect(impl->m_VariableModel, &VariableModel::requestVariableRangeUpdate, this,
194 194 &VariableController::onUpdateDateTime);
195 195
196 196 impl->m_VariableAcquisitionWorkerThread.start();
197 197 }
198 198
199 199 VariableController::~VariableController()
200 200 {
201 201 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
202 202 << QThread::currentThread();
203 203 this->waitForFinish();
204 204 }
205 205
206 206 VariableModel *VariableController::variableModel() noexcept
207 207 {
208 208 return impl->m_VariableModel;
209 209 }
210 210
211 211 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
212 212 {
213 213 return impl->m_VariableSelectionModel;
214 214 }
215 215
216 216 void VariableController::setTimeController(TimeController *timeController) noexcept
217 217 {
218 218 impl->m_TimeController = timeController;
219 219 }
220 220
221 221 std::shared_ptr<Variable>
222 222 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
223 223 {
224 224 if (impl->m_VariableModel->containsVariable(variable)) {
225 225 // Clones variable
226 226 auto duplicate = variable->clone();
227 227
228 228 // Adds clone to model
229 229 impl->m_VariableModel->addVariable(duplicate);
230 230
231 231 // Generates clone identifier
232 232 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
233 233
234 234 // Registers provider
235 235 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
236 236 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
237 237
238 238 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
239 239 if (duplicateProvider) {
240 240 impl->registerProvider(duplicateProvider);
241 241 }
242 242
243 243 return duplicate;
244 244 }
245 245 else {
246 246 qCCritical(LOG_VariableController())
247 247 << tr("Can't create duplicate of variable %1: variable not registered in the model")
248 248 .arg(variable->name());
249 249 return nullptr;
250 250 }
251 251 }
252 252
253 253 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
254 254 {
255 255 if (!variable) {
256 256 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
257 257 return;
258 258 }
259 259
260 260 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
261 261 // make some treatments before the deletion
262 262 emit variableAboutToBeDeleted(variable);
263 263
264 264 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
265 265 Q_ASSERT(variableIt != impl->m_VariableToIdentifierMap.cend());
266 266
267 267 auto variableId = variableIt->second;
268 268
269 269 // Removes variable's handler
270 270 impl->m_VarIdToVarRequestHandler.erase(variableId);
271 271
272 272 // Desynchronizes variable (if the variable is in a sync group)
273 273 auto syncGroupIt = impl->m_VariableIdGroupIdMap.find(variableId);
274 274 if (syncGroupIt != impl->m_VariableIdGroupIdMap.cend()) {
275 275 impl->desynchronize(variableIt, syncGroupIt->second);
276 276 }
277 277
278 278 // Deletes identifier
279 279 impl->m_VariableToIdentifierMap.erase(variableIt);
280 280
281 281 // Deletes provider
282 282 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
283 283 qCDebug(LOG_VariableController())
284 284 << tr("Number of providers deleted for variable %1: %2")
285 285 .arg(variable->name(), QString::number(nbProvidersDeleted));
286 286
287 287
288 288 // Deletes from model
289 289 impl->m_VariableModel->deleteVariable(variable);
290 290 }
291 291
292 292 void VariableController::deleteVariables(
293 293 const QVector<std::shared_ptr<Variable> > &variables) noexcept
294 294 {
295 295 for (auto variable : qAsConst(variables)) {
296 296 deleteVariable(variable);
297 297 }
298 298 }
299 299
300 300 QByteArray
301 301 VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const
302 302 {
303 303 auto encodedData = QByteArray{};
304 304
305 305 QVariantList ids;
306 306 for (auto &var : variables) {
307 307 auto itVar = impl->m_VariableToIdentifierMap.find(var);
308 308 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
309 309 qCCritical(LOG_VariableController())
310 310 << tr("Impossible to find the data for an unknown variable.");
311 311 }
312 312
313 313 ids << itVar->second.toByteArray();
314 314 }
315 315
316 316 QDataStream stream{&encodedData, QIODevice::WriteOnly};
317 317 stream << ids;
318 318
319 319 return encodedData;
320 320 }
321 321
322 322 QList<std::shared_ptr<Variable> >
323 323 VariableController::variablesForMimeData(const QByteArray &mimeData) const
324 324 {
325 325 auto variables = QList<std::shared_ptr<Variable> >{};
326 326 QDataStream stream{mimeData};
327 327
328 328 QVariantList ids;
329 329 stream >> ids;
330 330
331 331 for (auto id : ids) {
332 332 auto uuid = QUuid{id.toByteArray()};
333 333 auto var = impl->findVariable(uuid);
334 334 variables << var;
335 335 }
336 336
337 337 return variables;
338 338 }
339 339
340 340 std::shared_ptr<Variable>
341 341 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
342 342 std::shared_ptr<IDataProvider> provider) noexcept
343 343 {
344 344 if (!impl->m_TimeController) {
345 345 qCCritical(LOG_VariableController())
346 346 << tr("Impossible to create variable: The time controller is null");
347 347 return nullptr;
348 348 }
349 349
350 350 auto range = impl->m_TimeController->dateTime();
351 351
352 352 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
353 353 auto varId = QUuid::createUuid();
354 354
355 355 // Create the handler
356 356 auto varRequestHandler = std::make_unique<VariableRequestHandler>();
357 357 varRequestHandler->m_VarId = varId;
358 358
359 359 impl->m_VarIdToVarRequestHandler.insert(
360 360 std::make_pair(varId, std::move(varRequestHandler)));
361 361
362 362 // store the provider
363 363 impl->registerProvider(provider);
364 364
365 365 // Associate the provider
366 366 impl->m_VariableToProviderMap[newVariable] = provider;
367 367 impl->m_VariableToIdentifierMap[newVariable] = varId;
368 368
369 369 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false);
370 370
371 371 // auto varRequestId = QUuid::createUuid();
372 372 // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId;
373 373 // impl->processRequest(newVariable, range, varRequestId);
374 374 // impl->updateVariableRequest(varRequestId);
375 375
376 emit variableAdded(newVariable);
377
376 378 return newVariable;
377 379 }
378 380
379 381 qCCritical(LOG_VariableController()) << tr("Impossible to create variable");
380 382 return nullptr;
381 383 }
382 384
383 385 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
384 386 {
385 387 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
386 388 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
387 389 << QThread::currentThread()->objectName();
388 390 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
389 391
390 392 // NOTE we only permit the time modification for one variable
391 393 // DEPRECATED
392 394 // auto variables = QVector<std::shared_ptr<Variable> >{};
393 395 // for (const auto &selectedRow : qAsConst(selectedRows)) {
394 396 // if (auto selectedVariable =
395 397 // impl->m_VariableModel->variable(selectedRow.row())) {
396 398 // variables << selectedVariable;
397 399
398 400 // // notify that rescale operation has to be done
399 401 // emit rangeChanged(selectedVariable, dateTime);
400 402 // }
401 403 // }
402 404 // if (!variables.isEmpty()) {
403 405 // this->onRequestDataLoading(variables, dateTime, synchro);
404 406 // }
405 407 if (selectedRows.size() == 1) {
406 408
407 409 if (auto selectedVariable
408 410 = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) {
409 411
410 412 onUpdateDateTime(selectedVariable, dateTime);
411 413 }
412 414 }
413 415 else if (selectedRows.size() > 1) {
414 416 qCCritical(LOG_VariableController())
415 417 << tr("Impossible to set time for more than 1 variable in the same time");
416 418 }
417 419 else {
418 420 qCWarning(LOG_VariableController())
419 421 << tr("There is no variable selected to set the time one");
420 422 }
421 423 }
422 424
423 425 void VariableController::onUpdateDateTime(std::shared_ptr<Variable> variable,
424 426 const SqpRange &dateTime)
425 427 {
426 428 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
427 429 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
428 430 qCCritical(LOG_VariableController())
429 431 << tr("Impossible to onDateTimeOnSelection request for unknown variable");
430 432 return;
431 433 }
432 434
433 435 // notify that rescale operation has to be done
434 436 emit rangeChanged(variable, dateTime);
435 437
436 438 auto synchro
437 439 = impl->m_VariableIdGroupIdMap.find(itVar->second) != impl->m_VariableIdGroupIdMap.cend();
438 440
439 441 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{variable}, dateTime, synchro);
440 442 }
441 443
442 444 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
443 445 const SqpRange &cacheRangeRequested,
444 446 QVector<AcquisitionDataPacket> dataAcquired)
445 447 {
446 448 qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread();
447 449 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
448 450 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
449 451 if (!varRequestId.isNull()) {
450 452 impl->updateVariables(varRequestId);
451 453 }
452 454 }
453 455
454 456 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
455 457 {
456 458 qCDebug(LOG_VariableController())
457 459 << "TORM: variableController::onVariableRetrieveDataInProgress"
458 460 << QThread::currentThread()->objectName() << progress;
459 461 if (auto var = impl->findVariable(identifier)) {
460 462 impl->m_VariableModel->setDataProgress(var, progress);
461 463 }
462 464 else {
463 465 qCCritical(LOG_VariableController())
464 466 << tr("Impossible to notify progression of a null variable");
465 467 }
466 468 }
467 469
468 470 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
469 471 {
470 472 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested"
471 473 << QThread::currentThread()->objectName() << variable->name();
472 474
473 475 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
474 476 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
475 477 qCCritical(LOG_VariableController())
476 478 << tr("Impossible to onAbortProgressRequested request for unknown variable");
477 479 return;
478 480 }
479 481
480 482 auto varId = itVar->second;
481 483
482 484 auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId);
483 485 if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) {
484 486 qCCritical(LOG_VariableController())
485 487 << tr("Impossible to onAbortProgressRequested for variable with unknown handler");
486 488 return;
487 489 }
488 490
489 491 auto varHandler = itVarHandler->second.get();
490 492
491 493 // case where a variable has a running request
492 494 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
493 495 impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId);
494 496 }
495 497 }
496 498
497 499 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
498 500 {
499 501 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
500 502 << QThread::currentThread()->objectName() << vIdentifier;
501 503
502 504 if (auto var = impl->findVariable(vIdentifier)) {
503 505 this->onAbortProgressRequested(var);
504 506 }
505 507 else {
506 508 qCCritical(LOG_VariableController())
507 509 << tr("Impossible to abort Acquisition Requestof a null variable");
508 510 }
509 511 }
510 512
511 513 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
512 514 {
513 515 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
514 516 << QThread::currentThread()->objectName()
515 517 << synchronizationGroupId;
516 518 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
517 519 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
518 520 std::make_pair(synchronizationGroupId, vSynchroGroup));
519 521 }
520 522
521 523 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
522 524 {
523 525 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
524 526 }
525 527
526 528 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
527 529 QUuid synchronizationGroupId)
528 530
529 531 {
530 532 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
531 533 << synchronizationGroupId;
532 534 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
533 535 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
534 536 auto groupIdToVSGIt
535 537 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
536 538 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
537 539 impl->m_VariableIdGroupIdMap.insert(
538 540 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
539 541 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
540 542 }
541 543 else {
542 544 qCCritical(LOG_VariableController())
543 545 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
544 546 << variable->name();
545 547 }
546 548 }
547 549 else {
548 550 qCCritical(LOG_VariableController())
549 551 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
550 552 }
551 553 }
552 554
553 555 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
554 556 QUuid synchronizationGroupId)
555 557 {
556 558 // Gets variable id
557 559 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
558 560 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
559 561 qCCritical(LOG_VariableController())
560 562 << tr("Can't desynchronize variable %1: variable identifier not found")
561 563 .arg(variable->name());
562 564 return;
563 565 }
564 566
565 567 impl->desynchronize(variableIt, synchronizationGroupId);
566 568 }
567 569
568 570 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
569 571 const SqpRange &range, bool synchronise)
570 572 {
571 573 // variables is assumed synchronized
572 574 // TODO: Asser variables synchronization
573 575 // we want to load data of the variable for the dateTime.
574 576 if (variables.isEmpty()) {
575 577 return;
576 578 }
577 579
578 580 auto varRequestId = QUuid::createUuid();
579 581 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
580 582 << QThread::currentThread()->objectName() << varRequestId
581 583 << range << synchronise;
582 584
583 585 if (!synchronise) {
584 586 auto varIds = std::list<QUuid>{};
585 587 for (const auto &var : variables) {
586 588 auto vId = impl->m_VariableToIdentifierMap.at(var);
587 589 varIds.push_back(vId);
588 590 }
589 591 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
590 592 for (const auto &var : variables) {
591 593 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId
592 594 << varIds.size();
593 595 impl->processRequest(var, range, varRequestId);
594 596 }
595 597 }
596 598 else {
597 599 auto vId = impl->m_VariableToIdentifierMap.at(variables.first());
598 600 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
599 601 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
600 602 auto groupId = varIdToGroupIdIt->second;
601 603
602 604 auto vSynchronizationGroup
603 605 = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId);
604 606 auto vSyncIds = vSynchronizationGroup->getIds();
605 607
606 608 auto varIds = std::list<QUuid>{};
607 609 for (auto vId : vSyncIds) {
608 610 varIds.push_back(vId);
609 611 }
610 612 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
611 613
612 614 for (auto vId : vSyncIds) {
613 615 auto var = impl->findVariable(vId);
614 616
615 617 // Don't process already processed var
616 618 if (var != nullptr) {
617 619 qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name()
618 620 << varRequestId;
619 621 auto vSyncRangeRequested
620 622 = variables.contains(var)
621 623 ? range
622 624 : computeSynchroRangeRequested(var->range(), range,
623 625 variables.first()->range());
624 626 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
625 627 impl->processRequest(var, vSyncRangeRequested, varRequestId);
626 628 }
627 629 else {
628 630 qCCritical(LOG_VariableController())
629 631
630 632 << tr("Impossible to synchronize a null variable");
631 633 }
632 634 }
633 635 }
634 636 }
635 637
636 638 impl->updateVariables(varRequestId);
637 639 }
638 640
639 641
640 642 void VariableController::initialize()
641 643 {
642 644 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
643 645 impl->m_WorkingMutex.lock();
644 646 qCDebug(LOG_VariableController()) << tr("VariableController init END");
645 647 }
646 648
647 649 void VariableController::finalize()
648 650 {
649 651 impl->m_WorkingMutex.unlock();
650 652 }
651 653
652 654 void VariableController::waitForFinish()
653 655 {
654 656 QMutexLocker locker{&impl->m_WorkingMutex};
655 657 }
656 658
657 659 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
658 660 {
659 661 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
660 662 auto zoomType = AcquisitionZoomType::Unknown;
661 663 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
662 664 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
663 665 zoomType = AcquisitionZoomType::ZoomOut;
664 666 }
665 667 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
666 668 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
667 669 zoomType = AcquisitionZoomType::PanRight;
668 670 }
669 671 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
670 672 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
671 673 zoomType = AcquisitionZoomType::PanLeft;
672 674 }
673 675 else if (range.m_TStart >= oldRange.m_TStart && oldRange.m_TEnd >= range.m_TEnd) {
674 676 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
675 677 zoomType = AcquisitionZoomType::ZoomIn;
676 678 }
677 679 else {
678 680 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
679 681 }
680 682 return zoomType;
681 683 }
682 684
683 685 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
684 686 const SqpRange &rangeRequested,
685 687 QUuid varRequestId)
686 688 {
687 689 auto itVar = m_VariableToIdentifierMap.find(var);
688 690 if (itVar == m_VariableToIdentifierMap.cend()) {
689 691 qCCritical(LOG_VariableController())
690 692 << tr("Impossible to process request for unknown variable");
691 693 return;
692 694 }
693 695
694 696 auto varId = itVar->second;
695 697
696 698 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
697 699 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
698 700 qCCritical(LOG_VariableController())
699 701 << tr("Impossible to process request for variable with unknown handler");
700 702 return;
701 703 }
702 704
703 705 auto oldRange = var->range();
704 706
705 707 auto varHandler = itVarHandler->second.get();
706 708
707 709 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
708 710 oldRange = varHandler->m_RunningVarRequest.m_RangeRequested;
709 711 }
710 712
711 713 auto varRequest = VariableRequest{};
712 714 varRequest.m_VariableGroupId = varRequestId;
713 715 auto varStrategyRangesRequested
714 716 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
715 717 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
716 718 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
717 719
718 720 switch (varHandler->m_State) {
719 721 case VariableRequestHandlerState::OFF: {
720 722 qCDebug(LOG_VariableController()) << tr("Process Request OFF")
721 723 << varRequest.m_RangeRequested
722 724 << varRequest.m_CacheRangeRequested;
723 725 varHandler->m_RunningVarRequest = varRequest;
724 726 varHandler->m_State = VariableRequestHandlerState::RUNNING;
725 727 executeVarRequest(var, varRequest);
726 728 break;
727 729 }
728 730 case VariableRequestHandlerState::RUNNING: {
729 731 qCDebug(LOG_VariableController()) << tr("Process Request RUNNING")
730 732 << varRequest.m_RangeRequested
731 733 << varRequest.m_CacheRangeRequested;
732 734 varHandler->m_State = VariableRequestHandlerState::PENDING;
733 735 varHandler->m_PendingVarRequest = varRequest;
734 736 break;
735 737 }
736 738 case VariableRequestHandlerState::PENDING: {
737 739 qCDebug(LOG_VariableController()) << tr("Process Request PENDING")
738 740 << varRequest.m_RangeRequested
739 741 << varRequest.m_CacheRangeRequested;
740 742 auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId;
741 743 cancelVariableRequest(variableGroupIdToCancel);
742 744 // Cancel variable can make state downgrade
743 745 varHandler->m_State = VariableRequestHandlerState::PENDING;
744 746 varHandler->m_PendingVarRequest = varRequest;
745 747
746 748 break;
747 749 }
748 750 default:
749 751 qCCritical(LOG_VariableController())
750 752 << QObject::tr("Unknown VariableRequestHandlerState");
751 753 }
752 754 }
753 755
754 756 std::shared_ptr<Variable>
755 757 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
756 758 {
757 759 std::shared_ptr<Variable> var;
758 760 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
759 761
760 762 auto end = m_VariableToIdentifierMap.cend();
761 763 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
762 764 if (it != end) {
763 765 var = it->first;
764 766 }
765 767 else {
766 768 qCCritical(LOG_VariableController())
767 769 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
768 770 }
769 771
770 772 return var;
771 773 }
772 774
773 775 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
774 776 const QVector<AcquisitionDataPacket> acqDataPacketVector)
775 777 {
776 778 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
777 779 << acqDataPacketVector.size();
778 780 std::shared_ptr<IDataSeries> dataSeries;
779 781 if (!acqDataPacketVector.isEmpty()) {
780 782 dataSeries = acqDataPacketVector[0].m_DateSeries;
781 783 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
782 784 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
783 785 }
784 786 }
785 787 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
786 788 << acqDataPacketVector.size();
787 789 return dataSeries;
788 790 }
789 791
790 792 void VariableController::VariableControllerPrivate::registerProvider(
791 793 std::shared_ptr<IDataProvider> provider)
792 794 {
793 795 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
794 796 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
795 797 << provider->objectName();
796 798 m_ProviderSet.insert(provider);
797 799 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
798 800 &VariableAcquisitionWorker::onVariableDataAcquired);
799 801 connect(provider.get(), &IDataProvider::dataProvidedProgress,
800 802 m_VariableAcquisitionWorker.get(),
801 803 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
802 804 connect(provider.get(), &IDataProvider::dataProvidedFailed,
803 805 m_VariableAcquisitionWorker.get(),
804 806 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
805 807 }
806 808 else {
807 809 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
808 810 }
809 811 }
810 812
811 813 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
812 814 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
813 815 {
814 816 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
815 817 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
816 818 return QUuid();
817 819 }
818 820
819 821 auto varHandler = itVarHandler->second.get();
820 822 if (varHandler->m_State == VariableRequestHandlerState::OFF) {
821 823 qCCritical(LOG_VariableController())
822 824 << tr("acceptVariableRequest impossible on a variable with OFF state");
823 825 }
824 826
825 827 varHandler->m_RunningVarRequest.m_DataSeries = dataSeries;
826 828 varHandler->m_CanUpdate = true;
827 829
828 830 // Element traitΓ©, on a dΓ©jΓ  toutes les donnΓ©es necessaires
829 831 auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId;
830 832 qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId
831 833 << m_VarGroupIdToVarIds.size();
832 834
833 835 return varHandler->m_RunningVarRequest.m_VariableGroupId;
834 836 }
835 837
836 838 void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId)
837 839 {
838 840 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
839 841 << QThread::currentThread()->objectName() << varRequestId;
840 842
841 843 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
842 844 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
843 845 qCWarning(LOG_VariableController())
844 846 << tr("Impossible to updateVariables of unknown variables") << varRequestId;
845 847 return;
846 848 }
847 849
848 850 auto &varIds = varGroupIdToVarIdsIt->second;
849 851 auto varIdsEnd = varIds.end();
850 852 bool processVariableUpdate = true;
851 853 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
852 854 << varRequestId << varIds.size();
853 855 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate;
854 856 ++varIdsIt) {
855 857 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
856 858 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
857 859 processVariableUpdate &= itVarHandler->second->m_CanUpdate;
858 860 }
859 861 }
860 862
861 863 if (processVariableUpdate) {
862 864 qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size();
863 865 for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) {
864 866 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
865 867 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
866 868 if (auto var = findVariable(*varIdsIt)) {
867 869 auto &varRequest = itVarHandler->second->m_RunningVarRequest;
868 870 var->setRange(varRequest.m_RangeRequested);
869 871 var->setCacheRange(varRequest.m_CacheRangeRequested);
870 872 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
871 873 << varRequest.m_RangeRequested
872 874 << varRequest.m_CacheRangeRequested;
873 875 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
874 876 << var->nbPoints()
875 877 << varRequest.m_DataSeries->nbPoints();
876 878 var->mergeDataSeries(varRequest.m_DataSeries);
877 879 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
878 880 << var->nbPoints();
879 881
880 882 emit var->updated();
881 883 qCDebug(LOG_VariableController()) << tr("Update OK");
882 884 }
883 885 else {
884 886 qCCritical(LOG_VariableController())
885 887 << tr("Impossible to update data to a null variable");
886 888 }
887 889 }
888 890 }
889 891 updateVariableRequest(varRequestId);
890 892
891 893 // cleaning varRequestId
892 894 qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId;
893 895 m_VarGroupIdToVarIds.erase(varRequestId);
894 896 if (m_VarGroupIdToVarIds.empty()) {
895 897 emit q->acquisitionFinished();
896 898 }
897 899 }
898 900 }
899 901
900 902
901 903 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
902 904 {
903 905 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
904 906 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
905 907 qCCritical(LOG_VariableController()) << QObject::tr(
906 908 "Impossible to updateVariableRequest since varGroupdId isn't here anymore");
907 909
908 910 return;
909 911 }
910 912
911 913 auto &varIds = varGroupIdToVarIdsIt->second;
912 914 auto varIdsEnd = varIds.end();
913 915 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
914 916 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
915 917 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
916 918
917 919 auto varHandler = itVarHandler->second.get();
918 920 varHandler->m_CanUpdate = false;
919 921
920 922
921 923 switch (varHandler->m_State) {
922 924 case VariableRequestHandlerState::OFF: {
923 925 qCCritical(LOG_VariableController())
924 926 << QObject::tr("Impossible to update a variable with handler in OFF state");
925 927 } break;
926 928 case VariableRequestHandlerState::RUNNING: {
927 929 varHandler->m_State = VariableRequestHandlerState::OFF;
928 930 varHandler->m_RunningVarRequest = VariableRequest{};
929 931 break;
930 932 }
931 933 case VariableRequestHandlerState::PENDING: {
932 934 varHandler->m_State = VariableRequestHandlerState::RUNNING;
933 935 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
934 936 varHandler->m_PendingVarRequest = VariableRequest{};
935 937 auto var = findVariable(itVarHandler->first);
936 938 executeVarRequest(var, varHandler->m_RunningVarRequest);
937 939 updateVariables(varHandler->m_RunningVarRequest.m_VariableGroupId);
938 940 break;
939 941 }
940 942 default:
941 943 qCCritical(LOG_VariableController())
942 944 << QObject::tr("Unknown VariableRequestHandlerState");
943 945 }
944 946 }
945 947 }
946 948 }
947 949
948 950
949 951 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
950 952 {
951 953 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId;
952 954
953 955 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
954 956 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
955 957 qCCritical(LOG_VariableController())
956 958 << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId;
957 959 return;
958 960 }
959 961
960 962 auto &varIds = varGroupIdToVarIdsIt->second;
961 963 auto varIdsEnd = varIds.end();
962 964 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
963 965 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
964 966 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
965 967
966 968 auto varHandler = itVarHandler->second.get();
967 969 varHandler->m_VarId = QUuid{};
968 970 switch (varHandler->m_State) {
969 971 case VariableRequestHandlerState::OFF: {
970 972 qCWarning(LOG_VariableController())
971 973 << QObject::tr("Impossible to cancel a variable with no running request");
972 974 break;
973 975 }
974 976 case VariableRequestHandlerState::RUNNING: {
975 977
976 978 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
977 979 auto var = findVariable(itVarHandler->first);
978 980 auto varProvider = m_VariableToProviderMap.at(var);
979 981 if (varProvider != nullptr) {
980 982 m_VariableAcquisitionWorker->abortProgressRequested(
981 983 itVarHandler->first);
982 984 }
983 985 m_VariableModel->setDataProgress(var, 0.0);
984 986 varHandler->m_CanUpdate = false;
985 987 varHandler->m_State = VariableRequestHandlerState::OFF;
986 988 varHandler->m_RunningVarRequest = VariableRequest{};
987 989 }
988 990 else {
989 991 // TODO: log Impossible to cancel the running variable request beacause its
990 992 // varRequestId isn't not the canceled one
991 993 }
992 994 break;
993 995 }
994 996 case VariableRequestHandlerState::PENDING: {
995 997 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
996 998 auto var = findVariable(itVarHandler->first);
997 999 auto varProvider = m_VariableToProviderMap.at(var);
998 1000 if (varProvider != nullptr) {
999 1001 m_VariableAcquisitionWorker->abortProgressRequested(
1000 1002 itVarHandler->first);
1001 1003 }
1002 1004 m_VariableModel->setDataProgress(var, 0.0);
1003 1005 varHandler->m_CanUpdate = false;
1004 1006 varHandler->m_State = VariableRequestHandlerState::RUNNING;
1005 1007 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
1006 1008 varHandler->m_PendingVarRequest = VariableRequest{};
1007 1009 executeVarRequest(var, varHandler->m_RunningVarRequest);
1008 1010 }
1009 1011 else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) {
1010 1012 varHandler->m_State = VariableRequestHandlerState::RUNNING;
1011 1013 varHandler->m_PendingVarRequest = VariableRequest{};
1012 1014 }
1013 1015 else {
1014 1016 // TODO: log Impossible to cancel the variable request beacause its
1015 1017 // varRequestId isn't not the canceled one
1016 1018 }
1017 1019 break;
1018 1020 }
1019 1021 default:
1020 1022 qCCritical(LOG_VariableController())
1021 1023 << QObject::tr("Unknown VariableRequestHandlerState");
1022 1024 }
1023 1025 }
1024 1026 }
1025 1027 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId;
1026 1028 m_VarGroupIdToVarIds.erase(varRequestId);
1027 1029 if (m_VarGroupIdToVarIds.empty()) {
1028 1030 emit q->acquisitionFinished();
1029 1031 }
1030 1032 }
1031 1033
1032 1034 void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var,
1033 1035 VariableRequest &varRequest)
1034 1036 {
1035 1037 qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest");
1036 1038
1037 1039 auto varIdIt = m_VariableToIdentifierMap.find(var);
1038 1040 if (varIdIt == m_VariableToIdentifierMap.cend()) {
1039 1041 qCWarning(LOG_VariableController()) << tr(
1040 1042 "Can't execute request of a variable that is not registered (may has been deleted)");
1041 1043 return;
1042 1044 }
1043 1045
1044 1046 auto varId = varIdIt->second;
1045 1047
1046 1048 auto varCacheRange = var->cacheRange();
1047 1049 auto varCacheRangeRequested = varRequest.m_CacheRangeRequested;
1048 1050 auto notInCacheRangeList
1049 1051 = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested);
1050 1052 auto inCacheRangeList
1051 1053 = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested);
1052 1054
1053 1055 if (!notInCacheRangeList.empty()) {
1054 1056
1055 1057 auto varProvider = m_VariableToProviderMap.at(var);
1056 1058 if (varProvider != nullptr) {
1057 1059 qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested
1058 1060 << varRequest.m_CacheRangeRequested;
1059 1061 m_VariableAcquisitionWorker->pushVariableRequest(
1060 1062 varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested,
1061 1063 varRequest.m_CacheRangeRequested,
1062 1064 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
1063 1065 varProvider);
1064 1066 }
1065 1067 else {
1066 1068 qCCritical(LOG_VariableController())
1067 1069 << "Impossible to provide data with a null provider";
1068 1070 }
1069 1071
1070 1072 if (!inCacheRangeList.empty()) {
1071 1073 emit q->updateVarDisplaying(var, inCacheRangeList.first());
1072 1074 }
1073 1075 }
1074 1076 else {
1075 1077 acceptVariableRequest(varId,
1076 1078 var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested));
1077 1079 }
1078 1080 }
1079 1081
1080 1082 template <typename VariableIterator>
1081 1083 void VariableController::VariableControllerPrivate::desynchronize(VariableIterator variableIt,
1082 1084 const QUuid &syncGroupId)
1083 1085 {
1084 1086 const auto &variable = variableIt->first;
1085 1087 const auto &variableId = variableIt->second;
1086 1088
1087 1089 // Gets synchronization group
1088 1090 auto groupIt = m_GroupIdToVariableSynchronizationGroupMap.find(syncGroupId);
1089 1091 if (groupIt == m_GroupIdToVariableSynchronizationGroupMap.cend()) {
1090 1092 qCCritical(LOG_VariableController())
1091 1093 << tr("Can't desynchronize variable %1: unknown synchronization group")
1092 1094 .arg(variable->name());
1093 1095 return;
1094 1096 }
1095 1097
1096 1098 // Removes variable from synchronization group
1097 1099 auto synchronizationGroup = groupIt->second;
1098 1100 synchronizationGroup->removeVariableId(variableId);
1099 1101
1100 1102 // Removes link between variable and synchronization group
1101 1103 m_VariableIdGroupIdMap.erase(variableId);
1102 1104 }
@@ -1,384 +1,389
1 1 #include "Visualization/VisualizationTabWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "ui_VisualizationTabWidget.h"
4 4
5 5 #include "Visualization/VisualizationGraphWidget.h"
6 6 #include "Visualization/VisualizationZoneWidget.h"
7 7
8 8 #include "Visualization/MacScrollBarStyle.h"
9 9
10 10 #include "DataSource/DataSourceController.h"
11 11 #include "Variable/VariableController.h"
12 12
13 13 #include "Common/MimeTypesDef.h"
14 14
15 15 #include "DragAndDrop/DragDropGuiController.h"
16 16 #include "SqpApplication.h"
17 17
18 18 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
19 19
20 20 namespace {
21 21
22 22 /**
23 23 * Applies a function to all zones of the tab represented by its layout
24 24 * @param layout the layout that contains zones
25 25 * @param fun the function to apply to each zone
26 26 */
27 27 template <typename Fun>
28 28 void processZones(QLayout &layout, Fun fun)
29 29 {
30 30 for (auto i = 0; i < layout.count(); ++i) {
31 31 if (auto item = layout.itemAt(i)) {
32 32 if (auto visualizationZoneWidget
33 33 = qobject_cast<VisualizationZoneWidget *>(item->widget())) {
34 34 fun(*visualizationZoneWidget);
35 35 }
36 36 }
37 37 }
38 38 }
39 39
40 40 /// Generates a default name for a new zone, according to the number of zones already displayed in
41 41 /// the tab
42 42 QString defaultZoneName(QLayout &layout)
43 43 {
44 44 QSet<QString> existingNames;
45 45 processZones(layout,
46 46 [&existingNames](auto &zoneWidget) { existingNames.insert(zoneWidget.name()); });
47 47
48 48 int zoneNum = 1;
49 49 QString name;
50 50 do {
51 51 name = QObject::tr("Zone ").append(QString::number(zoneNum));
52 52 ++zoneNum;
53 53 } while (existingNames.contains(name));
54 54
55 55 return name;
56 56 }
57 57
58 58 } // namespace
59 59
60 60 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
61 61 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
62 62
63 63 QString m_Name;
64 64
65 65 #ifdef Q_OS_MAC
66 66 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
67 67 #endif
68 68
69 69 void dropGraph(int index, VisualizationTabWidget *tabWidget);
70 70 void dropZone(int index, VisualizationTabWidget *tabWidget);
71 71 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
72 72 VisualizationTabWidget *tabWidget);
73 73 void dropProducts(const QVariantList &productsMetaData, int index,
74 74 VisualizationTabWidget *tabWidget);
75 75 };
76 76
77 77 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
78 78 : QWidget{parent},
79 79 ui{new Ui::VisualizationTabWidget},
80 80 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
81 81 {
82 82 ui->setupUi(this);
83 83
84 84 #ifdef Q_OS_MAC
85 85 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
86 86 #endif
87 87
88 88 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Zone, "Zone");
89 89 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
90 90 ui->dragDropContainer->layout()->setSpacing(0);
91 91 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
92 92 VisualizationDragDropContainer::DropBehavior::Inserted);
93 93 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
94 94 VisualizationDragDropContainer::DropBehavior::Inserted);
95 95 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
96 96 VisualizationDragDropContainer::DropBehavior::Inserted);
97 97 ui->dragDropContainer->setMimeType(MIME_TYPE_PRODUCT_LIST,
98 98 VisualizationDragDropContainer::DropBehavior::Inserted);
99 99
100 100 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
101 101 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
102 102 ui->dragDropContainer);
103 103 });
104 104
105 105 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
106 106 &VisualizationTabWidget::dropMimeData);
107 107
108 108 sqpApp->dragDropGuiController().addDragDropScrollArea(ui->scrollArea);
109 109
110 110 // Widget is deleted when closed
111 111 setAttribute(Qt::WA_DeleteOnClose);
112 112 }
113 113
114 114 VisualizationTabWidget::~VisualizationTabWidget()
115 115 {
116 116 sqpApp->dragDropGuiController().removeDragDropScrollArea(ui->scrollArea);
117 117 delete ui;
118 118 }
119 119
120 120 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
121 121 {
122 122 ui->dragDropContainer->addDragWidget(zoneWidget);
123 123 }
124 124
125 125 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
126 126 {
127 127 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
128 128 }
129 129
130 130 QStringList VisualizationTabWidget::availableZoneWidgets() const
131 131 {
132 132 QStringList zones;
133 133 processZones(tabLayout(),
134 134 [&zones](VisualizationZoneWidget &zoneWidget) { zones << zoneWidget.name(); });
135 135
136 136 return zones;
137 137 }
138 138
139 139 VisualizationZoneWidget *VisualizationTabWidget::getZoneWithName(const QString &zoneName)
140 140 {
141 141 VisualizationZoneWidget *result = nullptr;
142 142 processZones(tabLayout(), [&zoneName, &result](VisualizationZoneWidget &zoneWidget) {
143 143 if (!result && zoneWidget.name() == zoneName) {
144 144 result = &zoneWidget;
145 145 }
146 146 });
147 147
148 148 return result;
149 149 }
150 150
151 151 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
152 152 {
153 153 return createZone({variable}, -1);
154 154 }
155 155
156 156 VisualizationZoneWidget *
157 157 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
158 158 {
159 159 auto zoneWidget = createEmptyZone(index);
160 160
161 161 // Creates a new graph into the zone
162 162 zoneWidget->createGraph(variables, index);
163 163
164 164 return zoneWidget;
165 165 }
166 166
167 167 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
168 168 {
169 169 auto zoneWidget
170 170 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
171 171 this->insertZone(index, zoneWidget);
172 172
173 173 return zoneWidget;
174 174 }
175 175
176 176 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
177 177 {
178 178 if (visitor) {
179 179 visitor->visitEnter(this);
180 180
181 181 // Apply visitor to zone children: widgets different from zones are not visited (no action)
182 182 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
183 183 zoneWidget.accept(visitor);
184 184 });
185 185
186 186 visitor->visitLeave(this);
187 187 }
188 188 else {
189 189 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
190 190 }
191 191 }
192 192
193 193 bool VisualizationTabWidget::canDrop(const Variable &variable) const
194 194 {
195 195 // A tab can always accomodate a variable
196 196 Q_UNUSED(variable);
197 197 return true;
198 198 }
199 199
200 200 bool VisualizationTabWidget::contains(const Variable &variable) const
201 201 {
202 202 Q_UNUSED(variable);
203 203 return false;
204 204 }
205 205
206 206 QString VisualizationTabWidget::name() const
207 207 {
208 208 return impl->m_Name;
209 209 }
210 210
211 211 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
212 212 {
213 213 // Closes zones in the tab
214 214 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
215 215
216 216 QWidget::closeEvent(event);
217 217 }
218 218
219 219 QLayout &VisualizationTabWidget::tabLayout() const noexcept
220 220 {
221 221 return *ui->dragDropContainer->layout();
222 222 }
223 223
224 224 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
225 225 {
226 226 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
227 227 impl->dropGraph(index, this);
228 228 }
229 229 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
230 230 impl->dropZone(index, this);
231 231 }
232 232 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
233 233 auto variables = sqpApp->variableController().variablesForMimeData(
234 234 mimeData->data(MIME_TYPE_VARIABLE_LIST));
235 235 impl->dropVariables(variables, index, this);
236 236 }
237 237 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
238 238 auto productsData = sqpApp->dataSourceController().productsDataForMimeData(
239 239 mimeData->data(MIME_TYPE_PRODUCT_LIST));
240 240 impl->dropProducts(productsData, index, this);
241 241 }
242 242 else {
243 243 qCWarning(LOG_VisualizationZoneWidget())
244 244 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
245 245 }
246 246 }
247 247
248 248 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
249 249 int index, VisualizationTabWidget *tabWidget)
250 250 {
251 251 auto &helper = sqpApp->dragDropGuiController();
252 252
253 253 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
254 254 if (!graphWidget) {
255 255 qCWarning(LOG_VisualizationZoneWidget())
256 256 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
257 257 "found or invalid.");
258 258 Q_ASSERT(false);
259 259 return;
260 260 }
261 261
262 262 auto parentDragDropContainer
263 263 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
264 264 if (!parentDragDropContainer) {
265 265 qCWarning(LOG_VisualizationZoneWidget())
266 266 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
267 267 "the dropped graph is not found.");
268 268 Q_ASSERT(false);
269 269 return;
270 270 }
271 271
272 272 auto nbGraph = parentDragDropContainer->countDragWidget();
273 273
274 274 const auto &variables = graphWidget->variables();
275 275
276 276 if (!variables.isEmpty()) {
277 277 // Abort the requests for the variables (if any)
278 278 // Commented, because it's not sure if it's needed or not
279 279 // for (const auto& var : variables)
280 280 //{
281 281 // sqpApp->variableController().onAbortProgressRequested(var);
282 282 //}
283 283
284 284 if (nbGraph == 1) {
285 285 // This is the only graph in the previous zone, close the zone
286 286 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
287 287 }
288 288 else {
289 289 // Close the graph
290 290 helper.delayedCloseWidget(graphWidget);
291 291 }
292 292
293 293 auto zoneWidget = tabWidget->createZone(variables, index);
294 294 auto firstGraph = zoneWidget->firstGraph();
295 295 if (firstGraph) {
296 296 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
297 297 }
298 298 else {
299 299 qCWarning(LOG_VisualizationZoneWidget())
300 300 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
301 301 Q_ASSERT(false);
302 302 }
303 303 }
304 304 else {
305 305 // The graph is empty, create an empty zone and move the graph inside
306 306
307 307 auto parentZoneWidget = graphWidget->parentZoneWidget();
308 308
309 309 parentDragDropContainer->layout()->removeWidget(graphWidget);
310 310
311 311 auto zoneWidget = tabWidget->createEmptyZone(index);
312 312 zoneWidget->addGraph(graphWidget);
313 313
314 314 // Close the old zone if it was the only graph inside
315 315 if (nbGraph == 1) {
316 316 helper.delayedCloseWidget(parentZoneWidget);
317 317 }
318 318 }
319 319 }
320 320
321 321 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
322 322 int index, VisualizationTabWidget *tabWidget)
323 323 {
324 324 auto &helper = sqpApp->dragDropGuiController();
325 325
326 326 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
327 327 if (!zoneWidget) {
328 328 qCWarning(LOG_VisualizationZoneWidget())
329 329 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
330 330 "found or invalid.");
331 331 Q_ASSERT(false);
332 332 return;
333 333 }
334 334
335 335 auto parentDragDropContainer
336 336 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
337 337 if (!parentDragDropContainer) {
338 338 qCWarning(LOG_VisualizationZoneWidget())
339 339 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
340 340 "the dropped zone is not found.");
341 341 Q_ASSERT(false);
342 342 return;
343 343 }
344 344
345 345 // Simple move of the zone, no variable operation associated
346 346 parentDragDropContainer->layout()->removeWidget(zoneWidget);
347 347 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
348 348 }
349 349
350 350 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
351 351 const QList<std::shared_ptr<Variable> > &variables, int index,
352 352 VisualizationTabWidget *tabWidget)
353 353 {
354 354 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
355 355 // compatible variable here
356 356 if (variables.count() > 1) {
357 357 qCWarning(LOG_VisualizationZoneWidget())
358 358 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
359 359 "aborted.");
360 360 return;
361 361 }
362 362
363 363 tabWidget->createZone(variables, index);
364 364 }
365 365
366 366 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropProducts(
367 367 const QVariantList &productsMetaData, int index, VisualizationTabWidget *tabWidget)
368 368 {
369 369 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
370 370 // compatible variable here
371 371 if (productsMetaData.count() != 1) {
372 372 qCWarning(LOG_VisualizationZoneWidget())
373 373 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
374 374 "aborted.");
375 375 return;
376 376 }
377 377
378 auto context = new QObject{tabWidget};
379 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
380 [this, index, tabWidget, context](auto variable) {
381 tabWidget->createZone({variable}, index);
382 delete context; // removes the connection
383 },
384 Qt::QueuedConnection);
385
378 386 auto productData = productsMetaData.first().toHash();
379 387 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
380 388 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
381
382
383 // TODO: add graph
384 389 }
@@ -1,639 +1,652
1 1 #include "Visualization/VisualizationZoneWidget.h"
2 2
3 3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 4 #include "Visualization/QCustomPlotSynchronizer.h"
5 5 #include "Visualization/VisualizationGraphWidget.h"
6 6 #include "Visualization/VisualizationWidget.h"
7 7 #include "ui_VisualizationZoneWidget.h"
8 8
9 9 #include "Common/MimeTypesDef.h"
10 10 #include "Common/VisualizationDef.h"
11 11
12 12 #include <Data/SqpRange.h>
13 13 #include <DataSource/DataSourceController.h>
14 14 #include <Time/TimeController.h>
15 15 #include <Variable/Variable.h>
16 16 #include <Variable/VariableController.h>
17 17
18 18 #include <Visualization/operations/FindVariableOperation.h>
19 19
20 20 #include <DragAndDrop/DragDropGuiController.h>
21 21 #include <QUuid>
22 22 #include <SqpApplication.h>
23 23 #include <cmath>
24 24
25 25 #include <QLayout>
26 26
27 27 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
28 28
29 29 namespace {
30 30
31 31 /**
32 32 * Applies a function to all graphs of the zone represented by its layout
33 33 * @param layout the layout that contains graphs
34 34 * @param fun the function to apply to each graph
35 35 */
36 36 template <typename Fun>
37 37 void processGraphs(QLayout &layout, Fun fun)
38 38 {
39 39 for (auto i = 0; i < layout.count(); ++i) {
40 40 if (auto item = layout.itemAt(i)) {
41 41 if (auto visualizationGraphWidget
42 42 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
43 43 fun(*visualizationGraphWidget);
44 44 }
45 45 }
46 46 }
47 47 }
48 48
49 49 /// Generates a default name for a new graph, according to the number of graphs already displayed in
50 50 /// the zone
51 51 QString defaultGraphName(QLayout &layout)
52 52 {
53 53 QSet<QString> existingNames;
54 54 processGraphs(
55 55 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
56 56
57 57 int zoneNum = 1;
58 58 QString name;
59 59 do {
60 60 name = QObject::tr("Graph ").append(QString::number(zoneNum));
61 61 ++zoneNum;
62 62 } while (existingNames.contains(name));
63 63
64 64 return name;
65 65 }
66 66
67 67 } // namespace
68 68
69 69 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
70 70
71 71 explicit VisualizationZoneWidgetPrivate()
72 72 : m_SynchronisationGroupId{QUuid::createUuid()},
73 73 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
74 74 {
75 75 }
76 76 QUuid m_SynchronisationGroupId;
77 77 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
78 78
79 79 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
80 80 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
81 81 VisualizationZoneWidget *zoneWidget);
82 82 void dropProducts(const QVariantList &productsData, int index,
83 83 VisualizationZoneWidget *zoneWidget);
84 84 };
85 85
86 86 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
87 87 : VisualizationDragWidget{parent},
88 88 ui{new Ui::VisualizationZoneWidget},
89 89 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
90 90 {
91 91 ui->setupUi(this);
92 92
93 93 ui->zoneNameLabel->setText(name);
94 94
95 95 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
96 96 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
97 97 VisualizationDragDropContainer::DropBehavior::Inserted);
98 98 ui->dragDropContainer->setMimeType(
99 99 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
100 100 ui->dragDropContainer->setMimeType(
101 101 MIME_TYPE_PRODUCT_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
102 102 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
103 103 VisualizationDragDropContainer::DropBehavior::Merged);
104 104 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
105 105 VisualizationDragDropContainer::DropBehavior::Forbidden);
106 106 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
107 107 VisualizationDragDropContainer::DropBehavior::Forbidden);
108 108 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
109 109 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
110 110 ui->dragDropContainer);
111 111 });
112 112
113 113 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
114 114 if (!mimeData) {
115 115 return false;
116 116 }
117 117
118 118 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
119 119 auto variables = sqpApp->variableController().variablesForMimeData(
120 120 mimeData->data(MIME_TYPE_VARIABLE_LIST));
121 121
122 122 if (variables.count() != 1) {
123 123 return false;
124 124 }
125 125 auto variable = variables.first();
126 126
127 127 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
128 128 return graphWidget->canDrop(*variable);
129 129 }
130 130 }
131 131
132 132 return true;
133 133 };
134 134 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
135 135
136 136 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
137 137 &VisualizationZoneWidget::dropMimeData);
138 138 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
139 139 &VisualizationZoneWidget::dropMimeDataOnGraph);
140 140
141 141 // 'Close' options : widget is deleted when closed
142 142 setAttribute(Qt::WA_DeleteOnClose);
143 143 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
144 144 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
145 145
146 146 // Synchronisation id
147 147 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
148 148 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
149 149 }
150 150
151 151 VisualizationZoneWidget::~VisualizationZoneWidget()
152 152 {
153 153 delete ui;
154 154 }
155 155
156 156 void VisualizationZoneWidget::setZoneRange(const SqpRange &range)
157 157 {
158 158 if (auto graph = firstGraph()) {
159 159 graph->setGraphRange(range);
160 160 }
161 161 else {
162 162 qCWarning(LOG_VisualizationZoneWidget())
163 163 << tr("setZoneRange:Cannot set the range of an empty zone.");
164 164 }
165 165 }
166 166
167 167 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
168 168 {
169 169 // Synchronize new graph with others in the zone
170 170 impl->m_Synchronizer->addGraph(*graphWidget);
171 171
172 172 ui->dragDropContainer->addDragWidget(graphWidget);
173 173 }
174 174
175 175 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
176 176 {
177 177 // Synchronize new graph with others in the zone
178 178 impl->m_Synchronizer->addGraph(*graphWidget);
179 179
180 180 ui->dragDropContainer->insertDragWidget(index, graphWidget);
181 181 }
182 182
183 183 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
184 184 {
185 185 return createGraph(variable, -1);
186 186 }
187 187
188 188 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
189 189 int index)
190 190 {
191 191 auto graphWidget
192 192 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
193 193
194 194
195 195 // Set graph properties
196 196 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
197 197 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
198 198
199 199
200 200 // Lambda to synchronize zone widget
201 201 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
202 202 const SqpRange &oldGraphRange) {
203 203
204 204 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
205 205 auto frameLayout = ui->dragDropContainer->layout();
206 206 for (auto i = 0; i < frameLayout->count(); ++i) {
207 207 auto graphChild
208 208 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
209 209 if (graphChild && (graphChild != graphWidget)) {
210 210
211 211 auto graphChildRange = graphChild->graphRange();
212 212 switch (zoomType) {
213 213 case AcquisitionZoomType::ZoomIn: {
214 214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
215 215 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
216 216 graphChildRange.m_TStart += deltaLeft;
217 217 graphChildRange.m_TEnd -= deltaRight;
218 218 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
219 219 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
220 220 << deltaLeft;
221 221 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
222 222 << deltaRight;
223 223 qCDebug(LOG_VisualizationZoneWidget())
224 224 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
225 225
226 226 break;
227 227 }
228 228
229 229 case AcquisitionZoomType::ZoomOut: {
230 230 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
231 231 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
232 232 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
233 233 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
234 234 << deltaLeft;
235 235 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
236 236 << deltaRight;
237 237 qCDebug(LOG_VisualizationZoneWidget())
238 238 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
239 239 graphChildRange.m_TStart -= deltaLeft;
240 240 graphChildRange.m_TEnd += deltaRight;
241 241 break;
242 242 }
243 243 case AcquisitionZoomType::PanRight: {
244 244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
245 245 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
246 246 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
247 247 graphChildRange.m_TStart += deltaLeft;
248 248 graphChildRange.m_TEnd += deltaRight;
249 249 qCDebug(LOG_VisualizationZoneWidget())
250 250 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
251 251 break;
252 252 }
253 253 case AcquisitionZoomType::PanLeft: {
254 254 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
255 255 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
256 256 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
257 257 graphChildRange.m_TStart -= deltaLeft;
258 258 graphChildRange.m_TEnd -= deltaRight;
259 259 break;
260 260 }
261 261 case AcquisitionZoomType::Unknown: {
262 262 qCDebug(LOG_VisualizationZoneWidget())
263 263 << tr("Impossible to synchronize: zoom type unknown");
264 264 break;
265 265 }
266 266 default:
267 267 qCCritical(LOG_VisualizationZoneWidget())
268 268 << tr("Impossible to synchronize: zoom type not take into account");
269 269 // No action
270 270 break;
271 271 }
272 272 graphChild->setFlags(GraphFlag::DisableAll);
273 273 qCDebug(LOG_VisualizationZoneWidget())
274 274 << tr("TORM: Range before: ") << graphChild->graphRange();
275 275 qCDebug(LOG_VisualizationZoneWidget())
276 276 << tr("TORM: Range after : ") << graphChildRange;
277 277 qCDebug(LOG_VisualizationZoneWidget())
278 278 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
279 279 graphChild->setGraphRange(graphChildRange);
280 280 graphChild->setFlags(GraphFlag::EnableAll);
281 281 }
282 282 }
283 283 };
284 284
285 285 // connection for synchronization
286 286 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
287 287 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
288 288 &VisualizationZoneWidget::onVariableAdded);
289 289 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
290 290 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
291 291
292 292 auto range = SqpRange{};
293 293 if (auto firstGraph = this->firstGraph()) {
294 294 // Case of a new graph in a existant zone
295 295 range = firstGraph->graphRange();
296 296 }
297 297 else {
298 298 // Case of a new graph as the first of the zone
299 299 range = variable->range();
300 300 }
301 301
302 302 this->insertGraph(index, graphWidget);
303 303
304 304 graphWidget->addVariable(variable, range);
305 305 graphWidget->setYRange(variable);
306 306
307 307 return graphWidget;
308 308 }
309 309
310 310 VisualizationGraphWidget *
311 311 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
312 312 {
313 313 if (variables.isEmpty()) {
314 314 return nullptr;
315 315 }
316 316
317 317 auto graphWidget = createGraph(variables.first(), index);
318 318 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
319 319 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
320 320 }
321 321
322 322 return graphWidget;
323 323 }
324 324
325 325 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
326 326 {
327 327 VisualizationGraphWidget *firstGraph = nullptr;
328 328 auto layout = ui->dragDropContainer->layout();
329 329 if (layout->count() > 0) {
330 330 if (auto visualizationGraphWidget
331 331 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
332 332 firstGraph = visualizationGraphWidget;
333 333 }
334 334 }
335 335
336 336 return firstGraph;
337 337 }
338 338
339 339 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
340 340 {
341 341 if (visitor) {
342 342 visitor->visitEnter(this);
343 343
344 344 // Apply visitor to graph children: widgets different from graphs are not visited (no
345 345 // action)
346 346 processGraphs(
347 347 *ui->dragDropContainer->layout(),
348 348 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
349 349
350 350 visitor->visitLeave(this);
351 351 }
352 352 else {
353 353 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
354 354 }
355 355 }
356 356
357 357 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
358 358 {
359 359 // A tab can always accomodate a variable
360 360 Q_UNUSED(variable);
361 361 return true;
362 362 }
363 363
364 364 bool VisualizationZoneWidget::contains(const Variable &variable) const
365 365 {
366 366 Q_UNUSED(variable);
367 367 return false;
368 368 }
369 369
370 370 QString VisualizationZoneWidget::name() const
371 371 {
372 372 return ui->zoneNameLabel->text();
373 373 }
374 374
375 375 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
376 376 {
377 377 Q_UNUSED(position);
378 378
379 379 auto mimeData = new QMimeData;
380 380 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
381 381
382 382 if (auto firstGraph = this->firstGraph()) {
383 383 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
384 384 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
385 385 }
386 386
387 387 return mimeData;
388 388 }
389 389
390 390 bool VisualizationZoneWidget::isDragAllowed() const
391 391 {
392 392 return true;
393 393 }
394 394
395 395 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
396 396 const QPointF &plotPosition,
397 397 VisualizationGraphWidget *graphWidget)
398 398 {
399 399 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
400 400 VisualizationGraphWidget &processedGraph) {
401 401
402 402 switch (sqpApp->plotsCursorMode()) {
403 403 case SqpApplication::PlotsCursorMode::Vertical:
404 404 processedGraph.removeHorizontalCursor();
405 405 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
406 406 break;
407 407 case SqpApplication::PlotsCursorMode::Temporal:
408 408 processedGraph.addVerticalCursor(plotPosition.x());
409 409 processedGraph.removeHorizontalCursor();
410 410 break;
411 411 case SqpApplication::PlotsCursorMode::Horizontal:
412 412 processedGraph.removeVerticalCursor();
413 413 if (&processedGraph == graphWidget) {
414 414 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
415 415 }
416 416 else {
417 417 processedGraph.removeHorizontalCursor();
418 418 }
419 419 break;
420 420 case SqpApplication::PlotsCursorMode::Cross:
421 421 if (&processedGraph == graphWidget) {
422 422 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
423 423 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
424 424 }
425 425 else {
426 426 processedGraph.removeHorizontalCursor();
427 427 processedGraph.removeVerticalCursor();
428 428 }
429 429 break;
430 430 case SqpApplication::PlotsCursorMode::NoCursor:
431 431 processedGraph.removeHorizontalCursor();
432 432 processedGraph.removeVerticalCursor();
433 433 break;
434 434 }
435 435
436 436
437 437 });
438 438 }
439 439
440 440 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
441 441 {
442 442 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
443 443 processedGraph.removeHorizontalCursor();
444 444 processedGraph.removeVerticalCursor();
445 445 });
446 446 }
447 447
448 448 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
449 449 {
450 450 // Closes graphs in the zone
451 451 processGraphs(*ui->dragDropContainer->layout(),
452 452 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
453 453
454 454 // Delete synchronization group from variable controller
455 455 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
456 456 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
457 457
458 458 QWidget::closeEvent(event);
459 459 }
460 460
461 461 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
462 462 {
463 463 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
464 464 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
465 465 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
466 466 }
467 467
468 468 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
469 469 {
470 470 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
471 471 Q_ARG(std::shared_ptr<Variable>, variable),
472 472 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
473 473 }
474 474
475 475 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
476 476 {
477 477 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
478 478 impl->dropGraph(index, this);
479 479 }
480 480 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
481 481 auto variables = sqpApp->variableController().variablesForMimeData(
482 482 mimeData->data(MIME_TYPE_VARIABLE_LIST));
483 483 impl->dropVariables(variables, index, this);
484 484 }
485 485 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
486 486 auto products = sqpApp->dataSourceController().productsDataForMimeData(
487 487 mimeData->data(MIME_TYPE_PRODUCT_LIST));
488 488 impl->dropProducts(products, index, this);
489 489 }
490 490 else {
491 491 qCWarning(LOG_VisualizationZoneWidget())
492 492 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
493 493 }
494 494 }
495 495
496 496 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
497 497 const QMimeData *mimeData)
498 498 {
499 499 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
500 500 if (!graphWidget) {
501 501 qCWarning(LOG_VisualizationZoneWidget())
502 502 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
503 503 "drop aborted");
504 504 Q_ASSERT(false);
505 505 return;
506 506 }
507 507
508 508 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
509 509 auto variables = sqpApp->variableController().variablesForMimeData(
510 510 mimeData->data(MIME_TYPE_VARIABLE_LIST));
511 511 for (const auto &var : variables) {
512 512 graphWidget->addVariable(var, graphWidget->graphRange());
513 513 }
514 514 }
515 515 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
516 516 auto products = sqpApp->dataSourceController().productsDataForMimeData(
517 517 mimeData->data(MIME_TYPE_PRODUCT_LIST));
518 518
519 auto context = new QObject{this};
520 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
521 [this, graphWidget, context](auto variable) {
522 graphWidget->addVariable(variable, graphWidget->graphRange());
523 delete context; // removes the connection
524 },
525 Qt::QueuedConnection);
526
519 527 auto productData = products.first().toHash();
520 528 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
521 529 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
522 530 }
523 531 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
524 532 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
525 533 graphWidget->setGraphRange(range);
526 534 }
527 535 else {
528 536 qCWarning(LOG_VisualizationZoneWidget())
529 537 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
530 538 }
531 539 }
532 540
533 541 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
534 542 int index, VisualizationZoneWidget *zoneWidget)
535 543 {
536 544 auto &helper = sqpApp->dragDropGuiController();
537 545
538 546 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
539 547 if (!graphWidget) {
540 548 qCWarning(LOG_VisualizationZoneWidget())
541 549 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
542 550 "found or invalid.");
543 551 Q_ASSERT(false);
544 552 return;
545 553 }
546 554
547 555 auto parentDragDropContainer
548 556 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
549 557 if (!parentDragDropContainer) {
550 558 qCWarning(LOG_VisualizationZoneWidget())
551 559 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
552 560 "the dropped graph is not found.");
553 561 Q_ASSERT(false);
554 562 return;
555 563 }
556 564
557 565 const auto &variables = graphWidget->variables();
558 566
559 567 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
560 568 // The drop didn't occur in the same zone
561 569
562 570 // Abort the requests for the variables (if any)
563 571 // Commented, because it's not sure if it's needed or not
564 572 // for (const auto& var : variables)
565 573 //{
566 574 // sqpApp->variableController().onAbortProgressRequested(var);
567 575 //}
568 576
569 577 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
570 578 auto nbGraph = parentDragDropContainer->countDragWidget();
571 579 if (nbGraph == 1) {
572 580 // This is the only graph in the previous zone, close the zone
573 581 helper.delayedCloseWidget(previousParentZoneWidget);
574 582 }
575 583 else {
576 584 // Close the graph
577 585 helper.delayedCloseWidget(graphWidget);
578 586 }
579 587
580 588 // Creates the new graph in the zone
581 589 auto newGraphWidget = zoneWidget->createGraph(variables, index);
582 590 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
583 591 }
584 592 else {
585 593 // The drop occurred in the same zone or the graph is empty
586 594 // Simple move of the graph, no variable operation associated
587 595 parentDragDropContainer->layout()->removeWidget(graphWidget);
588 596
589 597 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
590 598 // The graph is empty and dropped in a different zone.
591 599 // Take the range of the first graph in the zone (if existing).
592 600 auto layout = zoneWidget->ui->dragDropContainer->layout();
593 601 if (layout->count() > 0) {
594 602 if (auto visualizationGraphWidget
595 603 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
596 604 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
597 605 }
598 606 }
599 607 }
600 608
601 609 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
602 610 }
603 611 }
604 612
605 613 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
606 614 const QList<std::shared_ptr<Variable> > &variables, int index,
607 615 VisualizationZoneWidget *zoneWidget)
608 616 {
609 617 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
610 618 // compatible variable here
611 619 if (variables.count() > 1) {
612 620 qCWarning(LOG_VisualizationZoneWidget())
613 621 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
614 622 "aborted.");
615 623 return;
616 624 }
617 625
618 626 zoneWidget->createGraph(variables, index);
619 627 }
620 628
621 629 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
622 630 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
623 631 {
624 632 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
625 633 // compatible variable here
626 634 if (productsData.count() != 1) {
627 635 qCWarning(LOG_VisualizationZoneWidget())
628 636 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
629 637 "aborted.");
630 638 return;
631 639 }
632 640
641 auto context = new QObject{zoneWidget};
642 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
643 [this, index, zoneWidget, context](auto variable) {
644 zoneWidget->createGraph(variable, index);
645 delete context; // removes the connection
646 },
647 Qt::QueuedConnection);
648
633 649 auto productData = productsData.first().toHash();
634 650 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
635 651 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
636
637
638 // TODO: add graph
639 652 }
General Comments 0
You need to be logged in to leave comments. Login now