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