##// END OF EJS Templates
Adds 'Duplicate' action on variable menu
Alexandre Leroux -
r650:35ef72ac0d81
parent child
Show More
@@ -1,122 +1,129
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 * Clones the variable passed in parameter and adds the duplicate to the controller
46 * @param variable the variable to duplicate
47 * @return the duplicate created, nullptr if the variable couldn't be created
48 */
49 std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept;
50
51 /**
45 52 * Deletes from the controller the variable passed in parameter.
46 53 *
47 54 * Delete a variable includes:
48 55 * - the deletion of the various references to the variable in SciQlop
49 56 * - the deletion of the model variable
50 57 * - the deletion of the provider associated with the variable
51 58 * - removing the cache associated with the variable
52 59 *
53 60 * @param variable the variable to delete from the controller.
54 61 */
55 62 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
56 63
57 64 /**
58 65 * Deletes from the controller the variables passed in parameter.
59 66 * @param variables the variables to delete from the controller.
60 67 * @sa deleteVariable()
61 68 */
62 69 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
63 70
64 71 /**
65 72 * @brief abort the variable retrieve data progression
66 73 */
67 74 void abortProgress(std::shared_ptr<Variable> variable);
68 75
69 76 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
70 77 signals:
71 78 /// Signal emitted when a variable is about to be deleted from the controller
72 79 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
73 80
74 81 /// Signal emitted when a data acquisition is requested on a range for a variable
75 82 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
76 83
77 84 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
78 85 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
79 86
80 87 public slots:
81 88 /// Request the data loading of the variable whithin range
82 89 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
83 90 const SqpRange &oldRange, bool synchronise);
84 91 /**
85 92 * Creates a new variable and adds it to the model
86 93 * @param name the name of the new variable
87 94 * @param metadata the metadata of the new variable
88 95 * @param provider the data provider for the new variable
89 96 * @return the pointer to the new variable or nullptr if the creation failed
90 97 */
91 98 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
92 99 std::shared_ptr<IDataProvider> provider) noexcept;
93 100
94 101 /// Update the temporal parameters of every selected variable to dateTime
95 102 void onDateTimeOnSelection(const SqpRange &dateTime);
96 103
97 104
98 105 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
99 106 const SqpRange &cacheRangeRequested,
100 107 QVector<AcquisitionDataPacket> dataAcquired);
101 108
102 109 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
103 110
104 111 /// Cancel the current request for the variable
105 112 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
106 113
107 114 /// synchronization group methods
108 115 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
109 116 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
110 117 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
111 118
112 119 void initialize();
113 120 void finalize();
114 121
115 122 private:
116 123 void waitForFinish();
117 124
118 125 class VariableControllerPrivate;
119 126 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
120 127 };
121 128
122 129 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,743 +1,748
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableAcquisitionWorker.h>
3 3 #include <Variable/VariableCacheStrategy.h>
4 4 #include <Variable/VariableController.h>
5 5 #include <Variable/VariableModel.h>
6 6 #include <Variable/VariableSynchronizationGroup.h>
7 7
8 8 #include <Data/DataProviderParameters.h>
9 9 #include <Data/IDataProvider.h>
10 10 #include <Data/IDataSeries.h>
11 11 #include <Data/VariableRequest.h>
12 12 #include <Time/TimeController.h>
13 13
14 14 #include <QMutex>
15 15 #include <QThread>
16 16 #include <QUuid>
17 17 #include <QtCore/QItemSelectionModel>
18 18
19 19 #include <deque>
20 20 #include <set>
21 21 #include <unordered_map>
22 22
23 23 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
24 24
25 25 namespace {
26 26
27 27 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
28 28 const SqpRange &oldGraphRange)
29 29 {
30 30 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
31 31
32 32 auto varRangeRequested = varRange;
33 33 switch (zoomType) {
34 34 case AcquisitionZoomType::ZoomIn: {
35 35 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
36 36 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
37 37 varRangeRequested.m_TStart += deltaLeft;
38 38 varRangeRequested.m_TEnd -= deltaRight;
39 39 break;
40 40 }
41 41
42 42 case AcquisitionZoomType::ZoomOut: {
43 43 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
44 44 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
45 45 varRangeRequested.m_TStart -= deltaLeft;
46 46 varRangeRequested.m_TEnd += deltaRight;
47 47 break;
48 48 }
49 49 case AcquisitionZoomType::PanRight: {
50 50 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
51 51 varRangeRequested.m_TStart += deltaRight;
52 52 varRangeRequested.m_TEnd += deltaRight;
53 53 break;
54 54 }
55 55 case AcquisitionZoomType::PanLeft: {
56 56 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
57 57 varRangeRequested.m_TStart -= deltaLeft;
58 58 varRangeRequested.m_TEnd -= deltaLeft;
59 59 break;
60 60 }
61 61 case AcquisitionZoomType::Unknown: {
62 62 qCCritical(LOG_VariableController())
63 63 << VariableController::tr("Impossible to synchronize: zoom type unknown");
64 64 break;
65 65 }
66 66 default:
67 67 qCCritical(LOG_VariableController()) << VariableController::tr(
68 68 "Impossible to synchronize: zoom type not take into account");
69 69 // No action
70 70 break;
71 71 }
72 72
73 73 return varRangeRequested;
74 74 }
75 75 }
76 76
77 77 struct VariableController::VariableControllerPrivate {
78 78 explicit VariableControllerPrivate(VariableController *parent)
79 79 : m_WorkingMutex{},
80 80 m_VariableModel{new VariableModel{parent}},
81 81 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
82 82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
83 83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
84 84 q{parent}
85 85 {
86 86
87 87 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
88 88 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
89 89 }
90 90
91 91
92 92 virtual ~VariableControllerPrivate()
93 93 {
94 94 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
95 95 m_VariableAcquisitionWorkerThread.quit();
96 96 m_VariableAcquisitionWorkerThread.wait();
97 97 }
98 98
99 99
100 100 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
101 101 QUuid varRequestId);
102 102
103 103 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
104 104 const SqpRange &dateTime);
105 105
106 106 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
107 107 std::shared_ptr<IDataSeries>
108 108 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
109 109
110 110 void registerProvider(std::shared_ptr<IDataProvider> provider);
111 111
112 112 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
113 113 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
114 114 void updateVariableRequest(QUuid varRequestId);
115 115 void cancelVariableRequest(QUuid varRequestId);
116 116
117 117 QMutex m_WorkingMutex;
118 118 /// Variable model. The VariableController has the ownership
119 119 VariableModel *m_VariableModel;
120 120 QItemSelectionModel *m_VariableSelectionModel;
121 121
122 122
123 123 TimeController *m_TimeController{nullptr};
124 124 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
125 125 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
126 126 QThread m_VariableAcquisitionWorkerThread;
127 127
128 128 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
129 129 m_VariableToProviderMap;
130 130 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
131 131 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
132 132 m_GroupIdToVariableSynchronizationGroupMap;
133 133 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
134 134 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
135 135
136 136 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
137 137
138 138 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
139 139
140 140
141 141 VariableController *q;
142 142 };
143 143
144 144
145 145 VariableController::VariableController(QObject *parent)
146 146 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
147 147 {
148 148 qCDebug(LOG_VariableController()) << tr("VariableController construction")
149 149 << QThread::currentThread();
150 150
151 151 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
152 152 &VariableController::onAbortProgressRequested);
153 153
154 154 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
155 155 &VariableController::onDataProvided);
156 156 connect(impl->m_VariableAcquisitionWorker.get(),
157 157 &VariableAcquisitionWorker::variableRequestInProgress, this,
158 158 &VariableController::onVariableRetrieveDataInProgress);
159 159
160 160 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
161 161 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
162 162 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
163 163 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
164 164
165 165
166 166 impl->m_VariableAcquisitionWorkerThread.start();
167 167 }
168 168
169 169 VariableController::~VariableController()
170 170 {
171 171 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
172 172 << QThread::currentThread();
173 173 this->waitForFinish();
174 174 }
175 175
176 176 VariableModel *VariableController::variableModel() noexcept
177 177 {
178 178 return impl->m_VariableModel;
179 179 }
180 180
181 181 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
182 182 {
183 183 return impl->m_VariableSelectionModel;
184 184 }
185 185
186 186 void VariableController::setTimeController(TimeController *timeController) noexcept
187 187 {
188 188 impl->m_TimeController = timeController;
189 189 }
190 190
191 std::shared_ptr<Variable>
192 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
193 {
194 }
195
191 196 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
192 197 {
193 198 if (!variable) {
194 199 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
195 200 return;
196 201 }
197 202
198 203 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
199 204 // make some treatments before the deletion
200 205 emit variableAboutToBeDeleted(variable);
201 206
202 207 // Deletes identifier
203 208 impl->m_VariableToIdentifierMap.erase(variable);
204 209
205 210 // Deletes provider
206 211 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
207 212 qCDebug(LOG_VariableController())
208 213 << tr("Number of providers deleted for variable %1: %2")
209 214 .arg(variable->name(), QString::number(nbProvidersDeleted));
210 215
211 216
212 217 // Deletes from model
213 218 impl->m_VariableModel->deleteVariable(variable);
214 219 }
215 220
216 221 void VariableController::deleteVariables(
217 222 const QVector<std::shared_ptr<Variable> > &variables) noexcept
218 223 {
219 224 for (auto variable : qAsConst(variables)) {
220 225 deleteVariable(variable);
221 226 }
222 227 }
223 228
224 229 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
225 230 {
226 231 }
227 232
228 233 std::shared_ptr<Variable>
229 234 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
230 235 std::shared_ptr<IDataProvider> provider) noexcept
231 236 {
232 237 if (!impl->m_TimeController) {
233 238 qCCritical(LOG_VariableController())
234 239 << tr("Impossible to create variable: The time controller is null");
235 240 return nullptr;
236 241 }
237 242
238 243 auto range = impl->m_TimeController->dateTime();
239 244
240 245 if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) {
241 246 auto identifier = QUuid::createUuid();
242 247
243 248 // store the provider
244 249 impl->registerProvider(provider);
245 250
246 251 // Associate the provider
247 252 impl->m_VariableToProviderMap[newVariable] = provider;
248 253 impl->m_VariableToIdentifierMap[newVariable] = identifier;
249 254
250 255
251 256 auto varRequestId = QUuid::createUuid();
252 257 qCInfo(LOG_VariableController()) << "processRequest for" << name << varRequestId;
253 258 impl->processRequest(newVariable, range, varRequestId);
254 259 impl->updateVariableRequest(varRequestId);
255 260
256 261 return newVariable;
257 262 }
258 263 }
259 264
260 265 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
261 266 {
262 267 // TODO check synchronisation and Rescale
263 268 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
264 269 << QThread::currentThread()->objectName();
265 270 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
266 271 auto varRequestId = QUuid::createUuid();
267 272
268 273 for (const auto &selectedRow : qAsConst(selectedRows)) {
269 274 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
270 275 selectedVariable->setRange(dateTime);
271 276 impl->processRequest(selectedVariable, dateTime, varRequestId);
272 277
273 278 // notify that rescale operation has to be done
274 279 emit rangeChanged(selectedVariable, dateTime);
275 280 }
276 281 }
277 282 impl->updateVariableRequest(varRequestId);
278 283 }
279 284
280 285 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
281 286 const SqpRange &cacheRangeRequested,
282 287 QVector<AcquisitionDataPacket> dataAcquired)
283 288 {
284 289 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
285 290 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
286 291 if (!varRequestId.isNull()) {
287 292 impl->updateVariableRequest(varRequestId);
288 293 }
289 294 }
290 295
291 296 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
292 297 {
293 298 if (auto var = impl->findVariable(identifier)) {
294 299 impl->m_VariableModel->setDataProgress(var, progress);
295 300 }
296 301 else {
297 302 qCCritical(LOG_VariableController())
298 303 << tr("Impossible to notify progression of a null variable");
299 304 }
300 305 }
301 306
302 307 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
303 308 {
304 309 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
305 310 << QThread::currentThread()->objectName();
306 311
307 312 auto it = impl->m_VariableToIdentifierMap.find(variable);
308 313 if (it != impl->m_VariableToIdentifierMap.cend()) {
309 314 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
310 315 }
311 316 else {
312 317 qCWarning(LOG_VariableController())
313 318 << tr("Aborting progression of inexistant variable detected !!!")
314 319 << QThread::currentThread()->objectName();
315 320 }
316 321 }
317 322
318 323 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
319 324 {
320 325 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
321 326 << QThread::currentThread()->objectName()
322 327 << synchronizationGroupId;
323 328 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
324 329 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
325 330 std::make_pair(synchronizationGroupId, vSynchroGroup));
326 331 }
327 332
328 333 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
329 334 {
330 335 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
331 336 }
332 337
333 338 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
334 339 QUuid synchronizationGroupId)
335 340
336 341 {
337 342 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
338 343 << synchronizationGroupId;
339 344 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
340 345 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
341 346 auto groupIdToVSGIt
342 347 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
343 348 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
344 349 impl->m_VariableIdGroupIdMap.insert(
345 350 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
346 351 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
347 352 }
348 353 else {
349 354 qCCritical(LOG_VariableController())
350 355 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
351 356 << variable->name();
352 357 }
353 358 }
354 359 else {
355 360 qCCritical(LOG_VariableController())
356 361 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
357 362 }
358 363 }
359 364
360 365
361 366 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
362 367 const SqpRange &range, const SqpRange &oldRange,
363 368 bool synchronise)
364 369 {
365 370 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
366 371
367 372 // we want to load data of the variable for the dateTime.
368 373 // First we check if the cache contains some of them.
369 374 // For the other, we ask the provider to give them.
370 375
371 376 auto varRequestId = QUuid::createUuid();
372 377 qCInfo(LOG_VariableController()) << "VariableController::onRequestDataLoading"
373 378 << QThread::currentThread()->objectName() << varRequestId;
374 379
375 380 for (const auto &var : variables) {
376 381 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
377 382 impl->processRequest(var, range, varRequestId);
378 383 }
379 384
380 385 if (synchronise) {
381 386 // Get the group ids
382 387 qCDebug(LOG_VariableController())
383 388 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
384 389 auto groupIds = std::set<QUuid>{};
385 390 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
386 391 for (const auto &var : variables) {
387 392 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
388 393 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
389 394 auto vId = varToVarIdIt->second;
390 395 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
391 396 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
392 397 auto gId = varIdToGroupIdIt->second;
393 398 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
394 399 if (groupIds.find(gId) == groupIds.cend()) {
395 400 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
396 401 groupIds.insert(gId);
397 402 }
398 403 }
399 404 }
400 405 }
401 406
402 407 // We assume here all group ids exist
403 408 for (const auto &gId : groupIds) {
404 409 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
405 410 auto vSyncIds = vSynchronizationGroup->getIds();
406 411 qCDebug(LOG_VariableController()) << "Var in synchro group ";
407 412 for (auto vId : vSyncIds) {
408 413 auto var = impl->findVariable(vId);
409 414
410 415 // Don't process already processed var
411 416 if (!variables.contains(var)) {
412 417 if (var != nullptr) {
413 418 qCDebug(LOG_VariableController()) << "processRequest synchro for"
414 419 << var->name();
415 420 auto vSyncRangeRequested = computeSynchroRangeRequested(
416 421 var->range(), range, groupIdToOldRangeMap.at(gId));
417 422 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
418 423 impl->processRequest(var, vSyncRangeRequested, varRequestId);
419 424 }
420 425 else {
421 426 qCCritical(LOG_VariableController())
422 427
423 428 << tr("Impossible to synchronize a null variable");
424 429 }
425 430 }
426 431 }
427 432 }
428 433 }
429 434
430 435 impl->updateVariableRequest(varRequestId);
431 436 }
432 437
433 438
434 439 void VariableController::initialize()
435 440 {
436 441 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
437 442 impl->m_WorkingMutex.lock();
438 443 qCDebug(LOG_VariableController()) << tr("VariableController init END");
439 444 }
440 445
441 446 void VariableController::finalize()
442 447 {
443 448 impl->m_WorkingMutex.unlock();
444 449 }
445 450
446 451 void VariableController::waitForFinish()
447 452 {
448 453 QMutexLocker locker{&impl->m_WorkingMutex};
449 454 }
450 455
451 456 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
452 457 {
453 458 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
454 459 auto zoomType = AcquisitionZoomType::Unknown;
455 460 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
456 461 zoomType = AcquisitionZoomType::ZoomOut;
457 462 }
458 463 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
459 464 zoomType = AcquisitionZoomType::PanRight;
460 465 }
461 466 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
462 467 zoomType = AcquisitionZoomType::PanLeft;
463 468 }
464 469 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
465 470 zoomType = AcquisitionZoomType::ZoomIn;
466 471 }
467 472 else {
468 473 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
469 474 }
470 475 return zoomType;
471 476 }
472 477
473 478 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
474 479 const SqpRange &rangeRequested,
475 480 QUuid varRequestId)
476 481 {
477 482
478 483 // TODO: protect at
479 484 auto varRequest = VariableRequest{};
480 485 auto varId = m_VariableToIdentifierMap.at(var);
481 486
482 487 auto varStrategyRangesRequested
483 488 = m_VariableCacheStrategy->computeStrategyRanges(var->range(), rangeRequested);
484 489 auto notInCacheRangeList = var->provideNotInCacheRangeList(varStrategyRangesRequested.second);
485 490 auto inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second);
486 491
487 492 if (!notInCacheRangeList.empty()) {
488 493 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
489 494 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
490 495 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest RR ") << rangeRequested;
491 496 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest R ")
492 497 << varStrategyRangesRequested.first;
493 498 qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM processRequest CR ")
494 499 << varStrategyRangesRequested.second;
495 500 // store VarRequest
496 501 storeVariableRequest(varId, varRequestId, varRequest);
497 502
498 503 auto varProvider = m_VariableToProviderMap.at(var);
499 504 if (varProvider != nullptr) {
500 505 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
501 506 varRequestId, varId, varStrategyRangesRequested.first,
502 507 varStrategyRangesRequested.second,
503 508 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
504 509 varProvider);
505 510
506 511 if (!varRequestIdCanceled.isNull()) {
507 512 qCInfo(LOG_VariableAcquisitionWorker()) << tr("varRequestIdCanceled: ")
508 513 << varRequestIdCanceled;
509 514 cancelVariableRequest(varRequestIdCanceled);
510 515 }
511 516 }
512 517 else {
513 518 qCCritical(LOG_VariableController())
514 519 << "Impossible to provide data with a null provider";
515 520 }
516 521
517 522 if (!inCacheRangeList.empty()) {
518 523 emit q->updateVarDisplaying(var, inCacheRangeList.first());
519 524 }
520 525 }
521 526 else {
522 527
523 528 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
524 529 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
525 530 // store VarRequest
526 531 storeVariableRequest(varId, varRequestId, varRequest);
527 532 acceptVariableRequest(varId,
528 533 var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
529 534 }
530 535 }
531 536
532 537 std::shared_ptr<Variable>
533 538 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
534 539 {
535 540 std::shared_ptr<Variable> var;
536 541 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
537 542
538 543 auto end = m_VariableToIdentifierMap.cend();
539 544 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
540 545 if (it != end) {
541 546 var = it->first;
542 547 }
543 548 else {
544 549 qCCritical(LOG_VariableController())
545 550 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
546 551 }
547 552
548 553 return var;
549 554 }
550 555
551 556 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
552 557 const QVector<AcquisitionDataPacket> acqDataPacketVector)
553 558 {
554 559 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
555 560 << acqDataPacketVector.size();
556 561 std::shared_ptr<IDataSeries> dataSeries;
557 562 if (!acqDataPacketVector.isEmpty()) {
558 563 dataSeries = acqDataPacketVector[0].m_DateSeries;
559 564 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
560 565 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
561 566 }
562 567 }
563 568 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
564 569 << acqDataPacketVector.size();
565 570 return dataSeries;
566 571 }
567 572
568 573 void VariableController::VariableControllerPrivate::registerProvider(
569 574 std::shared_ptr<IDataProvider> provider)
570 575 {
571 576 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
572 577 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
573 578 << provider->objectName();
574 579 m_ProviderSet.insert(provider);
575 580 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
576 581 &VariableAcquisitionWorker::onVariableDataAcquired);
577 582 connect(provider.get(), &IDataProvider::dataProvidedProgress,
578 583 m_VariableAcquisitionWorker.get(),
579 584 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
580 585 }
581 586 else {
582 587 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
583 588 }
584 589 }
585 590
586 591 void VariableController::VariableControllerPrivate::storeVariableRequest(
587 592 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
588 593 {
589 594 // First request for the variable. we can create an entry for it
590 595 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
591 596 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
592 597 auto varRequestIdQueue = std::deque<QUuid>{};
593 598 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
594 599 varRequestIdQueue.push_back(varRequestId);
595 600 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
596 601 }
597 602 else {
598 603 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
599 604 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
600 605 varRequestIdQueue.push_back(varRequestId);
601 606 }
602 607
603 608 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
604 609 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
605 610 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
606 611 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
607 612 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
608 613 m_VarRequestIdToVarIdVarRequestMap.insert(
609 614 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
610 615 }
611 616 else {
612 617 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
613 618 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
614 619 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
615 620 }
616 621 }
617 622
618 623 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
619 624 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
620 625 {
621 626 QUuid varRequestId;
622 627 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
623 628 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
624 629 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
625 630 varRequestId = varRequestIdQueue.front();
626 631 auto varRequestIdToVarIdVarRequestMapIt
627 632 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
628 633 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
629 634 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
630 635 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
631 636 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
632 637 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
633 638 auto &varRequest = varIdToVarRequestMapIt->second;
634 639 varRequest.m_DataSeries = dataSeries;
635 640 varRequest.m_CanUpdate = true;
636 641 }
637 642 else {
638 643 qCDebug(LOG_VariableController())
639 644 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
640 645 "to a variableRequestId")
641 646 << varRequestId << varId;
642 647 }
643 648 }
644 649 else {
645 650 qCCritical(LOG_VariableController())
646 651 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
647 652 << varRequestId;
648 653 }
649 654
650 655 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in QUEUE ?")
651 656 << varRequestIdQueue.size();
652 657 varRequestIdQueue.pop_front();
653 658 qCDebug(LOG_VariableController()) << tr("2: erase REQUEST in QUEUE ?")
654 659 << varRequestIdQueue.size();
655 660 if (varRequestIdQueue.empty()) {
656 661 m_VarIdToVarRequestIdQueueMap.erase(varId);
657 662 }
658 663 }
659 664 else {
660 665 qCCritical(LOG_VariableController())
661 666 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
662 667 }
663 668
664 669 return varRequestId;
665 670 }
666 671
667 672 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
668 673 {
669 674
670 675 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
671 676 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
672 677 bool processVariableUpdate = true;
673 678 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
674 679 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
675 680 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
676 681 ++varIdToVarRequestMapIt) {
677 682 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
678 683 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
679 684 << processVariableUpdate;
680 685 }
681 686
682 687 if (processVariableUpdate) {
683 688 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
684 689 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
685 690 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
686 691 auto &varRequest = varIdToVarRequestMapIt->second;
687 692 var->setRange(varRequest.m_RangeRequested);
688 693 var->setCacheRange(varRequest.m_CacheRangeRequested);
689 694 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
690 695 << varRequest.m_RangeRequested;
691 696 qCDebug(LOG_VariableController()) << tr("2: onDataProvided")
692 697 << varRequest.m_CacheRangeRequested;
693 698 var->mergeDataSeries(varRequest.m_DataSeries);
694 699 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
695 700 << varRequest.m_DataSeries->range();
696 701 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
697 702
698 703 /// @todo MPL: confirm
699 704 // Variable update is notified only if there is no pending request for it
700 705 if (m_VarIdToVarRequestIdQueueMap.count(varIdToVarRequestMapIt->first) == 0) {
701 706 emit var->updated();
702 707 }
703 708 }
704 709 else {
705 710 qCCritical(LOG_VariableController())
706 711 << tr("Impossible to update data to a null variable");
707 712 }
708 713 }
709 714
710 715 // cleaning varRequestId
711 716 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
712 717 << m_VarRequestIdToVarIdVarRequestMap.size();
713 718 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
714 719 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
715 720 << m_VarRequestIdToVarIdVarRequestMap.size();
716 721 }
717 722 }
718 723 else {
719 724 qCCritical(LOG_VariableController())
720 725 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
721 726 }
722 727 }
723 728
724 729 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
725 730 {
726 731 // cleaning varRequestId
727 732 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
728 733
729 734 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
730 735 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
731 736 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
732 737 varRequestIdQueue.erase(
733 738 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
734 739 varRequestIdQueue.end());
735 740 if (varRequestIdQueue.empty()) {
736 741 varIdToVarRequestIdQueueMapIt
737 742 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
738 743 }
739 744 else {
740 745 ++varIdToVarRequestIdQueueMapIt;
741 746 }
742 747 }
743 748 }
@@ -1,222 +1,228
1 1 #include <Variable/RenameVariableDialog.h>
2 2 #include <Variable/Variable.h>
3 3 #include <Variable/VariableController.h>
4 4 #include <Variable/VariableInspectorWidget.h>
5 5 #include <Variable/VariableMenuHeaderWidget.h>
6 6 #include <Variable/VariableModel.h>
7 7
8 8 #include <ui_VariableInspectorWidget.h>
9 9
10 10 #include <QMouseEvent>
11 11 #include <QSortFilterProxyModel>
12 12 #include <QStyledItemDelegate>
13 13 #include <QWidgetAction>
14 14
15 15 #include <SqpApplication.h>
16 16
17 17 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
18 18
19 19
20 20 class QProgressBarItemDelegate : public QStyledItemDelegate {
21 21
22 22 public:
23 23 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
24 24
25 25 void paint(QPainter *painter, const QStyleOptionViewItem &option,
26 26 const QModelIndex &index) const
27 27 {
28 28 auto data = index.data(Qt::DisplayRole);
29 29 auto progressData = index.data(VariableRoles::ProgressRole);
30 30 if (data.isValid() && progressData.isValid()) {
31 31 auto name = data.value<QString>();
32 32 auto progress = progressData.value<double>();
33 33 if (progress > 0) {
34 34 auto cancelButtonWidth = 20;
35 35 auto progressBarOption = QStyleOptionProgressBar{};
36 36 auto progressRect = option.rect;
37 37 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
38 38 progressBarOption.rect = progressRect;
39 39 progressBarOption.minimum = 0;
40 40 progressBarOption.maximum = 100;
41 41 progressBarOption.progress = progress;
42 42 progressBarOption.text
43 43 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
44 44 progressBarOption.textVisible = true;
45 45 progressBarOption.textAlignment = Qt::AlignCenter;
46 46
47 47
48 48 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
49 49 painter);
50 50
51 51 // Cancel button
52 52 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
53 53 option.rect.height());
54 54 auto buttonOption = QStyleOptionButton{};
55 55 buttonOption.rect = buttonRect;
56 56 buttonOption.text = "X";
57 57
58 58 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
59 59 }
60 60 else {
61 61 QStyledItemDelegate::paint(painter, option, index);
62 62 }
63 63 }
64 64 else {
65 65 QStyledItemDelegate::paint(painter, option, index);
66 66 }
67 67 }
68 68
69 69 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
70 70 const QModelIndex &index)
71 71 {
72 72 if (event->type() == QEvent::MouseButtonRelease) {
73 73 auto data = index.data(Qt::DisplayRole);
74 74 auto progressData = index.data(VariableRoles::ProgressRole);
75 75 if (data.isValid() && progressData.isValid()) {
76 76 auto cancelButtonWidth = 20;
77 77 auto progressRect = option.rect;
78 78 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
79 79 // Cancel button
80 80 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
81 81 option.rect.height());
82 82
83 83 auto e = (QMouseEvent *)event;
84 84 auto clickX = e->x();
85 85 auto clickY = e->y();
86 86
87 87 auto x = buttonRect.left(); // the X coordinate
88 88 auto y = buttonRect.top(); // the Y coordinate
89 89 auto w = buttonRect.width(); // button width
90 90 auto h = buttonRect.height(); // button height
91 91
92 92 if (clickX > x && clickX < x + w) {
93 93 if (clickY > y && clickY < y + h) {
94 94 auto variableModel = sqpApp->variableController().variableModel();
95 95 variableModel->abortProgress(index);
96 96 }
97 97 }
98 98 else {
99 99 QStyledItemDelegate::editorEvent(event, model, option, index);
100 100 }
101 101 }
102 102 else {
103 103 QStyledItemDelegate::editorEvent(event, model, option, index);
104 104 }
105 105 }
106 106 else {
107 107 QStyledItemDelegate::editorEvent(event, model, option, index);
108 108 }
109 109 }
110 110 };
111 111
112 112 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
113 113 : QWidget{parent},
114 114 ui{new Ui::VariableInspectorWidget},
115 115 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
116 116 {
117 117 ui->setupUi(this);
118 118
119 119 // Sets model for table
120 120 // auto sortFilterModel = new QSortFilterProxyModel{this};
121 121 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
122 122
123 123 auto variableModel = sqpApp->variableController().variableModel();
124 124 ui->tableView->setModel(variableModel);
125 125
126 126 // Adds extra signal/slot between view and model, so the view can be updated instantly when
127 127 // there is a change of data in the model
128 128 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
129 129 SLOT(refresh()));
130 130
131 131 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
132 132 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
133 133
134 134 // Fixes column sizes
135 135 auto model = ui->tableView->model();
136 136 const auto count = model->columnCount();
137 137 for (auto i = 0; i < count; ++i) {
138 138 ui->tableView->setColumnWidth(
139 139 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
140 140 }
141 141
142 142 // Sets selection options
143 143 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
144 144 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
145 145
146 146 // Connection to show a menu when right clicking on the tree
147 147 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
148 148 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
149 149 &VariableInspectorWidget::onTableMenuRequested);
150 150 }
151 151
152 152 VariableInspectorWidget::~VariableInspectorWidget()
153 153 {
154 154 delete ui;
155 155 }
156 156
157 157 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
158 158 {
159 159 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
160 160
161 161 // Gets the model to retrieve the underlying selected variables
162 162 auto model = sqpApp->variableController().variableModel();
163 163 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
164 164 for (const auto &selectedRow : qAsConst(selectedRows)) {
165 165 if (auto selectedVariable = model->variable(selectedRow.row())) {
166 166 selectedVariables.push_back(selectedVariable);
167 167 }
168 168 }
169 169
170 170 QMenu tableMenu{};
171 171
172 172 // Emits a signal so that potential receivers can populate the menu before displaying it
173 173 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
174 174
175 175 // Adds menu-specific actions
176 176 if (!selectedVariables.isEmpty()) {
177 177 tableMenu.addSeparator();
178 178
179 // 'Rename' action (only if one variable selected)
179 // 'Rename' and 'Duplicate' actions (only if one variable selected)
180 180 if (selectedVariables.size() == 1) {
181 181 auto selectedVariable = selectedVariables.front();
182 182
183 auto duplicateFun = [&selectedVariable]() {
184 sqpApp->variableController().cloneVariable(selectedVariable);
185 };
186
187 tableMenu.addAction(tr("Duplicate"), duplicateFun);
188
183 189 auto renameFun = [&selectedVariable, &model, this]() {
184 190 // Generates forbidden names (names associated to existing variables)
185 191 auto allVariables = model->variables();
186 192 auto forbiddenNames = QVector<QString>(allVariables.size());
187 193 std::transform(allVariables.cbegin(), allVariables.cend(), forbiddenNames.begin(),
188 194 [](const auto &variable) { return variable->name(); });
189 195
190 196 RenameVariableDialog dialog{selectedVariable->name(), forbiddenNames, this};
191 197 if (dialog.exec() == QDialog::Accepted) {
192 198 selectedVariable->setName(dialog.name());
193 199 }
194 200 };
195 201
196 202 tableMenu.addAction(tr("Rename..."), renameFun);
197 203 }
198 204
199 205 // 'Delete' action
200 206 auto deleteFun = [&selectedVariables]() {
201 207 sqpApp->variableController().deleteVariables(selectedVariables);
202 208 };
203 209
204 210 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
205 211 }
206 212
207 213 if (!tableMenu.isEmpty()) {
208 214 // Generates menu header (inserted before first action)
209 215 auto firstAction = tableMenu.actions().first();
210 216 auto headerAction = new QWidgetAction{&tableMenu};
211 217 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
212 218 tableMenu.insertAction(firstAction, headerAction);
213 219
214 220 // Displays menu
215 221 tableMenu.exec(QCursor::pos());
216 222 }
217 223 }
218 224
219 225 void VariableInspectorWidget::refresh() noexcept
220 226 {
221 227 ui->tableView->viewport()->update();
222 228 }
General Comments 0
You need to be logged in to leave comments. Login now