##// END OF EJS Templates
Calls purge() method when setting cache range or data series of a variable
Alexandre Leroux -
r677:0efbd3cc5e8d
parent child
Show More
@@ -1,75 +1,74
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 28 explicit Variable(const QString &name, const SqpRange &dateTime,
29 29 const QVariantHash &metadata = {});
30 30
31 31 QString name() const noexcept;
32 32 SqpRange range() const noexcept;
33 33 void setRange(const SqpRange &range) noexcept;
34 34 SqpRange cacheRange() const noexcept;
35 35 void setCacheRange(const SqpRange &cacheRange) noexcept;
36 36
37 37 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
38 38 /// series between the range of the variable. The real range is updated each time the variable
39 39 /// range or the data series changed
40 40 /// @return the real range, invalid range if the data series is null or empty
41 41 /// @sa setDataSeries()
42 42 /// @sa setRange()
43 43 SqpRange realRange() const noexcept;
44 44
45 45 /// @return the data of the variable, nullptr if there is no data
46 46 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
47 47
48 48 QVariantHash metadata() const noexcept;
49 49
50 50 bool contains(const SqpRange &range) const noexcept;
51 51 bool intersect(const SqpRange &range) const noexcept;
52 52 bool isInside(const SqpRange &range) const noexcept;
53 53
54 54 bool cacheContains(const SqpRange &range) const noexcept;
55 55 bool cacheIntersect(const SqpRange &range) const noexcept;
56 56 bool cacheIsInside(const SqpRange &range) const noexcept;
57 57
58 58 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
59 59 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
60 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
61 60 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
62 61
63 62 signals:
64 63 void updated();
65 64
66 65 private:
67 66 class VariablePrivate;
68 67 spimpl::unique_impl_ptr<VariablePrivate> impl;
69 68 };
70 69
71 70 // Required for using shared_ptr in signals/slots
72 71 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
73 72 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
74 73
75 74 #endif // SCIQLOP_VARIABLE_H
@@ -1,279 +1,270
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 {
21 21 }
22 22
23 23 void lockRead() { m_Lock.lockForRead(); }
24 24 void lockWrite() { m_Lock.lockForWrite(); }
25 25 void unlock() { m_Lock.unlock(); }
26 26
27 void purgeDataSeries()
28 {
29 if (m_DataSeries) {
30 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
31 }
32 updateRealRange();
33 }
34
27 35 /// Updates real range according to current variable range and data series
28 36 void updateRealRange()
29 37 {
30 38 if (m_DataSeries) {
31 39 m_DataSeries->lockRead();
32 40 auto end = m_DataSeries->cend();
33 41 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
34 42 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
35 43
36 44 m_RealRange = (minXAxisIt != end && maxXAxisIt != end)
37 45 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
38 46 : INVALID_RANGE;
39 47 m_DataSeries->unlock();
40 48 }
41 49 else {
42 50 m_RealRange = INVALID_RANGE;
43 51 }
44 52 }
45 53
46 54 QString m_Name;
47 55
48 56 SqpRange m_Range;
49 57 SqpRange m_CacheRange;
50 58 QVariantHash m_Metadata;
51 59 std::shared_ptr<IDataSeries> m_DataSeries;
52 60 SqpRange m_RealRange;
53 61
54 62 QReadWriteLock m_Lock;
55 63 };
56 64
57 65 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
58 66 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
59 67 {
60 68 }
61 69
62 70 QString Variable::name() const noexcept
63 71 {
64 72 impl->lockRead();
65 73 auto name = impl->m_Name;
66 74 impl->unlock();
67 75 return name;
68 76 }
69 77
70 78 SqpRange Variable::range() const noexcept
71 79 {
72 80 impl->lockRead();
73 81 auto range = impl->m_Range;
74 82 impl->unlock();
75 83 return range;
76 84 }
77 85
78 86 void Variable::setRange(const SqpRange &range) noexcept
79 87 {
80 88 impl->lockWrite();
81 89 impl->m_Range = range;
82 90 impl->updateRealRange();
83 91 impl->unlock();
84 92 }
85 93
86 94 SqpRange Variable::cacheRange() const noexcept
87 95 {
88 96 impl->lockRead();
89 97 auto cacheRange = impl->m_CacheRange;
90 98 impl->unlock();
91 99 return cacheRange;
92 100 }
93 101
94 102 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
95 103 {
96 104 impl->lockWrite();
97 impl->m_CacheRange = cacheRange;
105 if (cacheRange != impl->m_CacheRange) {
106 impl->m_CacheRange = cacheRange;
107 impl->purgeDataSeries();
108 }
98 109 impl->unlock();
99 110 }
100 111
101 112 SqpRange Variable::realRange() const noexcept
102 113 {
103 114 return impl->m_RealRange;
104 115 }
105 116
106 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
107 {
108 qCDebug(LOG_Variable()) << "TORM Variable::setDataSeries"
109 << QThread::currentThread()->objectName();
110 if (!dataSeries) {
111 /// @todo ALX : log
112 return;
113 }
114 impl->lockWrite();
115 impl->m_DataSeries = dataSeries->clone();
116 impl->updateRealRange();
117 impl->unlock();
118 }
119
120 117 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
121 118 {
122 119 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
123 120 << QThread::currentThread()->objectName();
124 121 if (!dataSeries) {
125 122 /// @todo ALX : log
126 123 return;
127 124 }
128 125
129 126 // Add or merge the data
130 // Inits the data series of the variable
131 127 impl->lockWrite();
132 128 if (!impl->m_DataSeries) {
133 129 impl->m_DataSeries = dataSeries->clone();
134 130 }
135 131 else {
136 132 impl->m_DataSeries->merge(dataSeries.get());
137 133 }
134 impl->purgeDataSeries();
138 135 impl->unlock();
139
140 // sub the data
141 auto subData = this->dataSeries()->subDataSeries(this->cacheRange());
142 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries sub" << subData->range();
143 this->setDataSeries(subData);
144 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries set" << this->dataSeries()->range();
145 136 }
146 137
147 138 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
148 139 {
149 140 impl->lockRead();
150 141 auto dataSeries = impl->m_DataSeries;
151 142 impl->unlock();
152 143
153 144 return dataSeries;
154 145 }
155 146
156 147 QVariantHash Variable::metadata() const noexcept
157 148 {
158 149 impl->lockRead();
159 150 auto metadata = impl->m_Metadata;
160 151 impl->unlock();
161 152 return metadata;
162 153 }
163 154
164 155 bool Variable::contains(const SqpRange &range) const noexcept
165 156 {
166 157 impl->lockRead();
167 158 auto res = impl->m_Range.contains(range);
168 159 impl->unlock();
169 160 return res;
170 161 }
171 162
172 163 bool Variable::intersect(const SqpRange &range) const noexcept
173 164 {
174 165
175 166 impl->lockRead();
176 167 auto res = impl->m_Range.intersect(range);
177 168 impl->unlock();
178 169 return res;
179 170 }
180 171
181 172 bool Variable::isInside(const SqpRange &range) const noexcept
182 173 {
183 174 impl->lockRead();
184 175 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
185 176 impl->unlock();
186 177 return res;
187 178 }
188 179
189 180 bool Variable::cacheContains(const SqpRange &range) const noexcept
190 181 {
191 182 impl->lockRead();
192 183 auto res = impl->m_CacheRange.contains(range);
193 184 impl->unlock();
194 185 return res;
195 186 }
196 187
197 188 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
198 189 {
199 190 impl->lockRead();
200 191 auto res = impl->m_CacheRange.intersect(range);
201 192 impl->unlock();
202 193 return res;
203 194 }
204 195
205 196 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
206 197 {
207 198 impl->lockRead();
208 199 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
209 200 impl->unlock();
210 201 return res;
211 202 }
212 203
213 204
214 205 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
215 206 {
216 207 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
217 208
218 209 auto notInCache = QVector<SqpRange>{};
219 210
220 211 if (!this->cacheContains(range)) {
221 212 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
222 213 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
223 214 notInCache << range;
224 215 }
225 216 else if (range.m_TStart < impl->m_CacheRange.m_TStart
226 217 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
227 218 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
228 219 }
229 220 else if (range.m_TStart < impl->m_CacheRange.m_TStart
230 221 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
231 222 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
232 223 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
233 224 }
234 225 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
235 226 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
236 227 }
237 228 else {
238 229 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
239 230 << QThread::currentThread();
240 231 }
241 232 }
242 233
243 234 return notInCache;
244 235 }
245 236
246 237 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
247 238 {
248 239 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
249 240
250 241 auto inCache = QVector<SqpRange>{};
251 242
252 243
253 244 if (this->intersect(range)) {
254 245 if (range.m_TStart <= impl->m_CacheRange.m_TStart
255 246 && range.m_TEnd >= impl->m_CacheRange.m_TStart
256 247 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
257 248 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
258 249 }
259 250
260 251 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
261 252 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
262 253 inCache << range;
263 254 }
264 255 else if (range.m_TStart > impl->m_CacheRange.m_TStart
265 256 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
266 257 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
267 258 }
268 259 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
269 260 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
270 261 inCache << impl->m_CacheRange;
271 262 }
272 263 else {
273 264 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
274 265 << QThread::currentThread();
275 266 }
276 267 }
277 268
278 269 return inCache;
279 270 }
General Comments 0
You need to be logged in to leave comments. Login now