##// END OF EJS Templates
Updates variable attribute when data series is changing
Alexandre Leroux -
r718:a1a7563eadb0
parent child
Show More
@@ -1,304 +1,307
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/SqpRange.h>
4 #include <Data/SqpRange.h>
5
5
6 #include <QMutex>
6 #include <QMutex>
7 #include <QReadWriteLock>
7 #include <QReadWriteLock>
8 #include <QThread>
8 #include <QThread>
9
9
10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
11
11
12 struct Variable::VariablePrivate {
12 struct Variable::VariablePrivate {
13 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
13 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
14 const QVariantHash &metadata)
14 const QVariantHash &metadata)
15 : m_Name{name},
15 : m_Name{name},
16 m_Range{dateTime},
16 m_Range{dateTime},
17 m_Metadata{metadata},
17 m_Metadata{metadata},
18 m_DataSeries{nullptr},
18 m_DataSeries{nullptr},
19 m_RealRange{INVALID_RANGE},
19 m_RealRange{INVALID_RANGE},
20 m_NbPoints{0}
20 m_NbPoints{0}
21 {
21 {
22 }
22 }
23
23
24 VariablePrivate(const VariablePrivate &other)
24 VariablePrivate(const VariablePrivate &other)
25 : m_Name{other.m_Name},
25 : m_Name{other.m_Name},
26 m_Range{other.m_Range},
26 m_Range{other.m_Range},
27 m_Metadata{other.m_Metadata},
27 m_Metadata{other.m_Metadata},
28 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
28 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
29 m_RealRange{other.m_RealRange},
29 m_RealRange{other.m_RealRange},
30 m_NbPoints{other.m_NbPoints}
30 m_NbPoints{other.m_NbPoints}
31 {
31 {
32 }
32 }
33
33
34 void lockRead() { m_Lock.lockForRead(); }
34 void lockRead() { m_Lock.lockForRead(); }
35 void lockWrite() { m_Lock.lockForWrite(); }
35 void lockWrite() { m_Lock.lockForWrite(); }
36 void unlock() { m_Lock.unlock(); }
36 void unlock() { m_Lock.unlock(); }
37
37
38 void purgeDataSeries()
38 void purgeDataSeries()
39 {
39 {
40 if (m_DataSeries) {
40 if (m_DataSeries) {
41 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
41 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
42 }
42 }
43 updateRealRange();
43 updateRealRange();
44 updateNbPoints();
44 }
45 }
45
46
47 void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
48
46 /// Updates real range according to current variable range and data series
49 /// Updates real range according to current variable range and data series
47 void updateRealRange()
50 void updateRealRange()
48 {
51 {
49 if (m_DataSeries) {
52 if (m_DataSeries) {
50 m_DataSeries->lockRead();
53 m_DataSeries->lockRead();
51 auto end = m_DataSeries->cend();
54 auto end = m_DataSeries->cend();
52 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
55 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
53 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
56 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
54
57
55 m_RealRange = (minXAxisIt != end && maxXAxisIt != end)
58 m_RealRange = (minXAxisIt != end && maxXAxisIt != end)
56 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
59 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
57 : INVALID_RANGE;
60 : INVALID_RANGE;
58 m_DataSeries->unlock();
61 m_DataSeries->unlock();
59 }
62 }
60 else {
63 else {
61 m_RealRange = INVALID_RANGE;
64 m_RealRange = INVALID_RANGE;
62 }
65 }
63 }
66 }
64
67
65 QString m_Name;
68 QString m_Name;
66
69
67 SqpRange m_Range;
70 SqpRange m_Range;
68 SqpRange m_CacheRange;
71 SqpRange m_CacheRange;
69 QVariantHash m_Metadata;
72 QVariantHash m_Metadata;
70 std::shared_ptr<IDataSeries> m_DataSeries;
73 std::shared_ptr<IDataSeries> m_DataSeries;
71 SqpRange m_RealRange;
74 SqpRange m_RealRange;
72 int m_NbPoints;
75 int m_NbPoints;
73
76
74 QReadWriteLock m_Lock;
77 QReadWriteLock m_Lock;
75 };
78 };
76
79
77 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
80 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
78 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
81 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
79 {
82 {
80 }
83 }
81
84
82 Variable::Variable(const Variable &other)
85 Variable::Variable(const Variable &other)
83 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)}
86 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)}
84 {
87 {
85 }
88 }
86
89
87 std::shared_ptr<Variable> Variable::clone() const
90 std::shared_ptr<Variable> Variable::clone() const
88 {
91 {
89 return std::make_shared<Variable>(*this);
92 return std::make_shared<Variable>(*this);
90 }
93 }
91
94
92 QString Variable::name() const noexcept
95 QString Variable::name() const noexcept
93 {
96 {
94 impl->lockRead();
97 impl->lockRead();
95 auto name = impl->m_Name;
98 auto name = impl->m_Name;
96 impl->unlock();
99 impl->unlock();
97 return name;
100 return name;
98 }
101 }
99
102
100 void Variable::setName(const QString &name) noexcept
103 void Variable::setName(const QString &name) noexcept
101 {
104 {
102 impl->lockWrite();
105 impl->lockWrite();
103 impl->m_Name = name;
106 impl->m_Name = name;
104 impl->unlock();
107 impl->unlock();
105 }
108 }
106
109
107 SqpRange Variable::range() const noexcept
110 SqpRange Variable::range() const noexcept
108 {
111 {
109 impl->lockRead();
112 impl->lockRead();
110 auto range = impl->m_Range;
113 auto range = impl->m_Range;
111 impl->unlock();
114 impl->unlock();
112 return range;
115 return range;
113 }
116 }
114
117
115 void Variable::setRange(const SqpRange &range) noexcept
118 void Variable::setRange(const SqpRange &range) noexcept
116 {
119 {
117 impl->lockWrite();
120 impl->lockWrite();
118 impl->m_Range = range;
121 impl->m_Range = range;
119 impl->updateRealRange();
122 impl->updateRealRange();
120 impl->unlock();
123 impl->unlock();
121 }
124 }
122
125
123 SqpRange Variable::cacheRange() const noexcept
126 SqpRange Variable::cacheRange() const noexcept
124 {
127 {
125 impl->lockRead();
128 impl->lockRead();
126 auto cacheRange = impl->m_CacheRange;
129 auto cacheRange = impl->m_CacheRange;
127 impl->unlock();
130 impl->unlock();
128 return cacheRange;
131 return cacheRange;
129 }
132 }
130
133
131 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
134 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
132 {
135 {
133 impl->lockWrite();
136 impl->lockWrite();
134 if (cacheRange != impl->m_CacheRange) {
137 if (cacheRange != impl->m_CacheRange) {
135 impl->m_CacheRange = cacheRange;
138 impl->m_CacheRange = cacheRange;
136 impl->purgeDataSeries();
139 impl->purgeDataSeries();
137 }
140 }
138 impl->unlock();
141 impl->unlock();
139 }
142 }
140
143
141 int Variable::nbPoints() const noexcept
144 int Variable::nbPoints() const noexcept
142 {
145 {
143 return impl->m_NbPoints;
146 return impl->m_NbPoints;
144 }
147 }
145
148
146 SqpRange Variable::realRange() const noexcept
149 SqpRange Variable::realRange() const noexcept
147 {
150 {
148 return impl->m_RealRange;
151 return impl->m_RealRange;
149 }
152 }
150
153
151 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
154 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
152 {
155 {
153 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
156 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
154 << QThread::currentThread()->objectName();
157 << QThread::currentThread()->objectName();
155 if (!dataSeries) {
158 if (!dataSeries) {
156 /// @todo ALX : log
159 /// @todo ALX : log
157 return;
160 return;
158 }
161 }
159
162
160 // Add or merge the data
163 // Add or merge the data
161 impl->lockWrite();
164 impl->lockWrite();
162 if (!impl->m_DataSeries) {
165 if (!impl->m_DataSeries) {
163 impl->m_DataSeries = dataSeries->clone();
166 impl->m_DataSeries = dataSeries->clone();
164 }
167 }
165 else {
168 else {
166 impl->m_DataSeries->merge(dataSeries.get());
169 impl->m_DataSeries->merge(dataSeries.get());
167 }
170 }
168 impl->purgeDataSeries();
171 impl->purgeDataSeries();
169 impl->unlock();
172 impl->unlock();
170 }
173 }
171
174
172 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
175 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
173 {
176 {
174 impl->lockRead();
177 impl->lockRead();
175 auto dataSeries = impl->m_DataSeries;
178 auto dataSeries = impl->m_DataSeries;
176 impl->unlock();
179 impl->unlock();
177
180
178 return dataSeries;
181 return dataSeries;
179 }
182 }
180
183
181 QVariantHash Variable::metadata() const noexcept
184 QVariantHash Variable::metadata() const noexcept
182 {
185 {
183 impl->lockRead();
186 impl->lockRead();
184 auto metadata = impl->m_Metadata;
187 auto metadata = impl->m_Metadata;
185 impl->unlock();
188 impl->unlock();
186 return metadata;
189 return metadata;
187 }
190 }
188
191
189 bool Variable::contains(const SqpRange &range) const noexcept
192 bool Variable::contains(const SqpRange &range) const noexcept
190 {
193 {
191 impl->lockRead();
194 impl->lockRead();
192 auto res = impl->m_Range.contains(range);
195 auto res = impl->m_Range.contains(range);
193 impl->unlock();
196 impl->unlock();
194 return res;
197 return res;
195 }
198 }
196
199
197 bool Variable::intersect(const SqpRange &range) const noexcept
200 bool Variable::intersect(const SqpRange &range) const noexcept
198 {
201 {
199
202
200 impl->lockRead();
203 impl->lockRead();
201 auto res = impl->m_Range.intersect(range);
204 auto res = impl->m_Range.intersect(range);
202 impl->unlock();
205 impl->unlock();
203 return res;
206 return res;
204 }
207 }
205
208
206 bool Variable::isInside(const SqpRange &range) const noexcept
209 bool Variable::isInside(const SqpRange &range) const noexcept
207 {
210 {
208 impl->lockRead();
211 impl->lockRead();
209 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
212 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
210 impl->unlock();
213 impl->unlock();
211 return res;
214 return res;
212 }
215 }
213
216
214 bool Variable::cacheContains(const SqpRange &range) const noexcept
217 bool Variable::cacheContains(const SqpRange &range) const noexcept
215 {
218 {
216 impl->lockRead();
219 impl->lockRead();
217 auto res = impl->m_CacheRange.contains(range);
220 auto res = impl->m_CacheRange.contains(range);
218 impl->unlock();
221 impl->unlock();
219 return res;
222 return res;
220 }
223 }
221
224
222 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
225 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
223 {
226 {
224 impl->lockRead();
227 impl->lockRead();
225 auto res = impl->m_CacheRange.intersect(range);
228 auto res = impl->m_CacheRange.intersect(range);
226 impl->unlock();
229 impl->unlock();
227 return res;
230 return res;
228 }
231 }
229
232
230 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
233 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
231 {
234 {
232 impl->lockRead();
235 impl->lockRead();
233 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
236 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
234 impl->unlock();
237 impl->unlock();
235 return res;
238 return res;
236 }
239 }
237
240
238
241
239 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
242 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
240 {
243 {
241 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
244 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
242
245
243 auto notInCache = QVector<SqpRange>{};
246 auto notInCache = QVector<SqpRange>{};
244
247
245 if (!this->cacheContains(range)) {
248 if (!this->cacheContains(range)) {
246 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
249 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
247 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
250 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
248 notInCache << range;
251 notInCache << range;
249 }
252 }
250 else if (range.m_TStart < impl->m_CacheRange.m_TStart
253 else if (range.m_TStart < impl->m_CacheRange.m_TStart
251 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
254 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
252 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
255 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
253 }
256 }
254 else if (range.m_TStart < impl->m_CacheRange.m_TStart
257 else if (range.m_TStart < impl->m_CacheRange.m_TStart
255 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
258 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
256 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
259 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
257 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
260 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
258 }
261 }
259 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
262 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
260 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
263 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
261 }
264 }
262 else {
265 else {
263 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
266 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
264 << QThread::currentThread();
267 << QThread::currentThread();
265 }
268 }
266 }
269 }
267
270
268 return notInCache;
271 return notInCache;
269 }
272 }
270
273
271 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
274 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
272 {
275 {
273 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
276 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
274
277
275 auto inCache = QVector<SqpRange>{};
278 auto inCache = QVector<SqpRange>{};
276
279
277
280
278 if (this->intersect(range)) {
281 if (this->intersect(range)) {
279 if (range.m_TStart <= impl->m_CacheRange.m_TStart
282 if (range.m_TStart <= impl->m_CacheRange.m_TStart
280 && range.m_TEnd >= impl->m_CacheRange.m_TStart
283 && range.m_TEnd >= impl->m_CacheRange.m_TStart
281 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
284 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
282 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
285 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
283 }
286 }
284
287
285 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
288 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
286 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
289 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
287 inCache << range;
290 inCache << range;
288 }
291 }
289 else if (range.m_TStart > impl->m_CacheRange.m_TStart
292 else if (range.m_TStart > impl->m_CacheRange.m_TStart
290 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
293 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
291 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
294 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
292 }
295 }
293 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
296 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
294 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
297 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
295 inCache << impl->m_CacheRange;
298 inCache << impl->m_CacheRange;
296 }
299 }
297 else {
300 else {
298 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
301 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
299 << QThread::currentThread();
302 << QThread::currentThread();
300 }
303 }
301 }
304 }
302
305
303 return inCache;
306 return inCache;
304 }
307 }
General Comments 0
You need to be logged in to leave comments. Login now