##// END OF EJS Templates
Fix bug when creating two variables crash the app. ...
perrinel -
r756:a7f60f6512e6
parent child
Show More
@@ -1,84 +1,83
1 1 #ifndef SCIQLOP_VARIABLE_H
2 2 #define SCIQLOP_VARIABLE_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/DataSeriesIterator.h>
7 7 #include <Data/SqpRange.h>
8 8
9 9 #include <QLoggingCategory>
10 10 #include <QObject>
11 11
12 12 #include <Common/MetaTypes.h>
13 13 #include <Common/spimpl.h>
14 14
15 15 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
16 16
17 17 class IDataSeries;
18 18 class QString;
19 19
20 20 /**
21 21 * @brief The Variable class represents a variable in SciQlop.
22 22 */
23 23 class SCIQLOP_CORE_EXPORT Variable : public QObject {
24 24
25 25 Q_OBJECT
26 26
27 27 public:
28 explicit Variable(const QString &name, const SqpRange &dateTime,
29 const QVariantHash &metadata = {});
28 explicit Variable(const QString &name, const QVariantHash &metadata = {});
30 29
31 30 /// Copy ctor
32 31 explicit Variable(const Variable &other);
33 32
34 33 std::shared_ptr<Variable> clone() const;
35 34
36 35 QString name() const noexcept;
37 36 void setName(const QString &name) noexcept;
38 37 SqpRange range() const noexcept;
39 38 void setRange(const SqpRange &range) noexcept;
40 39 SqpRange cacheRange() const noexcept;
41 40 void setCacheRange(const SqpRange &cacheRange) noexcept;
42 41
43 42 /// @return the number of points hold by the variable. The number of points is updated each time
44 43 /// the data series changes
45 44 int nbPoints() const noexcept;
46 45
47 46 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
48 47 /// series between the range of the variable. The real range is updated each time the variable
49 48 /// range or the data series changed
50 49 /// @return the real range, invalid range if the data series is null or empty
51 50 /// @sa setDataSeries()
52 51 /// @sa setRange()
53 52 SqpRange realRange() const noexcept;
54 53
55 54 /// @return the data of the variable, nullptr if there is no data
56 55 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
57 56
58 57 QVariantHash metadata() const noexcept;
59 58
60 59 bool contains(const SqpRange &range) const noexcept;
61 60 bool intersect(const SqpRange &range) const noexcept;
62 61 bool isInside(const SqpRange &range) const noexcept;
63 62
64 63 bool cacheContains(const SqpRange &range) const noexcept;
65 64 bool cacheIntersect(const SqpRange &range) const noexcept;
66 65 bool cacheIsInside(const SqpRange &range) const noexcept;
67 66
68 67 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
69 68 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
70 69 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
71 70
72 71 signals:
73 72 void updated();
74 73
75 74 private:
76 75 class VariablePrivate;
77 76 spimpl::unique_impl_ptr<VariablePrivate> impl;
78 77 };
79 78
80 79 // Required for using shared_ptr in signals/slots
81 80 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
82 81 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
83 82
84 83 #endif // SCIQLOP_VARIABLE_H
@@ -1,96 +1,95
1 1 #ifndef SCIQLOP_VARIABLEMODEL_H
2 2 #define SCIQLOP_VARIABLEMODEL_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/SqpRange.h>
7 7
8 8 #include <QAbstractTableModel>
9 9 #include <QLoggingCategory>
10 10
11 11 #include <Common/MetaTypes.h>
12 12 #include <Common/spimpl.h>
13 13
14 14 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
15 15
16 16 enum VariableRoles { ProgressRole = Qt::UserRole };
17 17
18 18
19 19 class IDataSeries;
20 20 class Variable;
21 21
22 22 /**
23 23 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
24 24 */
25 25 class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel {
26 26 Q_OBJECT
27 27 public:
28 28 explicit VariableModel(QObject *parent = nullptr);
29 29
30 30 /**
31 31 * Adds an existing variable in the model.
32 32 * @param variable the variable to add.
33 33 * @remarks the variable's name is modified to avoid name duplicates
34 34 * @remarks this method does nothing if the variable already exists in the model
35 35 */
36 36 void addVariable(std::shared_ptr<Variable> variable) noexcept;
37 37
38 38 /**
39 39 * Checks that a variable is contained in the model
40 40 * @param variable the variable to check
41 41 * @return true if the variable is in the model, false otherwise
42 42 */
43 43 bool containsVariable(std::shared_ptr<Variable> variable) const noexcept;
44 44
45 45 /**
46 46 * Creates a new variable in the model
47 47 * @param name the name of the new variable
48 * @param dateTime the dateTime of the new variable
49 48 * @param metadata the metadata associated to the new variable
50 49 * @return the pointer to the new variable
51 50 */
52 std::shared_ptr<Variable> createVariable(const QString &name, const SqpRange &dateTime,
51 std::shared_ptr<Variable> createVariable(const QString &name,
53 52 const QVariantHash &metadata) noexcept;
54 53
55 54 /**
56 55 * Deletes a variable from the model, if it exists
57 56 * @param variable the variable to delete
58 57 */
59 58 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
60 59
61 60
62 61 std::shared_ptr<Variable> variable(int index) const;
63 62 std::vector<std::shared_ptr<Variable> > variables() const;
64 63
65 64 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
66 65
67 66
68 67 // /////////////////////////// //
69 68 // QAbstractTableModel methods //
70 69 // /////////////////////////// //
71 70
72 71 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
73 72 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
74 73 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
75 74 virtual QVariant headerData(int section, Qt::Orientation orientation,
76 75 int role = Qt::DisplayRole) const override;
77 76
78 77
79 78 void abortProgress(const QModelIndex &index);
80 79
81 80 signals:
82 81 void abortProgessRequested(std::shared_ptr<Variable> variable);
83 82
84 83 private:
85 84 class VariableModelPrivate;
86 85 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
87 86
88 87 private slots:
89 88 /// Slot called when data of a variable has been updated
90 89 void onVariableUpdated() noexcept;
91 90 };
92 91
93 92 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
94 93 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
95 94
96 95 #endif // SCIQLOP_VARIABLEMODEL_H
@@ -1,307 +1,315
1 1 #include "Variable/Variable.h"
2 2
3 3 #include <Data/IDataSeries.h>
4 4 #include <Data/SqpRange.h>
5 5
6 6 #include <QMutex>
7 7 #include <QReadWriteLock>
8 8 #include <QThread>
9 9
10 10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
11 11
12 12 struct Variable::VariablePrivate {
13 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
14 const QVariantHash &metadata)
13 explicit VariablePrivate(const QString &name, const QVariantHash &metadata)
15 14 : m_Name{name},
16 m_Range{dateTime},
15 m_Range{INVALID_RANGE},
16 m_CacheRange{INVALID_RANGE},
17 17 m_Metadata{metadata},
18 18 m_DataSeries{nullptr},
19 19 m_RealRange{INVALID_RANGE},
20 20 m_NbPoints{0}
21 21 {
22 22 }
23 23
24 24 VariablePrivate(const VariablePrivate &other)
25 25 : m_Name{other.m_Name},
26 26 m_Range{other.m_Range},
27 m_CacheRange{other.m_CacheRange},
27 28 m_Metadata{other.m_Metadata},
28 29 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
29 30 m_RealRange{other.m_RealRange},
30 31 m_NbPoints{other.m_NbPoints}
31 32 {
32 33 }
33 34
34 35 void lockRead() { m_Lock.lockForRead(); }
35 36 void lockWrite() { m_Lock.lockForWrite(); }
36 37 void unlock() { m_Lock.unlock(); }
37 38
38 39 void purgeDataSeries()
39 40 {
40 41 if (m_DataSeries) {
41 42 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
42 43 }
43 44 updateRealRange();
44 45 updateNbPoints();
45 46 }
46 47
47 48 void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
48 49
49 50 /// Updates real range according to current variable range and data series
50 51 void updateRealRange()
51 52 {
52 53 if (m_DataSeries) {
53 54 m_DataSeries->lockRead();
54 55 auto end = m_DataSeries->cend();
55 56 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
56 57 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
57 58
58 m_RealRange = (minXAxisIt != end && maxXAxisIt != end)
59 m_RealRange
60 = (minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x())
59 61 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
60 62 : INVALID_RANGE;
61 63 m_DataSeries->unlock();
62 64 }
63 65 else {
64 66 m_RealRange = INVALID_RANGE;
65 67 }
66 68 }
67 69
68 70 QString m_Name;
69 71
70 72 SqpRange m_Range;
71 73 SqpRange m_CacheRange;
72 74 QVariantHash m_Metadata;
73 75 std::shared_ptr<IDataSeries> m_DataSeries;
74 76 SqpRange m_RealRange;
75 77 int m_NbPoints;
76 78
77 79 QReadWriteLock m_Lock;
78 80 };
79 81
80 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
81 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
82 Variable::Variable(const QString &name, const QVariantHash &metadata)
83 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)}
82 84 {
83 85 }
84 86
85 87 Variable::Variable(const Variable &other)
86 88 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)}
87 89 {
88 90 }
89 91
90 92 std::shared_ptr<Variable> Variable::clone() const
91 93 {
92 94 return std::make_shared<Variable>(*this);
93 95 }
94 96
95 97 QString Variable::name() const noexcept
96 98 {
97 99 impl->lockRead();
98 100 auto name = impl->m_Name;
99 101 impl->unlock();
100 102 return name;
101 103 }
102 104
103 105 void Variable::setName(const QString &name) noexcept
104 106 {
105 107 impl->lockWrite();
106 108 impl->m_Name = name;
107 109 impl->unlock();
108 110 }
109 111
110 112 SqpRange Variable::range() const noexcept
111 113 {
112 114 impl->lockRead();
113 115 auto range = impl->m_Range;
114 116 impl->unlock();
115 117 return range;
116 118 }
117 119
118 120 void Variable::setRange(const SqpRange &range) noexcept
119 121 {
120 122 impl->lockWrite();
121 123 impl->m_Range = range;
122 124 impl->updateRealRange();
123 125 impl->unlock();
124 126 }
125 127
126 128 SqpRange Variable::cacheRange() const noexcept
127 129 {
128 130 impl->lockRead();
129 131 auto cacheRange = impl->m_CacheRange;
130 132 impl->unlock();
131 133 return cacheRange;
132 134 }
133 135
134 136 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
135 137 {
136 138 impl->lockWrite();
137 139 if (cacheRange != impl->m_CacheRange) {
138 140 impl->m_CacheRange = cacheRange;
139 141 impl->purgeDataSeries();
140 142 }
141 143 impl->unlock();
142 144 }
143 145
144 146 int Variable::nbPoints() const noexcept
145 147 {
146 148 return impl->m_NbPoints;
147 149 }
148 150
149 151 SqpRange Variable::realRange() const noexcept
150 152 {
151 153 return impl->m_RealRange;
152 154 }
153 155
154 156 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
155 157 {
156 158 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
157 159 << QThread::currentThread()->objectName();
158 160 if (!dataSeries) {
159 161 /// @todo ALX : log
160 162 return;
161 163 }
162 164
163 165 // Add or merge the data
164 166 impl->lockWrite();
165 167 if (!impl->m_DataSeries) {
166 168 impl->m_DataSeries = dataSeries->clone();
167 169 }
168 170 else {
169 171 impl->m_DataSeries->merge(dataSeries.get());
170 172 }
171 173 impl->purgeDataSeries();
172 174 impl->unlock();
173 175 }
174 176
175 177 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
176 178 {
177 179 impl->lockRead();
178 180 auto dataSeries = impl->m_DataSeries;
179 181 impl->unlock();
180 182
181 183 return dataSeries;
182 184 }
183 185
184 186 QVariantHash Variable::metadata() const noexcept
185 187 {
186 188 impl->lockRead();
187 189 auto metadata = impl->m_Metadata;
188 190 impl->unlock();
189 191 return metadata;
190 192 }
191 193
192 194 bool Variable::contains(const SqpRange &range) const noexcept
193 195 {
194 196 impl->lockRead();
195 197 auto res = impl->m_Range.contains(range);
196 198 impl->unlock();
197 199 return res;
198 200 }
199 201
200 202 bool Variable::intersect(const SqpRange &range) const noexcept
201 203 {
202 204
203 205 impl->lockRead();
204 206 auto res = impl->m_Range.intersect(range);
205 207 impl->unlock();
206 208 return res;
207 209 }
208 210
209 211 bool Variable::isInside(const SqpRange &range) const noexcept
210 212 {
211 213 impl->lockRead();
212 214 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
213 215 impl->unlock();
214 216 return res;
215 217 }
216 218
217 219 bool Variable::cacheContains(const SqpRange &range) const noexcept
218 220 {
219 221 impl->lockRead();
220 222 auto res = impl->m_CacheRange.contains(range);
221 223 impl->unlock();
222 224 return res;
223 225 }
224 226
225 227 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
226 228 {
227 229 impl->lockRead();
228 230 auto res = impl->m_CacheRange.intersect(range);
229 231 impl->unlock();
230 232 return res;
231 233 }
232 234
233 235 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
234 236 {
235 237 impl->lockRead();
236 238 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
237 239 impl->unlock();
238 240 return res;
239 241 }
240 242
241 243
242 244 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
243 245 {
244 246 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
245
246 247 auto notInCache = QVector<SqpRange>{};
248 if (impl->m_CacheRange != INVALID_RANGE) {
247 249
248 250 if (!this->cacheContains(range)) {
249 251 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
250 252 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
251 253 notInCache << range;
252 254 }
253 255 else if (range.m_TStart < impl->m_CacheRange.m_TStart
254 256 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
255 257 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
256 258 }
257 259 else if (range.m_TStart < impl->m_CacheRange.m_TStart
258 260 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
259 261 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
260 262 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
261 263 }
262 264 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
263 265 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
264 266 }
265 267 else {
266 268 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
267 269 << QThread::currentThread();
268 270 }
269 271 }
272 }
273 else {
274 notInCache << range;
275 }
270 276
271 277 return notInCache;
272 278 }
273 279
274 280 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
275 281 {
276 282 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
277 283
278 284 auto inCache = QVector<SqpRange>{};
279 285
286 if (impl->m_CacheRange != INVALID_RANGE) {
280 287
281 288 if (this->intersect(range)) {
282 289 if (range.m_TStart <= impl->m_CacheRange.m_TStart
283 290 && range.m_TEnd >= impl->m_CacheRange.m_TStart
284 291 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
285 292 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
286 293 }
287 294
288 295 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
289 296 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
290 297 inCache << range;
291 298 }
292 299 else if (range.m_TStart > impl->m_CacheRange.m_TStart
293 300 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
294 301 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
295 302 }
296 303 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
297 304 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
298 305 inCache << impl->m_CacheRange;
299 306 }
300 307 else {
301 308 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
302 309 << QThread::currentThread();
303 310 }
304 311 }
312 }
305 313
306 314 return inCache;
307 315 }
@@ -1,814 +1,813
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableAcquisitionWorker.h>
3 3 #include <Variable/VariableCacheStrategy.h>
4 4 #include <Variable/VariableController.h>
5 5 #include <Variable/VariableModel.h>
6 6 #include <Variable/VariableSynchronizationGroup.h>
7 7
8 8 #include <Data/DataProviderParameters.h>
9 9 #include <Data/IDataProvider.h>
10 10 #include <Data/IDataSeries.h>
11 11 #include <Data/VariableRequest.h>
12 12 #include <Time/TimeController.h>
13 13
14 14 #include <QMutex>
15 15 #include <QThread>
16 16 #include <QUuid>
17 17 #include <QtCore/QItemSelectionModel>
18 18
19 19 #include <deque>
20 20 #include <set>
21 21 #include <unordered_map>
22 22
23 23 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
24 24
25 25 namespace {
26 26
27 27 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
28 28 const SqpRange &oldGraphRange)
29 29 {
30 30 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
31 31
32 32 auto varRangeRequested = varRange;
33 33 switch (zoomType) {
34 34 case AcquisitionZoomType::ZoomIn: {
35 35 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
36 36 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
37 37 varRangeRequested.m_TStart += deltaLeft;
38 38 varRangeRequested.m_TEnd -= deltaRight;
39 39 break;
40 40 }
41 41
42 42 case AcquisitionZoomType::ZoomOut: {
43 43 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
44 44 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
45 45 varRangeRequested.m_TStart -= deltaLeft;
46 46 varRangeRequested.m_TEnd += deltaRight;
47 47 break;
48 48 }
49 49 case AcquisitionZoomType::PanRight: {
50 50 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
51 51 varRangeRequested.m_TStart += deltaRight;
52 52 varRangeRequested.m_TEnd += deltaRight;
53 53 break;
54 54 }
55 55 case AcquisitionZoomType::PanLeft: {
56 56 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
57 57 varRangeRequested.m_TStart -= deltaLeft;
58 58 varRangeRequested.m_TEnd -= deltaLeft;
59 59 break;
60 60 }
61 61 case AcquisitionZoomType::Unknown: {
62 62 qCCritical(LOG_VariableController())
63 63 << VariableController::tr("Impossible to synchronize: zoom type unknown");
64 64 break;
65 65 }
66 66 default:
67 67 qCCritical(LOG_VariableController()) << VariableController::tr(
68 68 "Impossible to synchronize: zoom type not take into account");
69 69 // No action
70 70 break;
71 71 }
72 72
73 73 return varRangeRequested;
74 74 }
75 75 }
76 76
77 77 struct VariableController::VariableControllerPrivate {
78 78 explicit VariableControllerPrivate(VariableController *parent)
79 79 : m_WorkingMutex{},
80 80 m_VariableModel{new VariableModel{parent}},
81 81 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
82 82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
83 83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
84 84 q{parent}
85 85 {
86 86
87 87 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
88 88 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
89 89 }
90 90
91 91
92 92 virtual ~VariableControllerPrivate()
93 93 {
94 94 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
95 95 m_VariableAcquisitionWorkerThread.quit();
96 96 m_VariableAcquisitionWorkerThread.wait();
97 97 }
98 98
99 99
100 100 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
101 101 QUuid varRequestId);
102 102
103 103 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
104 104 const SqpRange &dateTime);
105 105
106 106 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
107 107 std::shared_ptr<IDataSeries>
108 108 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
109 109
110 110 void registerProvider(std::shared_ptr<IDataProvider> provider);
111 111
112 112 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
113 113 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
114 114 void updateVariableRequest(QUuid varRequestId);
115 115 void cancelVariableRequest(QUuid varRequestId);
116 116
117 117 QMutex m_WorkingMutex;
118 118 /// Variable model. The VariableController has the ownership
119 119 VariableModel *m_VariableModel;
120 120 QItemSelectionModel *m_VariableSelectionModel;
121 121
122 122
123 123 TimeController *m_TimeController{nullptr};
124 124 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
125 125 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
126 126 QThread m_VariableAcquisitionWorkerThread;
127 127
128 128 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
129 129 m_VariableToProviderMap;
130 130 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
131 131 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
132 132 m_GroupIdToVariableSynchronizationGroupMap;
133 133 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
134 134 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
135 135
136 136 std::map<QUuid, std::map<QUuid, VariableRequest> > m_VarRequestIdToVarIdVarRequestMap;
137 137
138 138 std::map<QUuid, std::deque<QUuid> > m_VarIdToVarRequestIdQueueMap;
139 139
140 140
141 141 VariableController *q;
142 142 };
143 143
144 144
145 145 VariableController::VariableController(QObject *parent)
146 146 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
147 147 {
148 148 qCDebug(LOG_VariableController()) << tr("VariableController construction")
149 149 << QThread::currentThread();
150 150
151 151 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
152 152 &VariableController::onAbortProgressRequested);
153 153
154 154 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
155 155 &VariableController::onDataProvided);
156 156 connect(impl->m_VariableAcquisitionWorker.get(),
157 157 &VariableAcquisitionWorker::variableRequestInProgress, this,
158 158 &VariableController::onVariableRetrieveDataInProgress);
159 159
160 160 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
161 161 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
162 162 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
163 163 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
164 164
165 165
166 166 impl->m_VariableAcquisitionWorkerThread.start();
167 167 }
168 168
169 169 VariableController::~VariableController()
170 170 {
171 171 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
172 172 << QThread::currentThread();
173 173 this->waitForFinish();
174 174 }
175 175
176 176 VariableModel *VariableController::variableModel() noexcept
177 177 {
178 178 return impl->m_VariableModel;
179 179 }
180 180
181 181 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
182 182 {
183 183 return impl->m_VariableSelectionModel;
184 184 }
185 185
186 186 void VariableController::setTimeController(TimeController *timeController) noexcept
187 187 {
188 188 impl->m_TimeController = timeController;
189 189 }
190 190
191 191 std::shared_ptr<Variable>
192 192 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
193 193 {
194 194 if (impl->m_VariableModel->containsVariable(variable)) {
195 195 // Clones variable
196 196 auto duplicate = variable->clone();
197 197
198 198 // Adds clone to model
199 199 impl->m_VariableModel->addVariable(duplicate);
200 200
201 201 // Generates clone identifier
202 202 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
203 203
204 204 // Registers provider
205 205 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
206 206 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
207 207
208 208 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
209 209 if (duplicateProvider) {
210 210 impl->registerProvider(duplicateProvider);
211 211 }
212 212
213 213 return duplicate;
214 214 }
215 215 else {
216 216 qCCritical(LOG_VariableController())
217 217 << tr("Can't create duplicate of variable %1: variable not registered in the model")
218 218 .arg(variable->name());
219 219 return nullptr;
220 220 }
221 221 }
222 222
223 223 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
224 224 {
225 225 if (!variable) {
226 226 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
227 227 return;
228 228 }
229 229
230 230 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
231 231 // make some treatments before the deletion
232 232 emit variableAboutToBeDeleted(variable);
233 233
234 234 // Deletes identifier
235 235 impl->m_VariableToIdentifierMap.erase(variable);
236 236
237 237 // Deletes provider
238 238 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
239 239 qCDebug(LOG_VariableController())
240 240 << tr("Number of providers deleted for variable %1: %2")
241 241 .arg(variable->name(), QString::number(nbProvidersDeleted));
242 242
243 243
244 244 // Deletes from model
245 245 impl->m_VariableModel->deleteVariable(variable);
246 246 }
247 247
248 248 void VariableController::deleteVariables(
249 249 const QVector<std::shared_ptr<Variable> > &variables) noexcept
250 250 {
251 251 for (auto variable : qAsConst(variables)) {
252 252 deleteVariable(variable);
253 253 }
254 254 }
255 255
256 256 std::shared_ptr<Variable>
257 257 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
258 258 std::shared_ptr<IDataProvider> provider) noexcept
259 259 {
260 260 if (!impl->m_TimeController) {
261 261 qCCritical(LOG_VariableController())
262 262 << tr("Impossible to create variable: The time controller is null");
263 263 return nullptr;
264 264 }
265 265
266 266 auto range = impl->m_TimeController->dateTime();
267 267
268 if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) {
268 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
269 269 auto identifier = QUuid::createUuid();
270 270
271 271 // store the provider
272 272 impl->registerProvider(provider);
273 273
274 274 // Associate the provider
275 275 impl->m_VariableToProviderMap[newVariable] = provider;
276 276 impl->m_VariableToIdentifierMap[newVariable] = identifier;
277 277
278 278
279 279 auto varRequestId = QUuid::createUuid();
280 280 impl->processRequest(newVariable, range, varRequestId);
281 281 impl->updateVariableRequest(varRequestId);
282 282
283 283 return newVariable;
284 284 }
285 285 }
286 286
287 287 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
288 288 {
289 289 // TODO check synchronisation and Rescale
290 290 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
291 291 << QThread::currentThread()->objectName();
292 292 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
293 293 auto varRequestId = QUuid::createUuid();
294 294
295 295 for (const auto &selectedRow : qAsConst(selectedRows)) {
296 296 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
297 297 selectedVariable->setRange(dateTime);
298 298 impl->processRequest(selectedVariable, dateTime, varRequestId);
299 299
300 300 // notify that rescale operation has to be done
301 301 emit rangeChanged(selectedVariable, dateTime);
302 302 }
303 303 }
304 304 impl->updateVariableRequest(varRequestId);
305 305 }
306 306
307 307 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
308 308 const SqpRange &cacheRangeRequested,
309 309 QVector<AcquisitionDataPacket> dataAcquired)
310 310 {
311 311 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
312 312 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
313 313 if (!varRequestId.isNull()) {
314 314 impl->updateVariableRequest(varRequestId);
315 315 }
316 316 }
317 317
318 318 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
319 319 {
320 320 qCDebug(LOG_VariableController())
321 321 << "TORM: variableController::onVariableRetrieveDataInProgress"
322 322 << QThread::currentThread()->objectName() << progress;
323 323 if (auto var = impl->findVariable(identifier)) {
324 324 impl->m_VariableModel->setDataProgress(var, progress);
325 325 }
326 326 else {
327 327 qCCritical(LOG_VariableController())
328 328 << tr("Impossible to notify progression of a null variable");
329 329 }
330 330 }
331 331
332 332 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
333 333 {
334 334 auto it = impl->m_VariableToIdentifierMap.find(variable);
335 335 if (it != impl->m_VariableToIdentifierMap.cend()) {
336 336 impl->m_VariableAcquisitionWorker->abortProgressRequested(it->second);
337 337
338 338 QUuid varRequestId;
339 339 auto varIdToVarRequestIdQueueMapIt = impl->m_VarIdToVarRequestIdQueueMap.find(it->second);
340 340 if (varIdToVarRequestIdQueueMapIt != impl->m_VarIdToVarRequestIdQueueMap.cend()) {
341 341 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
342 342 varRequestId = varRequestIdQueue.front();
343 343 impl->cancelVariableRequest(varRequestId);
344 344
345 345 // Finish the progression for the request
346 346 impl->m_VariableModel->setDataProgress(variable, 0.0);
347 347 }
348 348 else {
349 349 qCWarning(LOG_VariableController())
350 350 << tr("Aborting progression of inexistant variable request detected !!!")
351 351 << QThread::currentThread()->objectName();
352 352 }
353 353 }
354 354 else {
355 355 qCWarning(LOG_VariableController())
356 356 << tr("Aborting progression of inexistant variable detected !!!")
357 357 << QThread::currentThread()->objectName();
358 358 }
359 359 }
360 360
361 361 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
362 362 {
363 363 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
364 364 << QThread::currentThread()->objectName()
365 365 << synchronizationGroupId;
366 366 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
367 367 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
368 368 std::make_pair(synchronizationGroupId, vSynchroGroup));
369 369 }
370 370
371 371 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
372 372 {
373 373 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
374 374 }
375 375
376 376 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
377 377 QUuid synchronizationGroupId)
378 378
379 379 {
380 380 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
381 381 << synchronizationGroupId;
382 382 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
383 383 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
384 384 auto groupIdToVSGIt
385 385 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
386 386 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
387 387 impl->m_VariableIdGroupIdMap.insert(
388 388 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
389 389 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
390 390 }
391 391 else {
392 392 qCCritical(LOG_VariableController())
393 393 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
394 394 << variable->name();
395 395 }
396 396 }
397 397 else {
398 398 qCCritical(LOG_VariableController())
399 399 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
400 400 }
401 401 }
402 402
403 403 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
404 404 QUuid synchronizationGroupId)
405 405 {
406 406 // Gets variable id
407 407 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
408 408 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
409 409 qCCritical(LOG_VariableController())
410 410 << tr("Can't desynchronize variable %1: variable identifier not found")
411 411 .arg(variable->name());
412 412 return;
413 413 }
414 414
415 415 // Gets synchronization group
416 416 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
417 417 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
418 418 qCCritical(LOG_VariableController())
419 419 << tr("Can't desynchronize variable %1: unknown synchronization group")
420 420 .arg(variable->name());
421 421 return;
422 422 }
423 423
424 424 auto variableId = variableIt->second;
425 425
426 426 // Removes variable from synchronization group
427 427 auto synchronizationGroup = groupIt->second;
428 428 synchronizationGroup->removeVariableId(variableId);
429 429
430 430 // Removes link between variable and synchronization group
431 431 impl->m_VariableIdGroupIdMap.erase(variableId);
432 432 }
433 433
434 434 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
435 435 const SqpRange &range, const SqpRange &oldRange,
436 436 bool synchronise)
437 437 {
438 438 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
439 439
440 440 // we want to load data of the variable for the dateTime.
441 441 // First we check if the cache contains some of them.
442 442 // For the other, we ask the provider to give them.
443 443
444 444 auto varRequestId = QUuid::createUuid();
445 445 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
446 446 << QThread::currentThread()->objectName() << varRequestId;
447 447
448 448 for (const auto &var : variables) {
449 449 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId;
450 450 impl->processRequest(var, range, varRequestId);
451 451 }
452 452
453 453 if (synchronise) {
454 454 // Get the group ids
455 455 qCDebug(LOG_VariableController())
456 456 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
457 457 auto groupIds = std::set<QUuid>{};
458 458 auto groupIdToOldRangeMap = std::map<QUuid, SqpRange>{};
459 459 for (const auto &var : variables) {
460 460 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
461 461 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
462 462 auto vId = varToVarIdIt->second;
463 463 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
464 464 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
465 465 auto gId = varIdToGroupIdIt->second;
466 466 groupIdToOldRangeMap.insert(std::make_pair(gId, var->range()));
467 467 if (groupIds.find(gId) == groupIds.cend()) {
468 468 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
469 469 groupIds.insert(gId);
470 470 }
471 471 }
472 472 }
473 473 }
474 474
475 475 // We assume here all group ids exist
476 476 for (const auto &gId : groupIds) {
477 477 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
478 478 auto vSyncIds = vSynchronizationGroup->getIds();
479 479 qCDebug(LOG_VariableController()) << "Var in synchro group ";
480 480 for (auto vId : vSyncIds) {
481 481 auto var = impl->findVariable(vId);
482 482
483 483 // Don't process already processed var
484 484 if (!variables.contains(var)) {
485 485 if (var != nullptr) {
486 486 qCDebug(LOG_VariableController()) << "processRequest synchro for"
487 487 << var->name();
488 488 auto vSyncRangeRequested = computeSynchroRangeRequested(
489 489 var->range(), range, groupIdToOldRangeMap.at(gId));
490 490 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
491 491 impl->processRequest(var, vSyncRangeRequested, varRequestId);
492 492 }
493 493 else {
494 494 qCCritical(LOG_VariableController())
495 495
496 496 << tr("Impossible to synchronize a null variable");
497 497 }
498 498 }
499 499 }
500 500 }
501 501 }
502 502
503 503 impl->updateVariableRequest(varRequestId);
504 504 }
505 505
506 506
507 507 void VariableController::initialize()
508 508 {
509 509 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
510 510 impl->m_WorkingMutex.lock();
511 511 qCDebug(LOG_VariableController()) << tr("VariableController init END");
512 512 }
513 513
514 514 void VariableController::finalize()
515 515 {
516 516 impl->m_WorkingMutex.unlock();
517 517 }
518 518
519 519 void VariableController::waitForFinish()
520 520 {
521 521 QMutexLocker locker{&impl->m_WorkingMutex};
522 522 }
523 523
524 524 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
525 525 {
526 526 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
527 527 auto zoomType = AcquisitionZoomType::Unknown;
528 528 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
529 529 zoomType = AcquisitionZoomType::ZoomOut;
530 530 }
531 531 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
532 532 zoomType = AcquisitionZoomType::PanRight;
533 533 }
534 534 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
535 535 zoomType = AcquisitionZoomType::PanLeft;
536 536 }
537 537 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
538 538 zoomType = AcquisitionZoomType::ZoomIn;
539 539 }
540 540 else {
541 541 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
542 542 }
543 543 return zoomType;
544 544 }
545 545
546 546 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
547 547 const SqpRange &rangeRequested,
548 548 QUuid varRequestId)
549 549 {
550 550
551 551 // TODO: protect at
552 552 auto varRequest = VariableRequest{};
553 553 auto varId = m_VariableToIdentifierMap.at(var);
554 554
555 555 auto varStrategyRangesRequested
556 556 = m_VariableCacheStrategy->computeStrategyRanges(var->range(), rangeRequested);
557 557 auto notInCacheRangeList = var->provideNotInCacheRangeList(varStrategyRangesRequested.second);
558 558 auto inCacheRangeList = var->provideInCacheRangeList(varStrategyRangesRequested.second);
559 559
560 560 if (!notInCacheRangeList.empty()) {
561 561 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
562 562 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
563 563
564 564 // store VarRequest
565 565 storeVariableRequest(varId, varRequestId, varRequest);
566 566
567 567 auto varProvider = m_VariableToProviderMap.at(var);
568 568 if (varProvider != nullptr) {
569 569 auto varRequestIdCanceled = m_VariableAcquisitionWorker->pushVariableRequest(
570 570 varRequestId, varId, varStrategyRangesRequested.first,
571 571 varStrategyRangesRequested.second,
572 572 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
573 573 varProvider);
574 574
575 575 if (!varRequestIdCanceled.isNull()) {
576 qCDebug(LOG_VariableAcquisitionWorker()) << tr("varRequestIdCanceled: ")
576 qCDebug(LOG_VariableAcquisitionWorker()) << tr("vsarRequestIdCanceled: ")
577 577 << varRequestIdCanceled;
578 578 cancelVariableRequest(varRequestIdCanceled);
579 579 }
580 580 }
581 581 else {
582 582 qCCritical(LOG_VariableController())
583 583 << "Impossible to provide data with a null provider";
584 584 }
585 585
586 586 if (!inCacheRangeList.empty()) {
587 587 emit q->updateVarDisplaying(var, inCacheRangeList.first());
588 588 }
589 589 }
590 590 else {
591
592 591 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
593 592 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
594 593 // store VarRequest
595 594 storeVariableRequest(varId, varRequestId, varRequest);
596 595 acceptVariableRequest(varId,
597 596 var->dataSeries()->subDataSeries(varStrategyRangesRequested.second));
598 597 }
599 598 }
600 599
601 600 std::shared_ptr<Variable>
602 601 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
603 602 {
604 603 std::shared_ptr<Variable> var;
605 604 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
606 605
607 606 auto end = m_VariableToIdentifierMap.cend();
608 607 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
609 608 if (it != end) {
610 609 var = it->first;
611 610 }
612 611 else {
613 612 qCCritical(LOG_VariableController())
614 613 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
615 614 }
616 615
617 616 return var;
618 617 }
619 618
620 619 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
621 620 const QVector<AcquisitionDataPacket> acqDataPacketVector)
622 621 {
623 622 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
624 623 << acqDataPacketVector.size();
625 624 std::shared_ptr<IDataSeries> dataSeries;
626 625 if (!acqDataPacketVector.isEmpty()) {
627 626 dataSeries = acqDataPacketVector[0].m_DateSeries;
628 627 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
629 628 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
630 629 }
631 630 }
632 631 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
633 632 << acqDataPacketVector.size();
634 633 return dataSeries;
635 634 }
636 635
637 636 void VariableController::VariableControllerPrivate::registerProvider(
638 637 std::shared_ptr<IDataProvider> provider)
639 638 {
640 639 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
641 640 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
642 641 << provider->objectName();
643 642 m_ProviderSet.insert(provider);
644 643 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
645 644 &VariableAcquisitionWorker::onVariableDataAcquired);
646 645 connect(provider.get(), &IDataProvider::dataProvidedProgress,
647 646 m_VariableAcquisitionWorker.get(),
648 647 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
649 648 }
650 649 else {
651 650 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
652 651 }
653 652 }
654 653
655 654 void VariableController::VariableControllerPrivate::storeVariableRequest(
656 655 QUuid varId, QUuid varRequestId, const VariableRequest &varRequest)
657 656 {
658 657 // First request for the variable. we can create an entry for it
659 658 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
660 659 if (varIdToVarRequestIdQueueMapIt == m_VarIdToVarRequestIdQueueMap.cend()) {
661 660 auto varRequestIdQueue = std::deque<QUuid>{};
662 661 qCDebug(LOG_VariableController()) << tr("Store REQUEST in QUEUE");
663 662 varRequestIdQueue.push_back(varRequestId);
664 663 m_VarIdToVarRequestIdQueueMap.insert(std::make_pair(varId, std::move(varRequestIdQueue)));
665 664 }
666 665 else {
667 666 qCDebug(LOG_VariableController()) << tr("Store REQUEST in EXISTING QUEUE");
668 667 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
669 668 varRequestIdQueue.push_back(varRequestId);
670 669 }
671 670
672 671 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
673 672 if (varRequestIdToVarIdVarRequestMapIt == m_VarRequestIdToVarIdVarRequestMap.cend()) {
674 673 auto varIdToVarRequestMap = std::map<QUuid, VariableRequest>{};
675 674 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
676 675 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in MAP");
677 676 m_VarRequestIdToVarIdVarRequestMap.insert(
678 677 std::make_pair(varRequestId, std::move(varIdToVarRequestMap)));
679 678 }
680 679 else {
681 680 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
682 681 qCDebug(LOG_VariableController()) << tr("Store REQUESTID in EXISTING MAP");
683 682 varIdToVarRequestMap.insert(std::make_pair(varId, varRequest));
684 683 }
685 684 }
686 685
687 686 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
688 687 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
689 688 {
690 689 QUuid varRequestId;
691 690 auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.find(varId);
692 691 if (varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.cend()) {
693 692 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
694 693 varRequestId = varRequestIdQueue.front();
695 694 auto varRequestIdToVarIdVarRequestMapIt
696 695 = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
697 696 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
698 697 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
699 698 auto varIdToVarRequestMapIt = varIdToVarRequestMap.find(varId);
700 699 if (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) {
701 700 qCDebug(LOG_VariableController()) << tr("acceptVariableRequest");
702 701 auto &varRequest = varIdToVarRequestMapIt->second;
703 702 varRequest.m_DataSeries = dataSeries;
704 703 varRequest.m_CanUpdate = true;
705 704 }
706 705 else {
707 706 qCDebug(LOG_VariableController())
708 707 << tr("Impossible to acceptVariableRequest of a unknown variable id attached "
709 708 "to a variableRequestId")
710 709 << varRequestId << varId;
711 710 }
712 711 }
713 712 else {
714 713 qCCritical(LOG_VariableController())
715 714 << tr("Impossible to acceptVariableRequest of a unknown variableRequestId")
716 715 << varRequestId;
717 716 }
718 717
719 718 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in QUEUE ?")
720 719 << varRequestIdQueue.size();
721 720 varRequestIdQueue.pop_front();
722 721 qCDebug(LOG_VariableController()) << tr("2: erase REQUEST in QUEUE ?")
723 722 << varRequestIdQueue.size();
724 723 if (varRequestIdQueue.empty()) {
725 724 m_VarIdToVarRequestIdQueueMap.erase(varId);
726 725 }
727 726 }
728 727 else {
729 728 qCCritical(LOG_VariableController())
730 729 << tr("Impossible to acceptVariableRequest of a unknown variable id") << varId;
731 730 }
732 731
733 732 return varRequestId;
734 733 }
735 734
736 735 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
737 736 {
738 737
739 738 auto varRequestIdToVarIdVarRequestMapIt = m_VarRequestIdToVarIdVarRequestMap.find(varRequestId);
740 739 if (varRequestIdToVarIdVarRequestMapIt != m_VarRequestIdToVarIdVarRequestMap.cend()) {
741 740 bool processVariableUpdate = true;
742 741 auto &varIdToVarRequestMap = varRequestIdToVarIdVarRequestMapIt->second;
743 742 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
744 743 (varIdToVarRequestMapIt != varIdToVarRequestMap.cend()) && processVariableUpdate;
745 744 ++varIdToVarRequestMapIt) {
746 745 processVariableUpdate &= varIdToVarRequestMapIt->second.m_CanUpdate;
747 746 qCDebug(LOG_VariableController()) << tr("updateVariableRequest")
748 747 << processVariableUpdate;
749 748 }
750 749
751 750 if (processVariableUpdate) {
752 751 for (auto varIdToVarRequestMapIt = varIdToVarRequestMap.cbegin();
753 752 varIdToVarRequestMapIt != varIdToVarRequestMap.cend(); ++varIdToVarRequestMapIt) {
754 753 if (auto var = findVariable(varIdToVarRequestMapIt->first)) {
755 754 auto &varRequest = varIdToVarRequestMapIt->second;
756 755 var->setRange(varRequest.m_RangeRequested);
757 756 var->setCacheRange(varRequest.m_CacheRangeRequested);
758 757 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
759 758 << varRequest.m_RangeRequested;
760 759 qCDebug(LOG_VariableController()) << tr("2: onDataProvided")
761 760 << varRequest.m_CacheRangeRequested;
762 761 var->mergeDataSeries(varRequest.m_DataSeries);
763 762 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
764 763 << varRequest.m_DataSeries->range();
765 764 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
766 765
767 766 /// @todo MPL: confirm
768 767 // Variable update is notified only if there is no pending request for it
769 768 // if
770 769 // (m_VarIdToVarRequestIdQueueMap.count(varIdToVarRequestMapIt->first)
771 770 // == 0) {
772 771 emit var->updated();
773 772 // }
774 773 }
775 774 else {
776 775 qCCritical(LOG_VariableController())
777 776 << tr("Impossible to update data to a null variable");
778 777 }
779 778 }
780 779
781 780 // cleaning varRequestId
782 781 qCDebug(LOG_VariableController()) << tr("0: erase REQUEST in MAP ?")
783 782 << m_VarRequestIdToVarIdVarRequestMap.size();
784 783 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
785 784 qCDebug(LOG_VariableController()) << tr("1: erase REQUEST in MAP ?")
786 785 << m_VarRequestIdToVarIdVarRequestMap.size();
787 786 }
788 787 }
789 788 else {
790 789 qCCritical(LOG_VariableController())
791 790 << tr("Cannot updateVariableRequest for a unknow varRequestId") << varRequestId;
792 791 }
793 792 }
794 793
795 794 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
796 795 {
797 796 // cleaning varRequestId
798 797 m_VarRequestIdToVarIdVarRequestMap.erase(varRequestId);
799 798
800 799 for (auto varIdToVarRequestIdQueueMapIt = m_VarIdToVarRequestIdQueueMap.begin();
801 800 varIdToVarRequestIdQueueMapIt != m_VarIdToVarRequestIdQueueMap.end();) {
802 801 auto &varRequestIdQueue = varIdToVarRequestIdQueueMapIt->second;
803 802 varRequestIdQueue.erase(
804 803 std::remove(varRequestIdQueue.begin(), varRequestIdQueue.end(), varRequestId),
805 804 varRequestIdQueue.end());
806 805 if (varRequestIdQueue.empty()) {
807 806 varIdToVarRequestIdQueueMapIt
808 807 = m_VarIdToVarRequestIdQueueMap.erase(varIdToVarRequestIdQueueMapIt);
809 808 }
810 809 else {
811 810 ++varIdToVarRequestIdQueueMapIt;
812 811 }
813 812 }
814 813 }
@@ -1,294 +1,293
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableModel.h>
3 3
4 4 #include <Common/DateUtils.h>
5 5 #include <Common/StringUtils.h>
6 6
7 7 #include <Data/IDataSeries.h>
8 8
9 9 #include <QSize>
10 10 #include <unordered_map>
11 11
12 12 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
13 13
14 14 namespace {
15 15
16 16 // Column indexes
17 17 const auto NAME_COLUMN = 0;
18 18 const auto TSTART_COLUMN = 1;
19 19 const auto TEND_COLUMN = 2;
20 20 const auto NBPOINTS_COLUMN = 3;
21 21 const auto UNIT_COLUMN = 4;
22 22 const auto MISSION_COLUMN = 5;
23 23 const auto PLUGIN_COLUMN = 6;
24 24 const auto NB_COLUMNS = 7;
25 25
26 26 // Column properties
27 27 const auto DEFAULT_HEIGHT = 25;
28 28 const auto DEFAULT_WIDTH = 100;
29 29
30 30 struct ColumnProperties {
31 31 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
32 32 int height = DEFAULT_HEIGHT)
33 33 : m_Name{name}, m_Width{width}, m_Height{height}
34 34 {
35 35 }
36 36
37 37 QString m_Name;
38 38 int m_Width;
39 39 int m_Height;
40 40 };
41 41
42 42 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
43 43 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
44 44 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
45 45 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
46 46 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
47 47
48 48 /// Format for datetimes
49 49 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
50 50
51 51 QString uniqueName(const QString &defaultName,
52 52 const std::vector<std::shared_ptr<Variable> > &variables)
53 53 {
54 54 auto forbiddenNames = std::vector<QString>(variables.size());
55 55 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
56 56 [](const auto &variable) { return variable->name(); });
57 57 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
58 58 Q_ASSERT(!uniqueName.isEmpty());
59 59
60 60 return uniqueName;
61 61 }
62 62
63 63 } // namespace
64 64
65 65 struct VariableModel::VariableModelPrivate {
66 66 /// Variables created in SciQlop
67 67 std::vector<std::shared_ptr<Variable> > m_Variables;
68 68 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
69 69
70 70 /// Return the row index of the variable. -1 if it's not found
71 71 int indexOfVariable(Variable *variable) const noexcept;
72 72 };
73 73
74 74 VariableModel::VariableModel(QObject *parent)
75 75 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
76 76 {
77 77 }
78 78
79 79 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
80 80 {
81 81 auto insertIndex = rowCount();
82 82 beginInsertRows({}, insertIndex, insertIndex);
83 83
84 84 // Generates unique name for the variable
85 85 variable->setName(uniqueName(variable->name(), impl->m_Variables));
86 86
87 87 impl->m_Variables.push_back(variable);
88 88 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
89 89
90 90 endInsertRows();
91 91 }
92 92
93 93 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
94 94 {
95 95 auto end = impl->m_Variables.cend();
96 96 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
97 97 }
98 98
99 99 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
100 const SqpRange &dateTime,
101 100 const QVariantHash &metadata) noexcept
102 101 {
103 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
102 auto variable = std::make_shared<Variable>(name, metadata);
104 103 addVariable(variable);
105 104
106 105 return variable;
107 106 }
108 107
109 108 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
110 109 {
111 110 if (!variable) {
112 111 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
113 112 return;
114 113 }
115 114
116 115 // Finds variable in the model
117 116 auto begin = impl->m_Variables.cbegin();
118 117 auto end = impl->m_Variables.cend();
119 118 auto it = std::find(begin, end, variable);
120 119 if (it != end) {
121 120 auto removeIndex = std::distance(begin, it);
122 121
123 122 // Deletes variable
124 123 beginRemoveRows({}, removeIndex, removeIndex);
125 124 impl->m_Variables.erase(it);
126 125 endRemoveRows();
127 126 }
128 127 else {
129 128 qCritical(LOG_VariableModel())
130 129 << tr("Can't delete variable %1 from the model: the variable is not in the model")
131 130 .arg(variable->name());
132 131 }
133 132
134 133 // Removes variable from progress map
135 134 impl->m_VariableToProgress.erase(variable);
136 135 }
137 136
138 137
139 138 std::shared_ptr<Variable> VariableModel::variable(int index) const
140 139 {
141 140 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
142 141 }
143 142
144 143 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
145 144 {
146 145 return impl->m_Variables;
147 146 }
148 147
149 148 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
150 149 {
151 150 if (progress > 0.0) {
152 151 impl->m_VariableToProgress[variable] = progress;
153 152 }
154 153 else {
155 154 impl->m_VariableToProgress.erase(variable);
156 155 }
157 156 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
158 157
159 158 emit dataChanged(modelIndex, modelIndex);
160 159 }
161 160
162 161 int VariableModel::columnCount(const QModelIndex &parent) const
163 162 {
164 163 Q_UNUSED(parent);
165 164
166 165 return NB_COLUMNS;
167 166 }
168 167
169 168 int VariableModel::rowCount(const QModelIndex &parent) const
170 169 {
171 170 Q_UNUSED(parent);
172 171
173 172 return impl->m_Variables.size();
174 173 }
175 174
176 175 QVariant VariableModel::data(const QModelIndex &index, int role) const
177 176 {
178 177 if (!index.isValid()) {
179 178 return QVariant{};
180 179 }
181 180
182 181 if (index.row() < 0 || index.row() >= rowCount()) {
183 182 return QVariant{};
184 183 }
185 184
186 185 if (role == Qt::DisplayRole) {
187 186 if (auto variable = impl->m_Variables.at(index.row()).get()) {
188 187 switch (index.column()) {
189 188 case NAME_COLUMN:
190 189 return variable->name();
191 190 case TSTART_COLUMN: {
192 191 auto range = variable->realRange();
193 192 return range != INVALID_RANGE
194 193 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
195 194 : QVariant{};
196 195 }
197 196 case TEND_COLUMN: {
198 197 auto range = variable->realRange();
199 198 return range != INVALID_RANGE
200 199 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
201 200 : QVariant{};
202 201 }
203 202 case NBPOINTS_COLUMN:
204 203 return variable->nbPoints();
205 204 case UNIT_COLUMN:
206 205 return variable->metadata().value(QStringLiteral("units"));
207 206 case MISSION_COLUMN:
208 207 return variable->metadata().value(QStringLiteral("mission"));
209 208 case PLUGIN_COLUMN:
210 209 return variable->metadata().value(QStringLiteral("plugin"));
211 210 default:
212 211 // No action
213 212 break;
214 213 }
215 214
216 215 qWarning(LOG_VariableModel())
217 216 << tr("Can't get data (unknown column %1)").arg(index.column());
218 217 }
219 218 else {
220 219 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
221 220 }
222 221 }
223 222 else if (role == VariableRoles::ProgressRole) {
224 223 if (auto variable = impl->m_Variables.at(index.row())) {
225 224
226 225 auto it = impl->m_VariableToProgress.find(variable);
227 226 if (it != impl->m_VariableToProgress.cend()) {
228 227 return it->second;
229 228 }
230 229 }
231 230 }
232 231
233 232 return QVariant{};
234 233 }
235 234
236 235 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
237 236 {
238 237 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
239 238 return QVariant{};
240 239 }
241 240
242 241 if (orientation == Qt::Horizontal) {
243 242 auto propertiesIt = COLUMN_PROPERTIES.find(section);
244 243 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
245 244 // Role is either DisplayRole or SizeHintRole
246 245 return (role == Qt::DisplayRole)
247 246 ? QVariant{propertiesIt->m_Name}
248 247 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
249 248 }
250 249 else {
251 250 qWarning(LOG_VariableModel())
252 251 << tr("Can't get header data (unknown column %1)").arg(section);
253 252 }
254 253 }
255 254
256 255 return QVariant{};
257 256 }
258 257
259 258 void VariableModel::abortProgress(const QModelIndex &index)
260 259 {
261 260 if (auto variable = impl->m_Variables.at(index.row())) {
262 261 emit abortProgessRequested(variable);
263 262 }
264 263 }
265 264
266 265 void VariableModel::onVariableUpdated() noexcept
267 266 {
268 267 // Finds variable that has been updated in the model
269 268 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
270 269 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
271 270
272 271 if (updatedVariableIndex > -1) {
273 272 emit dataChanged(createIndex(updatedVariableIndex, 0),
274 273 createIndex(updatedVariableIndex, columnCount() - 1));
275 274 }
276 275 }
277 276 }
278 277
279 278 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
280 279 {
281 280 auto begin = std::cbegin(m_Variables);
282 281 auto end = std::cend(m_Variables);
283 282 auto it
284 283 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
285 284
286 285 if (it != end) {
287 286 // Gets the index of the variable in the model: we assume here that views have the same
288 287 // order as the model
289 288 return std::distance(begin, it);
290 289 }
291 290 else {
292 291 return -1;
293 292 }
294 293 }
@@ -1,174 +1,177
1 1 #include <Variable/Variable.h>
2 2
3 3 #include <QObject>
4 4 #include <QtTest>
5 5
6 6 #include <memory>
7 7
8 8 class TestVariable : public QObject {
9 9 Q_OBJECT
10 10
11 11 private slots:
12 12 void testNotInCacheRangeList();
13 13
14 14 void testInCacheRangeList();
15 15 };
16 16
17 17
18 18 void TestVariable::testNotInCacheRangeList()
19 19 {
20 20 auto varRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
21 21 auto varRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 40, 0}};
22 22
23 23 auto sqpR = SqpRange{DateUtils::secondsSinceEpoch(varRS), DateUtils::secondsSinceEpoch(varRE)};
24 24
25 25 auto varCRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}};
26 26 auto varCRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
27
27 28 auto sqpCR
28 29 = SqpRange{DateUtils::secondsSinceEpoch(varCRS), DateUtils::secondsSinceEpoch(varCRE)};
29 30
30 Variable var{"Var test", sqpR};
31 Variable var{"Var test"};
32 var.setRange(sqpR);
31 33 var.setCacheRange(sqpCR);
32 34
33 35 // 1: [ts,te] < varTS
34 36 auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
35 37 auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}};
36 38 auto sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
37 39
38 40 auto notInCach = var.provideNotInCacheRangeList(sqp);
39 41
40 42 QCOMPARE(notInCach.size(), 1);
41 43
42 44 auto notInCachRange = notInCach.first();
43 45
44 46 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
45 47 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
46 48
47 49 // 2: ts < varTS < te < varTE
48 50 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
49 51 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
50 52 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
51 53 notInCach = var.provideNotInCacheRangeList(sqp);
52 54 QCOMPARE(notInCach.size(), 1);
53 55 notInCachRange = notInCach.first();
54 56 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
55 57 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRS));
56 58
57 59 // 3: varTS < ts < te < varTE
58 60 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
59 61 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
60 62 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
61 63 notInCach = var.provideNotInCacheRangeList(sqp);
62 64 QCOMPARE(notInCach.size(), 0);
63 65
64 66
65 67 // 4: varTS < ts < varTE < te
66 68 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
67 69 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
68 70 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
69 71 notInCach = var.provideNotInCacheRangeList(sqp);
70 72 QCOMPARE(notInCach.size(), 1);
71 73 notInCachRange = notInCach.first();
72 74 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRE));
73 75 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
74 76
75 77 // 5: varTS < varTE < ts < te
76 78 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 20, 0}};
77 79 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
78 80 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
79 81 notInCach = var.provideNotInCacheRangeList(sqp);
80 82 QCOMPARE(notInCach.size(), 1);
81 83 notInCachRange = notInCach.first();
82 84 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
83 85 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
84 86
85 87 // 6: ts <varTS < varTE < te
86 88 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}};
87 89 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
88 90 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
89 91 notInCach = var.provideNotInCacheRangeList(sqp);
90 92 QCOMPARE(notInCach.size(), 2);
91 93 notInCachRange = notInCach.first();
92 94 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
93 95 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRS));
94 96 notInCachRange = notInCach[1];
95 97 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRE));
96 98 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
97 99 }
98 100
99 101
100 102 void TestVariable::testInCacheRangeList()
101 103 {
102 104 auto varRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
103 105 auto varRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 40, 0}};
104 106
105 107 auto sqpR = SqpRange{DateUtils::secondsSinceEpoch(varRS), DateUtils::secondsSinceEpoch(varRE)};
106 108
107 109 auto varCRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}};
108 110 auto varCRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
109 111 auto sqpCR
110 112 = SqpRange{DateUtils::secondsSinceEpoch(varCRS), DateUtils::secondsSinceEpoch(varCRE)};
111 113
112 Variable var{"Var test", sqpR};
114 Variable var{"Var test"};
115 var.setRange(sqpR);
113 116 var.setCacheRange(sqpCR);
114 117
115 118 // 1: [ts,te] < varTS
116 119 auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
117 120 auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}};
118 121 auto sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
119 122
120 123 auto notInCach = var.provideInCacheRangeList(sqp);
121 124
122 125 QCOMPARE(notInCach.size(), 0);
123 126
124 127 // 2: ts < varTS < te < varTE
125 128 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
126 129 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
127 130 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
128 131 notInCach = var.provideInCacheRangeList(sqp);
129 132 QCOMPARE(notInCach.size(), 1);
130 133 auto notInCachRange = notInCach.first();
131 134 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRS));
132 135 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
133 136
134 137 // 3: varTS < ts < te < varTE
135 138 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
136 139 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
137 140 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
138 141 notInCach = var.provideInCacheRangeList(sqp);
139 142 QCOMPARE(notInCach.size(), 1);
140 143 notInCachRange = notInCach.first();
141 144 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
142 145 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te));
143 146
144 147 // 4: varTS < ts < varTE < te
145 148 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}};
146 149 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
147 150 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
148 151 notInCach = var.provideInCacheRangeList(sqp);
149 152 QCOMPARE(notInCach.size(), 1);
150 153 notInCachRange = notInCach.first();
151 154 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts));
152 155 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRE));
153 156
154 157 // 5: varTS < varTE < ts < te
155 158 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 20, 0}};
156 159 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
157 160 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
158 161 notInCach = var.provideInCacheRangeList(sqp);
159 162 QCOMPARE(notInCach.size(), 0);
160 163
161 164 // 6: ts <varTS < varTE < te
162 165 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}};
163 166 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
164 167 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
165 168 notInCach = var.provideInCacheRangeList(sqp);
166 169 QCOMPARE(notInCach.size(), 1);
167 170 notInCachRange = notInCach.first();
168 171 QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRS));
169 172 QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRE));
170 173 }
171 174
172 175
173 176 QTEST_MAIN(TestVariable)
174 177 #include "TestVariable.moc"
@@ -1,331 +1,333
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableCacheController.h>
3 3
4 4 #include <QObject>
5 5 #include <QtTest>
6 6
7 7 #include <memory>
8 8
9 9 class TestVariableCacheController : public QObject {
10 10 Q_OBJECT
11 11
12 12 private slots:
13 13 void testProvideNotInCacheDateTimeList();
14 14
15 15 void testAddDateTime();
16 16 };
17 17
18 18
19 19 void TestVariableCacheController::testProvideNotInCacheDateTimeList()
20 20 {
21 21 VariableCacheController variableCacheController{};
22 22
23 23 auto ts0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}};
24 24 auto te0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
25 25 auto sqp0 = SqpRange{DateUtils::secondsSinceEpoch(ts0), DateUtils::secondsSinceEpoch(te0)};
26 26
27 27 auto ts1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}};
28 28 auto te1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 8, 0, 0}};
29 29 auto sqp1 = SqpRange{DateUtils::secondsSinceEpoch(ts1), DateUtils::secondsSinceEpoch(te1)};
30 30
31 31 auto ts2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 18, 0, 0}};
32 32 auto te2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 20, 0, 0}};
33 33 auto sqp2 = SqpRange{DateUtils::secondsSinceEpoch(ts2), DateUtils::secondsSinceEpoch(te2)};
34 34
35 auto var0 = std::make_shared<Variable>("", sqp0);
35 auto var0 = std::make_shared<Variable>("");
36 var0->setRange(sqp0);
36 37
37 38 variableCacheController.addDateTime(var0, sqp0);
38 39 variableCacheController.addDateTime(var0, sqp1);
39 40 variableCacheController.addDateTime(var0, sqp2);
40 41
41 42 // first case [ts,te] < ts0
42 43 auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
43 44 auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}};
44 45 auto sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
45 46
46 47
47 48 auto notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
48 49
49 50 QCOMPARE(notInCach.size(), 1);
50 51 auto notInCacheSqp = notInCach.first();
51 52 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts));
52 53 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te));
53 54
54 55
55 56 // second case ts < ts0 && ts0 < te <= te0
56 57 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
57 58 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
58 59 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
59 60
60 61
61 62 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
62 63
63 64 QCOMPARE(notInCach.size(), 1);
64 65 notInCacheSqp = notInCach.first();
65 66 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts));
66 67 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts0));
67 68
68 69 // 3th case ts < ts0 && te0 < te <= ts1
69 70 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
70 71 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
71 72 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
72 73
73 74
74 75 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
75 76
76 77 QCOMPARE(notInCach.size(), 2);
77 78 notInCacheSqp = notInCach.first();
78 79 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts));
79 80 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts0));
80 81
81 82 notInCacheSqp = notInCach.at(1);
82 83 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0));
83 84 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te));
84 85
85 86 // 4th case ts < ts0 && ts1 < te <= te1
86 87 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
87 88 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 7, 0, 0}};
88 89 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
89 90
90 91
91 92 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
92 93
93 94 QCOMPARE(notInCach.size(), 2);
94 95 notInCacheSqp = notInCach.first();
95 96 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts));
96 97 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts0));
97 98
98 99 notInCacheSqp = notInCach.at(1);
99 100 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0));
100 101 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts1));
101 102
102 103 // 5th case ts < ts0 && te3 < te
103 104 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}};
104 105 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 22, 0, 0}};
105 106 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
106 107
107 108
108 109 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
109 110
110 111 QCOMPARE(notInCach.size(), 4);
111 112 notInCacheSqp = notInCach.first();
112 113 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts));
113 114 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts0));
114 115
115 116 notInCacheSqp = notInCach.at(1);
116 117 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0));
117 118 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts1));
118 119
119 120 notInCacheSqp = notInCach.at(2);
120 121 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te1));
121 122 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts2));
122 123
123 124 notInCacheSqp = notInCach.at(3);
124 125 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te2));
125 126 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te));
126 127
127 128
128 129 // 6th case ts2 < ts
129 130 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 45, 0, 0}};
130 131 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 47, 0, 0}};
131 132 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
132 133
133 134
134 135 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
135 136
136 137 QCOMPARE(notInCach.size(), 1);
137 138 notInCacheSqp = notInCach.first();
138 139 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts));
139 140 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te));
140 141
141 142 // 7th case ts = te0 && te < ts1
142 143 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
143 144 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
144 145 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
145 146
146 147
147 148 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
148 149
149 150 QCOMPARE(notInCach.size(), 1);
150 151 notInCacheSqp = notInCach.first();
151 152 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0));
152 153 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te));
153 154
154 155 // 8th case ts0 < ts < te0 && te < ts1
155 156 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
156 157 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
157 158 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
158 159
159 160
160 161 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
161 162
162 163 QCOMPARE(notInCach.size(), 1);
163 164 notInCacheSqp = notInCach.first();
164 165 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0));
165 166 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te));
166 167
167 168 // 9th case ts0 < ts < te0 && ts1 < te < te1
168 169 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}};
169 170 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 7, 0, 0}};
170 171 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
171 172
172 173
173 174 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
174 175
175 176 QCOMPARE(notInCach.size(), 1);
176 177 notInCacheSqp = notInCach.first();
177 178 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0));
178 179 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts1));
179 180
180 181 // 10th case te1 < ts < te < ts2
181 182 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 9, 0, 0}};
182 183 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 10, 0, 0}};
183 184 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
184 185
185 186
186 187 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
187 188
188 189 QCOMPARE(notInCach.size(), 1);
189 190 notInCacheSqp = notInCach.first();
190 191 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts));
191 192 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te));
192 193
193 194 // 11th case te0 < ts < ts1 && te3 < te
194 195 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
195 196 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 47, 0, 0}};
196 197 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
197 198
198 199
199 200 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
200 201
201 202 QCOMPARE(notInCach.size(), 3);
202 203 notInCacheSqp = notInCach.first();
203 204 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts));
204 205 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts1));
205 206
206 207 notInCacheSqp = notInCach.at(1);
207 208 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te1));
208 209 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts2));
209 210
210 211 notInCacheSqp = notInCach.at(2);
211 212 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te2));
212 213 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te));
213 214
214 215 // 12th case te0 < ts < ts1 && te3 < te
215 216 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}};
216 217 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 10, 0, 0}};
217 218 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
218 219
219 220 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
220 221
221 222 QCOMPARE(notInCach.size(), 2);
222 223 notInCacheSqp = notInCach.first();
223 224 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts));
224 225 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts1));
225 226
226 227 notInCacheSqp = notInCach.at(1);
227 228 QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te1));
228 229 QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te));
229 230
230 231
231 232 // 12th case ts0 < ts < te0
232 233 ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 10, 0}};
233 234 te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 50, 0}};
234 235 sqp = SqpRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)};
235 236
236 237 notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp);
237 238 QCOMPARE(notInCach.size(), 0);
238 239 }
239 240
240 241
241 242 void TestVariableCacheController::testAddDateTime()
242 243 {
243 244 VariableCacheController variableCacheController{};
244 245
245 246 auto ts0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}};
246 247 auto te0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
247 248 auto sqp0 = SqpRange{DateUtils::secondsSinceEpoch(ts0), DateUtils::secondsSinceEpoch(te0)};
248 249
249 250 auto ts1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}};
250 251 auto te1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 8, 0, 0}};
251 252 auto sqp1 = SqpRange{DateUtils::secondsSinceEpoch(ts1), DateUtils::secondsSinceEpoch(te1)};
252 253
253 254 auto ts2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 18, 0, 0}};
254 255 auto te2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 20, 0, 0}};
255 256 auto sqp2 = SqpRange{DateUtils::secondsSinceEpoch(ts2), DateUtils::secondsSinceEpoch(te2)};
256 257
257 258 auto ts01 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
258 259 auto te01 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}};
259 260 auto sqp01 = SqpRange{DateUtils::secondsSinceEpoch(ts01), DateUtils::secondsSinceEpoch(te01)};
260 261
261 262 auto ts3 = QDateTime{QDate{2017, 01, 01}, QTime{2, 14, 0, 0}};
262 263 auto te3 = QDateTime{QDate{2017, 01, 01}, QTime{2, 16, 0, 0}};
263 264 auto sqp3 = SqpRange{DateUtils::secondsSinceEpoch(ts3), DateUtils::secondsSinceEpoch(te3)};
264 265
265 266 auto ts03 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}};
266 267 auto te03 = QDateTime{QDate{2017, 01, 01}, QTime{2, 22, 0, 0}};
267 268 auto sqp03 = SqpRange{DateUtils::secondsSinceEpoch(ts03), DateUtils::secondsSinceEpoch(te03)};
268 269
269 270
270 auto var0 = std::make_shared<Variable>("", sqp0);
271 auto var0 = std::make_shared<Variable>("");
272 var0->setRange(sqp0);
271 273
272 274
273 275 // First case: add the first interval to the variable :sqp0
274 276 variableCacheController.addDateTime(var0, sqp0);
275 277 auto dateCacheList = variableCacheController.dateCacheList(var0);
276 278 QCOMPARE(dateCacheList.count(), 1);
277 279 auto dateCache = dateCacheList.at(0);
278 280 QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts0));
279 281 QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te0));
280 282
281 283 // 2nd case: add a second interval : sqp1 > sqp0
282 284 variableCacheController.addDateTime(var0, sqp1);
283 285 dateCacheList = variableCacheController.dateCacheList(var0);
284 286 QCOMPARE(dateCacheList.count(), 2);
285 287 dateCache = dateCacheList.at(0);
286 288 QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts0));
287 289 QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te0));
288 290
289 291 dateCache = dateCacheList.at(1);
290 292 QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts1));
291 293 QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te1));
292 294
293 295 // 3th case: merge sqp0 & sqp1 with sqp01
294 296 variableCacheController.addDateTime(var0, sqp01);
295 297 dateCacheList = variableCacheController.dateCacheList(var0);
296 298 QCOMPARE(dateCacheList.count(), 1);
297 299 dateCache = dateCacheList.at(0);
298 300 QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts0));
299 301 QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te1));
300 302
301 303
302 304 // 4th case: add a second interval : sqp1 > sqp0
303 305 variableCacheController.addDateTime(var0, sqp2);
304 306 variableCacheController.addDateTime(var0, sqp3);
305 307 dateCacheList = variableCacheController.dateCacheList(var0);
306 308 QCOMPARE(dateCacheList.count(), 3);
307 309 dateCache = dateCacheList.at(0);
308 310 QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts0));
309 311 QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te1));
310 312
311 313 dateCache = dateCacheList.at(1);
312 314 QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts3));
313 315 QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te3));
314 316
315 317 dateCache = dateCacheList.at(2);
316 318 QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts2));
317 319 QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te2));
318 320
319 321
320 322 // 5th case: merge all interval
321 323 variableCacheController.addDateTime(var0, sqp03);
322 324 dateCacheList = variableCacheController.dateCacheList(var0);
323 325 QCOMPARE(dateCacheList.count(), 1);
324 326 dateCache = dateCacheList.at(0);
325 327 QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts0));
326 328 QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te03));
327 329 }
328 330
329 331
330 332 QTEST_MAIN(TestVariableCacheController)
331 333 #include "TestVariableCacheController.moc"
@@ -1,267 +1,265
1 1 #include "AmdaProvider.h"
2 2 #include "AmdaDefs.h"
3 3 #include "AmdaResultParser.h"
4 4
5 5 #include <Common/DateUtils.h>
6 6 #include <Data/DataProviderParameters.h>
7 7 #include <Network/NetworkController.h>
8 8 #include <SqpApplication.h>
9 9 #include <Variable/Variable.h>
10 10
11 11 #include <QNetworkAccessManager>
12 12 #include <QNetworkReply>
13 13 #include <QTemporaryFile>
14 14 #include <QThread>
15 15
16 16 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
17 17
18 18 namespace {
19 19
20 20 /// URL format for a request on AMDA server. The parameters are as follows:
21 21 /// - %1: start date
22 22 /// - %2: end date
23 23 /// - %3: parameter id
24 24 const auto AMDA_URL_FORMAT = QStringLiteral(
25 25 "http://amda.irap.omp.eu/php/rest/"
26 26 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&outputFormat=ASCII&"
27 27 "timeFormat=ISO8601&gzip=0");
28 28
29 29 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
30 30 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
31 31
32 32 /// Formats a time to a date that can be passed in URL
33 33 QString dateFormat(double sqpRange) noexcept
34 34 {
35 35 auto dateTime = DateUtils::dateTime(sqpRange);
36 36 return dateTime.toString(AMDA_TIME_FORMAT);
37 37 }
38 38
39 39 AmdaResultParser::ValueType valueType(const QString &valueType)
40 40 {
41 41 if (valueType == QStringLiteral("scalar")) {
42 42 return AmdaResultParser::ValueType::SCALAR;
43 43 }
44 44 else if (valueType == QStringLiteral("vector")) {
45 45 return AmdaResultParser::ValueType::VECTOR;
46 46 }
47 47 else {
48 48 return AmdaResultParser::ValueType::UNKNOWN;
49 49 }
50 50 }
51 51
52 52 } // namespace
53 53
54 54 AmdaProvider::AmdaProvider()
55 55 {
56 56 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
57 57 if (auto app = sqpApp) {
58 58 auto &networkController = app->networkController();
59 59 connect(this, SIGNAL(requestConstructed(std::shared_ptr<QNetworkRequest>, QUuid,
60 60 std::function<void(QNetworkReply *, QUuid)>)),
61 61 &networkController,
62 62 SLOT(onProcessRequested(std::shared_ptr<QNetworkRequest>, QUuid,
63 63 std::function<void(QNetworkReply *, QUuid)>)));
64 64
65 65
66 66 connect(&sqpApp->networkController(),
67 67 SIGNAL(replyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)),
68 68 this,
69 69 SLOT(onReplyDownloadProgress(QUuid, std::shared_ptr<QNetworkRequest>, double)));
70 70 }
71 71 }
72 72
73 73 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
74 74 {
75 75 // No copy is made in the clone
76 76 return std::make_shared<AmdaProvider>();
77 77 }
78 78
79 79 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
80 80 {
81 81 // NOTE: Try to use multithread if possible
82 82 const auto times = parameters.m_Times;
83 83 const auto data = parameters.m_Data;
84 84 for (const auto &dateTime : qAsConst(times)) {
85 85 this->retrieveData(acqIdentifier, dateTime, data);
86 86
87 87
88 88 // TORM when AMDA will support quick asynchrone request
89 89 QThread::msleep(1000);
90 90 }
91 91 }
92 92
93 93 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
94 94 {
95 95 if (auto app = sqpApp) {
96 96 auto &networkController = app->networkController();
97 97 networkController.onReplyCanceled(acqIdentifier);
98 98 }
99 99 }
100 100
101 101 void AmdaProvider::onReplyDownloadProgress(QUuid acqIdentifier,
102 102 std::shared_ptr<QNetworkRequest> networkRequest,
103 103 double progress)
104 104 {
105 105 qCDebug(LOG_AmdaProvider()) << tr("onReplyDownloadProgress") << acqIdentifier
106 106 << networkRequest.get() << progress;
107 107 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
108 108 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
109 109
110 qCDebug(LOG_AmdaProvider()) << tr("1 onReplyDownloadProgress found") << progress;
111 110 auto requestPtr = networkRequest;
112 111 auto findRequest = [requestPtr](const auto &entry) { return requestPtr == entry.first; };
113 112
114 113 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
115 114 auto requestProgressMapEnd = requestProgressMap.end();
116 115 auto requestProgressMapIt
117 116 = std::find_if(requestProgressMap.begin(), requestProgressMapEnd, findRequest);
118 117
119 118 if (requestProgressMapIt != requestProgressMapEnd) {
120 119 requestProgressMapIt->second = progress;
121 120 }
122 121 else {
123 122 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve Request in progress")
124 123 << acqIdentifier << networkRequest.get() << progress;
125 124 }
126 125 }
127 126
128 127 acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
129 128 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
130 129 double finalProgress = 0.0;
131 130
132 131 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
133 132 auto fraq = requestProgressMap.size();
134 133
135 134 for (auto requestProgress : requestProgressMap) {
136 135 finalProgress += requestProgress.second;
137 136 qCDebug(LOG_AmdaProvider()) << tr("current final progress without freq:")
138 137 << finalProgress << requestProgress.second;
139 138 }
140 139
141 140 if (fraq > 0) {
142 141 finalProgress = finalProgress / fraq;
143 142 }
144 143
145 144 qCDebug(LOG_AmdaProvider()) << tr("2 onReplyDownloadProgress final progress") << fraq
146 145 << finalProgress;
147 146 emit dataProvidedProgress(acqIdentifier, finalProgress);
148 147 }
149 148 else {
150 149 emit dataProvidedProgress(acqIdentifier, 0.0);
151 150 }
152 151 }
153 152
154 153 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
155 154 {
156 155 // Retrieves product ID from data: if the value is invalid, no request is made
157 156 auto productId = data.value(AMDA_XML_ID_KEY).toString();
158 157 if (productId.isNull()) {
159 158 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
160 159 return;
161 160 }
162 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
163 161
164 162 // Retrieves the data type that determines whether the expected format for the result file is
165 163 // scalar, vector...
166 164 auto productValueType = valueType(data.value(AMDA_DATA_TYPE_KEY).toString());
167 165
168 166 // /////////// //
169 167 // Creates URL //
170 168 // /////////// //
171 169
172 170 auto startDate = dateFormat(dateTime.m_TStart);
173 171 auto endDate = dateFormat(dateTime.m_TEnd);
174 172
175 173 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
176 174 qCDebug(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
177 175 auto tempFile = std::make_shared<QTemporaryFile>();
178 176
179 177 // LAMBDA
180 178 auto httpDownloadFinished = [this, dateTime, tempFile,
181 179 productValueType](QNetworkReply *reply, QUuid dataId) noexcept {
182 180
183 181 // Don't do anything if the reply was abort
184 182 if (reply->error() != QNetworkReply::OperationCanceledError) {
185 183
186 184 if (tempFile) {
187 185 auto replyReadAll = reply->readAll();
188 186 if (!replyReadAll.isEmpty()) {
189 187 tempFile->write(replyReadAll);
190 188 }
191 189 tempFile->close();
192 190
193 191 // Parse results file
194 192 if (auto dataSeries
195 193 = AmdaResultParser::readTxt(tempFile->fileName(), productValueType)) {
196 194 emit dataProvided(dataId, dataSeries, dateTime);
197 195 }
198 196 else {
199 197 /// @todo ALX : debug
200 198 }
201 199 }
202 200 m_AcqIdToRequestProgressMap.erase(dataId);
203 201 }
204 202
205 203 };
206 204 auto httpFinishedLambda
207 205 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
208 206
209 207 // Don't do anything if the reply was abort
210 208 if (reply->error() != QNetworkReply::OperationCanceledError) {
211 209 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
212 210
213 qCInfo(LOG_AmdaProvider())
211 qCDebug(LOG_AmdaProvider())
214 212 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
215 213 // Executes request for downloading file //
216 214
217 215 // Creates destination file
218 216 if (tempFile->open()) {
219 217 // Executes request and store the request for progression
220 218 auto request = std::make_shared<QNetworkRequest>(downloadFileUrl);
221 219 updateRequestProgress(dataId, request, 0.0);
222 220 emit requestConstructed(request, dataId, httpDownloadFinished);
223 221 }
224 222 }
225 223 else {
226 224 m_AcqIdToRequestProgressMap.erase(dataId);
227 225 }
228 226 };
229 227
230 228 // //////////////// //
231 229 // Executes request //
232 230 // //////////////// //
233 231
234 232 auto request = std::make_shared<QNetworkRequest>(url);
235 233 qCDebug(LOG_AmdaProvider()) << tr("First Request creation") << request.get();
236 234 updateRequestProgress(token, request, 0.0);
237 235
238 236 emit requestConstructed(request, token, httpFinishedLambda);
239 237 }
240 238
241 239 void AmdaProvider::updateRequestProgress(QUuid acqIdentifier,
242 240 std::shared_ptr<QNetworkRequest> request, double progress)
243 241 {
244 242 auto acqIdToRequestProgressMapIt = m_AcqIdToRequestProgressMap.find(acqIdentifier);
245 243 if (acqIdToRequestProgressMapIt != m_AcqIdToRequestProgressMap.end()) {
246 244 auto &requestProgressMap = acqIdToRequestProgressMapIt->second;
247 245 auto requestProgressMapIt = requestProgressMap.find(request);
248 246 if (requestProgressMapIt != requestProgressMap.end()) {
249 247 requestProgressMapIt->second = progress;
250 248 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new progress for request")
251 249 << acqIdentifier << request.get() << progress;
252 250 }
253 251 else {
254 252 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new request") << acqIdentifier
255 253 << request.get() << progress;
256 254 acqIdToRequestProgressMapIt->second.insert(std::make_pair(request, progress));
257 255 }
258 256 }
259 257 else {
260 258 qCDebug(LOG_AmdaProvider()) << tr("updateRequestProgress new acqIdentifier")
261 259 << acqIdentifier << request.get() << progress;
262 260 auto requestProgressMap = std::map<std::shared_ptr<QNetworkRequest>, double>{};
263 261 requestProgressMap.insert(std::make_pair(request, progress));
264 262 m_AcqIdToRequestProgressMap.insert(
265 263 std::make_pair(acqIdentifier, std::move(requestProgressMap)));
266 264 }
267 265 }
@@ -1,197 +1,195
1 1 #include "AmdaProvider.h"
2 2 #include "AmdaResultParser.h"
3 3
4 4 #include "SqpApplication.h"
5 5 #include <Data/DataSeries.h>
6 6 #include <Data/IDataSeries.h>
7 7 #include <Data/ScalarSeries.h>
8 8 #include <Time/TimeController.h>
9 9 #include <Variable/Variable.h>
10 10 #include <Variable/VariableController.h>
11 11
12 12 #include <QObject>
13 13 #include <QtTest>
14 14
15 15 #include <memory>
16 16
17 17 // TEST with REF:
18 18 // AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00
19 19 // imf(0) - Type : Local Parameter @ CDPP/AMDA -
20 20 // Name : bx_gse - Units : nT - Size : 1 -
21 21 // Frame : GSE - Mission : ACE -
22 22 // Instrument : MFI - Dataset : mfi_final-prelim
23 23 // REFERENCE DOWNLOAD FILE =
24 24 // http://amda.irap.omp.eu/php/rest/getParameter.php?startTime=2012-01-01T12:00:00&stopTime=2012-01-03T12:00:00&parameterID=imf(0)&outputFormat=ASCII&timeFormat=ISO8601&gzip=0
25 25
26 26 namespace {
27 27
28 28 /// Path for the tests
29 29 const auto TESTS_RESOURCES_PATH
30 30 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaAcquisition"}.absoluteFilePath();
31 31
32 32 const auto TESTS_AMDA_REF_FILE = QString{"AmdaData-2012-01-01-12-00-00_2012-01-03-12-00-00.txt"};
33 33
34 34 template <typename T>
35 35 bool compareDataSeries(std::shared_ptr<IDataSeries> candidate, SqpRange candidateCacheRange,
36 36 std::shared_ptr<IDataSeries> reference)
37 37 {
38 38 auto compareLambda = [](const auto &it1, const auto &it2) {
39 39 return (it1.x() == it2.x()) && (it1.value() == it2.value());
40 40 };
41 41
42 42 auto candidateDS = std::dynamic_pointer_cast<T>(candidate);
43 43 auto referenceDS = std::dynamic_pointer_cast<T>(reference);
44 44
45 45 if (candidateDS && referenceDS) {
46 46
47 47 auto itRefs
48 48 = referenceDS->xAxisRange(candidateCacheRange.m_TStart, candidateCacheRange.m_TEnd);
49 49 qDebug() << " DISTANCE" << std::distance(candidateDS->cbegin(), candidateDS->cend())
50 50 << std::distance(itRefs.first, itRefs.second);
51 51
52 52 // auto xcValue = candidateDS->valuesData()->data();
53 53 // auto dist = std::distance(itRefs.first, itRefs.second);
54 54 // auto it = itRefs.first;
55 55 // for (auto i = 0; i < dist - 1; ++i) {
56 56 // ++it;
57 57 // qInfo() << "END:" << it->value();
58 58 // }
59 59 // qDebug() << "END:" << it->value() << xcValue.last();
60 60
61 61 return std::equal(candidateDS->cbegin(), candidateDS->cend(), itRefs.first, itRefs.second,
62 62 compareLambda);
63 63 }
64 64 else {
65 65 return false;
66 66 }
67 67 }
68 68 }
69 69
70 70 class TestAmdaAcquisition : public QObject {
71 71 Q_OBJECT
72 72
73 73 private slots:
74 74 void testAcquisition();
75 75 };
76 76
77 77 void TestAmdaAcquisition::testAcquisition()
78 78 {
79 79 // READ the ref file:
80 80 auto filePath = QFileInfo{TESTS_RESOURCES_PATH, TESTS_AMDA_REF_FILE}.absoluteFilePath();
81 81 auto results = AmdaResultParser::readTxt(filePath, AmdaResultParser::ValueType::SCALAR);
82 82
83 83 auto provider = std::make_shared<AmdaProvider>();
84 84 auto timeController = std::make_unique<TimeController>();
85 85
86 86 auto varRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 3, 0, 0}};
87 87 auto varRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 0, 0}};
88 88
89 89 auto sqpR = SqpRange{DateUtils::secondsSinceEpoch(varRS), DateUtils::secondsSinceEpoch(varRE)};
90 90
91 91 timeController->onTimeToUpdate(sqpR);
92 92
93 93 QVariantHash metaData;
94 94 metaData.insert("dataType", "scalar");
95 95 metaData.insert("xml:id", "imf(0)");
96 96
97 97 VariableController vc;
98 98 vc.setTimeController(timeController.get());
99 99
100 100 auto var = vc.createVariable("bx_gse", metaData, provider);
101 101
102 102 // 1 : Variable creation
103 QCOMPARE(var->range().m_TStart, sqpR.m_TStart);
104 QCOMPARE(var->range().m_TEnd, sqpR.m_TEnd);
105 103
106 104 qDebug() << " 1: TIMECONTROLLER" << timeController->dateTime();
107 105 qDebug() << " 1: RANGE " << var->range();
108 106 qDebug() << " 1: CACHERANGE" << var->cacheRange();
109 107
110 108 // wait for 10 sec before asking next request toi permit asynchrone process to finish.
111 109 auto timeToWaitMs = 10000;
112 110
113 111 QEventLoop loop;
114 112 QTimer::singleShot(timeToWaitMs, &loop, &QEventLoop::quit);
115 113 loop.exec();
116 114
117 115 // Tests on acquisition operation
118 116
119 117 int count = 1;
120 118
121 119 auto requestDataLoading = [&vc, var, timeToWaitMs, results, &count](auto tStart, auto tEnd) {
122 120 ++count;
123 121
124 122 auto nextSqpR
125 123 = SqpRange{DateUtils::secondsSinceEpoch(tStart), DateUtils::secondsSinceEpoch(tEnd)};
126 124 vc.onRequestDataLoading(QVector<std::shared_ptr<Variable> >{} << var, nextSqpR,
127 125 var->range(), true);
128 126
129 127 QEventLoop loop;
130 128 QTimer::singleShot(timeToWaitMs, &loop, &QEventLoop::quit);
131 129 loop.exec();
132 130
133 131 qInfo() << count << "RANGE " << var->range();
134 132 qInfo() << count << "CACHERANGE" << var->cacheRange();
135 133
136 134 QCOMPARE(var->range().m_TStart, nextSqpR.m_TStart);
137 135 QCOMPARE(var->range().m_TEnd, nextSqpR.m_TEnd);
138 136
139 137 // Verify dataserie
140 138 QVERIFY(compareDataSeries<ScalarSeries>(var->dataSeries(), var->cacheRange(), results));
141 139
142 140 };
143 141
144 142 // 2 : pan (jump) left for one hour
145 143 auto nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 1, 0, 0}};
146 144 auto nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 2, 0, 0}};
147 145 requestDataLoading(nextVarRS, nextVarRE);
148 146
149 147
150 148 // 3 : pan (jump) right for one hour
151 149 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 0, 0}};
152 150 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 0, 0}};
153 151 requestDataLoading(nextVarRS, nextVarRE);
154 152
155 153 // 4 : pan (overlay) right for 30 min
156 154 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 30, 0}};
157 155 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 30, 0}};
158 156 // requestDataLoading(nextVarRS, nextVarRE);
159 157
160 158 // 5 : pan (overlay) left for 30 min
161 159 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 0, 0}};
162 160 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 0, 0}};
163 161 // requestDataLoading(nextVarRS, nextVarRE);
164 162
165 163 // 6 : pan (overlay) left for 30 min - BIS
166 164 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 30, 0}};
167 165 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 30, 0}};
168 166 // requestDataLoading(nextVarRS, nextVarRE);
169 167
170 168 // 7 : Zoom in Inside 20 min range
171 169 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 50, 0}};
172 170 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 5, 10, 0}};
173 171 // requestDataLoading(nextVarRS, nextVarRE);
174 172
175 173 // 8 : Zoom out Inside 2 hours range
176 174 nextVarRS = QDateTime{QDate{2012, 01, 02}, QTime{2, 4, 0, 0}};
177 175 nextVarRE = QDateTime{QDate{2012, 01, 02}, QTime{2, 6, 0, 0}};
178 176 // requestDataLoading(nextVarRS, nextVarRE);
179 177
180 178
181 179 // Close the app after 10 sec
182 180 QTimer::singleShot(timeToWaitMs, &loop, &QEventLoop::quit);
183 181 loop.exec();
184 182 }
185 183
186 184 int main(int argc, char *argv[])
187 185 {
188 186 SqpApplication app(argc, argv);
189 187 app.setAttribute(Qt::AA_Use96Dpi, true);
190 188 TestAmdaAcquisition tc;
191 189 QTEST_SET_MAIN_SOURCE_PATH
192 190 return QTest::qExec(&tc, argc, argv);
193 191 }
194 192
195 193 // QTEST_MAIN(TestAmdaAcquisition)
196 194
197 195 #include "TestAmdaAcquisition.moc"
General Comments 0
You need to be logged in to leave comments. Login now