##// END OF EJS Templates
Merge pull request 301 from SciQLop-fork develop...
perrinel -
r773:9549ea5ab7e8 merge
parent child
Show More
@@ -0,0 +1,44
1 #ifndef SCIQLOP_VARIABLECACHESTRATEGYFACTORY_H
2 #define SCIQLOP_VARIABLECACHESTRATEGYFACTORY_H
3
4
5 #include <memory>
6 #include <stdexcept>
7
8 #include "VariableCacheStrategy.h"
9 #include "VariableSingleThresholdCacheStrategy.h"
10
11 #include <QLoggingCategory>
12 #include <QString>
13
14 Q_LOGGING_CATEGORY(LOG_VariableCacheStrategyFactory, "VariableCacheStrategyFactory")
15
16 enum class CacheStrategy { SingleThreshold, TwoThreashold };
17
18 class VariableCacheStrategyFactory {
19
20 using cacheStratPtr = std::unique_ptr<VariableCacheStrategy>;
21
22 public:
23 static cacheStratPtr createCacheStrategy(CacheStrategy specificStrategy)
24 {
25 switch (specificStrategy) {
26 case CacheStrategy::SingleThreshold: {
27 return std::unique_ptr<VariableCacheStrategy>{
28 new VariableSingleThresholdCacheStrategy{}};
29 break;
30 }
31 case CacheStrategy::TwoThreashold: {
32 qCCritical(LOG_VariableCacheStrategyFactory())
33 << QObject::tr("cache strategy not implemented yet");
34 break;
35 }
36 default:
37 qCCritical(LOG_VariableCacheStrategyFactory())
38 << QObject::tr("Unknown cache strategy");
39 }
40 }
41 };
42
43
44 #endif // VARIABLECACHESTRATEGYFACTORY_H
@@ -0,0 +1,32
1 #ifndef SCIQLOP_VARIABLESINGLETHRESHOLDCACHESTRATEGY_H
2 #define SCIQLOP_VARIABLESINGLETHRESHOLDCACHESTRATEGY_H
3
4 #include "Settings/SqpSettingsDefs.h"
5 #include "VariableCacheStrategy.h"
6
7
8 /// This class aims to hande the cache strategy.
9 class SCIQLOP_CORE_EXPORT VariableSingleThresholdCacheStrategy : public VariableCacheStrategy {
10 public:
11 VariableSingleThresholdCacheStrategy() = default;
12
13 std::pair<SqpRange, SqpRange> computeRange(const SqpRange &vRange,
14 const SqpRange &rangeRequested) override
15 {
16
17 auto varRanges = std::pair<SqpRange, SqpRange>{};
18
19 auto toleranceFactor = SqpSettings::toleranceValue(
20 GENERAL_TOLERANCE_AT_UPDATE_KEY, GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE);
21 auto tolerance = toleranceFactor * (rangeRequested.m_TEnd - rangeRequested.m_TStart);
22
23 varRanges.first = rangeRequested;
24 varRanges.second
25 = SqpRange{rangeRequested.m_TStart - tolerance, rangeRequested.m_TEnd + tolerance};
26
27 return varRanges;
28 }
29 };
30
31
32 #endif // SCIQLOP_VARIABLESINGLETHRESHOLDCACHESTRATEGY_H
@@ -0,0 +1,310
1 #include <QObject>
2 #include <QtTest>
3
4 #include <memory>
5
6 #include <Data/DataProviderParameters.h>
7 #include <Data/IDataProvider.h>
8 #include <Data/ScalarSeries.h>
9 #include <Time/TimeController.h>
10 #include <Variable/Variable.h>
11 #include <Variable/VariableController.h>
12 #include <Variable/VariableModel.h>
13
14 namespace {
15
16 /// Delay after each operation on the variable before validating it (in ms)
17 const auto OPERATION_DELAY = 100;
18
19 /**
20 * Generates values according to a range. The value generated for a time t is the number of seconds
21 * of difference between t and a reference value (which is midnight -> 00:00:00)
22 *
23 * Example: For a range between 00:00:10 and 00:00:20, the generated values are
24 * {10,11,12,13,14,15,16,17,18,19,20}
25 */
26 std::vector<double> values(const SqpRange &range)
27 {
28 QTime referenceTime{0, 0};
29
30 std::vector<double> result{};
31
32 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
33 auto time = DateUtils::dateTime(i).time();
34 result.push_back(referenceTime.secsTo(time));
35 }
36
37 return result;
38 }
39
40 /// Provider used for the tests
41 class TestProvider : public IDataProvider {
42 std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); }
43
44 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
45 {
46 const auto &ranges = parameters.m_Times;
47
48 for (const auto &range : ranges) {
49 // Generates data series
50 auto valuesData = values(range);
51
52 std::vector<double> xAxisData{};
53 for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) {
54 xAxisData.push_back(i);
55 }
56
57 auto dataSeries = std::make_shared<ScalarSeries>(
58 std::move(xAxisData), std::move(valuesData), Unit{"t", true}, Unit{});
59
60 emit dataProvided(acqIdentifier, dataSeries, range);
61 }
62 }
63
64 void requestDataAborting(QUuid acqIdentifier) override
65 {
66 // Does nothing
67 }
68 };
69
70 /**
71 * Interface representing an operation performed on a variable controller.
72 * This interface is used in tests to apply a set of operations and check the status of the
73 * controller after each operation
74 */
75 struct IOperation {
76 virtual ~IOperation() = default;
77 /// Executes the operation on the variable controller
78 virtual void exec(VariableController &variableController) const = 0;
79 };
80
81 /**
82 *Variable creation operation in the controller
83 */
84 struct Create : public IOperation {
85 explicit Create(int index) : m_Index{index} {}
86
87 void exec(VariableController &variableController) const override
88 {
89 auto variable = variableController.createVariable(QString::number(m_Index), {},
90 std::make_unique<TestProvider>());
91 }
92
93 int m_Index; ///< The index of the variable to create in the controller
94 };
95
96 /**
97 * Variable move/shift operation in the controller
98 */
99 struct Move : public IOperation {
100 explicit Move(int index, const SqpRange &newRange, bool shift = false)
101 : m_Index{index}, m_NewRange{newRange}, m_Shift{shift}
102 {
103 }
104
105 void exec(VariableController &variableController) const override
106 {
107 if (auto variable = variableController.variableModel()->variable(m_Index)) {
108 variableController.onRequestDataLoading({variable}, m_NewRange, variable->range(),
109 !m_Shift);
110 }
111 }
112
113 int m_Index; ///< The index of the variable to move
114 SqpRange m_NewRange; ///< The new range of the variable
115 bool m_Shift; ///< Performs a shift (
116 };
117
118 /**
119 * Variable synchronization/desynchronization operation in the controller
120 */
121 struct Synchronize : public IOperation {
122 explicit Synchronize(int index, QUuid syncId, bool synchronize = true)
123 : m_Index{index}, m_SyncId{syncId}, m_Synchronize{synchronize}
124 {
125 }
126
127 void exec(VariableController &variableController) const override
128 {
129 if (auto variable = variableController.variableModel()->variable(m_Index)) {
130 if (m_Synchronize) {
131 variableController.onAddSynchronized(variable, m_SyncId);
132 }
133 else {
134 variableController.desynchronize(variable, m_SyncId);
135 }
136 }
137 }
138
139 int m_Index; ///< The index of the variable to sync/desync
140 QUuid m_SyncId; ///< The synchronization group of the variable
141 bool m_Synchronize; ///< Performs sync or desync operation
142 };
143
144 /**
145 * Test Iteration
146 *
147 * A test iteration includes an operation to be performed, and a set of expected ranges after each
148 * operation. Each range is tested after the operation to ensure that:
149 * - the range of the variable is the expected range
150 * - the data of the variable are those generated for the expected range
151 */
152 struct Iteration {
153 std::shared_ptr<IOperation> m_Operation; ///< Operation to perform
154 std::map<int, SqpRange> m_ExpectedRanges; ///< Expected ranges (by variable index)
155 };
156
157 using Iterations = std::vector<Iteration>;
158
159 } // namespace
160
161 Q_DECLARE_METATYPE(Iterations)
162
163 class TestVariableSync : public QObject {
164 Q_OBJECT
165
166 private slots:
167 /// Input data for @sa testSync()
168 void testSync_data();
169
170 /// Tests synchronization between variables through several operations
171 void testSync();
172 };
173
174 void TestVariableSync::testSync_data()
175 {
176 // ////////////// //
177 // Test structure //
178 // ////////////// //
179
180 QTest::addColumn<QUuid>("syncId");
181 QTest::addColumn<SqpRange>("initialRange");
182 QTest::addColumn<Iterations>("iterations");
183
184 // ////////// //
185 // Test cases //
186 // ////////// //
187
188 // Id used to synchronize variables in the controller
189 auto syncId = QUuid::createUuid();
190
191 /// Generates a range according to a start time and a end time (the date is the same)
192 auto range = [](const QTime &startTime, const QTime &endTime) {
193 return SqpRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}),
194 DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})};
195 };
196
197 auto initialRange = range({12, 0}, {13, 0});
198
199 Iterations iterations{};
200 // Creates variables var0, var1 and var2
201 iterations.push_back({std::make_shared<Create>(0), {{0, initialRange}}});
202 iterations.push_back({std::make_shared<Create>(1), {{0, initialRange}, {1, initialRange}}});
203 iterations.push_back(
204 {std::make_shared<Create>(2), {{0, initialRange}, {1, initialRange}, {2, initialRange}}});
205
206 // Adds variables into the sync group (ranges don't need to be tested here)
207 iterations.push_back({std::make_shared<Synchronize>(0, syncId)});
208 iterations.push_back({std::make_shared<Synchronize>(1, syncId)});
209 iterations.push_back({std::make_shared<Synchronize>(2, syncId)});
210
211 // Moves var0: ranges of var0, var1 and var2 change
212 auto newRange = range({12, 30}, {13, 30});
213 iterations.push_back(
214 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
215
216 // Moves var1: ranges of var0, var1 and var2 change
217 newRange = range({13, 0}, {14, 0});
218 iterations.push_back(
219 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
220
221 // Moves var2: ranges of var0, var1 and var2 change
222 newRange = range({13, 30}, {14, 30});
223 iterations.push_back(
224 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}});
225
226 // Desyncs var2 and moves var0:
227 // - ranges of var0 and var1 change
228 // - range of var2 doesn't change anymore
229 auto var2Range = newRange;
230 newRange = range({13, 45}, {14, 45});
231 iterations.push_back({std::make_shared<Synchronize>(2, syncId, false)});
232 iterations.push_back(
233 {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, var2Range}}});
234
235 // Shifts var0: although var1 is synchronized with var0, its range doesn't change
236 auto var1Range = newRange;
237 newRange = range({14, 45}, {15, 45});
238 iterations.push_back({std::make_shared<Move>(0, newRange, true),
239 {{0, newRange}, {1, var1Range}, {2, var2Range}}});
240
241 // Moves var0 through several operations:
242 // - range of var0 changes
243 // - range or var1 changes according to the previous shift (one hour)
244 auto moveVar0 = [&iterations](const auto &var0NewRange, const auto &var1ExpectedRange) {
245 iterations.push_back(
246 {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}});
247 };
248 // Pan left
249 moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30}));
250 // Pan right
251 moveVar0(range({16, 0}, {17, 0}), range({15, 0}, {16, 0}));
252 // Zoom in
253 moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45}));
254 // Zoom out
255 moveVar0(range({12, 0}, {18, 0}), range({11, 0}, {17, 0}));
256
257 QTest::newRow("sync1") << syncId << initialRange << std::move(iterations);
258 }
259
260 void TestVariableSync::testSync()
261 {
262 // Inits controllers
263 TimeController timeController{};
264 VariableController variableController{};
265 variableController.setTimeController(&timeController);
266
267 QFETCH(QUuid, syncId);
268 QFETCH(SqpRange, initialRange);
269 timeController.onTimeToUpdate(initialRange);
270
271 // Synchronization group used
272 variableController.onAddSynchronizationGroupId(syncId);
273
274 // For each iteration:
275 // - execute operation
276 // - compare the variables' state to the expected states
277 QFETCH(Iterations, iterations);
278 for (const auto &iteration : iterations) {
279 iteration.m_Operation->exec(variableController);
280 QTest::qWait(OPERATION_DELAY);
281
282 for (const auto &expectedRangeEntry : iteration.m_ExpectedRanges) {
283 auto variableIndex = expectedRangeEntry.first;
284 auto expectedRange = expectedRangeEntry.second;
285
286 // Gets the variable in the controller
287 auto variable = variableController.variableModel()->variable(variableIndex);
288
289 // Compares variable's range to the expected range
290 QVERIFY(variable != nullptr);
291 auto range = variable->range();
292 QCOMPARE(range, expectedRange);
293
294 // Compares variable's data with values expected for its range
295 auto dataSeries = variable->dataSeries();
296 QVERIFY(dataSeries != nullptr);
297
298 auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd);
299 auto expectedValues = values(range);
300 QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(),
301 [](const auto &dataSeriesIt, const auto &expectedValue) {
302 return dataSeriesIt.value() == expectedValue;
303 }));
304 }
305 }
306 }
307
308 QTEST_MAIN(TestVariableSync)
309
310 #include "TestVariableSync.moc"
@@ -1,40 +1,31
1 #ifndef SCIQLOP_VARIABLECACHESTRATEGY_H
1 #ifndef SCIQLOP_VARIABLECACHESTRATEGY_H
2 #define SCIQLOP_VARIABLECACHESTRATEGY_H
2 #define SCIQLOP_VARIABLECACHESTRATEGY_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8
8
9 #include <Data/SqpRange.h>
9 #include <Data/SqpRange.h>
10
10
11 #include <QLoggingCategory>
11 #include <QLoggingCategory>
12
12
13 #include <Common/spimpl.h>
13 #include <Common/spimpl.h>
14 #include <utility>
14 #include <utility>
15
15
16
16
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableCacheStrategy)
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableCacheStrategy)
18
18
19 class Variable;
19 class Variable;
20
20
21 /**
22 * Possible types of zoom operation
23 */
24 enum class CacheStrategy { FixedTolerance, TwoThreashold };
25
26 /// This class aims to hande the cache strategy.
21 /// This class aims to hande the cache strategy.
27 class SCIQLOP_CORE_EXPORT VariableCacheStrategy : public QObject {
22 class SCIQLOP_CORE_EXPORT VariableCacheStrategy {
28 Q_OBJECT
29 public:
30 explicit VariableCacheStrategy(QObject *parent = 0);
31
32 std::pair<SqpRange, SqpRange> computeStrategyRanges(const SqpRange &vRange,
33 const SqpRange &rangeRequested);
34
23
35 private:
24 public:
36 class VariableCacheStrategyPrivate;
25 virtual std::pair<SqpRange, SqpRange> computeRange(const SqpRange &vRange,
37 spimpl::unique_impl_ptr<VariableCacheStrategyPrivate> impl;
26 const SqpRange &rangeRequested)
27 = 0;
38 };
28 };
39
29
30
40 #endif // SCIQLOP_VARIABLECACHESTRATEGY_H
31 #endif // SCIQLOP_VARIABLECACHESTRATEGY_H
@@ -1,83 +1,83
1 #include "Data/VectorSeries.h"
1 #include "Data/VectorSeries.h"
2
2
3 namespace {
3 namespace {
4
4
5 /**
5 /**
6 * Flatten the three components of a vector to a single QVector that can be passed to an ArrayData
6 * Flatten the three components of a vector to a single QVector that can be passed to an ArrayData
7 *
7 *
8 * Example:
8 * Example:
9 * xValues = {1, 2, 3}
9 * xValues = {1, 2, 3}
10 * yValues = {4, 5, 6}
10 * yValues = {4, 5, 6}
11 * zValues = {7, 8, 9}
11 * zValues = {7, 8, 9}
12 *
12 *
13 * result = {1, 4, 7, 2, 5, 8, 3, 6, 9}
13 * result = {1, 4, 7, 2, 5, 8, 3, 6, 9}
14 *
14 *
15 * @param xValues the x-component values of the vector
15 * @param xValues the x-component values of the vector
16 * @param yValues the y-component values of the vector
16 * @param yValues the y-component values of the vector
17 * @param zValues the z-component values of the vector
17 * @param zValues the z-component values of the vector
18 * @return the single QVector
18 * @return the single QVector
19 * @remarks the three components are consumed
19 * @remarks the three components are consumed
20 * @sa ArrayData
20 * @sa ArrayData
21 */
21 */
22 std::vector<double> flatten(std::vector<double> xValues, std::vector<double> yValues,
22 std::vector<double> flatten(std::vector<double> xValues, std::vector<double> yValues,
23 std::vector<double> zValues)
23 std::vector<double> zValues)
24 {
24 {
25 if (xValues.size() != yValues.size() || xValues.size() != zValues.size()) {
25 if (xValues.size() != yValues.size() || xValues.size() != zValues.size()) {
26 /// @todo ALX : log
26 /// @todo ALX : log
27 return {};
27 return {};
28 }
28 }
29
29
30 auto result = std::vector<double>();
30 auto result = std::vector<double>();
31 result.reserve(xValues.size() * 3);
31 result.reserve(xValues.size() * 3);
32 for (int i = 0; i < xValues.size(); i++) {
32 for (int i = 0; i < xValues.size(); i++) {
33 result.push_back(xValues[i]);
33 result.push_back(xValues[i]);
34 result.push_back(yValues[i]);
34 result.push_back(yValues[i]);
35 result.push_back(zValues[i]);
35 result.push_back(zValues[i]);
36 }
36 }
37
37
38 return result;
38 return result;
39 }
39 }
40
40
41 } // namespace
41 } // namespace
42
42
43 VectorSeries::VectorSeries(std::vector<double> xAxisData, std::vector<double> xValuesData,
43 VectorSeries::VectorSeries(std::vector<double> xAxisData, std::vector<double> xValuesData,
44 std::vector<double> yValuesData, std::vector<double> zValuesData,
44 std::vector<double> yValuesData, std::vector<double> zValuesData,
45 const Unit &xAxisUnit, const Unit &valuesUnit)
45 const Unit &xAxisUnit, const Unit &valuesUnit)
46 : VectorSeries{std::move(xAxisData), flatten(std::move(xValuesData), std::move(yValuesData),
46 : VectorSeries{std::move(xAxisData), flatten(std::move(xValuesData), std::move(yValuesData),
47 std::move(zValuesData)),
47 std::move(zValuesData)),
48 xAxisUnit, valuesUnit}
48 xAxisUnit, valuesUnit}
49 {
49 {
50 }
50 }
51
51
52 VectorSeries::VectorSeries(std::vector<double> xAxisData, std::vector<double> valuesData,
52 VectorSeries::VectorSeries(std::vector<double> xAxisData, std::vector<double> valuesData,
53 const Unit &xAxisUnit, const Unit &valuesUnit)
53 const Unit &xAxisUnit, const Unit &valuesUnit)
54 : DataSeries{std::make_shared<ArrayData<1> >(std::move(xAxisData)), xAxisUnit,
54 : DataSeries{std::make_shared<ArrayData<1> >(std::move(xAxisData)), xAxisUnit,
55 std::make_shared<ArrayData<2> >(std::move(valuesData), 3), valuesUnit}
55 std::make_shared<ArrayData<2> >(std::move(valuesData), 3), valuesUnit}
56 {
56 {
57 }
57 }
58
58
59 std::unique_ptr<IDataSeries> VectorSeries::clone() const
59 std::unique_ptr<IDataSeries> VectorSeries::clone() const
60 {
60 {
61 return std::make_unique<VectorSeries>(*this);
61 return std::make_unique<VectorSeries>(*this);
62 }
62 }
63
63
64 std::shared_ptr<IDataSeries> VectorSeries::subDataSeries(const SqpRange &range)
64 std::shared_ptr<IDataSeries> VectorSeries::subDataSeries(const SqpRange &range)
65 {
65 {
66 auto subXAxisData = std::vector<double>();
66 auto subXAxisData = std::vector<double>();
67 auto subValuesData = std::vector<double>();
67 auto subValuesData = std::vector<double>();
68
68
69 this->lockRead();
69 this->lockRead();
70 {
70 {
71 auto bounds = xAxisRange(range.m_TStart, range.m_TEnd);
71 auto bounds = xAxisRange(range.m_TStart, range.m_TEnd);
72 for (auto it = bounds.first; it != bounds.second; ++it) {
72 for (auto it = bounds.first; it != bounds.second; ++it) {
73 subXAxisData.push_back(it->x());
73 subXAxisData.push_back(it->x());
74 subValuesData.push_back(it->value(0));
74 subValuesData.push_back(it->value(0));
75 subValuesData.push_back(it->value(1));
75 subValuesData.push_back(it->value(1));
76 subValuesData.push_back(it->value(2));
76 subValuesData.push_back(it->value(2));
77 }
77 }
78 }
78 }
79 this->unlock();
79 this->unlock();
80
80
81 return std::make_shared<VectorSeries>(std::move(subXAxisData), std::move(subValuesData),
81 return std::make_shared<VectorSeries>(std::move(subXAxisData), std::move(subValuesData),
82 this->xAxisUnit(), this->valuesUnit());
82 this->xAxisUnit(), this->valuesUnit());
83 }
83 }
@@ -1,839 +1,842
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableAcquisitionWorker.h>
2 #include <Variable/VariableAcquisitionWorker.h>
3 #include <Variable/VariableCacheStrategy.h>
3 #include <Variable/VariableCacheStrategy.h>
4 #include <Variable/VariableCacheStrategyFactory.h>
4 #include <Variable/VariableController.h>
5 #include <Variable/VariableController.h>
5 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableSynchronizationGroup.h>
7 #include <Variable/VariableSynchronizationGroup.h>
7
8
8 #include <Data/DataProviderParameters.h>
9 #include <Data/DataProviderParameters.h>
9 #include <Data/IDataProvider.h>
10 #include <Data/IDataProvider.h>
10 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/VariableRequest.h>
12 #include <Data/VariableRequest.h>
12 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
13
14
14 #include <QMutex>
15 #include <QMutex>
15 #include <QThread>
16 #include <QThread>
16 #include <QUuid>
17 #include <QUuid>
17 #include <QtCore/QItemSelectionModel>
18 #include <QtCore/QItemSelectionModel>
18
19
19 #include <deque>
20 #include <deque>
20 #include <set>
21 #include <set>
21 #include <unordered_map>
22 #include <unordered_map>
22
23
23 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
24 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
24
25
25 namespace {
26 namespace {
26
27
27 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
28 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
28 const SqpRange &oldGraphRange)
29 const SqpRange &oldGraphRange)
29 {
30 {
30 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
31 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
31
32
32 auto varRangeRequested = varRange;
33 auto varRangeRequested = varRange;
33 switch (zoomType) {
34 switch (zoomType) {
34 case AcquisitionZoomType::ZoomIn: {
35 case AcquisitionZoomType::ZoomIn: {
35 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
36 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
36 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
37 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
37 varRangeRequested.m_TStart += deltaLeft;
38 varRangeRequested.m_TStart += deltaLeft;
38 varRangeRequested.m_TEnd -= deltaRight;
39 varRangeRequested.m_TEnd -= deltaRight;
39 break;
40 break;
40 }
41 }
41
42
42 case AcquisitionZoomType::ZoomOut: {
43 case AcquisitionZoomType::ZoomOut: {
43 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
44 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
44 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
45 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
45 varRangeRequested.m_TStart -= deltaLeft;
46 varRangeRequested.m_TStart -= deltaLeft;
46 varRangeRequested.m_TEnd += deltaRight;
47 varRangeRequested.m_TEnd += deltaRight;
47 break;
48 break;
48 }
49 }
49 case AcquisitionZoomType::PanRight: {
50 case AcquisitionZoomType::PanRight: {
50 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
51 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
51 varRangeRequested.m_TStart += deltaRight;
52 varRangeRequested.m_TStart += deltaRight;
52 varRangeRequested.m_TEnd += deltaRight;
53 varRangeRequested.m_TEnd += deltaRight;
53 break;
54 break;
54 }
55 }
55 case AcquisitionZoomType::PanLeft: {
56 case AcquisitionZoomType::PanLeft: {
56 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
57 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
57 varRangeRequested.m_TStart -= deltaLeft;
58 varRangeRequested.m_TStart -= deltaLeft;
58 varRangeRequested.m_TEnd -= deltaLeft;
59 varRangeRequested.m_TEnd -= deltaLeft;
59 break;
60 break;
60 }
61 }
61 case AcquisitionZoomType::Unknown: {
62 case AcquisitionZoomType::Unknown: {
62 qCCritical(LOG_VariableController())
63 qCCritical(LOG_VariableController())
63 << VariableController::tr("Impossible to synchronize: zoom type unknown");
64 << VariableController::tr("Impossible to synchronize: zoom type unknown");
64 break;
65 break;
65 }
66 }
66 default:
67 default:
67 qCCritical(LOG_VariableController()) << VariableController::tr(
68 qCCritical(LOG_VariableController()) << VariableController::tr(
68 "Impossible to synchronize: zoom type not take into account");
69 "Impossible to synchronize: zoom type not take into account");
69 // No action
70 // No action
70 break;
71 break;
71 }
72 }
72
73
73 return varRangeRequested;
74 return varRangeRequested;
74 }
75 }
75 }
76 }
76
77
77 struct VariableController::VariableControllerPrivate {
78 struct VariableController::VariableControllerPrivate {
78 explicit VariableControllerPrivate(VariableController *parent)
79 explicit VariableControllerPrivate(VariableController *parent)
79 : m_WorkingMutex{},
80 : m_WorkingMutex{},
80 m_VariableModel{new VariableModel{parent}},
81 m_VariableModel{new VariableModel{parent}},
81 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
82 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
83 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
84 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
85 CacheStrategy::SingleThreshold)},
83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
86 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
84 q{parent}
87 q{parent}
85 {
88 {
86
89
87 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
90 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
88 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
91 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
89 }
92 }
90
93
91
94
92 virtual ~VariableControllerPrivate()
95 virtual ~VariableControllerPrivate()
93 {
96 {
94 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
97 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
95 m_VariableAcquisitionWorkerThread.quit();
98 m_VariableAcquisitionWorkerThread.quit();
96 m_VariableAcquisitionWorkerThread.wait();
99 m_VariableAcquisitionWorkerThread.wait();
97 }
100 }
98
101
99
102
100 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
103 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
101 QUuid varRequestId);
104 QUuid varRequestId);
102
105
103 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
106 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
104 const SqpRange &dateTime);
107 const SqpRange &dateTime);
105
108
106 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
109 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
107 std::shared_ptr<IDataSeries>
110 std::shared_ptr<IDataSeries>
108 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
111 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
109
112
110 void registerProvider(std::shared_ptr<IDataProvider> provider);
113 void registerProvider(std::shared_ptr<IDataProvider> provider);
111
114
112 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
115 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
113 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
116 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
114 void updateVariableRequest(QUuid varRequestId);
117 void updateVariableRequest(QUuid varRequestId);
115 void cancelVariableRequest(QUuid varRequestId);
118 void cancelVariableRequest(QUuid varRequestId);
116
119
117 QMutex m_WorkingMutex;
120 QMutex m_WorkingMutex;
118 /// Variable model. The VariableController has the ownership
121 /// Variable model. The VariableController has the ownership
119 VariableModel *m_VariableModel;
122 VariableModel *m_VariableModel;
120 QItemSelectionModel *m_VariableSelectionModel;
123 QItemSelectionModel *m_VariableSelectionModel;
121
124
122
125
123 TimeController *m_TimeController{nullptr};
126 TimeController *m_TimeController{nullptr};
124 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
127 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
125 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
128 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
126 QThread m_VariableAcquisitionWorkerThread;
129 QThread m_VariableAcquisitionWorkerThread;
127
130
128 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
131 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
129 m_VariableToProviderMap;
132 m_VariableToProviderMap;
130 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
133 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
131 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
134 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
132 m_GroupIdToVariableSynchronizationGroupMap;
135 m_GroupIdToVariableSynchronizationGroupMap;
133 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
136 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
134 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
137 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
135
138
136 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
139 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
137
140
138 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
141 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
139
142
140
143
141 VariableController *q;
144 VariableController *q;
142 };
145 };
143
146
144
147
145 VariableController::VariableController(QObject *parent)
148 VariableController::VariableController(QObject *parent)
146 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
149 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
147 {
150 {
148 qCDebug(LOG_VariableController()) << tr("VariableController construction")
151 qCDebug(LOG_VariableController()) << tr("VariableController construction")
149 << QThread::currentThread();
152 << QThread::currentThread();
150
153
151 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
154 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
152 &VariableController::onAbortProgressRequested);
155 &VariableController::onAbortProgressRequested);
153
156
154 connect(impl->m_VariableAcquisitionWorker.get(),
157 connect(impl->m_VariableAcquisitionWorker.get(),
155 &VariableAcquisitionWorker::variableCanceledRequested, this,
158 &VariableAcquisitionWorker::variableCanceledRequested, this,
156 &VariableController::onAbortAcquisitionRequested);
159 &VariableController::onAbortAcquisitionRequested);
157
160
158 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
161 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
159 &VariableController::onDataProvided);
162 &VariableController::onDataProvided);
160 connect(impl->m_VariableAcquisitionWorker.get(),
163 connect(impl->m_VariableAcquisitionWorker.get(),
161 &VariableAcquisitionWorker::variableRequestInProgress, this,
164 &VariableAcquisitionWorker::variableRequestInProgress, this,
162 &VariableController::onVariableRetrieveDataInProgress);
165 &VariableController::onVariableRetrieveDataInProgress);
163
166
164
167
165 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
168 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
166 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
169 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
167 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
170 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
168 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
171 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
169
172
170
173
171 impl->m_VariableAcquisitionWorkerThread.start();
174 impl->m_VariableAcquisitionWorkerThread.start();
172 }
175 }
173
176
174 VariableController::~VariableController()
177 VariableController::~VariableController()
175 {
178 {
176 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
179 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
177 << QThread::currentThread();
180 << QThread::currentThread();
178 this->waitForFinish();
181 this->waitForFinish();
179 }
182 }
180
183
181 VariableModel *VariableController::variableModel() noexcept
184 VariableModel *VariableController::variableModel() noexcept
182 {
185 {
183 return impl->m_VariableModel;
186 return impl->m_VariableModel;
184 }
187 }
185
188
186 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
189 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
187 {
190 {
188 return impl->m_VariableSelectionModel;
191 return impl->m_VariableSelectionModel;
189 }
192 }
190
193
191 void VariableController::setTimeController(TimeController *timeController) noexcept
194 void VariableController::setTimeController(TimeController *timeController) noexcept
192 {
195 {
193 impl->m_TimeController = timeController;
196 impl->m_TimeController = timeController;
194 }
197 }
195
198
196 std::shared_ptr<Variable>
199 std::shared_ptr<Variable>
197 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
200 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
198 {
201 {
199 if (impl->m_VariableModel->containsVariable(variable)) {
202 if (impl->m_VariableModel->containsVariable(variable)) {
200 // Clones variable
203 // Clones variable
201 auto duplicate = variable->clone();
204 auto duplicate = variable->clone();
202
205
203 // Adds clone to model
206 // Adds clone to model
204 impl->m_VariableModel->addVariable(duplicate);
207 impl->m_VariableModel->addVariable(duplicate);
205
208
206 // Generates clone identifier
209 // Generates clone identifier
207 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
210 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
208
211
209 // Registers provider
212 // Registers provider
210 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
213 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
211 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
214 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
212
215
213 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
216 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
214 if (duplicateProvider) {
217 if (duplicateProvider) {
215 impl->registerProvider(duplicateProvider);
218 impl->registerProvider(duplicateProvider);
216 }
219 }
217
220
218 return duplicate;
221 return duplicate;
219 }
222 }
220 else {
223 else {
221 qCCritical(LOG_VariableController())
224 qCCritical(LOG_VariableController())
222 << tr("Can't create duplicate of variable %1: variable not registered in the model")
225 << tr("Can't create duplicate of variable %1: variable not registered in the model")
223 .arg(variable->name());
226 .arg(variable->name());
224 return nullptr;
227 return nullptr;
225 }
228 }
226 }
229 }
227
230
228 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
231 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
229 {
232 {
230 if (!variable) {
233 if (!variable) {
231 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
234 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
232 return;
235 return;
233 }
236 }
234
237
235 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
238 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
236 // make some treatments before the deletion
239 // make some treatments before the deletion
237 emit variableAboutToBeDeleted(variable);
240 emit variableAboutToBeDeleted(variable);
238
241
239 // Deletes identifier
242 // Deletes identifier
240 impl->m_VariableToIdentifierMap.erase(variable);
243 impl->m_VariableToIdentifierMap.erase(variable);
241
244
242 // Deletes provider
245 // Deletes provider
243 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
246 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
244 qCDebug(LOG_VariableController())
247 qCDebug(LOG_VariableController())
245 << tr("Number of providers deleted for variable %1: %2")
248 << tr("Number of providers deleted for variable %1: %2")
246 .arg(variable->name(), QString::number(nbProvidersDeleted));
249 .arg(variable->name(), QString::number(nbProvidersDeleted));
247
250
248
251
249 // Deletes from model
252 // Deletes from model
250 impl->m_VariableModel->deleteVariable(variable);
253 impl->m_VariableModel->deleteVariable(variable);
251 }
254 }
252
255
253 void VariableController::deleteVariables(
256 void VariableController::deleteVariables(
254 const QVector<std::shared_ptr<Variable> > &variables) noexcept
257 const QVector<std::shared_ptr<Variable> > &variables) noexcept
255 {
258 {
256 for (auto variable : qAsConst(variables)) {
259 for (auto variable : qAsConst(variables)) {
257 deleteVariable(variable);
260 deleteVariable(variable);
258 }
261 }
259 }
262 }
260
263
261 std::shared_ptr<Variable>
264 std::shared_ptr<Variable>
262 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
265 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
263 std::shared_ptr<IDataProvider> provider) noexcept
266 std::shared_ptr<IDataProvider> provider) noexcept
264 {
267 {
265 if (!impl->m_TimeController) {
268 if (!impl->m_TimeController) {
266 qCCritical(LOG_VariableController())
269 qCCritical(LOG_VariableController())
267 << tr("Impossible to create variable: The time controller is null");
270 << tr("Impossible to create variable: The time controller is null");
268 return nullptr;
271 return nullptr;
269 }
272 }
270
273
271 auto range = impl->m_TimeController->dateTime();
274 auto range = impl->m_TimeController->dateTime();
272
275
273 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
276 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
274 auto identifier = QUuid::createUuid();
277 auto identifier = QUuid::createUuid();
275
278
276 // store the provider
279 // store the provider
277 impl->registerProvider(provider);
280 impl->registerProvider(provider);
278
281
279 // Associate the provider
282 // Associate the provider
280 impl->m_VariableToProviderMap[newVariable] = provider;
283 impl->m_VariableToProviderMap[newVariable] = provider;
281 qCInfo(LOG_VariableController()) << "createVariable: " << identifier;
284 qCInfo(LOG_VariableController()) << "createVariable: " << identifier;
282 impl->m_VariableToIdentifierMap[newVariable] = identifier;
285 impl->m_VariableToIdentifierMap[newVariable] = identifier;
283
286
284
287
285 auto varRequestId = QUuid::createUuid();
288 auto varRequestId = QUuid::createUuid();
286 impl->processRequest(newVariable, range, varRequestId);
289 impl->processRequest(newVariable, range, varRequestId);
287 impl->updateVariableRequest(varRequestId);
290 impl->updateVariableRequest(varRequestId);
288
291
289 return newVariable;
292 return newVariable;
290 }
293 }
291 }
294 }
292
295
293 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
296 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
294 {
297 {
295 // TODO check synchronisation and Rescale
298 // TODO check synchronisation and Rescale
296 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
299 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
297 << QThread::currentThread()->objectName();
300 << QThread::currentThread()->objectName();
298 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
301 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
299 auto varRequestId = QUuid::createUuid();
302 auto varRequestId = QUuid::createUuid();
300
303
301 for (const auto &selectedRow : qAsConst(selectedRows)) {
304 for (const auto &selectedRow : qAsConst(selectedRows)) {
302 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
305 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
303 selectedVariable->setRange(dateTime);
306 selectedVariable->setRange(dateTime);
304 impl->processRequest(selectedVariable, dateTime, varRequestId);
307 impl->processRequest(selectedVariable, dateTime, varRequestId);
305
308
306 // notify that rescale operation has to be done
309 // notify that rescale operation has to be done
307 emit rangeChanged(selectedVariable, dateTime);
310 emit rangeChanged(selectedVariable, dateTime);
308 }
311 }
309 }
312 }
310 impl->updateVariableRequest(varRequestId);
313 impl->updateVariableRequest(varRequestId);
311 }
314 }
312
315
313 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
316 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
314 const SqpRange &cacheRangeRequested,
317 const SqpRange &cacheRangeRequested,
315 QVector<AcquisitionDataPacket> dataAcquired)
318 QVector<AcquisitionDataPacket> dataAcquired)
316 {
319 {
317 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
320 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
318 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
321 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
319 if (!varRequestId.isNull()) {
322 if (!varRequestId.isNull()) {
320 impl->updateVariableRequest(varRequestId);
323 impl->updateVariableRequest(varRequestId);
321 }
324 }
322 }
325 }
323
326
324 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
327 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
325 {
328 {
326 qCDebug(LOG_VariableController())
329 qCDebug(LOG_VariableController())
327 << "TORM: variableController::onVariableRetrieveDataInProgress"
330 << "TORM: variableController::onVariableRetrieveDataInProgress"
328 << QThread::currentThread()->objectName() << progress;
331 << QThread::currentThread()->objectName() << progress;
329 if (auto var = impl->findVariable(identifier)) {
332 if (auto var = impl->findVariable(identifier)) {
330 impl->m_VariableModel->setDataProgress(var, progress);
333 impl->m_VariableModel->setDataProgress(var, progress);
331 }
334 }
332 else {
335 else {
333 qCCritical(LOG_VariableController())
336 qCCritical(LOG_VariableController())
334 << tr("Impossible to notify progression of a null variable");
337 << tr("Impossible to notify progression of a null variable");
335 }
338 }
336 }
339 }
337
340
338 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
341 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
339 {
342 {
340 auto it = impl->m_VariableToIdentifierMap.find(variable);
343 auto it = impl->m_VariableToIdentifierMap.find(variable);
341 if (it != impl->m_VariableToIdentifierMap.cend()) {
344 if (it != impl->m_VariableToIdentifierMap.cend()) {
342 impl->m_VariableAcquisitionWorker->abortProgressRequested(it->second);
345 impl->m_VariableAcquisitionWorker->abortProgressRequested(it->second);
343
346
344 QUuid varRequestId;
347 QUuid varRequestId;
345 auto varIdToVarRequestIdQueueMapIt = impl->m_VarIdToVarRequestIdQueueMap.find(it->second);
348 auto varIdToVarRequestIdQueueMapIt = impl->m_VarIdToVarRequestIdQueueMap.find(it->second);
346 if (varIdToVarRequestIdQueueMapIt != impl->m_VarIdToVarRequestIdQueueMap.cend()) {
349 if (varIdToVarRequestIdQueueMapIt != impl->m_VarIdToVarRequestIdQueueMap.cend()) {
347 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
350 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
348 varRequestId = varRequestIdQueue.front();
351 varRequestId = varRequestIdQueue.front();
349 impl->cancelVariableRequest(varRequestId);
352 impl->cancelVariableRequest(varRequestId);
350
353
351 // Finish the progression for the request
354 // Finish the progression for the request
352 impl->m_VariableModel->setDataProgress(variable, 0.0);
355 impl->m_VariableModel->setDataProgress(variable, 0.0);
353 }
356 }
354 else {
357 else {
355 qCWarning(LOG_VariableController())
358 qCWarning(LOG_VariableController())
356 << tr("Aborting progression of inexistant variable request detected !!!")
359 << tr("Aborting progression of inexistant variable request detected !!!")
357 << QThread::currentThread()->objectName();
360 << QThread::currentThread()->objectName();
358 }
361 }
359 }
362 }
360 else {
363 else {
361 qCWarning(LOG_VariableController())
364 qCWarning(LOG_VariableController())
362 << tr("Aborting progression of inexistant variable detected !!!")
365 << tr("Aborting progression of inexistant variable detected !!!")
363 << QThread::currentThread()->objectName();
366 << QThread::currentThread()->objectName();
364 }
367 }
365 }
368 }
366
369
367 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
370 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
368 {
371 {
369 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
372 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
370 << QThread::currentThread()->objectName() << vIdentifier;
373 << QThread::currentThread()->objectName() << vIdentifier;
371
374
372 if (auto var = impl->findVariable(vIdentifier)) {
375 if (auto var = impl->findVariable(vIdentifier)) {
373 this->onAbortProgressRequested(var);
376 this->onAbortProgressRequested(var);
374 }
377 }
375 else {
378 else {
376 qCCritical(LOG_VariableController())
379 qCCritical(LOG_VariableController())
377 << tr("Impossible to abort Acquisition Requestof a null variable");
380 << tr("Impossible to abort Acquisition Requestof a null variable");
378 }
381 }
379 }
382 }
380
383
381 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
384 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
382 {
385 {
383 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
386 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
384 << QThread::currentThread()->objectName()
387 << QThread::currentThread()->objectName()
385 << synchronizationGroupId;
388 << synchronizationGroupId;
386 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
389 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
387 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
390 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
388 std::make_pair(synchronizationGroupId, vSynchroGroup));
391 std::make_pair(synchronizationGroupId, vSynchroGroup));
389 }
392 }
390
393
391 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
394 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
392 {
395 {
393 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
396 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
394 }
397 }
395
398
396 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
399 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
397 QUuid synchronizationGroupId)
400 QUuid synchronizationGroupId)
398
401
399 {
402 {
400 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
403 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
401 << synchronizationGroupId;
404 << synchronizationGroupId;
402 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
405 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
403 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
406 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
404 auto groupIdToVSGIt
407 auto groupIdToVSGIt
405 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
408 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
406 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
409 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
407 impl->m_VariableIdGroupIdMap.insert(
410 impl->m_VariableIdGroupIdMap.insert(
408 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
411 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
409 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
412 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
410 }
413 }
411 else {
414 else {
412 qCCritical(LOG_VariableController())
415 qCCritical(LOG_VariableController())
413 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
416 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
414 << variable->name();
417 << variable->name();
415 }
418 }
416 }
419 }
417 else {
420 else {
418 qCCritical(LOG_VariableController())
421 qCCritical(LOG_VariableController())
419 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
422 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
420 }
423 }
421 }
424 }
422
425
423 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
426 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
424 QUuid synchronizationGroupId)
427 QUuid synchronizationGroupId)
425 {
428 {
426 // Gets variable id
429 // Gets variable id
427 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
430 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
428 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
431 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
429 qCCritical(LOG_VariableController())
432 qCCritical(LOG_VariableController())
430 << tr("Can't desynchronize variable %1: variable identifier not found")
433 << tr("Can't desynchronize variable %1: variable identifier not found")
431 .arg(variable->name());
434 .arg(variable->name());
432 return;
435 return;
433 }
436 }
434
437
435 // Gets synchronization group
438 // Gets synchronization group
436 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
439 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
437 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
440 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
438 qCCritical(LOG_VariableController())
441 qCCritical(LOG_VariableController())
439 << tr("Can't desynchronize variable %1: unknown synchronization group")
442 << tr("Can't desynchronize variable %1: unknown synchronization group")
440 .arg(variable->name());
443 .arg(variable->name());
441 return;
444 return;
442 }
445 }
443
446
444 auto variableId = variableIt->second;
447 auto variableId = variableIt->second;
445
448
446 // Removes variable from synchronization group
449 // Removes variable from synchronization group
447 auto synchronizationGroup = groupIt->second;
450 auto synchronizationGroup = groupIt->second;
448 synchronizationGroup->removeVariableId(variableId);
451 synchronizationGroup->removeVariableId(variableId);
449
452
450 // Removes link between variable and synchronization group
453 // Removes link between variable and synchronization group
451 impl->m_VariableIdGroupIdMap.erase(variableId);
454 impl->m_VariableIdGroupIdMap.erase(variableId);
452 }
455 }
453
456
454 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
457 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
455 const SqpRange &range, const SqpRange &oldRange,
458 const SqpRange &range, const SqpRange &oldRange,
456 bool synchronise)
459 bool synchronise)
457 {
460 {
458 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
461 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
459
462
460 // we want to load data of the variable for the dateTime.
463 // we want to load data of the variable for the dateTime.
461 // First we check if the cache contains some of them.
464 // First we check if the cache contains some of them.
462 // For the other, we ask the provider to give them.
465 // For the other, we ask the provider to give them.
463
466
464 auto varRequestId = QUuid::createUuid();
467 auto varRequestId = QUuid::createUuid();
465 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
468 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
466 << QThread::currentThread()->objectName() << varRequestId;
469 << QThread::currentThread()->objectName() << varRequestId;
467
470
468 for (const auto &var : variables) {
471 for (const auto &var : variables) {
469 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
472 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
470 impl->processRequest(var, range, varRequestId);
473 impl->processRequest(var, range, varRequestId);
471 }
474 }
472
475
473 if (synchronise) {
476 if (synchronise) {
474 // Get the group ids
477 // Get the group ids
475 qCDebug(LOG_VariableController())
478 qCDebug(LOG_VariableController())
476 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
479 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
477 auto groupIds = std::set<QUuid>{};
480 auto groupIds = std::set<QUuid>{};
478 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
481 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
479 for (const auto &var : variables) {
482 for (const auto &var : variables) {
480 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
483 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
481 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
484 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
482 auto vId = varToVarIdIt->second;
485 auto vId = varToVarIdIt->second;
483 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
486 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
484 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
487 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
485 auto gId = varIdToGroupIdIt->second;
488 auto gId = varIdToGroupIdIt->second;
486 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
489 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
487 if (groupIds.find(gId) == groupIds.cend()) {
490 if (groupIds.find(gId) == groupIds.cend()) {
488 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
491 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
489 groupIds.insert(gId);
492 groupIds.insert(gId);
490 }
493 }
491 }
494 }
492 }
495 }
493 }
496 }
494
497
495 // We assume here all group ids exist
498 // We assume here all group ids exist
496 for (const auto &gId : groupIds) {
499 for (const auto &gId : groupIds) {
497 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
500 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
498 auto vSyncIds = vSynchronizationGroup->getIds();
501 auto vSyncIds = vSynchronizationGroup->getIds();
499 qCDebug(LOG_VariableController()) << "Var in synchro group ";
502 qCDebug(LOG_VariableController()) << "Var in synchro group ";
500 for (auto vId : vSyncIds) {
503 for (auto vId : vSyncIds) {
501 auto var = impl->findVariable(vId);
504 auto var = impl->findVariable(vId);
502
505
503 // Don't process already processed var
506 // Don't process already processed var
504 if (!variables.contains(var)) {
507 if (!variables.contains(var)) {
505 if (var != nullptr) {
508 if (var != nullptr) {
506 qCDebug(LOG_VariableController()) << "processRequest synchro for"
509 qCDebug(LOG_VariableController()) << "processRequest synchro for"
507 << var->name();
510 << var->name();
508 auto vSyncRangeRequested = computeSynchroRangeRequested(
511 auto vSyncRangeRequested = computeSynchroRangeRequested(
509 var->range(), range, groupIdToOldRangeMap.at(gId));
512 var->range(), range, groupIdToOldRangeMap.at(gId));
510 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
513 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
511 impl->processRequest(var, vSyncRangeRequested, varRequestId);
514 impl->processRequest(var, vSyncRangeRequested, varRequestId);
512 }
515 }
513 else {
516 else {
514 qCCritical(LOG_VariableController())
517 qCCritical(LOG_VariableController())
515
518
516 << tr("Impossible to synchronize a null variable");
519 << tr("Impossible to synchronize a null variable");
517 }
520 }
518 }
521 }
519 }
522 }
520 }
523 }
521 }
524 }
522
525
523 impl->updateVariableRequest(varRequestId);
526 impl->updateVariableRequest(varRequestId);
524 }
527 }
525
528
526
529
527 void VariableController::initialize()
530 void VariableController::initialize()
528 {
531 {
529 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
532 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
530 impl->m_WorkingMutex.lock();
533 impl->m_WorkingMutex.lock();
531 qCDebug(LOG_VariableController()) << tr("VariableController init END");
534 qCDebug(LOG_VariableController()) << tr("VariableController init END");
532 }
535 }
533
536
534 void VariableController::finalize()
537 void VariableController::finalize()
535 {
538 {
536 impl->m_WorkingMutex.unlock();
539 impl->m_WorkingMutex.unlock();
537 }
540 }
538
541
539 void VariableController::waitForFinish()
542 void VariableController::waitForFinish()
540 {
543 {
541 QMutexLocker locker{&impl->m_WorkingMutex};
544 QMutexLocker locker{&impl->m_WorkingMutex};
542 }
545 }
543
546
544 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
547 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
545 {
548 {
546 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
549 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
547 auto zoomType = AcquisitionZoomType::Unknown;
550 auto zoomType = AcquisitionZoomType::Unknown;
548 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
551 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
549 zoomType = AcquisitionZoomType::ZoomOut;
552 zoomType = AcquisitionZoomType::ZoomOut;
550 }
553 }
551 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
554 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
552 zoomType = AcquisitionZoomType::PanRight;
555 zoomType = AcquisitionZoomType::PanRight;
553 }
556 }
554 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
557 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
555 zoomType = AcquisitionZoomType::PanLeft;
558 zoomType = AcquisitionZoomType::PanLeft;
556 }
559 }
557 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
560 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
558 zoomType = AcquisitionZoomType::ZoomIn;
561 zoomType = AcquisitionZoomType::ZoomIn;
559 }
562 }
560 else {
563 else {
561 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
564 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
562 }
565 }
563 return zoomType;
566 return zoomType;
564 }
567 }
565
568
566 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
569 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
567 const SqpRange &rangeRequested,
570 const SqpRange &rangeRequested,
568 QUuid varRequestId)
571 QUuid varRequestId)
569 {
572 {
570
573
571 // TODO: protect at
574 // TODO: protect at
572 auto varRequest = VariableRequest{};
575 auto varRequest = VariableRequest{};
573 auto varId = m_VariableToIdentifierMap.at(var);
576 auto varId = m_VariableToIdentifierMap.at(var);
574
577
575 auto varStrategyRangesRequested
578 auto varStrategyRangesRequested
576 = m_VariableCacheStrategy->computeStrategyRanges(var->range(), rangeRequested);
579 = m_VariableCacheStrategy->computeRange(var->range(), rangeRequested);
577
580
578 auto notInCacheRangeList = QVector<SqpRange>{varStrategyRangesRequested.second};
581 auto notInCacheRangeList = QVector<SqpRange>{varStrategyRangesRequested.second};
579 auto inCacheRangeList = QVector<SqpRange>{};
582 auto inCacheRangeList = QVector<SqpRange>{};
580 if (m_VarIdToVarRequestIdQueueMap.find(varId) == m_VarIdToVarRequestIdQueueMap.cend()) {
583 if (m_VarIdToVarRequestIdQueueMap.find(varId) == m_VarIdToVarRequestIdQueueMap.cend()) {
581 notInCacheRangeList = var->provideNotInCacheRangeList(varStrategyRangesRequested.second);
584 notInCacheRangeList = var->provideNotInCacheRangeList(varStrategyRangesRequested.second);
582 inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second);
585 inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second);
583 }
586 }
584
587
585 if (!notInCacheRangeList.empty()) {
588 if (!notInCacheRangeList.empty()) {
586 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
589 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
587 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
590 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
588
591
589 // store VarRequest
592 // store VarRequest
590 storeVariableRequest(varId, varRequestId, varRequest);
593 storeVariableRequest(varId, varRequestId, varRequest);
591
594
592 auto varProvider = m_VariableToProviderMap.at(var);
595 auto varProvider = m_VariableToProviderMap.at(var);
593 if (varProvider != nullptr) {
596 if (varProvider != nullptr) {
594 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
597 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
595 varRequestId, varId, varStrategyRangesRequested.first,
598 varRequestId, varId, varStrategyRangesRequested.first,
596 varStrategyRangesRequested.second,
599 varStrategyRangesRequested.second,
597 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
600 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
598 varProvider);
601 varProvider);
599
602
600 if (!varRequestIdCanceled.isNull()) {
603 if (!varRequestIdCanceled.isNull()) {
601 qCDebug(LOG_VariableAcquisitionWorker()) << tr("vsarRequestIdCanceled: ")
604 qCDebug(LOG_VariableAcquisitionWorker()) << tr("vsarRequestIdCanceled: ")
602 << varRequestIdCanceled;
605 << varRequestIdCanceled;
603 cancelVariableRequest(varRequestIdCanceled);
606 cancelVariableRequest(varRequestIdCanceled);
604 }
607 }
605 }
608 }
606 else {
609 else {
607 qCCritical(LOG_VariableController())
610 qCCritical(LOG_VariableController())
608 << "Impossible to provide data with a null provider";
611 << "Impossible to provide data with a null provider";
609 }
612 }
610
613
611 if (!inCacheRangeList.empty()) {
614 if (!inCacheRangeList.empty()) {
612 emit q->updateVarDisplaying(var, inCacheRangeList.first());
615 emit q->updateVarDisplaying(var, inCacheRangeList.first());
613 }
616 }
614 }
617 }
615 else {
618 else {
616 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
619 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
617 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
620 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
618 // store VarRequest
621 // store VarRequest
619 storeVariableRequest(varId, varRequestId, varRequest);
622 storeVariableRequest(varId, varRequestId, varRequest);
620 acceptVariableRequest(varId,
623 acceptVariableRequest(varId,
621 var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
624 var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
622 }
625 }
623 }
626 }
624
627
625 std::shared_ptr<Variable>
628 std::shared_ptr<Variable>
626 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
629 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
627 {
630 {
628 std::shared_ptr<Variable> var;
631 std::shared_ptr<Variable> var;
629 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
632 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
630
633
631 auto end = m_VariableToIdentifierMap.cend();
634 auto end = m_VariableToIdentifierMap.cend();
632 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
635 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
633 if (it != end) {
636 if (it != end) {
634 var = it->first;
637 var = it->first;
635 }
638 }
636 else {
639 else {
637 qCCritical(LOG_VariableController())
640 qCCritical(LOG_VariableController())
638 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
641 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
639 }
642 }
640
643
641 return var;
644 return var;
642 }
645 }
643
646
644 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
647 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
645 const QVector<AcquisitionDataPacket> acqDataPacketVector)
648 const QVector<AcquisitionDataPacket> acqDataPacketVector)
646 {
649 {
647 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
650 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
648 << acqDataPacketVector.size();
651 << acqDataPacketVector.size();
649 std::shared_ptr<IDataSeries> dataSeries;
652 std::shared_ptr<IDataSeries> dataSeries;
650 if (!acqDataPacketVector.isEmpty()) {
653 if (!acqDataPacketVector.isEmpty()) {
651 dataSeries = acqDataPacketVector[0].m_DateSeries;
654 dataSeries = acqDataPacketVector[0].m_DateSeries;
652 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
655 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
653 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
656 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
654 }
657 }
655 }
658 }
656 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
659 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
657 << acqDataPacketVector.size();
660 << acqDataPacketVector.size();
658 return dataSeries;
661 return dataSeries;
659 }
662 }
660
663
661 void VariableController::VariableControllerPrivate::registerProvider(
664 void VariableController::VariableControllerPrivate::registerProvider(
662 std::shared_ptr<IDataProvider> provider)
665 std::shared_ptr<IDataProvider> provider)
663 {
666 {
664 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
667 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
665 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
668 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
666 << provider->objectName();
669 << provider->objectName();
667 m_ProviderSet.insert(provider);
670 m_ProviderSet.insert(provider);
668 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
671 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
669 &VariableAcquisitionWorker::onVariableDataAcquired);
672 &VariableAcquisitionWorker::onVariableDataAcquired);
670 connect(provider.get(), &IDataProvider::dataProvidedProgress,
673 connect(provider.get(), &IDataProvider::dataProvidedProgress,
671 m_VariableAcquisitionWorker.get(),
674 m_VariableAcquisitionWorker.get(),
672 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
675 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
673 connect(provider.get(), &IDataProvider::dataProvidedFailed,
676 connect(provider.get(), &IDataProvider::dataProvidedFailed,
674 m_VariableAcquisitionWorker.get(),
677 m_VariableAcquisitionWorker.get(),
675 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
678 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
676 }
679 }
677 else {
680 else {
678 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
681 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
679 }
682 }
680 }
683 }
681
684
682 void VariableController::VariableControllerPrivate::storeVariableRequest(
685 void VariableController::VariableControllerPrivate::storeVariableRequest(
683 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
686 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
684 {
687 {
685 // First request for the variable. we can create an entry for it
688 // First request for the variable. we can create an entry for it
686 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
689 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
687 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
690 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
688 auto varRequestIdQueue = std::deque<QUuid>{};
691 auto varRequestIdQueue = std::deque<QUuid>{};
689 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
692 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
690 varRequestIdQueue.push_back(varRequestId);
693 varRequestIdQueue.push_back(varRequestId);
691 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
694 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
692 }
695 }
693 else {
696 else {
694 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
697 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
695 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
698 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
696 varRequestIdQueue.push_back(varRequestId);
699 varRequestIdQueue.push_back(varRequestId);
697 }
700 }
698
701
699 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
702 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
700 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
703 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
701 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
704 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
702 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
705 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
703 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
706 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
704 m_VarRequestIdToVarIdVarRequestMap.insert(
707 m_VarRequestIdToVarIdVarRequestMap.insert(
705 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
708 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
706 }
709 }
707 else {
710 else {
708 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
711 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
709 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
712 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
710 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
713 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
711 }
714 }
712 }
715 }
713
716
714 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
717 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
715 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
718 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
716 {
719 {
717 QUuid varRequestId;
720 QUuid varRequestId;
718 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
721 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
719 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
722 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
720 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
723 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
721 varRequestId = varRequestIdQueue.front();
724 varRequestId = varRequestIdQueue.front();
722 auto varRequestIdToVarIdVarRequestMapIt
725 auto varRequestIdToVarIdVarRequestMapIt
723 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
726 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
724 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
727 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
725 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
728 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
726 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
729 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
727 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
730 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
728 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
731 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
729 auto &varRequest = varIdToVarRequestMapIt->second;
732 auto &varRequest = varIdToVarRequestMapIt->second;
730 varRequest.m_DataSeries = dataSeries;
733 varRequest.m_DataSeries = dataSeries;
731 varRequest.m_CanUpdate = true;
734 varRequest.m_CanUpdate = true;
732 }
735 }
733 else {
736 else {
734 qCDebug(LOG_VariableController())
737 qCDebug(LOG_VariableController())
735 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
738 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
736 "to a variableRequestId")
739 "to a variableRequestId")
737 << varRequestId << varId;
740 << varRequestId << varId;
738 }
741 }
739 }
742 }
740 else {
743 else {
741 qCCritical(LOG_VariableController())
744 qCCritical(LOG_VariableController())
742 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
745 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
743 << varRequestId;
746 << varRequestId;
744 }
747 }
745
748
746 varRequestIdQueue.pop_front();
749 varRequestIdQueue.pop_front();
747 if (varRequestIdQueue.empty()) {
750 if (varRequestIdQueue.empty()) {
748 qCDebug(LOG_VariableController())
751 qCDebug(LOG_VariableController())
749 << tr("TORM Erase REQUEST because it has been accepted") << varId;
752 << tr("TORM Erase REQUEST because it has been accepted") << varId;
750 m_VarIdToVarRequestIdQueueMap.erase(varId);
753 m_VarIdToVarRequestIdQueueMap.erase(varId);
751 }
754 }
752 }
755 }
753 else {
756 else {
754 qCCritical(LOG_VariableController())
757 qCCritical(LOG_VariableController())
755 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
758 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
756 }
759 }
757
760
758 return varRequestId;
761 return varRequestId;
759 }
762 }
760
763
761 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
764 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
762 {
765 {
763
766
764 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
767 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
765 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
768 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
766 bool processVariableUpdate = true;
769 bool processVariableUpdate = true;
767 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
770 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
768 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
771 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
769 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
772 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
770 ++varIdToVarRequestMapIt) {
773 ++varIdToVarRequestMapIt) {
771 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
774 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
772 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
775 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
773 << processVariableUpdate;
776 << processVariableUpdate;
774 }
777 }
775
778
776 if (processVariableUpdate) {
779 if (processVariableUpdate) {
777 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
780 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
778 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
781 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
779 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
782 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
780 auto &varRequest = varIdToVarRequestMapIt->second;
783 auto &varRequest = varIdToVarRequestMapIt->second;
781 var->setRange(varRequest.m_RangeRequested);
784 var->setRange(varRequest.m_RangeRequested);
782 var->setCacheRange(varRequest.m_CacheRangeRequested);
785 var->setCacheRange(varRequest.m_CacheRangeRequested);
783 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
786 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
784 << varRequest.m_RangeRequested;
787 << varRequest.m_RangeRequested;
785 qCDebug(LOG_VariableController()) << tr("2: onDataProvided")
788 qCDebug(LOG_VariableController()) << tr("2: onDataProvided")
786 << varRequest.m_CacheRangeRequested;
789 << varRequest.m_CacheRangeRequested;
787 var->mergeDataSeries(varRequest.m_DataSeries);
790 var->mergeDataSeries(varRequest.m_DataSeries);
788 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
791 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
789 << varRequest.m_DataSeries->range();
792 << varRequest.m_DataSeries->range();
790 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
793 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
791
794
792 /// @todo MPL: confirm
795 /// @todo MPL: confirm
793 // Variable update is notified only if there is no pending request for it
796 // Variable update is notified only if there is no pending request for it
794 // if
797 // if
795 // (m_VarIdToVarRequestIdQueueMap.count(varIdToVarRequestMapIt->first)
798 // (m_VarIdToVarRequestIdQueueMap.count(varIdToVarRequestMapIt->first)
796 // == 0) {
799 // == 0) {
797 emit var->updated();
800 emit var->updated();
798 // }
801 // }
799 }
802 }
800 else {
803 else {
801 qCCritical(LOG_VariableController())
804 qCCritical(LOG_VariableController())
802 << tr("Impossible to update data to a null variable");
805 << tr("Impossible to update data to a null variable");
803 }
806 }
804 }
807 }
805
808
806 // cleaning varRequestId
809 // cleaning varRequestId
807 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
810 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
808 << m_VarRequestIdToVarIdVarRequestMap.size();
811 << m_VarRequestIdToVarIdVarRequestMap.size();
809 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
812 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
810 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
813 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
811 << m_VarRequestIdToVarIdVarRequestMap.size();
814 << m_VarRequestIdToVarIdVarRequestMap.size();
812 }
815 }
813 }
816 }
814 else {
817 else {
815 qCCritical(LOG_VariableController())
818 qCCritical(LOG_VariableController())
816 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
819 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
817 }
820 }
818 }
821 }
819
822
820 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
823 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
821 {
824 {
822 // cleaning varRequestId
825 // cleaning varRequestId
823 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
826 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
824
827
825 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
828 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
826 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
829 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
827 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
830 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
828 varRequestIdQueue.erase(
831 varRequestIdQueue.erase(
829 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
832 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
830 varRequestIdQueue.end());
833 varRequestIdQueue.end());
831 if (varRequestIdQueue.empty()) {
834 if (varRequestIdQueue.empty()) {
832 varIdToVarRequestIdQueueMapIt
835 varIdToVarRequestIdQueueMapIt
833 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
836 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
834 }
837 }
835 else {
838 else {
836 ++varIdToVarRequestIdQueueMapIt;
839 ++varIdToVarRequestIdQueueMapIt;
837 }
840 }
838 }
841 }
839 }
842 }
@@ -1,20 +1,20
1
1
2
2
3 tests = [
3 tests = [
4 [['Common/TestStringUtils.cpp'],'test_string_utils','StringUtils test'],
4 [['Common/TestStringUtils.cpp'],'test_string_utils','StringUtils test'],
5 [['Data/TestDataSeries.cpp'],'test_data','DataSeries test'],
5 [['Data/TestDataSeries.cpp'],'test_data','DataSeries test'],
6 [['Data/TestOneDimArrayData.cpp'],'test_1d','One Dim Array test'],
6 [['Data/TestOneDimArrayData.cpp'],'test_1d','One Dim Array test'],
7 [['Data/TestTwoDimArrayData.cpp'],'test_2d','Two Dim Array test'],
7 [['Data/TestTwoDimArrayData.cpp'],'test_2d','Two Dim Array test'],
8 [['DataSource/TestDataSourceController.cpp'],'test_data_source','DataSourceController test'],
8 [['DataSource/TestDataSourceController.cpp'],'test_data_source','DataSourceController test'],
9 [['Variable/TestVariableCacheController.cpp'],'test_variable_cache','VariableCacheController test'],
9 [['Variable/TestVariableCacheController.cpp'],'test_variable_cache','VariableCacheController test'],
10 [['Variable/TestVariableController.cpp'],'test_variable_controler','VariableController test'],
10 [['Variable/TestVariable.cpp'],'test_variable','Variable test'],
11 [['Variable/TestVariable.cpp'],'test_variable','Variable test']
11 [['Variable/TestVariableSync.cpp'],'test_variable_sync','Variable synchronization test']
12 ]
12 ]
13
13
14 foreach unit_test : tests
14 foreach unit_test : tests
15 test_moc_files = qt5.preprocess(moc_sources : unit_test[0])
15 test_moc_files = qt5.preprocess(moc_sources : unit_test[0])
16 test_exe = executable(unit_test[1],unit_test[0] , test_moc_files,
16 test_exe = executable(unit_test[1],unit_test[0] , test_moc_files,
17 dependencies : [sciqlop_core, qt5test])
17 dependencies : [sciqlop_core, qt5test])
18 test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])])
18 test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])])
19 endforeach
19 endforeach
20
20
@@ -1,80 +1,80
1
1
2 gui_moc_headers = [
2 gui_moc_headers = [
3 'include/DataSource/DataSourceWidget.h',
3 'include/DataSource/DataSourceWidget.h',
4 'include/Settings/SqpSettingsDialog.h',
4 'include/Settings/SqpSettingsDialog.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
6 'include/SidePane/SqpSidePane.h',
6 'include/SidePane/SqpSidePane.h',
7 'include/SqpApplication.h',
7 'include/SqpApplication.h',
8 'include/TimeWidget/TimeWidget.h',
8 'include/TimeWidget/TimeWidget.h',
9 'include/Variable/VariableInspectorWidget.h',
9 'include/Variable/VariableInspectorWidget.h',
10 'include/Variable/RenameVariableDialog.h',
10 'include/Variable/RenameVariableDialog.h',
11 'include/Visualization/qcustomplot.h',
11 'include/Visualization/qcustomplot.h',
12 'include/Visualization/VisualizationGraphWidget.h',
12 'include/Visualization/VisualizationGraphWidget.h',
13 'include/Visualization/VisualizationTabWidget.h',
13 'include/Visualization/VisualizationTabWidget.h',
14 'include/Visualization/VisualizationWidget.h',
14 'include/Visualization/VisualizationWidget.h',
15 'include/Visualization/VisualizationZoneWidget.h'
15 'include/Visualization/VisualizationZoneWidget.h'
16 ]
16 ]
17
17
18 gui_ui_files = [
18 gui_ui_files = [
19 'ui/DataSource/DataSourceWidget.ui',
19 'ui/DataSource/DataSourceWidget.ui',
20 'ui/Settings/SqpSettingsDialog.ui',
20 'ui/Settings/SqpSettingsDialog.ui',
21 'ui/Settings/SqpSettingsGeneralWidget.ui',
21 'ui/Settings/SqpSettingsGeneralWidget.ui',
22 'ui/SidePane/SqpSidePane.ui',
22 'ui/SidePane/SqpSidePane.ui',
23 'ui/TimeWidget/TimeWidget.ui',
23 'ui/TimeWidget/TimeWidget.ui',
24 'ui/Variable/VariableInspectorWidget.ui',
24 'ui/Variable/VariableInspectorWidget.ui',
25 'ui/Variable/VariableMenuHeaderWidget.ui',
26 'ui/Variable/RenameVariableDialog.ui',
25 'ui/Variable/RenameVariableDialog.ui',
26 'ui/Variable/VariableMenuHeaderWidget.ui',
27 'ui/Visualization/VisualizationGraphWidget.ui',
27 'ui/Visualization/VisualizationGraphWidget.ui',
28 'ui/Visualization/VisualizationTabWidget.ui',
28 'ui/Visualization/VisualizationTabWidget.ui',
29 'ui/Visualization/VisualizationWidget.ui',
29 'ui/Visualization/VisualizationWidget.ui',
30 'ui/Visualization/VisualizationZoneWidget.ui'
30 'ui/Visualization/VisualizationZoneWidget.ui'
31 ]
31 ]
32
32
33 gui_qresources = ['resources/sqpguiresources.qrc']
33 gui_qresources = ['resources/sqpguiresources.qrc']
34
34
35 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
35 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
36 ui_files : gui_ui_files,
36 ui_files : gui_ui_files,
37 qresources : gui_qresources)
37 qresources : gui_qresources)
38
38
39 gui_sources = [
39 gui_sources = [
40 'src/SqpApplication.cpp',
40 'src/SqpApplication.cpp',
41 'src/Common/ColorUtils.cpp',
41 'src/Common/ColorUtils.cpp',
42 'src/DataSource/DataSourceTreeWidgetItem.cpp',
42 'src/DataSource/DataSourceTreeWidgetItem.cpp',
43 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
43 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
44 'src/DataSource/DataSourceWidget.cpp',
44 'src/DataSource/DataSourceWidget.cpp',
45 'src/Settings/SqpSettingsDialog.cpp',
45 'src/Settings/SqpSettingsDialog.cpp',
46 'src/Settings/SqpSettingsGeneralWidget.cpp',
46 'src/Settings/SqpSettingsGeneralWidget.cpp',
47 'src/SidePane/SqpSidePane.cpp',
47 'src/SidePane/SqpSidePane.cpp',
48 'src/TimeWidget/TimeWidget.cpp',
48 'src/TimeWidget/TimeWidget.cpp',
49 'src/Variable/VariableInspectorWidget.cpp',
49 'src/Variable/VariableInspectorWidget.cpp',
50 'src/Variable/VariableMenuHeaderWidget.cpp',
50 'src/Variable/VariableMenuHeaderWidget.cpp',
51 'src/Variable/RenameVariableDialog.cpp',
51 'src/Variable/RenameVariableDialog.cpp',
52 'src/Visualization/VisualizationGraphHelper.cpp',
52 'src/Visualization/VisualizationGraphHelper.cpp',
53 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
53 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
54 'src/Visualization/VisualizationGraphWidget.cpp',
54 'src/Visualization/VisualizationGraphWidget.cpp',
55 'src/Visualization/VisualizationTabWidget.cpp',
55 'src/Visualization/VisualizationTabWidget.cpp',
56 'src/Visualization/VisualizationWidget.cpp',
56 'src/Visualization/VisualizationWidget.cpp',
57 'src/Visualization/VisualizationZoneWidget.cpp',
57 'src/Visualization/VisualizationZoneWidget.cpp',
58 'src/Visualization/qcustomplot.cpp',
58 'src/Visualization/qcustomplot.cpp',
59 'src/Visualization/QCustomPlotSynchronizer.cpp',
59 'src/Visualization/QCustomPlotSynchronizer.cpp',
60 'src/Visualization/operations/FindVariableOperation.cpp',
60 'src/Visualization/operations/FindVariableOperation.cpp',
61 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
61 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
62 'src/Visualization/operations/MenuBuilder.cpp',
62 'src/Visualization/operations/MenuBuilder.cpp',
63 'src/Visualization/operations/RemoveVariableOperation.cpp',
63 'src/Visualization/operations/RemoveVariableOperation.cpp',
64 'src/Visualization/operations/RescaleAxeOperation.cpp'
64 'src/Visualization/operations/RescaleAxeOperation.cpp'
65 ]
65 ]
66
66
67 gui_inc = include_directories(['include'])
67 gui_inc = include_directories(['include'])
68
68
69 sciqlop_gui_lib = library('sciqlopgui',
69 sciqlop_gui_lib = library('sciqlopgui',
70 gui_sources,
70 gui_sources,
71 gui_moc_files,
71 gui_moc_files,
72 include_directories : [gui_inc],
72 include_directories : [gui_inc],
73 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
73 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
74 install : true
74 install : true
75 )
75 )
76
76
77 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
77 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
78 include_directories : gui_inc,
78 include_directories : gui_inc,
79 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
79 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
80
80
@@ -1,232 +1,239
1 #include <Variable/RenameVariableDialog.h>
1 #include <Variable/RenameVariableDialog.h>
2 #include <Variable/Variable.h>
2 #include <Variable/Variable.h>
3 #include <Variable/VariableController.h>
3 #include <Variable/VariableController.h>
4 #include <Variable/VariableInspectorWidget.h>
4 #include <Variable/VariableInspectorWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7
7
8 #include <ui_VariableInspectorWidget.h>
8 #include <ui_VariableInspectorWidget.h>
9
9
10 #include <QMouseEvent>
10 #include <QMouseEvent>
11 #include <QSortFilterProxyModel>
11 #include <QSortFilterProxyModel>
12 #include <QStyledItemDelegate>
12 #include <QStyledItemDelegate>
13 #include <QWidgetAction>
13 #include <QWidgetAction>
14
14
15 #include <SqpApplication.h>
15 #include <SqpApplication.h>
16
16
17 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
17 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
18
18
19
19
20 class QProgressBarItemDelegate : public QStyledItemDelegate {
20 class QProgressBarItemDelegate : public QStyledItemDelegate {
21
21
22 public:
22 public:
23 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
23 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
24
24
25 void paint(QPainter *painter, const QStyleOptionViewItem &option,
25 void paint(QPainter *painter, const QStyleOptionViewItem &option,
26 const QModelIndex &index) const
26 const QModelIndex &index) const
27 {
27 {
28 auto data = index.data(Qt::DisplayRole);
28 auto data = index.data(Qt::DisplayRole);
29 auto progressData = index.data(VariableRoles::ProgressRole);
29 auto progressData = index.data(VariableRoles::ProgressRole);
30 if (data.isValid() && progressData.isValid()) {
30 if (data.isValid() && progressData.isValid()) {
31 auto name = data.value<QString>();
31 auto name = data.value<QString>();
32 auto progress = progressData.value<double>();
32 auto progress = progressData.value<double>();
33 if (progress > 0) {
33 if (progress > 0) {
34 auto cancelButtonWidth = 20;
34 auto cancelButtonWidth = 20;
35 auto progressBarOption = QStyleOptionProgressBar{};
35 auto progressBarOption = QStyleOptionProgressBar{};
36 auto progressRect = option.rect;
36 auto progressRect = option.rect;
37 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
37 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
38 progressBarOption.rect = progressRect;
38 progressBarOption.rect = progressRect;
39 progressBarOption.minimum = 0;
39 progressBarOption.minimum = 0;
40 progressBarOption.maximum = 100;
40 progressBarOption.maximum = 100;
41 progressBarOption.progress = progress;
41 progressBarOption.progress = progress;
42 progressBarOption.text
42 progressBarOption.text
43 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
43 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
44 progressBarOption.textVisible = true;
44 progressBarOption.textVisible = true;
45 progressBarOption.textAlignment = Qt::AlignCenter;
45 progressBarOption.textAlignment = Qt::AlignCenter;
46
46
47
47
48 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
48 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
49 painter);
49 painter);
50
50
51 // Cancel button
51 // Cancel button
52 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
52 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
53 option.rect.height());
53 option.rect.height());
54 auto buttonOption = QStyleOptionButton{};
54 auto buttonOption = QStyleOptionButton{};
55 buttonOption.rect = buttonRect;
55 buttonOption.rect = buttonRect;
56 buttonOption.text = "X";
56 buttonOption.text = "X";
57
57
58 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
58 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
59 }
59 }
60 else {
60 else {
61 QStyledItemDelegate::paint(painter, option, index);
61 QStyledItemDelegate::paint(painter, option, index);
62 }
62 }
63 }
63 }
64 else {
64 else {
65 QStyledItemDelegate::paint(painter, option, index);
65 QStyledItemDelegate::paint(painter, option, index);
66 }
66 }
67 }
67 }
68
68
69 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
69 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
70 const QModelIndex &index)
70 const QModelIndex &index)
71 {
71 {
72 if (event->type() == QEvent::MouseButtonRelease) {
72 if (event->type() == QEvent::MouseButtonRelease) {
73 auto data = index.data(Qt::DisplayRole);
73 auto data = index.data(Qt::DisplayRole);
74 auto progressData = index.data(VariableRoles::ProgressRole);
74 auto progressData = index.data(VariableRoles::ProgressRole);
75 if (data.isValid() && progressData.isValid()) {
75 if (data.isValid() && progressData.isValid()) {
76 auto cancelButtonWidth = 20;
76 auto cancelButtonWidth = 20;
77 auto progressRect = option.rect;
77 auto progressRect = option.rect;
78 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
78 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
79 // Cancel button
79 // Cancel button
80 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
80 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
81 option.rect.height());
81 option.rect.height());
82
82
83 auto e = (QMouseEvent *)event;
83 auto e = (QMouseEvent *)event;
84 auto clickX = e->x();
84 auto clickX = e->x();
85 auto clickY = e->y();
85 auto clickY = e->y();
86
86
87 auto x = buttonRect.left(); // the X coordinate
87 auto x = buttonRect.left(); // the X coordinate
88 auto y = buttonRect.top(); // the Y coordinate
88 auto y = buttonRect.top(); // the Y coordinate
89 auto w = buttonRect.width(); // button width
89 auto w = buttonRect.width(); // button width
90 auto h = buttonRect.height(); // button height
90 auto h = buttonRect.height(); // button height
91
91
92 if (clickX > x && clickX < x + w) {
92 if (clickX > x && clickX < x + w) {
93 if (clickY > y && clickY < y + h) {
93 if (clickY > y && clickY < y + h) {
94 auto variableModel = sqpApp->variableController().variableModel();
94 auto variableModel = sqpApp->variableController().variableModel();
95 variableModel->abortProgress(index);
95 variableModel->abortProgress(index);
96 }
96 }
97 return true;
97 return true;
98 }
98 }
99 else {
99 else {
100 return QStyledItemDelegate::editorEvent(event, model, option, index);
100 return QStyledItemDelegate::editorEvent(event, model, option, index);
101 }
101 }
102 }
102 }
103 else {
103 else {
104 return QStyledItemDelegate::editorEvent(event, model, option, index);
104 return QStyledItemDelegate::editorEvent(event, model, option, index);
105 }
105 }
106 }
106 }
107 else {
107 else {
108 return QStyledItemDelegate::editorEvent(event, model, option, index);
108 return QStyledItemDelegate::editorEvent(event, model, option, index);
109 }
109 }
110
110
111
111
112 return QStyledItemDelegate::editorEvent(event, model, option, index);
112 return QStyledItemDelegate::editorEvent(event, model, option, index);
113 }
113 }
114 };
114 };
115
115
116 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
116 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
117 : QWidget{parent},
117 : QWidget{parent},
118 ui{new Ui::VariableInspectorWidget},
118 ui{new Ui::VariableInspectorWidget},
119 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
119 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
120 {
120 {
121 ui->setupUi(this);
121 ui->setupUi(this);
122
122
123 // Sets model for table
123 // Sets model for table
124 // auto sortFilterModel = new QSortFilterProxyModel{this};
124 // auto sortFilterModel = new QSortFilterProxyModel{this};
125 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
125 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
126
126
127 auto variableModel = sqpApp->variableController().variableModel();
127 auto variableModel = sqpApp->variableController().variableModel();
128 ui->tableView->setModel(variableModel);
128 ui->tableView->setModel(variableModel);
129
129
130 // Adds extra signal/slot between view and model, so the view can be updated instantly when
130 // Adds extra signal/slot between view and model, so the view can be updated instantly when
131 // there is a change of data in the model
131 // there is a change of data in the model
132 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
132 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
133 SLOT(refresh()));
133 SLOT(refresh()));
134
134
135 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
135 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
136 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
136 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
137
137
138 // Fixes column sizes
138 // Fixes column sizes
139 auto model = ui->tableView->model();
139 auto model = ui->tableView->model();
140 const auto count = model->columnCount();
140 const auto count = model->columnCount();
141 for (auto i = 0; i < count; ++i) {
141 for (auto i = 0; i < count; ++i) {
142 ui->tableView->setColumnWidth(
142 ui->tableView->setColumnWidth(
143 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
143 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
144 }
144 }
145
145
146 // Sets selection options
146 // Sets selection options
147 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
147 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
148 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
148 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
149
149
150 // Connection to show a menu when right clicking on the tree
150 // Connection to show a menu when right clicking on the tree
151 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
151 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
152 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
152 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
153 &VariableInspectorWidget::onTableMenuRequested);
153 &VariableInspectorWidget::onTableMenuRequested);
154 }
154 }
155
155
156 VariableInspectorWidget::~VariableInspectorWidget()
156 VariableInspectorWidget::~VariableInspectorWidget()
157 {
157 {
158 delete ui;
158 delete ui;
159 }
159 }
160
160
161 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
161 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
162 {
162 {
163 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
163 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
164
164
165 // Gets the model to retrieve the underlying selected variables
165 // Gets the model to retrieve the underlying selected variables
166 auto model = sqpApp->variableController().variableModel();
166 auto model = sqpApp->variableController().variableModel();
167 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
167 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
168 for (const auto &selectedRow : qAsConst(selectedRows)) {
168 for (const auto &selectedRow : qAsConst(selectedRows)) {
169 if (auto selectedVariable = model->variable(selectedRow.row())) {
169 if (auto selectedVariable = model->variable(selectedRow.row())) {
170 selectedVariables.push_back(selectedVariable);
170 selectedVariables.push_back(selectedVariable);
171 }
171 }
172 }
172 }
173
173
174 QMenu tableMenu{};
174 QMenu tableMenu{};
175
175
176 // Emits a signal so that potential receivers can populate the menu before displaying it
176 // Emits a signal so that potential receivers can populate the menu before displaying it
177 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
177 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
178
178
179 // Adds menu-specific actions
179 // Adds menu-specific actions
180 if (!selectedVariables.isEmpty()) {
180 if (!selectedVariables.isEmpty()) {
181 tableMenu.addSeparator();
181 tableMenu.addSeparator();
182
182
183 // 'Rename' and 'Duplicate' actions (only if one variable selected)
183 // 'Rename' and 'Duplicate' actions (only if one variable selected)
184 if (selectedVariables.size() == 1) {
184 if (selectedVariables.size() == 1) {
185 auto selectedVariable = selectedVariables.front();
185 auto selectedVariable = selectedVariables.front();
186
186
187 auto duplicateFun = [&selectedVariable]() {
187 auto duplicateFun = [varW = std::weak_ptr<Variable>(selectedVariable)]()
188 sqpApp->variableController().cloneVariable(selectedVariable);
188 {
189 if (auto var = varW.lock()) {
190 sqpApp->variableController().cloneVariable(var);
191 }
189 };
192 };
190
193
191 tableMenu.addAction(tr("Duplicate"), duplicateFun);
194 tableMenu.addAction(tr("Duplicate"), duplicateFun);
192
195
193 auto renameFun = [&selectedVariable, &model, this]() {
196 auto renameFun = [ varW = std::weak_ptr<Variable>(selectedVariable), &model, this ]()
194 // Generates forbidden names (names associated to existing variables)
197 {
195 auto allVariables = model->variables();
198 if (auto var = varW.lock()) {
196 auto forbiddenNames = QVector<QString>(allVariables.size());
199 // Generates forbidden names (names associated to existing variables)
197 std::transform(allVariables.cbegin(), allVariables.cend(), forbiddenNames.begin(),
200 auto allVariables = model->variables();
198 [](const auto &variable) { return variable->name(); });
201 auto forbiddenNames = QVector<QString>(allVariables.size());
199
202 std::transform(allVariables.cbegin(), allVariables.cend(),
200 RenameVariableDialog dialog{selectedVariable->name(), forbiddenNames, this};
203 forbiddenNames.begin(),
201 if (dialog.exec() == QDialog::Accepted) {
204 [](const auto &variable) { return variable->name(); });
202 selectedVariable->setName(dialog.name());
205
206 RenameVariableDialog dialog{var->name(), forbiddenNames, this};
207 if (dialog.exec() == QDialog::Accepted) {
208 var->setName(dialog.name());
209 }
203 }
210 }
204 };
211 };
205
212
206 tableMenu.addAction(tr("Rename..."), renameFun);
213 tableMenu.addAction(tr("Rename..."), renameFun);
207 }
214 }
208
215
209 // 'Delete' action
216 // 'Delete' action
210 auto deleteFun = [&selectedVariables]() {
217 auto deleteFun = [&selectedVariables]() {
211 sqpApp->variableController().deleteVariables(selectedVariables);
218 sqpApp->variableController().deleteVariables(selectedVariables);
212 };
219 };
213
220
214 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
221 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
215 }
222 }
216
223
217 if (!tableMenu.isEmpty()) {
224 if (!tableMenu.isEmpty()) {
218 // Generates menu header (inserted before first action)
225 // Generates menu header (inserted before first action)
219 auto firstAction = tableMenu.actions().first();
226 auto firstAction = tableMenu.actions().first();
220 auto headerAction = new QWidgetAction{&tableMenu};
227 auto headerAction = new QWidgetAction{&tableMenu};
221 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
228 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
222 tableMenu.insertAction(firstAction, headerAction);
229 tableMenu.insertAction(firstAction, headerAction);
223
230
224 // Displays menu
231 // Displays menu
225 tableMenu.exec(QCursor::pos());
232 tableMenu.exec(QCursor::pos());
226 }
233 }
227 }
234 }
228
235
229 void VariableInspectorWidget::refresh() noexcept
236 void VariableInspectorWidget::refresh() noexcept
230 {
237 {
231 ui->tableView->viewport()->update();
238 ui->tableView->viewport()->update();
232 }
239 }
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now