##// END OF EJS Templates
VariableController2 tests refactoring...
jeandet -
r3:7c9c9e90e0b8
parent child
Show More
@@ -1,102 +1,102
1 #ifndef SCIQLOP_VARIABLE_H
1 #ifndef SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/DataSeriesIterator.h>
6 #include <Data/DataSeriesIterator.h>
7 #include <Data/DataSeriesType.h>
7 #include <Data/DataSeriesType.h>
8 #include <Data/DateTimeRange.h>
8 #include <Data/DateTimeRange.h>
9
9
10 #include <QLoggingCategory>
10 #include <QLoggingCategory>
11 #include <QObject>
11 #include <QObject>
12 #include <QUuid>
12 #include <QUuid>
13
13
14 #include <Common/deprecate.h>
14 #include <Common/deprecate.h>
15 #include <Common/MetaTypes.h>
15 #include <Common/MetaTypes.h>
16 #include <Common/spimpl.h>
16 #include <Common/spimpl.h>
17
17
18 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
18 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
19
19
20 class IDataSeries;
20 class IDataSeries;
21 class QString;
21 class QString;
22
22
23 /**
23 /**
24 * @brief The Variable class represents a variable in SciQlop.
24 * @brief The Variable class represents a variable in SciQlop.
25 */
25 */
26 class SCIQLOP_CORE_EXPORT Variable : public QObject {
26 class SCIQLOP_CORE_EXPORT Variable : public QObject {
27
27
28 Q_OBJECT
28 Q_OBJECT
29
29
30 public:
30 public:
31 explicit Variable(const QString &name, const QVariantHash &metadata = {});
31 explicit Variable(const QString &name, const QVariantHash &metadata = {});
32
32
33 /// Copy ctor
33 /// Copy ctor
34 explicit Variable(const Variable &other);
34 explicit Variable(const Variable &other);
35
35
36 std::shared_ptr<Variable> clone() const;
36 std::shared_ptr<Variable> clone() const;
37
37
38 QString name() const noexcept;
38 QString name() const noexcept;
39 void setName(const QString &name) noexcept;
39 void setName(const QString &name) noexcept;
40 DateTimeRange range() const noexcept;
40 DateTimeRange range() const noexcept;
41 void setRange(const DateTimeRange &range) noexcept;
41 void setRange(const DateTimeRange &range) noexcept;
42 DateTimeRange cacheRange() const noexcept;
42 DateTimeRange cacheRange() const noexcept;
43 void setCacheRange(const DateTimeRange &cacheRange) noexcept;
43 void setCacheRange(const DateTimeRange &cacheRange) noexcept;
44
44
45 /// @return the number of points hold by the variable. The number of points is updated each time
45 /// @return the number of points hold by the variable. The number of points is updated each time
46 /// the data series changes
46 /// the data series changes
47 int nbPoints() const noexcept;
47 unsigned int nbPoints() const noexcept;
48
48
49 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
49 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
50 /// series between the range of the variable. The real range is updated each time the variable
50 /// series between the range of the variable. The real range is updated each time the variable
51 /// range or the data series changed
51 /// range or the data series changed
52 /// @return the real range, invalid range if the data series is null or empty
52 /// @return the real range, invalid range if the data series is null or empty
53 /// @sa setDataSeries()
53 /// @sa setDataSeries()
54 /// @sa setRange()
54 /// @sa setRange()
55 DateTimeRange realRange() const noexcept;
55 DateTimeRange realRange() const noexcept;
56
56
57 /// @return the data of the variable, nullptr if there is no data
57 /// @return the data of the variable, nullptr if there is no data
58 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
58 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
59
59
60 /// @return the type of data that the variable holds
60 /// @return the type of data that the variable holds
61 DataSeriesType type() const noexcept;
61 DataSeriesType type() const noexcept;
62
62
63 QVariantHash metadata() const noexcept;
63 QVariantHash metadata() const noexcept;
64
64
65 bool contains(const DateTimeRange &range) const noexcept;
65 bool contains(const DateTimeRange &range) const noexcept;
66 bool intersect(const DateTimeRange &range) const noexcept;
66 bool intersect(const DateTimeRange &range) const noexcept;
67 bool isInside(const DateTimeRange &range) const noexcept;
67 bool isInside(const DateTimeRange &range) const noexcept;
68
68
69 bool cacheContains(const DateTimeRange &range) const noexcept;
69 bool cacheContains(const DateTimeRange &range) const noexcept;
70 bool cacheIntersect(const DateTimeRange &range) const noexcept;
70 bool cacheIntersect(const DateTimeRange &range) const noexcept;
71 bool cacheIsInside(const DateTimeRange &range) const noexcept;
71 bool cacheIsInside(const DateTimeRange &range) const noexcept;
72
72
73 QVector<DateTimeRange> provideNotInCacheRangeList(const DateTimeRange &range) const noexcept;
73 QVector<DateTimeRange> provideNotInCacheRangeList(const DateTimeRange &range) const noexcept;
74 QVector<DateTimeRange> provideInCacheRangeList(const DateTimeRange &range) const noexcept;
74 QVector<DateTimeRange> provideInCacheRangeList(const DateTimeRange &range) const noexcept;
75 DEPRECATE(
75 DEPRECATE(
76 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
76 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
77 )
77 )
78 void mergeDataSeries(IDataSeries* dataSeries) noexcept;
78 void mergeDataSeries(IDataSeries* dataSeries) noexcept;
79
79
80 static QVector<DateTimeRange> provideNotInCacheRangeList(const DateTimeRange &oldRange,
80 static QVector<DateTimeRange> provideNotInCacheRangeList(const DateTimeRange &oldRange,
81 const DateTimeRange &nextRange);
81 const DateTimeRange &nextRange);
82
82
83 static QVector<DateTimeRange> provideInCacheRangeList(const DateTimeRange &oldRange,
83 static QVector<DateTimeRange> provideInCacheRangeList(const DateTimeRange &oldRange,
84 const DateTimeRange &nextRange);
84 const DateTimeRange &nextRange);
85
85
86 QUuid ID(){return _uuid;}
86 QUuid ID(){return _uuid;}
87 signals:
87 signals:
88 void updated();
88 void updated();
89 /// Signal emitted when when the data series of the variable is loaded for the first time
89 /// Signal emitted when when the data series of the variable is loaded for the first time
90 void dataInitialized();
90 void dataInitialized();
91
91
92 private:
92 private:
93 class VariablePrivate;
93 class VariablePrivate;
94 spimpl::unique_impl_ptr<VariablePrivate> impl;
94 spimpl::unique_impl_ptr<VariablePrivate> impl;
95 QUuid _uuid;
95 QUuid _uuid;
96 };
96 };
97
97
98 // Required for using shared_ptr in signals/slots
98 // Required for using shared_ptr in signals/slots
99 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
99 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
100 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
100 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
101
101
102 #endif // SCIQLOP_VARIABLE_H
102 #endif // SCIQLOP_VARIABLE_H
@@ -1,461 +1,461
1 #include "Variable/Variable.h"
1 #include "Variable/Variable.h"
2
2
3 #include <Data/IDataSeries.h>
3 #include <Data/IDataSeries.h>
4 #include <Data/DateTimeRange.h>
4 #include <Data/DateTimeRange.h>
5
5
6 #include <QMutex>
6 #include <QMutex>
7 #include <QReadWriteLock>
7 #include <QReadWriteLock>
8 #include <QThread>
8 #include <QThread>
9 #include <Common/debug.h>
9 #include <Common/debug.h>
10
10
11 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
11 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
12
12
13 namespace {
13 namespace {
14
14
15 /**
15 /**
16 * Searches in metadata for a value that can be converted to DataSeriesType
16 * Searches in metadata for a value that can be converted to DataSeriesType
17 * @param metadata the metadata where to search
17 * @param metadata the metadata where to search
18 * @return the value converted to a DataSeriesType if it was found, UNKNOWN type otherwise
18 * @return the value converted to a DataSeriesType if it was found, UNKNOWN type otherwise
19 * @sa DataSeriesType
19 * @sa DataSeriesType
20 */
20 */
21 DataSeriesType findDataSeriesType(const QVariantHash &metadata)
21 DataSeriesType findDataSeriesType(const QVariantHash &metadata)
22 {
22 {
23 auto dataSeriesType = DataSeriesType::UNKNOWN;
23 auto dataSeriesType = DataSeriesType::UNKNOWN;
24
24
25 // Go through the metadata and stop at the first value that could be converted to DataSeriesType
25 // Go through the metadata and stop at the first value that could be converted to DataSeriesType
26 for (auto it = metadata.cbegin(), end = metadata.cend();
26 for (auto it = metadata.cbegin(), end = metadata.cend();
27 it != end && dataSeriesType == DataSeriesType::UNKNOWN; ++it) {
27 it != end && dataSeriesType == DataSeriesType::UNKNOWN; ++it) {
28 dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString());
28 dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString());
29 }
29 }
30
30
31 return dataSeriesType;
31 return dataSeriesType;
32 }
32 }
33
33
34 } // namespace
34 } // namespace
35
35
36 struct Variable::VariablePrivate {
36 struct Variable::VariablePrivate {
37 explicit VariablePrivate(const QString &name, const QVariantHash &metadata)
37 explicit VariablePrivate(const QString &name, const QVariantHash &metadata)
38 : m_Name{name},
38 : m_Name{name},
39 m_Range{INVALID_RANGE},
39 m_Range{INVALID_RANGE},
40 m_CacheRange{INVALID_RANGE},
40 m_CacheRange{INVALID_RANGE},
41 m_Metadata{metadata},
41 m_Metadata{metadata},
42 m_DataSeries{nullptr},
42 m_DataSeries{nullptr},
43 m_RealRange{INVALID_RANGE},
43 m_RealRange{INVALID_RANGE},
44 m_NbPoints{0},
44 m_NbPoints{0},
45 m_Type{findDataSeriesType(m_Metadata)}
45 m_Type{findDataSeriesType(m_Metadata)}
46 {
46 {
47 }
47 }
48
48
49 VariablePrivate(const VariablePrivate &other)
49 VariablePrivate(const VariablePrivate &other)
50 : m_Name{other.m_Name},
50 : m_Name{other.m_Name},
51 m_Range{other.m_Range},
51 m_Range{other.m_Range},
52 m_CacheRange{other.m_CacheRange},
52 m_CacheRange{other.m_CacheRange},
53 m_Metadata{other.m_Metadata},
53 m_Metadata{other.m_Metadata},
54 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
54 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
55 m_RealRange{other.m_RealRange},
55 m_RealRange{other.m_RealRange},
56 m_NbPoints{other.m_NbPoints},
56 m_NbPoints{other.m_NbPoints},
57 m_Type{findDataSeriesType(m_Metadata)}
57 m_Type{findDataSeriesType(m_Metadata)}
58 {
58 {
59 }
59 }
60
60
61 void lockRead() { m_Lock.lockForRead(); }
61 void lockRead() { m_Lock.lockForRead(); }
62 void lockWrite() { m_Lock.lockForWrite(); }
62 void lockWrite() { m_Lock.lockForWrite(); }
63 void unlock() { m_Lock.unlock(); }
63 void unlock() { m_Lock.unlock(); }
64
64
65 void purgeDataSeries()
65 void purgeDataSeries()
66 {
66 {
67 if (m_DataSeries) {
67 if (m_DataSeries) {
68 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
68 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
69 }
69 }
70 updateRealRange();
70 updateRealRange();
71 updateNbPoints();
71 updateNbPoints();
72 }
72 }
73
73
74 void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
74 void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
75
75
76 /// Updates real range according to current variable range and data series
76 /// Updates real range according to current variable range and data series
77 void updateRealRange()
77 void updateRealRange()
78 {
78 {
79 if (m_DataSeries) {
79 if (m_DataSeries) {
80 m_DataSeries->lockRead();
80 m_DataSeries->lockRead();
81 auto end = m_DataSeries->cend();
81 auto end = m_DataSeries->cend();
82 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
82 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
83 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
83 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
84
84
85 m_RealRange
85 m_RealRange
86 = (minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x())
86 = (minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x())
87 ? DateTimeRange{minXAxisIt->x(), maxXAxisIt->x()}
87 ? DateTimeRange{minXAxisIt->x(), maxXAxisIt->x()}
88 : INVALID_RANGE;
88 : INVALID_RANGE;
89 m_DataSeries->unlock();
89 m_DataSeries->unlock();
90 }
90 }
91 else {
91 else {
92 m_RealRange = INVALID_RANGE;
92 m_RealRange = INVALID_RANGE;
93 }
93 }
94 }
94 }
95
95
96 QString m_Name;
96 QString m_Name;
97
97
98 DateTimeRange m_Range;
98 DateTimeRange m_Range;
99 DateTimeRange m_CacheRange;
99 DateTimeRange m_CacheRange;
100 QVariantHash m_Metadata;
100 QVariantHash m_Metadata;
101 std::shared_ptr<IDataSeries> m_DataSeries;
101 std::shared_ptr<IDataSeries> m_DataSeries;
102 DateTimeRange m_RealRange;
102 DateTimeRange m_RealRange;
103 int m_NbPoints;
103 unsigned int m_NbPoints;
104 DataSeriesType m_Type;
104 DataSeriesType m_Type;
105
105
106 QReadWriteLock m_Lock;
106 QReadWriteLock m_Lock;
107 };
107 };
108
108
109 Variable::Variable(const QString &name, const QVariantHash &metadata)
109 Variable::Variable(const QString &name, const QVariantHash &metadata)
110 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)},
110 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)},
111 _uuid{QUuid::createUuid()}
111 _uuid{QUuid::createUuid()}
112 {
112 {
113 }
113 }
114
114
115 Variable::Variable(const Variable &other)
115 Variable::Variable(const Variable &other)
116 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)},
116 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)},
117 _uuid{QUuid::createUuid()} //is a clone but must have a != uuid
117 _uuid{QUuid::createUuid()} //is a clone but must have a != uuid
118 {
118 {
119 }
119 }
120
120
121 std::shared_ptr<Variable> Variable::clone() const
121 std::shared_ptr<Variable> Variable::clone() const
122 {
122 {
123 return std::make_shared<Variable>(*this);
123 return std::make_shared<Variable>(*this);
124 }
124 }
125
125
126 QString Variable::name() const noexcept
126 QString Variable::name() const noexcept
127 {
127 {
128 impl->lockRead();
128 impl->lockRead();
129 auto name = impl->m_Name;
129 auto name = impl->m_Name;
130 impl->unlock();
130 impl->unlock();
131 return name;
131 return name;
132 }
132 }
133
133
134 void Variable::setName(const QString &name) noexcept
134 void Variable::setName(const QString &name) noexcept
135 {
135 {
136 impl->lockWrite();
136 impl->lockWrite();
137 impl->m_Name = name;
137 impl->m_Name = name;
138 impl->unlock();
138 impl->unlock();
139 }
139 }
140
140
141 DateTimeRange Variable::range() const noexcept
141 DateTimeRange Variable::range() const noexcept
142 {
142 {
143 impl->lockRead();
143 impl->lockRead();
144 auto range = impl->m_Range;
144 auto range = impl->m_Range;
145 impl->unlock();
145 impl->unlock();
146 return range;
146 return range;
147 }
147 }
148
148
149 void Variable::setRange(const DateTimeRange &range) noexcept
149 void Variable::setRange(const DateTimeRange &range) noexcept
150 {
150 {
151 impl->lockWrite();
151 impl->lockWrite();
152 impl->m_Range = range;
152 impl->m_Range = range;
153 impl->updateRealRange();
153 impl->updateRealRange();
154 impl->unlock();
154 impl->unlock();
155 }
155 }
156
156
157 DateTimeRange Variable::cacheRange() const noexcept
157 DateTimeRange Variable::cacheRange() const noexcept
158 {
158 {
159 impl->lockRead();
159 impl->lockRead();
160 auto cacheRange = impl->m_CacheRange;
160 auto cacheRange = impl->m_CacheRange;
161 impl->unlock();
161 impl->unlock();
162 return cacheRange;
162 return cacheRange;
163 }
163 }
164
164
165 void Variable::setCacheRange(const DateTimeRange &cacheRange) noexcept
165 void Variable::setCacheRange(const DateTimeRange &cacheRange) noexcept
166 {
166 {
167 impl->lockWrite();
167 impl->lockWrite();
168 if (cacheRange != impl->m_CacheRange) {
168 if (cacheRange != impl->m_CacheRange) {
169 impl->m_CacheRange = cacheRange;
169 impl->m_CacheRange = cacheRange;
170 }
170 }
171 impl->unlock();
171 impl->unlock();
172 }
172 }
173
173
174 int Variable::nbPoints() const noexcept
174 unsigned int Variable::nbPoints() const noexcept
175 {
175 {
176 return impl->m_NbPoints;
176 return impl->m_NbPoints;
177 }
177 }
178
178
179 DateTimeRange Variable::realRange() const noexcept
179 DateTimeRange Variable::realRange() const noexcept
180 {
180 {
181 return impl->m_RealRange;
181 return impl->m_RealRange;
182 }
182 }
183
183
184 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
184 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
185 {
185 {
186 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
186 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
187 << QThread::currentThread()->objectName();
187 << QThread::currentThread()->objectName();
188 if (!dataSeries) {
188 if (!dataSeries) {
189 /// @todo ALX : log
189 /// @todo ALX : log
190 return;
190 return;
191 }
191 }
192
192
193 auto dataInit = false;
193 auto dataInit = false;
194
194
195 // Add or merge the data
195 // Add or merge the data
196 impl->lockWrite();
196 impl->lockWrite();
197 if (!impl->m_DataSeries) {
197 if (!impl->m_DataSeries) {
198 impl->m_DataSeries = dataSeries->clone();
198 impl->m_DataSeries = dataSeries->clone();
199 dataInit = true;
199 dataInit = true;
200 }
200 }
201 else {
201 else {
202 impl->m_DataSeries->merge(dataSeries.get());
202 impl->m_DataSeries->merge(dataSeries.get());
203 }
203 }
204 impl->purgeDataSeries();
204 impl->purgeDataSeries();
205 impl->unlock();
205 impl->unlock();
206
206
207 if (dataInit) {
207 if (dataInit) {
208 emit dataInitialized();
208 emit dataInitialized();
209 }
209 }
210 }
210 }
211
211
212 void Variable::mergeDataSeries(IDataSeries *dataSeries) noexcept
212 void Variable::mergeDataSeries(IDataSeries *dataSeries) noexcept
213 {
213 {
214 if (dataSeries==nullptr) {
214 if (dataSeries==nullptr) {
215 SCIQLOP_ERROR("Given IDataSeries is nullptr");
215 SCIQLOP_ERROR("Given IDataSeries is nullptr");
216 return;
216 return;
217 }
217 }
218
218
219 auto dataInit = false;
219 auto dataInit = false;
220 // @TODO move to impl to Pimpl this is what it stands for...
220 // @TODO move to impl to Pimpl this is what it stands for...
221 // Add or merge the data
221 // Add or merge the data
222 impl->lockWrite();
222 impl->lockWrite();
223 if (!impl->m_DataSeries) {
223 if (!impl->m_DataSeries) {
224 //@TODO find a better way
224 //@TODO find a better way
225 impl->m_DataSeries = dataSeries->clone();
225 impl->m_DataSeries = dataSeries->clone();
226 dataInit = true;
226 dataInit = true;
227 delete dataSeries;
227 delete dataSeries;
228 }
228 }
229 else {
229 else {
230 impl->m_DataSeries->merge(dataSeries);
230 impl->m_DataSeries->merge(dataSeries);
231 }
231 }
232 impl->purgeDataSeries();
232 impl->purgeDataSeries();
233 impl->unlock();
233 impl->unlock();
234
234
235 if (dataInit) {
235 if (dataInit) {
236 emit dataInitialized();
236 emit dataInitialized();
237 }
237 }
238 }
238 }
239
239
240
240
241 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
241 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
242 {
242 {
243 impl->lockRead();
243 impl->lockRead();
244 auto dataSeries = impl->m_DataSeries;
244 auto dataSeries = impl->m_DataSeries;
245 impl->unlock();
245 impl->unlock();
246
246
247 return dataSeries;
247 return dataSeries;
248 }
248 }
249
249
250 DataSeriesType Variable::type() const noexcept
250 DataSeriesType Variable::type() const noexcept
251 {
251 {
252 impl->lockRead();
252 impl->lockRead();
253 auto type = impl->m_Type;
253 auto type = impl->m_Type;
254 impl->unlock();
254 impl->unlock();
255
255
256 return type;
256 return type;
257 }
257 }
258
258
259 QVariantHash Variable::metadata() const noexcept
259 QVariantHash Variable::metadata() const noexcept
260 {
260 {
261 impl->lockRead();
261 impl->lockRead();
262 auto metadata = impl->m_Metadata;
262 auto metadata = impl->m_Metadata;
263 impl->unlock();
263 impl->unlock();
264 return metadata;
264 return metadata;
265 }
265 }
266
266
267 bool Variable::contains(const DateTimeRange &range) const noexcept
267 bool Variable::contains(const DateTimeRange &range) const noexcept
268 {
268 {
269 impl->lockRead();
269 impl->lockRead();
270 auto res = impl->m_Range.contains(range);
270 auto res = impl->m_Range.contains(range);
271 impl->unlock();
271 impl->unlock();
272 return res;
272 return res;
273 }
273 }
274
274
275 bool Variable::intersect(const DateTimeRange &range) const noexcept
275 bool Variable::intersect(const DateTimeRange &range) const noexcept
276 {
276 {
277
277
278 impl->lockRead();
278 impl->lockRead();
279 auto res = impl->m_Range.intersect(range);
279 auto res = impl->m_Range.intersect(range);
280 impl->unlock();
280 impl->unlock();
281 return res;
281 return res;
282 }
282 }
283
283
284 bool Variable::isInside(const DateTimeRange &range) const noexcept
284 bool Variable::isInside(const DateTimeRange &range) const noexcept
285 {
285 {
286 impl->lockRead();
286 impl->lockRead();
287 auto res = range.contains(DateTimeRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
287 auto res = range.contains(DateTimeRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
288 impl->unlock();
288 impl->unlock();
289 return res;
289 return res;
290 }
290 }
291
291
292 bool Variable::cacheContains(const DateTimeRange &range) const noexcept
292 bool Variable::cacheContains(const DateTimeRange &range) const noexcept
293 {
293 {
294 impl->lockRead();
294 impl->lockRead();
295 auto res = impl->m_CacheRange.contains(range);
295 auto res = impl->m_CacheRange.contains(range);
296 impl->unlock();
296 impl->unlock();
297 return res;
297 return res;
298 }
298 }
299
299
300 bool Variable::cacheIntersect(const DateTimeRange &range) const noexcept
300 bool Variable::cacheIntersect(const DateTimeRange &range) const noexcept
301 {
301 {
302 impl->lockRead();
302 impl->lockRead();
303 auto res = impl->m_CacheRange.intersect(range);
303 auto res = impl->m_CacheRange.intersect(range);
304 impl->unlock();
304 impl->unlock();
305 return res;
305 return res;
306 }
306 }
307
307
308 bool Variable::cacheIsInside(const DateTimeRange &range) const noexcept
308 bool Variable::cacheIsInside(const DateTimeRange &range) const noexcept
309 {
309 {
310 impl->lockRead();
310 impl->lockRead();
311 auto res = range.contains(DateTimeRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
311 auto res = range.contains(DateTimeRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
312 impl->unlock();
312 impl->unlock();
313 return res;
313 return res;
314 }
314 }
315
315
316
316
317 QVector<DateTimeRange> Variable::provideNotInCacheRangeList(const DateTimeRange &range) const noexcept
317 QVector<DateTimeRange> Variable::provideNotInCacheRangeList(const DateTimeRange &range) const noexcept
318 {
318 {
319 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
319 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
320 auto notInCache = QVector<DateTimeRange>{};
320 auto notInCache = QVector<DateTimeRange>{};
321 if (impl->m_CacheRange != INVALID_RANGE) {
321 if (impl->m_CacheRange != INVALID_RANGE) {
322
322
323 if (!this->cacheContains(range)) {
323 if (!this->cacheContains(range)) {
324 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
324 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
325 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
325 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
326 notInCache << range;
326 notInCache << range;
327 }
327 }
328 else if (range.m_TStart < impl->m_CacheRange.m_TStart
328 else if (range.m_TStart < impl->m_CacheRange.m_TStart
329 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
329 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
330 notInCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TStart};
330 notInCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TStart};
331 }
331 }
332 else if (range.m_TStart < impl->m_CacheRange.m_TStart
332 else if (range.m_TStart < impl->m_CacheRange.m_TStart
333 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
333 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
334 notInCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TStart}
334 notInCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TStart}
335 << DateTimeRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
335 << DateTimeRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
336 }
336 }
337 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
337 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
338 notInCache << DateTimeRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
338 notInCache << DateTimeRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
339 }
339 }
340 else {
340 else {
341 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
341 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
342 << QThread::currentThread();
342 << QThread::currentThread();
343 }
343 }
344 }
344 }
345 }
345 }
346 else {
346 else {
347 notInCache << range;
347 notInCache << range;
348 }
348 }
349
349
350 return notInCache;
350 return notInCache;
351 }
351 }
352
352
353 QVector<DateTimeRange> Variable::provideInCacheRangeList(const DateTimeRange &range) const noexcept
353 QVector<DateTimeRange> Variable::provideInCacheRangeList(const DateTimeRange &range) const noexcept
354 {
354 {
355 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
355 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
356
356
357 auto inCache = QVector<DateTimeRange>{};
357 auto inCache = QVector<DateTimeRange>{};
358
358
359 if (impl->m_CacheRange != INVALID_RANGE) {
359 if (impl->m_CacheRange != INVALID_RANGE) {
360
360
361 if (this->cacheIntersect(range)) {
361 if (this->cacheIntersect(range)) {
362 if (range.m_TStart <= impl->m_CacheRange.m_TStart
362 if (range.m_TStart <= impl->m_CacheRange.m_TStart
363 && range.m_TEnd >= impl->m_CacheRange.m_TStart
363 && range.m_TEnd >= impl->m_CacheRange.m_TStart
364 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
364 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
365 inCache << DateTimeRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
365 inCache << DateTimeRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
366 }
366 }
367
367
368 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
368 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
369 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
369 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
370 inCache << range;
370 inCache << range;
371 }
371 }
372 else if (range.m_TStart > impl->m_CacheRange.m_TStart
372 else if (range.m_TStart > impl->m_CacheRange.m_TStart
373 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
373 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
374 inCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
374 inCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
375 }
375 }
376 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
376 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
377 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
377 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
378 inCache << impl->m_CacheRange;
378 inCache << impl->m_CacheRange;
379 }
379 }
380 else {
380 else {
381 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
381 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
382 << QThread::currentThread();
382 << QThread::currentThread();
383 }
383 }
384 }
384 }
385 }
385 }
386
386
387 return inCache;
387 return inCache;
388 }
388 }
389
389
390
390
391 QVector<DateTimeRange> Variable::provideNotInCacheRangeList(const DateTimeRange &oldRange,
391 QVector<DateTimeRange> Variable::provideNotInCacheRangeList(const DateTimeRange &oldRange,
392 const DateTimeRange &nextRange)
392 const DateTimeRange &nextRange)
393 {
393 {
394
394
395 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
395 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
396 auto notInCache = QVector<DateTimeRange>{};
396 auto notInCache = QVector<DateTimeRange>{};
397 if (oldRange != INVALID_RANGE) {
397 if (oldRange != INVALID_RANGE) {
398
398
399 if (!oldRange.contains(nextRange)) {
399 if (!oldRange.contains(nextRange)) {
400 if (nextRange.m_TEnd <= oldRange.m_TStart || nextRange.m_TStart >= oldRange.m_TEnd) {
400 if (nextRange.m_TEnd <= oldRange.m_TStart || nextRange.m_TStart >= oldRange.m_TEnd) {
401 notInCache << nextRange;
401 notInCache << nextRange;
402 }
402 }
403 else if (nextRange.m_TStart < oldRange.m_TStart
403 else if (nextRange.m_TStart < oldRange.m_TStart
404 && nextRange.m_TEnd <= oldRange.m_TEnd) {
404 && nextRange.m_TEnd <= oldRange.m_TEnd) {
405 notInCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TStart};
405 notInCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TStart};
406 }
406 }
407 else if (nextRange.m_TStart < oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
407 else if (nextRange.m_TStart < oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
408 notInCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TStart}
408 notInCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TStart}
409 << DateTimeRange{oldRange.m_TEnd, nextRange.m_TEnd};
409 << DateTimeRange{oldRange.m_TEnd, nextRange.m_TEnd};
410 }
410 }
411 else if (nextRange.m_TStart < oldRange.m_TEnd) {
411 else if (nextRange.m_TStart < oldRange.m_TEnd) {
412 notInCache << DateTimeRange{oldRange.m_TEnd, nextRange.m_TEnd};
412 notInCache << DateTimeRange{oldRange.m_TEnd, nextRange.m_TEnd};
413 }
413 }
414 else {
414 else {
415 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
415 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
416 << QThread::currentThread();
416 << QThread::currentThread();
417 }
417 }
418 }
418 }
419 }
419 }
420 else {
420 else {
421 notInCache << nextRange;
421 notInCache << nextRange;
422 }
422 }
423
423
424 return notInCache;
424 return notInCache;
425 }
425 }
426
426
427 QVector<DateTimeRange> Variable::provideInCacheRangeList(const DateTimeRange &oldRange,
427 QVector<DateTimeRange> Variable::provideInCacheRangeList(const DateTimeRange &oldRange,
428 const DateTimeRange &nextRange)
428 const DateTimeRange &nextRange)
429 {
429 {
430 // This code assume that cach is contigue. Can return 0 or 1 SqpRange
430 // This code assume that cach is contigue. Can return 0 or 1 SqpRange
431
431
432 auto inCache = QVector<DateTimeRange>{};
432 auto inCache = QVector<DateTimeRange>{};
433
433
434 if (oldRange != INVALID_RANGE) {
434 if (oldRange != INVALID_RANGE) {
435
435
436 if (oldRange.intersect(nextRange)) {
436 if (oldRange.intersect(nextRange)) {
437 if (nextRange.m_TStart <= oldRange.m_TStart && nextRange.m_TEnd >= oldRange.m_TStart
437 if (nextRange.m_TStart <= oldRange.m_TStart && nextRange.m_TEnd >= oldRange.m_TStart
438 && nextRange.m_TEnd < oldRange.m_TEnd) {
438 && nextRange.m_TEnd < oldRange.m_TEnd) {
439 inCache << DateTimeRange{oldRange.m_TStart, nextRange.m_TEnd};
439 inCache << DateTimeRange{oldRange.m_TStart, nextRange.m_TEnd};
440 }
440 }
441
441
442 else if (nextRange.m_TStart >= oldRange.m_TStart
442 else if (nextRange.m_TStart >= oldRange.m_TStart
443 && nextRange.m_TEnd <= oldRange.m_TEnd) {
443 && nextRange.m_TEnd <= oldRange.m_TEnd) {
444 inCache << nextRange;
444 inCache << nextRange;
445 }
445 }
446 else if (nextRange.m_TStart > oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
446 else if (nextRange.m_TStart > oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
447 inCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TEnd};
447 inCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TEnd};
448 }
448 }
449 else if (nextRange.m_TStart <= oldRange.m_TStart
449 else if (nextRange.m_TStart <= oldRange.m_TStart
450 && nextRange.m_TEnd >= oldRange.m_TEnd) {
450 && nextRange.m_TEnd >= oldRange.m_TEnd) {
451 inCache << oldRange;
451 inCache << oldRange;
452 }
452 }
453 else {
453 else {
454 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
454 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
455 << QThread::currentThread();
455 << QThread::currentThread();
456 }
456 }
457 }
457 }
458 }
458 }
459
459
460 return inCache;
460 return inCache;
461 }
461 }
@@ -1,108 +1,139
1 #include <cmath>
1 #include <cmath>
2 #include <algorithm>
3 #include <numeric>
2 #include <QtTest>
4 #include <QtTest>
3 #include <QObject>
5 #include <QObject>
4 #include <Variable/VariableController2.h>
6 #include <Variable/VariableController2.h>
5 #include <Data/DateTimeRange.h>
7 #include <Data/DateTimeRange.h>
6 #include <Data/IDataProvider.h>
8 #include <Data/IDataProvider.h>
7 #include <Data/ScalarSeries.h>
9 #include <Data/ScalarSeries.h>
8 #include <Data/DataProviderParameters.h>
10 #include <Data/DataProviderParameters.h>
9 #include <Common/containers.h>
11 #include <Common/containers.h>
10
12
11 class FakeProvider: public IDataProvider
13 template<int slope>
14 class SimpleRange: public IDataProvider
12 {
15 {
13 public:
16 public:
14 FakeProvider() = default;
17 SimpleRange() = default;
15
18
16 std::shared_ptr<IDataProvider> clone() const override{ return std::make_shared<FakeProvider>(); }
19 std::shared_ptr<IDataProvider> clone() const override{ return std::make_shared<SimpleRange>(); }
17
20
18 IDataSeries* getData(const DataProviderParameters &parameters) override
21 IDataSeries* getData(const DataProviderParameters &parameters) override
19 {
22 {
20 auto tstart = parameters.m_Times[0].m_TStart;
23 auto tstart = parameters.m_Times[0].m_TStart;
21 auto tend = parameters.m_Times[0].m_TEnd;
24 auto tend = parameters.m_Times[0].m_TEnd;
22 std::vector<double> x;
25 std::vector<double> x;
23 std::vector<double> y;
26 std::vector<double> y;
24 for(auto i = tstart;i<tend;i+=1.) //1 seconde data resolution
27 for(auto i = tstart;i<tend;i+=1.) //1 seconde data resolution
25 {
28 {
26 x.push_back(i);
29 x.push_back(i);
27 y.push_back(i);
30 y.push_back(i*slope);
28 }
31 }
29 auto serie = new ScalarSeries(std::move(x),std::move(y),Unit("Secondes",true),Unit("Volts",false));
32 auto serie = new ScalarSeries(std::move(x),std::move(y),Unit("Secondes",true),Unit("Volts",false));
30 return serie;
33 return serie;
31 }
34 }
32
35
33
36
34
37
35 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
38 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override
36 {
39 {
37 Q_UNUSED(acqIdentifier)
40 Q_UNUSED(acqIdentifier)
38 Q_UNUSED(parameters)
41 Q_UNUSED(parameters)
39 }
42 }
40
43
41 void requestDataAborting(QUuid acqIdentifier) override
44 void requestDataAborting(QUuid acqIdentifier) override
42 {
45 {
43 Q_UNUSED(acqIdentifier)
46 Q_UNUSED(acqIdentifier)
44 }
47 }
45
48
46 };
49 };
47
50
51
52 template <class T>
53 auto sumdiff(T begin, T end)
54 {
55 std::vector<double> diff_vect(end-begin-1);
56 auto diff = [](auto next,auto item)
57 {
58 return next.value() - item.value();
59 };
60 std::transform (begin+1, end, begin, diff_vect.begin(),diff);
61 return std::accumulate(diff_vect.cbegin(), diff_vect.cend(), 0);
62 }
63
64 template <int slope=1>
65 struct RangeType
66 {
67 static void check_properties(std::shared_ptr<Variable> v, DateTimeRange r)
68 {
69 auto s = sumdiff(v->dataSeries()->cbegin(), v->dataSeries()->cend()) / slope;
70 QCOMPARE(v->nbPoints(), int(s)+1);
71 QCOMPARE(r.m_TStart, v->dataSeries()->begin()->value()/slope);
72 }
73 };
74
75 template <class T>
76 void check_variable_state(std::shared_ptr<Variable> v, DateTimeRange r)
77 {
78 QCOMPARE(v->nbPoints(), int(r.delta()));
79 T::check_properties(v,r);
80 }
81
48 class TestVariableController2 : public QObject
82 class TestVariableController2 : public QObject
49 {
83 {
50 Q_OBJECT
84 Q_OBJECT
51 public:
85 public:
52 explicit TestVariableController2(QObject *parent = nullptr) : QObject(parent){}
86 explicit TestVariableController2(QObject *parent = nullptr) : QObject(parent){}
53 signals:
87 signals:
54
88
55 private slots:
89 private slots:
56 void initTestCase(){}
90 void initTestCase(){}
57 void cleanupTestCase(){}
91 void cleanupTestCase(){}
58
92
59 void testCreateVariable()
93 void testCreateVariable()
60 {
94 {
61 VariableController2 vc;
95 VariableController2 vc;
62 bool callbackCalled = false;
96 bool callbackCalled = false;
63 connect(&vc,&VariableController2::variableAdded, [&callbackCalled](std::shared_ptr<Variable>){callbackCalled=true;});
97 connect(&vc,&VariableController2::variableAdded, [&callbackCalled](std::shared_ptr<Variable>){callbackCalled=true;});
64 auto provider = std::make_shared<FakeProvider>();
98 auto provider = std::make_shared<SimpleRange<1>>();
65 QVERIFY(!callbackCalled);
99 QVERIFY(!callbackCalled);
66 auto var1 = vc.createVariable("var1",{},provider,DateTimeRange());
100 auto var1 = vc.createVariable("var1",{},provider,DateTimeRange());
67 QVERIFY(SciQLop::containers::contains(vc.variables(), var1));
101 QVERIFY(SciQLop::containers::contains(vc.variables(), var1));
68 QVERIFY(callbackCalled);
102 QVERIFY(callbackCalled);
69 }
103 }
70
104
71 void testDeleteVariable()
105 void testDeleteVariable()
72 {
106 {
73 VariableController2 vc;
107 VariableController2 vc;
74 bool callbackCalled = false;
108 bool callbackCalled = false;
75 connect(&vc,&VariableController2::variableDeleted, [&callbackCalled](std::shared_ptr<Variable>){callbackCalled=true;});
109 connect(&vc,&VariableController2::variableDeleted, [&callbackCalled](std::shared_ptr<Variable>){callbackCalled=true;});
76 auto provider = std::make_shared<FakeProvider>();
110 auto provider = std::make_shared<SimpleRange<1>>();
77 auto var1 = vc.createVariable("var1",{},provider,DateTimeRange());
111 auto var1 = vc.createVariable("var1",{},provider,DateTimeRange());
78 QVERIFY(SciQLop::containers::contains(vc.variables(), var1));
112 QVERIFY(SciQLop::containers::contains(vc.variables(), var1));
79 QVERIFY(!callbackCalled);
113 QVERIFY(!callbackCalled);
80 vc.deleteVariable(var1);
114 vc.deleteVariable(var1);
81 QVERIFY(!SciQLop::containers::contains(vc.variables(), var1));
115 QVERIFY(!SciQLop::containers::contains(vc.variables(), var1));
82 QVERIFY(callbackCalled);
116 QVERIFY(callbackCalled);
83 }
117 }
84
118
85 void testGetData()
119 void testGetData()
86 {
120 {
87 VariableController2 vc;
121 VariableController2 vc;
88 auto provider = std::make_shared<FakeProvider>();
122 auto provider = std::make_shared<SimpleRange<10>>();
89 auto range1 = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(14,00),
123 auto range1 = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(14,00),
90 QDate(2018,8,7),QTime(16,00));
124 QDate(2018,8,7),QTime(16,00));
91 auto range2 = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(12,00),
125 auto range2 = DateTimeRange::fromDateTime(QDate(2018,8,7),QTime(12,00),
92 QDate(2018,8,7),QTime(18,00));
126 QDate(2018,8,7),QTime(18,00));
93 auto var1 = vc.createVariable("var1", {}, provider, range1);
127 auto var1 = vc.createVariable("var1", {}, provider, range1);
94 QCOMPARE(var1->nbPoints(), int(range1.delta()));
128 check_variable_state<RangeType<10>>(var1, range1);
95 vc.changeRange(var1, range2);
129 vc.changeRange(var1, range2);
96 QCOMPARE(var1->nbPoints(), int(range2.delta()));
130 check_variable_state<RangeType<10>>(var1, range2);
97
98 }
131 }
99
132
100 private:
101
102 };
133 };
103
134
104
135
105 QTEST_MAIN(TestVariableController2)
136 QTEST_MAIN(TestVariableController2)
106
137
107 #include "TestVariableController2.moc"
138 #include "TestVariableController2.moc"
108
139
General Comments 0
You need to be logged in to leave comments. Login now