##// END OF EJS Templates
Drag of variables
trabillard -
r851:73092e810307
parent child
Show More
@@ -1,130 +1,132
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 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
72 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
71 73
72 74 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
73 75 signals:
74 76 /// Signal emitted when a variable is about to be deleted from the controller
75 77 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
76 78
77 79 /// Signal emitted when a data acquisition is requested on a range for a variable
78 80 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
79 81
80 82 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
81 83 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
82 84
83 85 public slots:
84 86 /// Request the data loading of the variable whithin range
85 87 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
86 88 bool synchronise);
87 89 /**
88 90 * Creates a new variable and adds it to the model
89 91 * @param name the name of the new variable
90 92 * @param metadata the metadata of the new variable
91 93 * @param provider the data provider for the new variable
92 94 * @return the pointer to the new variable or nullptr if the creation failed
93 95 */
94 96 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
95 97 std::shared_ptr<IDataProvider> provider) noexcept;
96 98
97 99 /// Update the temporal parameters of every selected variable to dateTime
98 100 void onDateTimeOnSelection(const SqpRange &dateTime);
99 101
100 102
101 103 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
102 104 const SqpRange &cacheRangeRequested,
103 105 QVector<AcquisitionDataPacket> dataAcquired);
104 106
105 107 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
106 108
107 109 /// Cancel the current request for the variable
108 110 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
109 111 void onAbortAcquisitionRequested(QUuid vIdentifier);
110 112
111 113 // synchronization group methods
112 114 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
113 115 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
114 116 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
115 117
116 118 /// Desynchronizes the variable of the group whose identifier is passed in parameter
117 119 /// @remarks the method does nothing if the variable is not part of the group
118 120 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
119 121
120 122 void initialize();
121 123 void finalize();
122 124
123 125 private:
124 126 void waitForFinish();
125 127
126 128 class VariableControllerPrivate;
127 129 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
128 130 };
129 131
130 132 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,95 +1,109
1 1 #ifndef SCIQLOP_VARIABLEMODEL_H
2 2 #define SCIQLOP_VARIABLEMODEL_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/SqpRange.h>
7 7
8 8 #include <QAbstractTableModel>
9 9 #include <QLoggingCategory>
10 10
11 11 #include <Common/MetaTypes.h>
12 12 #include <Common/spimpl.h>
13 13
14 14 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
15 15
16 16 enum VariableRoles { ProgressRole = Qt::UserRole };
17 17
18 18
19 19 class IDataSeries;
20 20 class Variable;
21 class VariableController;
21 22
22 23 /**
23 24 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
24 25 */
25 26 class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel {
26 27 Q_OBJECT
27 28 public:
28 explicit VariableModel(QObject *parent = nullptr);
29 explicit VariableModel(VariableController *parent = nullptr);
29 30
30 31 /**
31 32 * Adds an existing variable in the model.
32 33 * @param variable the variable to add.
33 34 * @remarks the variable's name is modified to avoid name duplicates
34 35 * @remarks this method does nothing if the variable already exists in the model
35 36 */
36 37 void addVariable(std::shared_ptr<Variable> variable) noexcept;
37 38
38 39 /**
39 40 * Checks that a variable is contained in the model
40 41 * @param variable the variable to check
41 42 * @return true if the variable is in the model, false otherwise
42 43 */
43 44 bool containsVariable(std::shared_ptr<Variable> variable) const noexcept;
44 45
45 46 /**
46 47 * Creates a new variable in the model
47 48 * @param name the name of the new variable
48 49 * @param metadata the metadata associated to the new variable
49 50 * @return the pointer to the new variable
50 51 */
51 52 std::shared_ptr<Variable> createVariable(const QString &name,
52 53 const QVariantHash &metadata) noexcept;
53 54
54 55 /**
55 56 * Deletes a variable from the model, if it exists
56 57 * @param variable the variable to delete
57 58 */
58 59 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
59 60
60 61
61 62 std::shared_ptr<Variable> variable(int index) const;
62 63 std::vector<std::shared_ptr<Variable> > variables() const;
63 64
64 65 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
65 66
66 67
67 68 // /////////////////////////// //
68 69 // QAbstractTableModel methods //
69 70 // /////////////////////////// //
70 71
71 72 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
72 73 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
73 74 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
74 75 virtual QVariant headerData(int section, Qt::Orientation orientation,
75 76 int role = Qt::DisplayRole) const override;
76
77 virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
78
79 // ///////////////// //
80 // Drag&Drop methods //
81 // ///////////////// //
82
83 virtual Qt::DropActions supportedDropActions() const override;
84 virtual Qt::DropActions supportedDragActions() const override;
85 virtual QStringList mimeTypes() const override;
86 virtual QMimeData *mimeData(const QModelIndexList &indexes) const override;
87 virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
88 const QModelIndex &parent) const override;
89 virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
90 const QModelIndex &parent) override;
77 91
78 92 void abortProgress(const QModelIndex &index);
79 93
80 94 signals:
81 95 void abortProgessRequested(std::shared_ptr<Variable> variable);
82 96
83 97 private:
84 98 class VariableModelPrivate;
85 99 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
86 100
87 101 private slots:
88 102 /// Slot called when data of a variable has been updated
89 103 void onVariableUpdated() noexcept;
90 104 };
91 105
92 106 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
93 107 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
94 108
95 109 #endif // SCIQLOP_VARIABLEMODEL_H
@@ -1,1012 +1,1053
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 #include <QDataStream>
15 16 #include <QMutex>
16 17 #include <QThread>
17 18 #include <QUuid>
18 19 #include <QtCore/QItemSelectionModel>
19 20
20 21 #include <deque>
21 22 #include <set>
22 23 #include <unordered_map>
23 24
24 25 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
25 26
26 27 namespace {
27 28
28 29 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
29 30 const SqpRange &oldGraphRange)
30 31 {
31 32 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
32 33
33 34 auto varRangeRequested = varRange;
34 35 switch (zoomType) {
35 36 case AcquisitionZoomType::ZoomIn: {
36 37 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
37 38 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
38 39 varRangeRequested.m_TStart += deltaLeft;
39 40 varRangeRequested.m_TEnd -= deltaRight;
40 41 break;
41 42 }
42 43
43 44 case AcquisitionZoomType::ZoomOut: {
44 45 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
45 46 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
46 47 varRangeRequested.m_TStart -= deltaLeft;
47 48 varRangeRequested.m_TEnd += deltaRight;
48 49 break;
49 50 }
50 51 case AcquisitionZoomType::PanRight: {
51 52 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
52 53 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
53 54 varRangeRequested.m_TStart += deltaLeft;
54 55 varRangeRequested.m_TEnd += deltaRight;
55 56 break;
56 57 }
57 58 case AcquisitionZoomType::PanLeft: {
58 59 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
59 60 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
60 61 varRangeRequested.m_TStart -= deltaLeft;
61 62 varRangeRequested.m_TEnd -= deltaRight;
62 63 break;
63 64 }
64 65 case AcquisitionZoomType::Unknown: {
65 66 qCCritical(LOG_VariableController())
66 67 << VariableController::tr("Impossible to synchronize: zoom type unknown");
67 68 break;
68 69 }
69 70 default:
70 71 qCCritical(LOG_VariableController()) << VariableController::tr(
71 72 "Impossible to synchronize: zoom type not take into account");
72 73 // No action
73 74 break;
74 75 }
75 76
76 77 return varRangeRequested;
77 78 }
78 79 }
79 80
80 81 enum class VariableRequestHandlerState { OFF, RUNNING, PENDING };
81 82
82 83 struct VariableRequestHandler {
83 84
84 85 VariableRequestHandler()
85 86 {
86 87 m_CanUpdate = false;
87 88 m_State = VariableRequestHandlerState::OFF;
88 89 }
89 90
90 91 QUuid m_VarId;
91 92 VariableRequest m_RunningVarRequest;
92 93 VariableRequest m_PendingVarRequest;
93 94 VariableRequestHandlerState m_State;
94 95 bool m_CanUpdate;
95 96 };
96 97
97 98 struct VariableController::VariableControllerPrivate {
98 99 explicit VariableControllerPrivate(VariableController *parent)
99 100 : m_WorkingMutex{},
100 101 m_VariableModel{new VariableModel{parent}},
101 102 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
102 103 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
103 104 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
104 105 CacheStrategy::SingleThreshold)},
105 106 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
106 107 q{parent}
107 108 {
108 109
109 110 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
110 111 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
111 112 }
112 113
113 114
114 115 virtual ~VariableControllerPrivate()
115 116 {
116 117 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
117 118 m_VariableAcquisitionWorkerThread.quit();
118 119 m_VariableAcquisitionWorkerThread.wait();
119 120 }
120 121
121 122
122 123 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
123 124 QUuid varRequestId);
124 125
125 126 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
126 127 std::shared_ptr<IDataSeries>
127 128 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
128 129
129 130 void registerProvider(std::shared_ptr<IDataProvider> provider);
130 131
131 132 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
132 133 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
133 134 void updateVariables(QUuid varRequestId);
134 135 void updateVariableRequest(QUuid varRequestId);
135 136 void cancelVariableRequest(QUuid varRequestId);
136 137 void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest);
137 138
138 139 QMutex m_WorkingMutex;
139 140 /// Variable model. The VariableController has the ownership
140 141 VariableModel *m_VariableModel;
141 142 QItemSelectionModel *m_VariableSelectionModel;
142 143
143 144
144 145 TimeController *m_TimeController{nullptr};
145 146 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
146 147 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
147 148 QThread m_VariableAcquisitionWorkerThread;
148 149
149 150 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
150 151 m_VariableToProviderMap;
151 152 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
152 153 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
153 154 m_GroupIdToVariableSynchronizationGroupMap;
154 155 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
155 156 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
156 157
157 158 std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds;
158 159 std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler;
159 160
160 161 VariableController *q;
161 162 };
162 163
163 164
164 165 VariableController::VariableController(QObject *parent)
165 166 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
166 167 {
167 168 qCDebug(LOG_VariableController()) << tr("VariableController construction")
168 169 << QThread::currentThread();
169 170
170 171 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
171 172 &VariableController::onAbortProgressRequested);
172 173
173 174 connect(impl->m_VariableAcquisitionWorker.get(),
174 175 &VariableAcquisitionWorker::variableCanceledRequested, this,
175 176 &VariableController::onAbortAcquisitionRequested);
176 177
177 178 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
178 179 &VariableController::onDataProvided);
179 180 connect(impl->m_VariableAcquisitionWorker.get(),
180 181 &VariableAcquisitionWorker::variableRequestInProgress, this,
181 182 &VariableController::onVariableRetrieveDataInProgress);
182 183
183 184
184 185 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
185 186 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
186 187 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
187 188 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
188 189
189 190
190 191 impl->m_VariableAcquisitionWorkerThread.start();
191 192 }
192 193
193 194 VariableController::~VariableController()
194 195 {
195 196 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
196 197 << QThread::currentThread();
197 198 this->waitForFinish();
198 199 }
199 200
200 201 VariableModel *VariableController::variableModel() noexcept
201 202 {
202 203 return impl->m_VariableModel;
203 204 }
204 205
205 206 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
206 207 {
207 208 return impl->m_VariableSelectionModel;
208 209 }
209 210
210 211 void VariableController::setTimeController(TimeController *timeController) noexcept
211 212 {
212 213 impl->m_TimeController = timeController;
213 214 }
214 215
215 216 std::shared_ptr<Variable>
216 217 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
217 218 {
218 219 if (impl->m_VariableModel->containsVariable(variable)) {
219 220 // Clones variable
220 221 auto duplicate = variable->clone();
221 222
222 223 // Adds clone to model
223 224 impl->m_VariableModel->addVariable(duplicate);
224 225
225 226 // Generates clone identifier
226 227 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
227 228
228 229 // Registers provider
229 230 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
230 231 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
231 232
232 233 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
233 234 if (duplicateProvider) {
234 235 impl->registerProvider(duplicateProvider);
235 236 }
236 237
237 238 return duplicate;
238 239 }
239 240 else {
240 241 qCCritical(LOG_VariableController())
241 242 << tr("Can't create duplicate of variable %1: variable not registered in the model")
242 243 .arg(variable->name());
243 244 return nullptr;
244 245 }
245 246 }
246 247
247 248 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
248 249 {
249 250 if (!variable) {
250 251 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
251 252 return;
252 253 }
253 254
254 255 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
255 256 // make some treatments before the deletion
256 257 emit variableAboutToBeDeleted(variable);
257 258
258 259 // Deletes identifier
259 260 impl->m_VariableToIdentifierMap.erase(variable);
260 261
261 262 // Deletes provider
262 263 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
263 264 qCDebug(LOG_VariableController())
264 265 << tr("Number of providers deleted for variable %1: %2")
265 266 .arg(variable->name(), QString::number(nbProvidersDeleted));
266 267
267 268
268 269 // Deletes from model
269 270 impl->m_VariableModel->deleteVariable(variable);
270 271 }
271 272
272 273 void VariableController::deleteVariables(
273 274 const QVector<std::shared_ptr<Variable> > &variables) noexcept
274 275 {
275 276 for (auto variable : qAsConst(variables)) {
276 277 deleteVariable(variable);
277 278 }
278 279 }
279 280
281 QByteArray
282 VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const
283 {
284 auto encodedData = QByteArray{};
285
286 QVariantList ids;
287 for (auto &var : variables) {
288 auto itVar = impl->m_VariableToIdentifierMap.find(var);
289 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
290 qCCritical(LOG_VariableController())
291 << tr("Impossible to find the data for an unknown variable.");
292 }
293
294 ids << itVar->second.toByteArray();
295 }
296
297 QDataStream stream{&encodedData, QIODevice::WriteOnly};
298 stream << ids;
299
300 return encodedData;
301 }
302
303 QList<std::shared_ptr<Variable> >
304 VariableController::variablesForMimeData(const QByteArray &mimeData) const
305 {
306 auto variables = QList<std::shared_ptr<Variable> >{};
307 QDataStream stream{mimeData};
308
309 QVariantList ids;
310 stream >> ids;
311
312 for (auto id : ids) {
313 auto uuid = QUuid(id.toByteArray());
314 auto var = impl->findVariable(uuid);
315 variables << var;
316 }
317
318 return variables;
319 }
320
280 321 std::shared_ptr<Variable>
281 322 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
282 323 std::shared_ptr<IDataProvider> provider) noexcept
283 324 {
284 325 if (!impl->m_TimeController) {
285 326 qCCritical(LOG_VariableController())
286 327 << tr("Impossible to create variable: The time controller is null");
287 328 return nullptr;
288 329 }
289 330
290 331 auto range = impl->m_TimeController->dateTime();
291 332
292 333 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
293 334 auto varId = QUuid::createUuid();
294 335
295 336 // Create the handler
296 337 auto varRequestHandler = std::make_unique<VariableRequestHandler>();
297 338 varRequestHandler->m_VarId = varId;
298 339
299 340 impl->m_VarIdToVarRequestHandler.insert(
300 341 std::make_pair(varId, std::move(varRequestHandler)));
301 342
302 343 // store the provider
303 344 impl->registerProvider(provider);
304 345
305 346 // Associate the provider
306 347 impl->m_VariableToProviderMap[newVariable] = provider;
307 348 impl->m_VariableToIdentifierMap[newVariable] = varId;
308 349
309 350 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false);
310 351
311 352 // auto varRequestId = QUuid::createUuid();
312 353 // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId;
313 354 // impl->processRequest(newVariable, range, varRequestId);
314 355 // impl->updateVariableRequest(varRequestId);
315 356
316 357 return newVariable;
317 358 }
318 359 }
319 360
320 361 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
321 362 {
322 363 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
323 364 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
324 365 << QThread::currentThread()->objectName();
325 366 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
326 367
327 368 // NOTE we only permit the time modification for one variable
328 369 // DEPRECATED
329 370 // auto variables = QVector<std::shared_ptr<Variable> >{};
330 371 // for (const auto &selectedRow : qAsConst(selectedRows)) {
331 372 // if (auto selectedVariable =
332 373 // impl->m_VariableModel->variable(selectedRow.row())) {
333 374 // variables << selectedVariable;
334 375
335 376 // // notify that rescale operation has to be done
336 377 // emit rangeChanged(selectedVariable, dateTime);
337 378 // }
338 379 // }
339 380 // if (!variables.isEmpty()) {
340 381 // this->onRequestDataLoading(variables, dateTime, synchro);
341 382 // }
342 383 if (selectedRows.size() == 1) {
343 384
344 385 if (auto selectedVariable
345 386 = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) {
346 387
347 388 auto itVar = impl->m_VariableToIdentifierMap.find(selectedVariable);
348 389 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
349 390 qCCritical(LOG_VariableController())
350 391 << tr("Impossible to onDateTimeOnSelection request for unknown variable");
351 392 return;
352 393 }
353 394
354 395 // notify that rescale operation has to be done
355 396 emit rangeChanged(selectedVariable, dateTime);
356 397
357 398 auto synchro = impl->m_VariableIdGroupIdMap.find(itVar->second)
358 399 != impl->m_VariableIdGroupIdMap.cend();
359 400
360 401 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{selectedVariable},
361 402 dateTime, synchro);
362 403 }
363 404 }
364 405 else if (selectedRows.size() > 1) {
365 406 qCCritical(LOG_VariableController())
366 407 << tr("Impossible to set time for more than 1 variable in the same time");
367 408 }
368 409 else {
369 410 qCWarning(LOG_VariableController())
370 411 << tr("There is no variable selected to set the time one");
371 412 }
372 413 }
373 414
374 415 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
375 416 const SqpRange &cacheRangeRequested,
376 417 QVector<AcquisitionDataPacket> dataAcquired)
377 418 {
378 419 qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread();
379 420 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
380 421 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
381 422 if (!varRequestId.isNull()) {
382 423 impl->updateVariables(varRequestId);
383 424 }
384 425 }
385 426
386 427 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
387 428 {
388 429 qCDebug(LOG_VariableController())
389 430 << "TORM: variableController::onVariableRetrieveDataInProgress"
390 431 << QThread::currentThread()->objectName() << progress;
391 432 if (auto var = impl->findVariable(identifier)) {
392 433 impl->m_VariableModel->setDataProgress(var, progress);
393 434 }
394 435 else {
395 436 qCCritical(LOG_VariableController())
396 437 << tr("Impossible to notify progression of a null variable");
397 438 }
398 439 }
399 440
400 441 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
401 442 {
402 443 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested"
403 444 << QThread::currentThread()->objectName() << variable->name();
404 445
405 446 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
406 447 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
407 448 qCCritical(LOG_VariableController())
408 449 << tr("Impossible to onAbortProgressRequested request for unknown variable");
409 450 return;
410 451 }
411 452
412 453 auto varId = itVar->second;
413 454
414 455 auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId);
415 456 if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) {
416 457 qCCritical(LOG_VariableController())
417 458 << tr("Impossible to onAbortProgressRequested for variable with unknown handler");
418 459 return;
419 460 }
420 461
421 462 auto varHandler = itVarHandler->second.get();
422 463
423 464 // case where a variable has a running request
424 465 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
425 466 impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId);
426 467 }
427 468 }
428 469
429 470 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
430 471 {
431 472 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
432 473 << QThread::currentThread()->objectName() << vIdentifier;
433 474
434 475 if (auto var = impl->findVariable(vIdentifier)) {
435 476 this->onAbortProgressRequested(var);
436 477 }
437 478 else {
438 479 qCCritical(LOG_VariableController())
439 480 << tr("Impossible to abort Acquisition Requestof a null variable");
440 481 }
441 482 }
442 483
443 484 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
444 485 {
445 486 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
446 487 << QThread::currentThread()->objectName()
447 488 << synchronizationGroupId;
448 489 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
449 490 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
450 491 std::make_pair(synchronizationGroupId, vSynchroGroup));
451 492 }
452 493
453 494 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
454 495 {
455 496 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
456 497 }
457 498
458 499 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
459 500 QUuid synchronizationGroupId)
460 501
461 502 {
462 503 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
463 504 << synchronizationGroupId;
464 505 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
465 506 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
466 507 auto groupIdToVSGIt
467 508 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
468 509 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
469 510 impl->m_VariableIdGroupIdMap.insert(
470 511 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
471 512 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
472 513 }
473 514 else {
474 515 qCCritical(LOG_VariableController())
475 516 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
476 517 << variable->name();
477 518 }
478 519 }
479 520 else {
480 521 qCCritical(LOG_VariableController())
481 522 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
482 523 }
483 524 }
484 525
485 526 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
486 527 QUuid synchronizationGroupId)
487 528 {
488 529 // Gets variable id
489 530 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
490 531 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
491 532 qCCritical(LOG_VariableController())
492 533 << tr("Can't desynchronize variable %1: variable identifier not found")
493 534 .arg(variable->name());
494 535 return;
495 536 }
496 537
497 538 // Gets synchronization group
498 539 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
499 540 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
500 541 qCCritical(LOG_VariableController())
501 542 << tr("Can't desynchronize variable %1: unknown synchronization group")
502 543 .arg(variable->name());
503 544 return;
504 545 }
505 546
506 547 auto variableId = variableIt->second;
507 548
508 549 // Removes variable from synchronization group
509 550 auto synchronizationGroup = groupIt->second;
510 551 synchronizationGroup->removeVariableId(variableId);
511 552
512 553 // Removes link between variable and synchronization group
513 554 impl->m_VariableIdGroupIdMap.erase(variableId);
514 555 }
515 556
516 557 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
517 558 const SqpRange &range, bool synchronise)
518 559 {
519 560 // variables is assumed synchronized
520 561 // TODO: Asser variables synchronization
521 562 // we want to load data of the variable for the dateTime.
522 563 if (variables.isEmpty()) {
523 564 return;
524 565 }
525 566
526 567 auto varRequestId = QUuid::createUuid();
527 568 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
528 569 << QThread::currentThread()->objectName() << varRequestId
529 570 << range << synchronise;
530 571
531 572 if (!synchronise) {
532 573 auto varIds = std::list<QUuid>{};
533 574 for (const auto &var : variables) {
534 575 auto vId = impl->m_VariableToIdentifierMap.at(var);
535 576 varIds.push_back(vId);
536 577 }
537 578 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
538 579 for (const auto &var : variables) {
539 580 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId
540 581 << varIds.size();
541 582 impl->processRequest(var, range, varRequestId);
542 583 }
543 584 }
544 585 else {
545 586 auto vId = impl->m_VariableToIdentifierMap.at(variables.first());
546 587 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
547 588 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
548 589 auto groupId = varIdToGroupIdIt->second;
549 590
550 591 auto vSynchronizationGroup
551 592 = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId);
552 593 auto vSyncIds = vSynchronizationGroup->getIds();
553 594
554 595 auto varIds = std::list<QUuid>{};
555 596 for (auto vId : vSyncIds) {
556 597 varIds.push_back(vId);
557 598 }
558 599 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
559 600
560 601 for (auto vId : vSyncIds) {
561 602 auto var = impl->findVariable(vId);
562 603
563 604 // Don't process already processed var
564 605 if (var != nullptr) {
565 606 qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name()
566 607 << varRequestId;
567 608 auto vSyncRangeRequested
568 609 = variables.contains(var)
569 610 ? range
570 611 : computeSynchroRangeRequested(var->range(), range,
571 612 variables.first()->range());
572 613 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
573 614 impl->processRequest(var, vSyncRangeRequested, varRequestId);
574 615 }
575 616 else {
576 617 qCCritical(LOG_VariableController())
577 618
578 619 << tr("Impossible to synchronize a null variable");
579 620 }
580 621 }
581 622 }
582 623 }
583 624
584 625 impl->updateVariables(varRequestId);
585 626 }
586 627
587 628
588 629 void VariableController::initialize()
589 630 {
590 631 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
591 632 impl->m_WorkingMutex.lock();
592 633 qCDebug(LOG_VariableController()) << tr("VariableController init END");
593 634 }
594 635
595 636 void VariableController::finalize()
596 637 {
597 638 impl->m_WorkingMutex.unlock();
598 639 }
599 640
600 641 void VariableController::waitForFinish()
601 642 {
602 643 QMutexLocker locker{&impl->m_WorkingMutex};
603 644 }
604 645
605 646 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
606 647 {
607 648 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
608 649 auto zoomType = AcquisitionZoomType::Unknown;
609 650 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
610 651 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
611 652 zoomType = AcquisitionZoomType::ZoomOut;
612 653 }
613 654 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
614 655 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
615 656 zoomType = AcquisitionZoomType::PanRight;
616 657 }
617 658 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
618 659 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
619 660 zoomType = AcquisitionZoomType::PanLeft;
620 661 }
621 662 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
622 663 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
623 664 zoomType = AcquisitionZoomType::ZoomIn;
624 665 }
625 666 else {
626 667 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
627 668 }
628 669 return zoomType;
629 670 }
630 671
631 672 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
632 673 const SqpRange &rangeRequested,
633 674 QUuid varRequestId)
634 675 {
635 676 auto itVar = m_VariableToIdentifierMap.find(var);
636 677 if (itVar == m_VariableToIdentifierMap.cend()) {
637 678 qCCritical(LOG_VariableController())
638 679 << tr("Impossible to process request for unknown variable");
639 680 return;
640 681 }
641 682
642 683 auto varId = itVar->second;
643 684
644 685 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
645 686 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
646 687 qCCritical(LOG_VariableController())
647 688 << tr("Impossible to process request for variable with unknown handler");
648 689 return;
649 690 }
650 691
651 692 auto oldRange = var->range();
652 693
653 694 auto varHandler = itVarHandler->second.get();
654 695
655 696 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
656 697 oldRange = varHandler->m_RunningVarRequest.m_RangeRequested;
657 698 }
658 699
659 700 auto varRequest = VariableRequest{};
660 701 varRequest.m_VariableGroupId = varRequestId;
661 702 auto varStrategyRangesRequested
662 703 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
663 704 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
664 705 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
665 706
666 707 switch (varHandler->m_State) {
667 708 case VariableRequestHandlerState::OFF: {
668 709 qCDebug(LOG_VariableController()) << tr("Process Request OFF")
669 710 << varRequest.m_RangeRequested
670 711 << varRequest.m_CacheRangeRequested;
671 712 varHandler->m_RunningVarRequest = varRequest;
672 713 varHandler->m_State = VariableRequestHandlerState::RUNNING;
673 714 executeVarRequest(var, varRequest);
674 715 break;
675 716 }
676 717 case VariableRequestHandlerState::RUNNING: {
677 718 qCDebug(LOG_VariableController()) << tr("Process Request RUNNING")
678 719 << varRequest.m_RangeRequested
679 720 << varRequest.m_CacheRangeRequested;
680 721 varHandler->m_State = VariableRequestHandlerState::PENDING;
681 722 varHandler->m_PendingVarRequest = varRequest;
682 723 break;
683 724 }
684 725 case VariableRequestHandlerState::PENDING: {
685 726 qCDebug(LOG_VariableController()) << tr("Process Request PENDING")
686 727 << varRequest.m_RangeRequested
687 728 << varRequest.m_CacheRangeRequested;
688 729 auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId;
689 730 cancelVariableRequest(variableGroupIdToCancel);
690 731 // Cancel variable can make state downgrade
691 732 varHandler->m_State = VariableRequestHandlerState::PENDING;
692 733 varHandler->m_PendingVarRequest = varRequest;
693 734
694 735 break;
695 736 }
696 737 default:
697 738 qCCritical(LOG_VariableController())
698 739 << QObject::tr("Unknown VariableRequestHandlerState");
699 740 }
700 741 }
701 742
702 743 std::shared_ptr<Variable>
703 744 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
704 745 {
705 746 std::shared_ptr<Variable> var;
706 747 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
707 748
708 749 auto end = m_VariableToIdentifierMap.cend();
709 750 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
710 751 if (it != end) {
711 752 var = it->first;
712 753 }
713 754 else {
714 755 qCCritical(LOG_VariableController())
715 756 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
716 757 }
717 758
718 759 return var;
719 760 }
720 761
721 762 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
722 763 const QVector<AcquisitionDataPacket> acqDataPacketVector)
723 764 {
724 765 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
725 766 << acqDataPacketVector.size();
726 767 std::shared_ptr<IDataSeries> dataSeries;
727 768 if (!acqDataPacketVector.isEmpty()) {
728 769 dataSeries = acqDataPacketVector[0].m_DateSeries;
729 770 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
730 771 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
731 772 }
732 773 }
733 774 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
734 775 << acqDataPacketVector.size();
735 776 return dataSeries;
736 777 }
737 778
738 779 void VariableController::VariableControllerPrivate::registerProvider(
739 780 std::shared_ptr<IDataProvider> provider)
740 781 {
741 782 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
742 783 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
743 784 << provider->objectName();
744 785 m_ProviderSet.insert(provider);
745 786 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
746 787 &VariableAcquisitionWorker::onVariableDataAcquired);
747 788 connect(provider.get(), &IDataProvider::dataProvidedProgress,
748 789 m_VariableAcquisitionWorker.get(),
749 790 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
750 791 connect(provider.get(), &IDataProvider::dataProvidedFailed,
751 792 m_VariableAcquisitionWorker.get(),
752 793 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
753 794 }
754 795 else {
755 796 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
756 797 }
757 798 }
758 799
759 800 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
760 801 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
761 802 {
762 803 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
763 804 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
764 805 return QUuid();
765 806 }
766 807
767 808 auto varHandler = itVarHandler->second.get();
768 809 if (varHandler->m_State == VariableRequestHandlerState::OFF) {
769 810 qCCritical(LOG_VariableController())
770 811 << tr("acceptVariableRequest impossible on a variable with OFF state");
771 812 }
772 813
773 814 varHandler->m_RunningVarRequest.m_DataSeries = dataSeries;
774 815 varHandler->m_CanUpdate = true;
775 816
776 817 // Element traitΓ©, on a dΓ©jΓ  toutes les donnΓ©es necessaires
777 818 auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId;
778 819 qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId
779 820 << m_VarGroupIdToVarIds.size();
780 821
781 822 return varHandler->m_RunningVarRequest.m_VariableGroupId;
782 823 }
783 824
784 825 void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId)
785 826 {
786 827 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
787 828 << QThread::currentThread()->objectName() << varRequestId;
788 829
789 830 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
790 831 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
791 832 qCWarning(LOG_VariableController())
792 833 << tr("Impossible to updateVariables of unknown variables") << varRequestId;
793 834 return;
794 835 }
795 836
796 837 auto &varIds = varGroupIdToVarIdsIt->second;
797 838 auto varIdsEnd = varIds.end();
798 839 bool processVariableUpdate = true;
799 840 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
800 841 << varRequestId << varIds.size();
801 842 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate;
802 843 ++varIdsIt) {
803 844 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
804 845 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
805 846 processVariableUpdate &= itVarHandler->second->m_CanUpdate;
806 847 }
807 848 }
808 849
809 850 if (processVariableUpdate) {
810 851 qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size();
811 852 for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) {
812 853 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
813 854 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
814 855 if (auto var = findVariable(*varIdsIt)) {
815 856 auto &varRequest = itVarHandler->second->m_RunningVarRequest;
816 857 var->setRange(varRequest.m_RangeRequested);
817 858 var->setCacheRange(varRequest.m_CacheRangeRequested);
818 859 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
819 860 << varRequest.m_RangeRequested
820 861 << varRequest.m_CacheRangeRequested;
821 862 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
822 863 << var->nbPoints()
823 864 << varRequest.m_DataSeries->nbPoints();
824 865 var->mergeDataSeries(varRequest.m_DataSeries);
825 866 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
826 867 << var->nbPoints();
827 868
828 869 emit var->updated();
829 870 qCDebug(LOG_VariableController()) << tr("Update OK");
830 871 }
831 872 else {
832 873 qCCritical(LOG_VariableController())
833 874 << tr("Impossible to update data to a null variable");
834 875 }
835 876 }
836 877 }
837 878 updateVariableRequest(varRequestId);
838 879
839 880 // cleaning varRequestId
840 881 qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId;
841 882 m_VarGroupIdToVarIds.erase(varRequestId);
842 883 }
843 884 }
844 885
845 886
846 887 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
847 888 {
848 889 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
849 890 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
850 891 qCCritical(LOG_VariableController()) << QObject::tr(
851 892 "Impossible to updateVariableRequest since varGroupdId isn't here anymore");
852 893
853 894 return;
854 895 }
855 896
856 897 auto &varIds = varGroupIdToVarIdsIt->second;
857 898 auto varIdsEnd = varIds.end();
858 899 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
859 900 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
860 901 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
861 902
862 903 auto varHandler = itVarHandler->second.get();
863 904 varHandler->m_CanUpdate = false;
864 905
865 906
866 907 switch (varHandler->m_State) {
867 908 case VariableRequestHandlerState::OFF: {
868 909 qCCritical(LOG_VariableController())
869 910 << QObject::tr("Impossible to update a variable with handler in OFF state");
870 911 } break;
871 912 case VariableRequestHandlerState::RUNNING: {
872 913 varHandler->m_State = VariableRequestHandlerState::OFF;
873 914 varHandler->m_RunningVarRequest = VariableRequest{};
874 915 break;
875 916 }
876 917 case VariableRequestHandlerState::PENDING: {
877 918 varHandler->m_State = VariableRequestHandlerState::RUNNING;
878 919 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
879 920 varHandler->m_PendingVarRequest = VariableRequest{};
880 921 auto var = findVariable(itVarHandler->first);
881 922 executeVarRequest(var, varHandler->m_RunningVarRequest);
882 923 break;
883 924 }
884 925 default:
885 926 qCCritical(LOG_VariableController())
886 927 << QObject::tr("Unknown VariableRequestHandlerState");
887 928 }
888 929 }
889 930 }
890 931 }
891 932
892 933
893 934 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
894 935 {
895 936 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId;
896 937
897 938 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
898 939 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
899 940 qCCritical(LOG_VariableController())
900 941 << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId;
901 942 return;
902 943 }
903 944
904 945 auto &varIds = varGroupIdToVarIdsIt->second;
905 946 auto varIdsEnd = varIds.end();
906 947 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
907 948 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
908 949 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
909 950
910 951 auto varHandler = itVarHandler->second.get();
911 952 varHandler->m_VarId = QUuid{};
912 953 switch (varHandler->m_State) {
913 954 case VariableRequestHandlerState::OFF: {
914 955 qCWarning(LOG_VariableController())
915 956 << QObject::tr("Impossible to cancel a variable with no running request");
916 957 break;
917 958 }
918 959 case VariableRequestHandlerState::RUNNING: {
919 960
920 961 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
921 962 auto var = findVariable(itVarHandler->first);
922 963 auto varProvider = m_VariableToProviderMap.at(var);
923 964 if (varProvider != nullptr) {
924 965 m_VariableAcquisitionWorker->abortProgressRequested(
925 966 itVarHandler->first);
926 967 }
927 968 m_VariableModel->setDataProgress(var, 0.0);
928 969 varHandler->m_CanUpdate = false;
929 970 varHandler->m_State = VariableRequestHandlerState::OFF;
930 971 varHandler->m_RunningVarRequest = VariableRequest{};
931 972 }
932 973 else {
933 974 // TODO: log Impossible to cancel the running variable request beacause its
934 975 // varRequestId isn't not the canceled one
935 976 }
936 977 break;
937 978 }
938 979 case VariableRequestHandlerState::PENDING: {
939 980 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
940 981 auto var = findVariable(itVarHandler->first);
941 982 auto varProvider = m_VariableToProviderMap.at(var);
942 983 if (varProvider != nullptr) {
943 984 m_VariableAcquisitionWorker->abortProgressRequested(
944 985 itVarHandler->first);
945 986 }
946 987 m_VariableModel->setDataProgress(var, 0.0);
947 988 varHandler->m_CanUpdate = false;
948 989 varHandler->m_State = VariableRequestHandlerState::RUNNING;
949 990 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
950 991 varHandler->m_PendingVarRequest = VariableRequest{};
951 992 executeVarRequest(var, varHandler->m_RunningVarRequest);
952 993 }
953 994 else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) {
954 995 varHandler->m_State = VariableRequestHandlerState::RUNNING;
955 996 varHandler->m_PendingVarRequest = VariableRequest{};
956 997 }
957 998 else {
958 999 // TODO: log Impossible to cancel the variable request beacause its
959 1000 // varRequestId isn't not the canceled one
960 1001 }
961 1002 break;
962 1003 }
963 1004 default:
964 1005 qCCritical(LOG_VariableController())
965 1006 << QObject::tr("Unknown VariableRequestHandlerState");
966 1007 }
967 1008 }
968 1009 }
969 1010 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId;
970 1011 m_VarGroupIdToVarIds.erase(varRequestId);
971 1012 }
972 1013
973 1014 void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var,
974 1015 VariableRequest &varRequest)
975 1016 {
976 1017 qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest");
977 1018
978 1019 auto varId = m_VariableToIdentifierMap.at(var);
979 1020
980 1021 auto varCacheRange = var->cacheRange();
981 1022 auto varCacheRangeRequested = varRequest.m_CacheRangeRequested;
982 1023 auto notInCacheRangeList
983 1024 = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested);
984 1025 auto inCacheRangeList
985 1026 = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested);
986 1027
987 1028 if (!notInCacheRangeList.empty()) {
988 1029
989 1030 auto varProvider = m_VariableToProviderMap.at(var);
990 1031 if (varProvider != nullptr) {
991 1032 qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested
992 1033 << varRequest.m_CacheRangeRequested;
993 1034 m_VariableAcquisitionWorker->pushVariableRequest(
994 1035 varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested,
995 1036 varRequest.m_CacheRangeRequested,
996 1037 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
997 1038 varProvider);
998 1039 }
999 1040 else {
1000 1041 qCCritical(LOG_VariableController())
1001 1042 << "Impossible to provide data with a null provider";
1002 1043 }
1003 1044
1004 1045 if (!inCacheRangeList.empty()) {
1005 1046 emit q->updateVarDisplaying(var, inCacheRangeList.first());
1006 1047 }
1007 1048 }
1008 1049 else {
1009 1050 acceptVariableRequest(varId,
1010 1051 var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested));
1011 1052 }
1012 1053 }
@@ -1,293 +1,349
1 1 #include <Variable/Variable.h>
2 #include <Variable/VariableController.h>
2 3 #include <Variable/VariableModel.h>
3 4
4 5 #include <Common/DateUtils.h>
6 #include <Common/MimeTypesDef.h>
5 7 #include <Common/StringUtils.h>
6 8
7 9 #include <Data/IDataSeries.h>
8 10
11 #include <QMimeData>
9 12 #include <QSize>
10 13 #include <unordered_map>
11 14
12 15 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
13 16
14 17 namespace {
15 18
16 19 // Column indexes
17 20 const auto NAME_COLUMN = 0;
18 21 const auto TSTART_COLUMN = 1;
19 22 const auto TEND_COLUMN = 2;
20 23 const auto NBPOINTS_COLUMN = 3;
21 24 const auto UNIT_COLUMN = 4;
22 25 const auto MISSION_COLUMN = 5;
23 26 const auto PLUGIN_COLUMN = 6;
24 27 const auto NB_COLUMNS = 7;
25 28
26 29 // Column properties
27 30 const auto DEFAULT_HEIGHT = 25;
28 31 const auto DEFAULT_WIDTH = 100;
29 32
30 33 struct ColumnProperties {
31 34 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
32 35 int height = DEFAULT_HEIGHT)
33 36 : m_Name{name}, m_Width{width}, m_Height{height}
34 37 {
35 38 }
36 39
37 40 QString m_Name;
38 41 int m_Width;
39 42 int m_Height;
40 43 };
41 44
42 45 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
43 46 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
44 47 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
45 48 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
46 49 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
47 50
48 51 /// Format for datetimes
49 52 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
50 53
51 54 QString uniqueName(const QString &defaultName,
52 55 const std::vector<std::shared_ptr<Variable> > &variables)
53 56 {
54 57 auto forbiddenNames = std::vector<QString>(variables.size());
55 58 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
56 59 [](const auto &variable) { return variable->name(); });
57 60 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
58 61 Q_ASSERT(!uniqueName.isEmpty());
59 62
60 63 return uniqueName;
61 64 }
62 65
63 66 } // namespace
64 67
65 68 struct VariableModel::VariableModelPrivate {
66 69 /// Variables created in SciQlop
67 70 std::vector<std::shared_ptr<Variable> > m_Variables;
68 71 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
72 VariableController *m_VariableController;
69 73
70 74 /// Return the row index of the variable. -1 if it's not found
71 75 int indexOfVariable(Variable *variable) const noexcept;
72 76 };
73 77
74 VariableModel::VariableModel(QObject *parent)
78 VariableModel::VariableModel(VariableController *parent)
75 79 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
76 80 {
81 impl->m_VariableController = parent;
77 82 }
78 83
79 84 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
80 85 {
81 86 auto insertIndex = rowCount();
82 87 beginInsertRows({}, insertIndex, insertIndex);
83 88
84 89 // Generates unique name for the variable
85 90 variable->setName(uniqueName(variable->name(), impl->m_Variables));
86 91
87 92 impl->m_Variables.push_back(variable);
88 93 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
89 94
90 95 endInsertRows();
91 96 }
92 97
93 98 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
94 99 {
95 100 auto end = impl->m_Variables.cend();
96 101 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
97 102 }
98 103
99 104 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
100 105 const QVariantHash &metadata) noexcept
101 106 {
102 107 auto variable = std::make_shared<Variable>(name, metadata);
103 108 addVariable(variable);
104 109
105 110 return variable;
106 111 }
107 112
108 113 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
109 114 {
110 115 if (!variable) {
111 116 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
112 117 return;
113 118 }
114 119
115 120 // Finds variable in the model
116 121 auto begin = impl->m_Variables.cbegin();
117 122 auto end = impl->m_Variables.cend();
118 123 auto it = std::find(begin, end, variable);
119 124 if (it != end) {
120 125 auto removeIndex = std::distance(begin, it);
121 126
122 127 // Deletes variable
123 128 beginRemoveRows({}, removeIndex, removeIndex);
124 129 impl->m_Variables.erase(it);
125 130 endRemoveRows();
126 131 }
127 132 else {
128 133 qCritical(LOG_VariableModel())
129 134 << tr("Can't delete variable %1 from the model: the variable is not in the model")
130 135 .arg(variable->name());
131 136 }
132 137
133 138 // Removes variable from progress map
134 139 impl->m_VariableToProgress.erase(variable);
135 140 }
136 141
137 142
138 143 std::shared_ptr<Variable> VariableModel::variable(int index) const
139 144 {
140 145 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
141 146 }
142 147
143 148 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
144 149 {
145 150 return impl->m_Variables;
146 151 }
147 152
148 153 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
149 154 {
150 155 if (progress > 0.0) {
151 156 impl->m_VariableToProgress[variable] = progress;
152 157 }
153 158 else {
154 159 impl->m_VariableToProgress.erase(variable);
155 160 }
156 161 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
157 162
158 163 emit dataChanged(modelIndex, modelIndex);
159 164 }
160 165
161 166 int VariableModel::columnCount(const QModelIndex &parent) const
162 167 {
163 168 Q_UNUSED(parent);
164 169
165 170 return NB_COLUMNS;
166 171 }
167 172
168 173 int VariableModel::rowCount(const QModelIndex &parent) const
169 174 {
170 175 Q_UNUSED(parent);
171 176
172 177 return impl->m_Variables.size();
173 178 }
174 179
175 180 QVariant VariableModel::data(const QModelIndex &index, int role) const
176 181 {
177 182 if (!index.isValid()) {
178 183 return QVariant{};
179 184 }
180 185
181 186 if (index.row() < 0 || index.row() >= rowCount()) {
182 187 return QVariant{};
183 188 }
184 189
185 190 if (role == Qt::DisplayRole) {
186 191 if (auto variable = impl->m_Variables.at(index.row()).get()) {
187 192 switch (index.column()) {
188 193 case NAME_COLUMN:
189 194 return variable->name();
190 195 case TSTART_COLUMN: {
191 196 auto range = variable->realRange();
192 197 return range != INVALID_RANGE
193 198 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
194 199 : QVariant{};
195 200 }
196 201 case TEND_COLUMN: {
197 202 auto range = variable->realRange();
198 203 return range != INVALID_RANGE
199 204 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
200 205 : QVariant{};
201 206 }
202 207 case NBPOINTS_COLUMN:
203 208 return variable->nbPoints();
204 209 case UNIT_COLUMN:
205 210 return variable->metadata().value(QStringLiteral("units"));
206 211 case MISSION_COLUMN:
207 212 return variable->metadata().value(QStringLiteral("mission"));
208 213 case PLUGIN_COLUMN:
209 214 return variable->metadata().value(QStringLiteral("plugin"));
210 215 default:
211 216 // No action
212 217 break;
213 218 }
214 219
215 220 qWarning(LOG_VariableModel())
216 221 << tr("Can't get data (unknown column %1)").arg(index.column());
217 222 }
218 223 else {
219 224 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
220 225 }
221 226 }
222 227 else if (role == VariableRoles::ProgressRole) {
223 228 if (auto variable = impl->m_Variables.at(index.row())) {
224 229
225 230 auto it = impl->m_VariableToProgress.find(variable);
226 231 if (it != impl->m_VariableToProgress.cend()) {
227 232 return it->second;
228 233 }
229 234 }
230 235 }
231 236
232 237 return QVariant{};
233 238 }
234 239
235 240 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
236 241 {
237 242 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
238 243 return QVariant{};
239 244 }
240 245
241 246 if (orientation == Qt::Horizontal) {
242 247 auto propertiesIt = COLUMN_PROPERTIES.find(section);
243 248 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
244 249 // Role is either DisplayRole or SizeHintRole
245 250 return (role == Qt::DisplayRole)
246 251 ? QVariant{propertiesIt->m_Name}
247 252 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
248 253 }
249 254 else {
250 255 qWarning(LOG_VariableModel())
251 256 << tr("Can't get header data (unknown column %1)").arg(section);
252 257 }
253 258 }
254 259
255 260 return QVariant{};
256 261 }
257 262
263 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
264 {
265 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
266 }
267
268 Qt::DropActions VariableModel::supportedDropActions() const
269 {
270 return Qt::MoveAction;
271 }
272
273 Qt::DropActions VariableModel::supportedDragActions() const
274 {
275 return Qt::CopyAction | Qt::MoveAction;
276 }
277
278 QStringList VariableModel::mimeTypes() const
279 {
280 return {MIME_TYPE_VARIABLE_LIST};
281 }
282
283 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
284 {
285 auto mimeData = new QMimeData;
note

The QMimeData object is handled by Qt. Apparently this is the common way implement such method within Qt cf QTreeWidget::mimeData or QAbstractItemModel::mimeData.

286
287 QList<std::shared_ptr<Variable> > variableList;
288
289 for (const auto &index : indexes) {
290 auto variable = impl->m_Variables.at(index.row());
291 if (variable.get() && index.isValid()) {
292 variableList << variable;
293 }
294 }
295
296 auto encodedData = impl->m_VariableController->mimeDataForVariables(variableList);
297 mimeData->setData(MIME_TYPE_VARIABLE_LIST, encodedData);
298
299 return mimeData;
300 }
301
302 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
303 int column, const QModelIndex &parent) const
304 {
305 return false;
306 }
307
308 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
309 const QModelIndex &parent)
310 {
311 return false;
312 }
313
258 314 void VariableModel::abortProgress(const QModelIndex &index)
259 315 {
260 316 if (auto variable = impl->m_Variables.at(index.row())) {
261 317 emit abortProgessRequested(variable);
262 318 }
263 319 }
264 320
265 321 void VariableModel::onVariableUpdated() noexcept
266 322 {
267 323 // Finds variable that has been updated in the model
268 324 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
269 325 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
270 326
271 327 if (updatedVariableIndex > -1) {
272 328 emit dataChanged(createIndex(updatedVariableIndex, 0),
273 329 createIndex(updatedVariableIndex, columnCount() - 1));
274 330 }
275 331 }
276 332 }
277 333
278 334 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
279 335 {
280 336 auto begin = std::cbegin(m_Variables);
281 337 auto end = std::cend(m_Variables);
282 338 auto it
283 339 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
284 340
285 341 if (it != end) {
286 342 // Gets the index of the variable in the model: we assume here that views have the same
287 343 // order as the model
288 344 return std::distance(begin, it);
289 345 }
290 346 else {
291 347 return -1;
292 348 }
293 349 }
General Comments 1
Under Review
author

Auto status change to "Under Review"

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