##// END OF EJS Templates
Adds getters/setters for variable states
Alexandre Leroux -
r808:7c7e13374a74
parent child
Show More
@@ -1,83 +1,89
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 #include <Variable/VariableStates.h>
16
15 17 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
16 18
17 19 class IDataSeries;
18 20 class QString;
19 21
20 22 /**
21 23 * @brief The Variable class represents a variable in SciQlop.
22 24 */
23 25 class SCIQLOP_CORE_EXPORT Variable : public QObject {
24 26
25 27 Q_OBJECT
26 28
27 29 public:
28 30 explicit Variable(const QString &name, const QVariantHash &metadata = {});
29 31
30 32 /// Copy ctor
31 33 explicit Variable(const Variable &other);
32 34
33 35 std::shared_ptr<Variable> clone() const;
34 36
35 37 QString name() const noexcept;
36 38 void setName(const QString &name) noexcept;
37 39 SqpRange range() const noexcept;
38 40 void setRange(const SqpRange &range) noexcept;
39 41 SqpRange cacheRange() const noexcept;
40 42 void setCacheRange(const SqpRange &cacheRange) noexcept;
41 43
44 /// @return the properties associated to the current state of the variable
45 StateData stateData() const noexcept;
46 void setState(std::unique_ptr<IVariableState> state) noexcept;
47
42 48 /// @return the number of points hold by the variable. The number of points is updated each time
43 49 /// the data series changes
44 50 int nbPoints() const noexcept;
45 51
46 52 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
47 53 /// series between the range of the variable. The real range is updated each time the variable
48 54 /// range or the data series changed
49 55 /// @return the real range, invalid range if the data series is null or empty
50 56 /// @sa setDataSeries()
51 57 /// @sa setRange()
52 58 SqpRange realRange() const noexcept;
53 59
54 60 /// @return the data of the variable, nullptr if there is no data
55 61 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
56 62
57 63 QVariantHash metadata() const noexcept;
58 64
59 65 bool contains(const SqpRange &range) const noexcept;
60 66 bool intersect(const SqpRange &range) const noexcept;
61 67 bool isInside(const SqpRange &range) const noexcept;
62 68
63 69 bool cacheContains(const SqpRange &range) const noexcept;
64 70 bool cacheIntersect(const SqpRange &range) const noexcept;
65 71 bool cacheIsInside(const SqpRange &range) const noexcept;
66 72
67 73 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
68 74 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
69 75 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
70 76
71 77 signals:
72 78 void updated();
73 79
74 80 private:
75 81 class VariablePrivate;
76 82 spimpl::unique_impl_ptr<VariablePrivate> impl;
77 83 };
78 84
79 85 // Required for using shared_ptr in signals/slots
80 86 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
81 87 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
82 88
83 89 #endif // SCIQLOP_VARIABLE_H
@@ -1,315 +1,338
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 QVariantHash &metadata)
14 14 : m_Name{name},
15 15 m_Range{INVALID_RANGE},
16 16 m_CacheRange{INVALID_RANGE},
17 17 m_Metadata{metadata},
18 18 m_DataSeries{nullptr},
19 19 m_RealRange{INVALID_RANGE},
20 m_NbPoints{0}
20 m_NbPoints{0},
21 m_State{std::make_unique<LoadedState>()}
22
21 23 {
22 24 }
23 25
24 26 VariablePrivate(const VariablePrivate &other)
25 27 : m_Name{other.m_Name},
26 28 m_Range{other.m_Range},
27 29 m_CacheRange{other.m_CacheRange},
28 30 m_Metadata{other.m_Metadata},
29 31 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
30 32 m_RealRange{other.m_RealRange},
31 m_NbPoints{other.m_NbPoints}
33 m_NbPoints{other.m_NbPoints},
34 m_State{other.m_State->clone()}
35
32 36 {
33 37 }
34 38
35 39 void lockRead() { m_Lock.lockForRead(); }
36 40 void lockWrite() { m_Lock.lockForWrite(); }
37 41 void unlock() { m_Lock.unlock(); }
38 42
39 43 void purgeDataSeries()
40 44 {
41 45 if (m_DataSeries) {
42 46 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
43 47 }
44 48 updateRealRange();
45 49 updateNbPoints();
46 50 }
47 51
48 52 void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
49 53
50 54 /// Updates real range according to current variable range and data series
51 55 void updateRealRange()
52 56 {
53 57 if (m_DataSeries) {
54 58 m_DataSeries->lockRead();
55 59 auto end = m_DataSeries->cend();
56 60 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
57 61 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
58 62
59 63 m_RealRange
60 64 = (minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x())
61 65 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
62 66 : INVALID_RANGE;
63 67 m_DataSeries->unlock();
64 68 }
65 69 else {
66 70 m_RealRange = INVALID_RANGE;
67 71 }
68 72 }
69 73
70 74 QString m_Name;
71 75
72 76 SqpRange m_Range;
73 77 SqpRange m_CacheRange;
74 78 QVariantHash m_Metadata;
75 79 std::shared_ptr<IDataSeries> m_DataSeries;
76 80 SqpRange m_RealRange;
77 81 int m_NbPoints;
82 std::unique_ptr<IVariableState> m_State;
78 83
79 84 QReadWriteLock m_Lock;
80 85 };
81 86
82 87 Variable::Variable(const QString &name, const QVariantHash &metadata)
83 88 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)}
84 89 {
85 90 }
86 91
87 92 Variable::Variable(const Variable &other)
88 93 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)}
89 94 {
90 95 }
91 96
92 97 std::shared_ptr<Variable> Variable::clone() const
93 98 {
94 99 return std::make_shared<Variable>(*this);
95 100 }
96 101
97 102 QString Variable::name() const noexcept
98 103 {
99 104 impl->lockRead();
100 105 auto name = impl->m_Name;
101 106 impl->unlock();
102 107 return name;
103 108 }
104 109
105 110 void Variable::setName(const QString &name) noexcept
106 111 {
107 112 impl->lockWrite();
108 113 impl->m_Name = name;
109 114 impl->unlock();
110 115 }
111 116
112 117 SqpRange Variable::range() const noexcept
113 118 {
114 119 impl->lockRead();
115 120 auto range = impl->m_Range;
116 121 impl->unlock();
117 122 return range;
118 123 }
119 124
120 125 void Variable::setRange(const SqpRange &range) noexcept
121 126 {
122 127 impl->lockWrite();
123 128 impl->m_Range = range;
124 129 impl->updateRealRange();
125 130 impl->unlock();
126 131 }
127 132
128 133 SqpRange Variable::cacheRange() const noexcept
129 134 {
130 135 impl->lockRead();
131 136 auto cacheRange = impl->m_CacheRange;
132 137 impl->unlock();
133 138 return cacheRange;
134 139 }
135 140
136 141 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
137 142 {
138 143 impl->lockWrite();
139 144 if (cacheRange != impl->m_CacheRange) {
140 145 impl->m_CacheRange = cacheRange;
141 146 impl->purgeDataSeries();
142 147 }
143 148 impl->unlock();
144 149 }
145 150
151 StateData Variable::stateData() const noexcept
152 {
153 impl->lockRead();
154 Q_ASSERT(impl->m_State != nullptr);
155 auto stateData = impl->m_State->data();
156 impl->unlock();
157
158 return stateData;
159 }
160
161 void Variable::setState(std::unique_ptr<IVariableState> state) noexcept
162 {
163 Q_ASSERT(state != nullptr);
164 impl->lockWrite();
165 impl->m_State = std::move(state);
166 impl->unlock();
167 }
168
146 169 int Variable::nbPoints() const noexcept
147 170 {
148 171 return impl->m_NbPoints;
149 172 }
150 173
151 174 SqpRange Variable::realRange() const noexcept
152 175 {
153 176 return impl->m_RealRange;
154 177 }
155 178
156 179 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
157 180 {
158 181 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
159 182 << QThread::currentThread()->objectName();
160 183 if (!dataSeries) {
161 184 /// @todo ALX : log
162 185 return;
163 186 }
164 187
165 188 // Add or merge the data
166 189 impl->lockWrite();
167 190 if (!impl->m_DataSeries) {
168 191 impl->m_DataSeries = dataSeries->clone();
169 192 }
170 193 else {
171 194 impl->m_DataSeries->merge(dataSeries.get());
172 195 }
173 196 impl->purgeDataSeries();
174 197 impl->unlock();
175 198 }
176 199
177 200 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
178 201 {
179 202 impl->lockRead();
180 203 auto dataSeries = impl->m_DataSeries;
181 204 impl->unlock();
182 205
183 206 return dataSeries;
184 207 }
185 208
186 209 QVariantHash Variable::metadata() const noexcept
187 210 {
188 211 impl->lockRead();
189 212 auto metadata = impl->m_Metadata;
190 213 impl->unlock();
191 214 return metadata;
192 215 }
193 216
194 217 bool Variable::contains(const SqpRange &range) const noexcept
195 218 {
196 219 impl->lockRead();
197 220 auto res = impl->m_Range.contains(range);
198 221 impl->unlock();
199 222 return res;
200 223 }
201 224
202 225 bool Variable::intersect(const SqpRange &range) const noexcept
203 226 {
204 227
205 228 impl->lockRead();
206 229 auto res = impl->m_Range.intersect(range);
207 230 impl->unlock();
208 231 return res;
209 232 }
210 233
211 234 bool Variable::isInside(const SqpRange &range) const noexcept
212 235 {
213 236 impl->lockRead();
214 237 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
215 238 impl->unlock();
216 239 return res;
217 240 }
218 241
219 242 bool Variable::cacheContains(const SqpRange &range) const noexcept
220 243 {
221 244 impl->lockRead();
222 245 auto res = impl->m_CacheRange.contains(range);
223 246 impl->unlock();
224 247 return res;
225 248 }
226 249
227 250 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
228 251 {
229 252 impl->lockRead();
230 253 auto res = impl->m_CacheRange.intersect(range);
231 254 impl->unlock();
232 255 return res;
233 256 }
234 257
235 258 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
236 259 {
237 260 impl->lockRead();
238 261 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
239 262 impl->unlock();
240 263 return res;
241 264 }
242 265
243 266
244 267 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
245 268 {
246 269 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
247 270 auto notInCache = QVector<SqpRange>{};
248 271 if (impl->m_CacheRange != INVALID_RANGE) {
249 272
250 273 if (!this->cacheContains(range)) {
251 274 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
252 275 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
253 276 notInCache << range;
254 277 }
255 278 else if (range.m_TStart < impl->m_CacheRange.m_TStart
256 279 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
257 280 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
258 281 }
259 282 else if (range.m_TStart < impl->m_CacheRange.m_TStart
260 283 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
261 284 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
262 285 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
263 286 }
264 287 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
265 288 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
266 289 }
267 290 else {
268 291 qCCritical(LOG_Variable())
269 292 << tr("Detection of unknown case.") << QThread::currentThread();
270 293 }
271 294 }
272 295 }
273 296 else {
274 297 notInCache << range;
275 298 }
276 299
277 300 return notInCache;
278 301 }
279 302
280 303 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
281 304 {
282 305 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
283 306
284 307 auto inCache = QVector<SqpRange>{};
285 308
286 309 if (impl->m_CacheRange != INVALID_RANGE) {
287 310
288 311 if (this->intersect(range)) {
289 312 if (range.m_TStart <= impl->m_CacheRange.m_TStart
290 313 && range.m_TEnd >= impl->m_CacheRange.m_TStart
291 314 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
292 315 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
293 316 }
294 317
295 318 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
296 319 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
297 320 inCache << range;
298 321 }
299 322 else if (range.m_TStart > impl->m_CacheRange.m_TStart
300 323 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
301 324 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
302 325 }
303 326 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
304 327 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
305 328 inCache << impl->m_CacheRange;
306 329 }
307 330 else {
308 331 qCCritical(LOG_Variable())
309 332 << tr("Detection of unknown case.") << QThread::currentThread();
310 333 }
311 334 }
312 335 }
313 336
314 337 return inCache;
315 338 }
General Comments 0
You need to be logged in to leave comments. Login now