##// END OF EJS Templates
Merge branch 'feature/DataSeriesIterator' into develop
Alexandre Leroux -
r559:575b804cd7dd merge
parent child
Show More
@@ -1,230 +1,298
1 #ifndef SCIQLOP_ARRAYDATA_H
1 #ifndef SCIQLOP_ARRAYDATA_H
2 #define SCIQLOP_ARRAYDATA_H
2 #define SCIQLOP_ARRAYDATA_H
3
3
4 #include <Common/SortUtils.h>
4 #include <Common/SortUtils.h>
5
5
6 #include <QReadLocker>
6 #include <QReadLocker>
7 #include <QReadWriteLock>
7 #include <QReadWriteLock>
8 #include <QVector>
8 #include <QVector>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 template <int Dim>
12 template <int Dim>
13 class ArrayData;
13 class ArrayData;
14
14
15 using DataContainer = QVector<QVector<double> >;
15 using DataContainer = QVector<QVector<double> >;
16
16
17 namespace arraydata_detail {
17 namespace arraydata_detail {
18
18
19 /// Struct used to sort ArrayData
19 /// Struct used to sort ArrayData
20 template <int Dim>
20 template <int Dim>
21 struct Sort {
21 struct Sort {
22 static std::shared_ptr<ArrayData<Dim> > sort(const DataContainer &data,
22 static std::shared_ptr<ArrayData<Dim> > sort(const DataContainer &data,
23 const std::vector<int> &sortPermutation)
23 const std::vector<int> &sortPermutation)
24 {
24 {
25 auto nbComponents = data.size();
25 auto nbComponents = data.size();
26 auto sortedData = DataContainer(nbComponents);
26 auto sortedData = DataContainer(nbComponents);
27
27
28 for (auto i = 0; i < nbComponents; ++i) {
28 for (auto i = 0; i < nbComponents; ++i) {
29 sortedData[i] = SortUtils::sort(data.at(i), sortPermutation);
29 sortedData[i] = SortUtils::sort(data.at(i), sortPermutation);
30 }
30 }
31
31
32 return std::make_shared<ArrayData<Dim> >(std::move(sortedData));
32 return std::make_shared<ArrayData<Dim> >(std::move(sortedData));
33 }
33 }
34 };
34 };
35
35
36 /// Specialization for uni-dimensional ArrayData
36 /// Specialization for uni-dimensional ArrayData
37 template <>
37 template <>
38 struct Sort<1> {
38 struct Sort<1> {
39 static std::shared_ptr<ArrayData<1> > sort(const DataContainer &data,
39 static std::shared_ptr<ArrayData<1> > sort(const DataContainer &data,
40 const std::vector<int> &sortPermutation)
40 const std::vector<int> &sortPermutation)
41 {
41 {
42 return std::make_shared<ArrayData<1> >(SortUtils::sort(data.at(0), sortPermutation));
42 return std::make_shared<ArrayData<1> >(SortUtils::sort(data.at(0), sortPermutation));
43 }
43 }
44 };
44 };
45
45
46 } // namespace arraydata_detail
46 } // namespace arraydata_detail
47
47
48 /**
48 /**
49 * @brief The ArrayData class represents a dataset for a data series.
49 * @brief The ArrayData class represents a dataset for a data series.
50 *
50 *
51 * A dataset can be unidimensional or two-dimensional. This property is determined by the Dim
51 * A dataset can be unidimensional or two-dimensional. This property is determined by the Dim
52 * template-parameter. In a case of a two-dimensional dataset, each dataset component has the same
52 * template-parameter. In a case of a two-dimensional dataset, each dataset component has the same
53 * number of values
53 * number of values
54 *
54 *
55 * @tparam Dim the dimension of the ArrayData (one or two)
55 * @tparam Dim the dimension of the ArrayData (one or two)
56 * @sa IDataSeries
56 * @sa IDataSeries
57 */
57 */
58 template <int Dim>
58 template <int Dim>
59 class ArrayData {
59 class ArrayData {
60 public:
60 public:
61 class IteratorValue {
62 public:
63 explicit IteratorValue(const DataContainer &container, bool begin) : m_Its{}
64 {
65 for (auto i = 0; i < container.size(); ++i) {
66 m_Its.push_back(begin ? container.at(i).cbegin() : container.at(i).cend());
67 }
68 }
69
70 double at(int index) const { return *m_Its.at(index); }
71 double first() const { return *m_Its.front(); }
72
73 void next()
74 {
75 for (auto &it : m_Its) {
76 ++it;
77 }
78 }
79
80 bool operator==(const IteratorValue &other) const { return m_Its == other.m_Its; }
81
82 private:
83 std::vector<DataContainer::value_type::const_iterator> m_Its;
84 };
85
86 class Iterator {
87 public:
88 using iterator_category = std::forward_iterator_tag;
89 using value_type = const IteratorValue;
90 using difference_type = std::ptrdiff_t;
91 using pointer = value_type *;
92 using reference = value_type &;
93
94 Iterator(const DataContainer &container, bool begin) : m_CurrentValue{container, begin} {}
95
96 virtual ~Iterator() noexcept = default;
97 Iterator(const Iterator &) = default;
98 Iterator(Iterator &&) = default;
99 Iterator &operator=(const Iterator &) = default;
100 Iterator &operator=(Iterator &&) = default;
101
102 Iterator &operator++()
103 {
104 m_CurrentValue.next();
105 return *this;
106 }
107
108 pointer operator->() const { return &m_CurrentValue; }
109 reference operator*() const { return m_CurrentValue; }
110
111 bool operator==(const Iterator &other) const
112 {
113 return m_CurrentValue == other.m_CurrentValue;
114 }
115
116 bool operator!=(const Iterator &other) const { return !(*this == other); }
117
118 private:
119 IteratorValue m_CurrentValue;
120 };
121
61 // ///// //
122 // ///// //
62 // Ctors //
123 // Ctors //
63 // ///// //
124 // ///// //
64
125
65 /**
126 /**
66 * Ctor for a unidimensional ArrayData
127 * Ctor for a unidimensional ArrayData
67 * @param data the data the ArrayData will hold
128 * @param data the data the ArrayData will hold
68 */
129 */
69 template <int D = Dim, typename = std::enable_if_t<D == 1> >
130 template <int D = Dim, typename = std::enable_if_t<D == 1> >
70 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
131 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
71 {
132 {
72 m_Data[0] = std::move(data);
133 m_Data[0] = std::move(data);
73 }
134 }
74
135
75 /**
136 /**
76 * Ctor for a two-dimensional ArrayData. The number of components (number of vectors) must be
137 * Ctor for a two-dimensional ArrayData. The number of components (number of vectors) must be
77 * greater than 2 and each component must have the same number of values
138 * greater than 2 and each component must have the same number of values
78 * @param data the data the ArrayData will hold
139 * @param data the data the ArrayData will hold
79 * @throws std::invalid_argument if the number of components is less than 2
140 * @throws std::invalid_argument if the number of components is less than 2
80 * @remarks if the number of values is not the same for each component, no value is set
141 * @remarks if the number of values is not the same for each component, no value is set
81 */
142 */
82 template <int D = Dim, typename = std::enable_if_t<D == 2> >
143 template <int D = Dim, typename = std::enable_if_t<D == 2> >
83 explicit ArrayData(DataContainer data)
144 explicit ArrayData(DataContainer data)
84 {
145 {
85 auto nbComponents = data.size();
146 auto nbComponents = data.size();
86 if (nbComponents < 2) {
147 if (nbComponents < 2) {
87 throw std::invalid_argument{
148 throw std::invalid_argument{
88 QString{"A multidimensional ArrayData must have at least 2 components (found: %1"}
149 QString{"A multidimensional ArrayData must have at least 2 components (found: %1"}
89 .arg(data.size())
150 .arg(data.size())
90 .toStdString()};
151 .toStdString()};
91 }
152 }
92
153
93 auto nbValues = data.front().size();
154 auto nbValues = data.front().size();
94 if (std::all_of(data.cbegin(), data.cend(), [nbValues](const auto &component) {
155 if (std::all_of(data.cbegin(), data.cend(), [nbValues](const auto &component) {
95 return component.size() == nbValues;
156 return component.size() == nbValues;
96 })) {
157 })) {
97 m_Data = std::move(data);
158 m_Data = std::move(data);
98 }
159 }
99 else {
160 else {
100 m_Data = DataContainer{nbComponents, QVector<double>{}};
161 m_Data = DataContainer{nbComponents, QVector<double>{}};
101 }
162 }
102 }
163 }
103
164
104 /// Copy ctor
165 /// Copy ctor
105 explicit ArrayData(const ArrayData &other)
166 explicit ArrayData(const ArrayData &other)
106 {
167 {
107 QReadLocker otherLocker{&other.m_Lock};
168 QReadLocker otherLocker{&other.m_Lock};
108 m_Data = other.m_Data;
169 m_Data = other.m_Data;
109 }
170 }
110
171
111 // /////////////// //
172 // /////////////// //
112 // General methods //
173 // General methods //
113 // /////////////// //
174 // /////////////// //
114
175
115 /**
176 /**
116 * Merges into the array data an other array data. The two array datas must have the same number
177 * Merges into the array data an other array data. The two array datas must have the same number
117 * of components so the merge can be done
178 * of components so the merge can be done
118 * @param other the array data to merge with
179 * @param other the array data to merge with
119 * @param prepend if true, the other array data is inserted at the beginning, otherwise it is
180 * @param prepend if true, the other array data is inserted at the beginning, otherwise it is
120 * inserted at the end
181 * inserted at the end
121 */
182 */
122 void add(const ArrayData<Dim> &other, bool prepend = false)
183 void add(const ArrayData<Dim> &other, bool prepend = false)
123 {
184 {
124 QWriteLocker locker{&m_Lock};
185 QWriteLocker locker{&m_Lock};
125 QReadLocker otherLocker{&other.m_Lock};
186 QReadLocker otherLocker{&other.m_Lock};
126
187
127 auto nbComponents = m_Data.size();
188 auto nbComponents = m_Data.size();
128 if (nbComponents != other.m_Data.size()) {
189 if (nbComponents != other.m_Data.size()) {
129 return;
190 return;
130 }
191 }
131
192
132 for (auto componentIndex = 0; componentIndex < nbComponents; ++componentIndex) {
193 for (auto componentIndex = 0; componentIndex < nbComponents; ++componentIndex) {
133 if (prepend) {
194 if (prepend) {
134 const auto &otherData = other.data(componentIndex);
195 const auto &otherData = other.data(componentIndex);
135 const auto otherDataSize = otherData.size();
196 const auto otherDataSize = otherData.size();
136
197
137 auto &data = m_Data[componentIndex];
198 auto &data = m_Data[componentIndex];
138 data.insert(data.begin(), otherDataSize, 0.);
199 data.insert(data.begin(), otherDataSize, 0.);
139
200
140 for (auto i = 0; i < otherDataSize; ++i) {
201 for (auto i = 0; i < otherDataSize; ++i) {
141 data.replace(i, otherData.at(i));
202 data.replace(i, otherData.at(i));
142 }
203 }
143 }
204 }
144 else {
205 else {
145 m_Data[componentIndex] += other.data(componentIndex);
206 m_Data[componentIndex] += other.data(componentIndex);
146 }
207 }
147 }
208 }
148 }
209 }
149
210
150 void clear()
211 void clear()
151 {
212 {
152 QWriteLocker locker{&m_Lock};
213 QWriteLocker locker{&m_Lock};
153
214
154 auto nbComponents = m_Data.size();
215 auto nbComponents = m_Data.size();
155 for (auto i = 0; i < nbComponents; ++i) {
216 for (auto i = 0; i < nbComponents; ++i) {
156 m_Data[i].clear();
217 m_Data[i].clear();
157 }
218 }
158 }
219 }
159
220
160 /**
221 /**
161 * @return the data of a component
222 * @return the data of a component
162 * @param componentIndex the index of the component to retrieve the data
223 * @param componentIndex the index of the component to retrieve the data
163 * @return the component's data, empty vector if the index is invalid
224 * @return the component's data, empty vector if the index is invalid
164 */
225 */
165 QVector<double> data(int componentIndex) const noexcept
226 QVector<double> data(int componentIndex) const noexcept
166 {
227 {
167 QReadLocker locker{&m_Lock};
228 QReadLocker locker{&m_Lock};
168
229
169 return (componentIndex >= 0 && componentIndex < m_Data.size()) ? m_Data.at(componentIndex)
230 return (componentIndex >= 0 && componentIndex < m_Data.size()) ? m_Data.at(componentIndex)
170 : QVector<double>{};
231 : QVector<double>{};
171 }
232 }
172
233
173 /// @return the size (i.e. number of values) of a single component
234 /// @return the size (i.e. number of values) of a single component
174 /// @remarks in a case of a two-dimensional ArrayData, each component has the same size
235 /// @remarks in a case of a two-dimensional ArrayData, each component has the same size
175 int size() const
236 int size() const
176 {
237 {
177 QReadLocker locker{&m_Lock};
238 QReadLocker locker{&m_Lock};
178 return m_Data[0].size();
239 return m_Data[0].size();
179 }
240 }
180
241
181 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> &sortPermutation)
242 std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> &sortPermutation)
182 {
243 {
183 QReadLocker locker{&m_Lock};
244 QReadLocker locker{&m_Lock};
184 return arraydata_detail::Sort<Dim>::sort(m_Data, sortPermutation);
245 return arraydata_detail::Sort<Dim>::sort(m_Data, sortPermutation);
185 }
246 }
186
247
248 // ///////// //
249 // Iterators //
250 // ///////// //
251
252 Iterator cbegin() const { return Iterator{m_Data, true}; }
253 Iterator cend() const { return Iterator{m_Data, false}; }
254
187 // ///////////// //
255 // ///////////// //
188 // 1-dim methods //
256 // 1-dim methods //
189 // ///////////// //
257 // ///////////// //
190
258
191 /**
259 /**
192 * @return the data at a specified index
260 * @return the data at a specified index
193 * @remarks index must be a valid position
261 * @remarks index must be a valid position
194 * @remarks this method is only available for a unidimensional ArrayData
262 * @remarks this method is only available for a unidimensional ArrayData
195 */
263 */
196 template <int D = Dim, typename = std::enable_if_t<D == 1> >
264 template <int D = Dim, typename = std::enable_if_t<D == 1> >
197 double at(int index) const noexcept
265 double at(int index) const noexcept
198 {
266 {
199 QReadLocker locker{&m_Lock};
267 QReadLocker locker{&m_Lock};
200 return m_Data[0].at(index);
268 return m_Data[0].at(index);
201 }
269 }
202
270
203 /**
271 /**
204 * @return the data as a vector, as a const reference
272 * @return the data as a vector, as a const reference
205 * @remarks this method is only available for a unidimensional ArrayData
273 * @remarks this method is only available for a unidimensional ArrayData
206 */
274 */
207 template <int D = Dim, typename = std::enable_if_t<D == 1> >
275 template <int D = Dim, typename = std::enable_if_t<D == 1> >
208 const QVector<double> &cdata() const noexcept
276 const QVector<double> &cdata() const noexcept
209 {
277 {
210 QReadLocker locker{&m_Lock};
278 QReadLocker locker{&m_Lock};
211 return m_Data.at(0);
279 return m_Data.at(0);
212 }
280 }
213
281
214 /**
282 /**
215 * @return the data as a vector
283 * @return the data as a vector
216 * @remarks this method is only available for a unidimensional ArrayData
284 * @remarks this method is only available for a unidimensional ArrayData
217 */
285 */
218 template <int D = Dim, typename = std::enable_if_t<D == 1> >
286 template <int D = Dim, typename = std::enable_if_t<D == 1> >
219 QVector<double> data() const noexcept
287 QVector<double> data() const noexcept
220 {
288 {
221 QReadLocker locker{&m_Lock};
289 QReadLocker locker{&m_Lock};
222 return m_Data[0];
290 return m_Data[0];
223 }
291 }
224
292
225 private:
293 private:
226 DataContainer m_Data;
294 DataContainer m_Data;
227 mutable QReadWriteLock m_Lock;
295 mutable QReadWriteLock m_Lock;
228 };
296 };
229
297
230 #endif // SCIQLOP_ARRAYDATA_H
298 #endif // SCIQLOP_ARRAYDATA_H
@@ -1,190 +1,288
1 #ifndef SCIQLOP_DATASERIES_H
1 #ifndef SCIQLOP_DATASERIES_H
2 #define SCIQLOP_DATASERIES_H
2 #define SCIQLOP_DATASERIES_H
3
3
4 #include <Common/SortUtils.h>
4 #include <Common/SortUtils.h>
5
5
6 #include <Data/ArrayData.h>
6 #include <Data/ArrayData.h>
7 #include <Data/IDataSeries.h>
7 #include <Data/IDataSeries.h>
8
8
9 #include <QLoggingCategory>
9 #include <QLoggingCategory>
10
10
11 #include <QReadLocker>
11 #include <QReadLocker>
12 #include <QReadWriteLock>
12 #include <QReadWriteLock>
13 #include <memory>
13 #include <memory>
14
14
15 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeries)
15 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeries)
16 Q_LOGGING_CATEGORY(LOG_DataSeries, "DataSeries")
16 Q_LOGGING_CATEGORY(LOG_DataSeries, "DataSeries")
17
17
18
18
19 /**
19 /**
20 * @brief The DataSeries class is the base (abstract) implementation of IDataSeries.
20 * @brief The DataSeries class is the base (abstract) implementation of IDataSeries.
21 *
21 *
22 * It proposes to set a dimension for the values ​​data.
22 * It proposes to set a dimension for the values ​​data.
23 *
23 *
24 * A DataSeries is always sorted on its x-axis data.
24 * A DataSeries is always sorted on its x-axis data.
25 *
25 *
26 * @tparam Dim The dimension of the values data
26 * @tparam Dim The dimension of the values data
27 *
27 *
28 */
28 */
29 template <int Dim>
29 template <int Dim>
30 class DataSeries : public IDataSeries {
30 class DataSeries : public IDataSeries {
31 public:
31 public:
32 class IteratorValue {
33 public:
34 explicit IteratorValue(const DataSeries &dataSeries, bool begin)
35 : m_XIt(begin ? dataSeries.xAxisData()->cbegin() : dataSeries.xAxisData()->cend()),
36 m_ValuesIt(begin ? dataSeries.valuesData()->cbegin()
37 : dataSeries.valuesData()->cend())
38 {
39 }
40
41 double x() const { return m_XIt->at(0); }
42 double value() const { return m_ValuesIt->at(0); }
43 double value(int componentIndex) const { return m_ValuesIt->at(componentIndex); }
44
45 void next()
46 {
47 ++m_XIt;
48 ++m_ValuesIt;
49 }
50
51 bool operator==(const IteratorValue &other) const
52 {
53 return std::tie(m_XIt, m_ValuesIt) == std::tie(other.m_XIt, other.m_ValuesIt);
54 }
55
56 private:
57 ArrayData<1>::Iterator m_XIt;
58 typename ArrayData<Dim>::Iterator m_ValuesIt;
59 };
60
61 class Iterator {
62 public:
63 using iterator_category = std::forward_iterator_tag;
64 using value_type = const IteratorValue;
65 using difference_type = std::ptrdiff_t;
66 using pointer = value_type *;
67 using reference = value_type &;
68
69 Iterator(const DataSeries &dataSeries, bool begin) : m_CurrentValue{dataSeries, begin} {}
70 virtual ~Iterator() noexcept = default;
71 Iterator(const Iterator &) = default;
72 Iterator(Iterator &&) = default;
73 Iterator &operator=(const Iterator &) = default;
74 Iterator &operator=(Iterator &&) = default;
75
76 Iterator &operator++()
77 {
78 m_CurrentValue.next();
79 return *this;
80 }
81
82 pointer operator->() const { return &m_CurrentValue; }
83
84 reference operator*() const { return m_CurrentValue; }
85
86 bool operator==(const Iterator &other) const
87 {
88 return m_CurrentValue == other.m_CurrentValue;
89 }
90
91 bool operator!=(const Iterator &other) const { return !(*this == other); }
92
93 private:
94 IteratorValue m_CurrentValue;
95 };
96
32 /// @sa IDataSeries::xAxisData()
97 /// @sa IDataSeries::xAxisData()
33 std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
98 std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
34 const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; }
99 const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; }
35
100
36 /// @sa IDataSeries::xAxisUnit()
101 /// @sa IDataSeries::xAxisUnit()
37 Unit xAxisUnit() const override { return m_XAxisUnit; }
102 Unit xAxisUnit() const override { return m_XAxisUnit; }
38
103
39 /// @return the values dataset
104 /// @return the values dataset
40 std::shared_ptr<ArrayData<Dim> > valuesData() { return m_ValuesData; }
105 std::shared_ptr<ArrayData<Dim> > valuesData() { return m_ValuesData; }
41 const std::shared_ptr<ArrayData<Dim> > valuesData() const { return m_ValuesData; }
106 const std::shared_ptr<ArrayData<Dim> > valuesData() const { return m_ValuesData; }
42
107
43 /// @sa IDataSeries::valuesUnit()
108 /// @sa IDataSeries::valuesUnit()
44 Unit valuesUnit() const override { return m_ValuesUnit; }
109 Unit valuesUnit() const override { return m_ValuesUnit; }
45
110
46
111
47 SqpRange range() const override
112 SqpRange range() const override
48 {
113 {
49 if (!m_XAxisData->cdata().isEmpty()) {
114 if (!m_XAxisData->cdata().isEmpty()) {
50 return SqpRange{m_XAxisData->cdata().first(), m_XAxisData->cdata().last()};
115 return SqpRange{m_XAxisData->cdata().first(), m_XAxisData->cdata().last()};
51 }
116 }
52
117
53 return SqpRange{};
118 return SqpRange{};
54 }
119 }
55
120
56 void clear()
121 void clear()
57 {
122 {
58 m_XAxisData->clear();
123 m_XAxisData->clear();
59 m_ValuesData->clear();
124 m_ValuesData->clear();
60 }
125 }
61
126
62 /// Merges into the data series an other data series
127 /// Merges into the data series an other data series
63 /// @remarks the data series to merge with is cleared after the operation
128 /// @remarks the data series to merge with is cleared after the operation
64 void merge(IDataSeries *dataSeries) override
129 void merge(IDataSeries *dataSeries) override
65 {
130 {
66 dataSeries->lockWrite();
131 dataSeries->lockWrite();
67 lockWrite();
132 lockWrite();
68
133
69 if (auto other = dynamic_cast<DataSeries<Dim> *>(dataSeries)) {
134 if (auto other = dynamic_cast<DataSeries<Dim> *>(dataSeries)) {
70 const auto &otherXAxisData = other->xAxisData()->cdata();
135 const auto &otherXAxisData = other->xAxisData()->cdata();
71 const auto &xAxisData = m_XAxisData->cdata();
136 const auto &xAxisData = m_XAxisData->cdata();
72
137
73 // As data series are sorted, we can improve performances of merge, by call the sort
138 // As data series are sorted, we can improve performances of merge, by call the sort
74 // method only if the two data series overlap.
139 // method only if the two data series overlap.
75 if (!otherXAxisData.empty()) {
140 if (!otherXAxisData.empty()) {
76 auto firstValue = otherXAxisData.front();
141 auto firstValue = otherXAxisData.front();
77 auto lastValue = otherXAxisData.back();
142 auto lastValue = otherXAxisData.back();
78
143
79 auto xAxisDataBegin = xAxisData.cbegin();
144 auto xAxisDataBegin = xAxisData.cbegin();
80 auto xAxisDataEnd = xAxisData.cend();
145 auto xAxisDataEnd = xAxisData.cend();
81
146
82 bool prepend;
147 bool prepend;
83 bool sortNeeded;
148 bool sortNeeded;
84
149
85 if (std::lower_bound(xAxisDataBegin, xAxisDataEnd, firstValue) == xAxisDataEnd) {
150 if (std::lower_bound(xAxisDataBegin, xAxisDataEnd, firstValue) == xAxisDataEnd) {
86 // Other data series if after data series
151 // Other data series if after data series
87 prepend = false;
152 prepend = false;
88 sortNeeded = false;
153 sortNeeded = false;
89 }
154 }
90 else if (std::upper_bound(xAxisDataBegin, xAxisDataEnd, lastValue)
155 else if (std::upper_bound(xAxisDataBegin, xAxisDataEnd, lastValue)
91 == xAxisDataBegin) {
156 == xAxisDataBegin) {
92 // Other data series if before data series
157 // Other data series if before data series
93 prepend = true;
158 prepend = true;
94 sortNeeded = false;
159 sortNeeded = false;
95 }
160 }
96 else {
161 else {
97 // The two data series overlap
162 // The two data series overlap
98 prepend = false;
163 prepend = false;
99 sortNeeded = true;
164 sortNeeded = true;
100 }
165 }
101
166
102 // Makes the merge
167 // Makes the merge
103 m_XAxisData->add(*other->xAxisData(), prepend);
168 m_XAxisData->add(*other->xAxisData(), prepend);
104 m_ValuesData->add(*other->valuesData(), prepend);
169 m_ValuesData->add(*other->valuesData(), prepend);
105
170
106 if (sortNeeded) {
171 if (sortNeeded) {
107 sort();
172 sort();
108 }
173 }
109 }
174 }
110
175
111 // Clears the other data series
176 // Clears the other data series
112 other->clear();
177 other->clear();
113 }
178 }
114 else {
179 else {
115 qCWarning(LOG_DataSeries())
180 qCWarning(LOG_DataSeries())
116 << QObject::tr("Detection of a type of IDataSeries we cannot merge with !");
181 << QObject::tr("Detection of a type of IDataSeries we cannot merge with !");
117 }
182 }
118 unlock();
183 unlock();
119 dataSeries->unlock();
184 dataSeries->unlock();
120 }
185 }
121
186
187 // ///////// //
188 // Iterators //
189 // ///////// //
190
191 Iterator cbegin() const { return Iterator{*this, true}; }
192
193 Iterator cend() const { return Iterator{*this, false}; }
194
195 std::pair<Iterator, Iterator> subData(double min, double max) const
196 {
197 if (min > max) {
198 std::swap(min, max);
199 }
200
201 auto begin = cbegin();
202 auto end = cend();
203
204 auto lowerIt
205 = std::lower_bound(begin, end, min, [](const auto &itValue, const auto &value) {
206 return itValue.x() == value;
207 });
208 auto upperIt
209 = std::upper_bound(begin, end, max, [](const auto &value, const auto &itValue) {
210 return itValue.x() == value;
211 });
212
213 return std::make_pair(lowerIt, upperIt);
214 }
215
216 // /////// //
217 // Mutexes //
218 // /////// //
219
122 virtual void lockRead() { m_Lock.lockForRead(); }
220 virtual void lockRead() { m_Lock.lockForRead(); }
123 virtual void lockWrite() { m_Lock.lockForWrite(); }
221 virtual void lockWrite() { m_Lock.lockForWrite(); }
124 virtual void unlock() { m_Lock.unlock(); }
222 virtual void unlock() { m_Lock.unlock(); }
125
223
126 protected:
224 protected:
127 /// Protected ctor (DataSeries is abstract). The vectors must have the same size, otherwise a
225 /// Protected ctor (DataSeries is abstract). The vectors must have the same size, otherwise a
128 /// DataSeries with no values will be created.
226 /// DataSeries with no values will be created.
129 /// @remarks data series is automatically sorted on its x-axis data
227 /// @remarks data series is automatically sorted on its x-axis data
130 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit,
228 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit,
131 std::shared_ptr<ArrayData<Dim> > valuesData, const Unit &valuesUnit)
229 std::shared_ptr<ArrayData<Dim> > valuesData, const Unit &valuesUnit)
132 : m_XAxisData{xAxisData},
230 : m_XAxisData{xAxisData},
133 m_XAxisUnit{xAxisUnit},
231 m_XAxisUnit{xAxisUnit},
134 m_ValuesData{valuesData},
232 m_ValuesData{valuesData},
135 m_ValuesUnit{valuesUnit}
233 m_ValuesUnit{valuesUnit}
136 {
234 {
137 if (m_XAxisData->size() != m_ValuesData->size()) {
235 if (m_XAxisData->size() != m_ValuesData->size()) {
138 clear();
236 clear();
139 }
237 }
140
238
141 // Sorts data if it's not the case
239 // Sorts data if it's not the case
142 const auto &xAxisCData = m_XAxisData->cdata();
240 const auto &xAxisCData = m_XAxisData->cdata();
143 if (!std::is_sorted(xAxisCData.cbegin(), xAxisCData.cend())) {
241 if (!std::is_sorted(xAxisCData.cbegin(), xAxisCData.cend())) {
144 sort();
242 sort();
145 }
243 }
146 }
244 }
147
245
148 /// Copy ctor
246 /// Copy ctor
149 explicit DataSeries(const DataSeries<Dim> &other)
247 explicit DataSeries(const DataSeries<Dim> &other)
150 : m_XAxisData{std::make_shared<ArrayData<1> >(*other.m_XAxisData)},
248 : m_XAxisData{std::make_shared<ArrayData<1> >(*other.m_XAxisData)},
151 m_XAxisUnit{other.m_XAxisUnit},
249 m_XAxisUnit{other.m_XAxisUnit},
152 m_ValuesData{std::make_shared<ArrayData<Dim> >(*other.m_ValuesData)},
250 m_ValuesData{std::make_shared<ArrayData<Dim> >(*other.m_ValuesData)},
153 m_ValuesUnit{other.m_ValuesUnit}
251 m_ValuesUnit{other.m_ValuesUnit}
154 {
252 {
155 // Since a series is ordered from its construction and is always ordered, it is not
253 // Since a series is ordered from its construction and is always ordered, it is not
156 // necessary to call the sort method here ('other' is sorted)
254 // necessary to call the sort method here ('other' is sorted)
157 }
255 }
158
256
159 /// Assignment operator
257 /// Assignment operator
160 template <int D>
258 template <int D>
161 DataSeries &operator=(DataSeries<D> other)
259 DataSeries &operator=(DataSeries<D> other)
162 {
260 {
163 std::swap(m_XAxisData, other.m_XAxisData);
261 std::swap(m_XAxisData, other.m_XAxisData);
164 std::swap(m_XAxisUnit, other.m_XAxisUnit);
262 std::swap(m_XAxisUnit, other.m_XAxisUnit);
165 std::swap(m_ValuesData, other.m_ValuesData);
263 std::swap(m_ValuesData, other.m_ValuesData);
166 std::swap(m_ValuesUnit, other.m_ValuesUnit);
264 std::swap(m_ValuesUnit, other.m_ValuesUnit);
167
265
168 return *this;
266 return *this;
169 }
267 }
170
268
171 private:
269 private:
172 /**
270 /**
173 * Sorts data series on its x-axis data
271 * Sorts data series on its x-axis data
174 */
272 */
175 void sort() noexcept
273 void sort() noexcept
176 {
274 {
177 auto permutation = SortUtils::sortPermutation(*m_XAxisData, std::less<double>());
275 auto permutation = SortUtils::sortPermutation(*m_XAxisData, std::less<double>());
178 m_XAxisData = m_XAxisData->sort(permutation);
276 m_XAxisData = m_XAxisData->sort(permutation);
179 m_ValuesData = m_ValuesData->sort(permutation);
277 m_ValuesData = m_ValuesData->sort(permutation);
180 }
278 }
181
279
182 std::shared_ptr<ArrayData<1> > m_XAxisData;
280 std::shared_ptr<ArrayData<1> > m_XAxisData;
183 Unit m_XAxisUnit;
281 Unit m_XAxisUnit;
184 std::shared_ptr<ArrayData<Dim> > m_ValuesData;
282 std::shared_ptr<ArrayData<Dim> > m_ValuesData;
185 Unit m_ValuesUnit;
283 Unit m_ValuesUnit;
186
284
187 QReadWriteLock m_Lock;
285 QReadWriteLock m_Lock;
188 };
286 };
189
287
190 #endif // SCIQLOP_DATASERIES_H
288 #endif // SCIQLOP_DATASERIES_H
@@ -1,72 +1,73
1 #ifndef SCIQLOP_IDATASERIES_H
1 #ifndef SCIQLOP_IDATASERIES_H
2 #define SCIQLOP_IDATASERIES_H
2 #define SCIQLOP_IDATASERIES_H
3
3
4 #include <Common/MetaTypes.h>
4 #include <Common/MetaTypes.h>
5 #include <Data/SqpRange.h>
5 #include <Data/SqpRange.h>
6
6
7 #include <memory>
7 #include <memory>
8
8
9 #include <QString>
9 #include <QString>
10
10
11 template <int Dim>
11 template <int Dim>
12 class ArrayData;
12 class ArrayData;
13
13
14 struct Unit {
14 struct Unit {
15 explicit Unit(const QString &name = {}, bool timeUnit = false)
15 explicit Unit(const QString &name = {}, bool timeUnit = false)
16 : m_Name{name}, m_TimeUnit{timeUnit}
16 : m_Name{name}, m_TimeUnit{timeUnit}
17 {
17 {
18 }
18 }
19
19
20 inline bool operator==(const Unit &other) const
20 inline bool operator==(const Unit &other) const
21 {
21 {
22 return std::tie(m_Name, m_TimeUnit) == std::tie(other.m_Name, other.m_TimeUnit);
22 return std::tie(m_Name, m_TimeUnit) == std::tie(other.m_Name, other.m_TimeUnit);
23 }
23 }
24 inline bool operator!=(const Unit &other) const { return !(*this == other); }
24 inline bool operator!=(const Unit &other) const { return !(*this == other); }
25
25
26 QString m_Name; ///< Unit name
26 QString m_Name; ///< Unit name
27 bool m_TimeUnit; ///< The unit is a unit of time (UTC)
27 bool m_TimeUnit; ///< The unit is a unit of time (UTC)
28 };
28 };
29
29
30 /**
30 /**
31 * @brief The IDataSeries aims to declare a data series.
31 * @brief The IDataSeries aims to declare a data series.
32 *
32 *
33 * A data series is an entity that contains at least :
33 * A data series is an entity that contains at least :
34 * - one dataset representing the x-axis
34 * - one dataset representing the x-axis
35 * - one dataset representing the values
35 * - one dataset representing the values
36 *
36 *
37 * Each dataset is represented by an ArrayData, and is associated with a unit.
37 * Each dataset is represented by an ArrayData, and is associated with a unit.
38 *
38 *
39 * An ArrayData can be unidimensional or two-dimensional, depending on the implementation of the
39 * An ArrayData can be unidimensional or two-dimensional, depending on the implementation of the
40 * IDataSeries. The x-axis dataset is always unidimensional.
40 * IDataSeries. The x-axis dataset is always unidimensional.
41 *
41 *
42 * @sa ArrayData
42 * @sa ArrayData
43 */
43 */
44 class IDataSeries {
44 class IDataSeries {
45 public:
45 public:
46 virtual ~IDataSeries() noexcept = default;
46 virtual ~IDataSeries() noexcept = default;
47
47
48 /// Returns the x-axis dataset
48 /// Returns the x-axis dataset
49 virtual std::shared_ptr<ArrayData<1> > xAxisData() = 0;
49 virtual std::shared_ptr<ArrayData<1> > xAxisData() = 0;
50
50
51 /// Returns the x-axis dataset (as const)
51 /// Returns the x-axis dataset (as const)
52 virtual const std::shared_ptr<ArrayData<1> > xAxisData() const = 0;
52 virtual const std::shared_ptr<ArrayData<1> > xAxisData() const = 0;
53
53
54 virtual Unit xAxisUnit() const = 0;
54 virtual Unit xAxisUnit() const = 0;
55
55
56 virtual Unit valuesUnit() const = 0;
56 virtual Unit valuesUnit() const = 0;
57
57
58 virtual void merge(IDataSeries *dataSeries) = 0;
58 virtual void merge(IDataSeries *dataSeries) = 0;
59 virtual std::shared_ptr<IDataSeries> subData(const SqpRange &range) = 0;
59 /// @todo Review the name and signature of this method
60 virtual std::shared_ptr<IDataSeries> subDataSeries(const SqpRange &range) = 0;
60
61
61 virtual std::unique_ptr<IDataSeries> clone() const = 0;
62 virtual std::unique_ptr<IDataSeries> clone() const = 0;
62 virtual SqpRange range() const = 0;
63 virtual SqpRange range() const = 0;
63
64
64 virtual void lockRead() = 0;
65 virtual void lockRead() = 0;
65 virtual void lockWrite() = 0;
66 virtual void lockWrite() = 0;
66 virtual void unlock() = 0;
67 virtual void unlock() = 0;
67 };
68 };
68
69
69 // Required for using shared_ptr in signals/slots
70 // Required for using shared_ptr in signals/slots
70 SCIQLOP_REGISTER_META_TYPE(IDATASERIES_PTR_REGISTRY, std::shared_ptr<IDataSeries>)
71 SCIQLOP_REGISTER_META_TYPE(IDATASERIES_PTR_REGISTRY, std::shared_ptr<IDataSeries>)
71
72
72 #endif // SCIQLOP_IDATASERIES_H
73 #endif // SCIQLOP_IDATASERIES_H
@@ -1,27 +1,27
1 #ifndef SCIQLOP_SCALARSERIES_H
1 #ifndef SCIQLOP_SCALARSERIES_H
2 #define SCIQLOP_SCALARSERIES_H
2 #define SCIQLOP_SCALARSERIES_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/DataSeries.h>
6 #include <Data/DataSeries.h>
7
7
8 /**
8 /**
9 * @brief The ScalarSeries class is the implementation for a data series representing a scalar.
9 * @brief The ScalarSeries class is the implementation for a data series representing a scalar.
10 */
10 */
11 class SCIQLOP_CORE_EXPORT ScalarSeries : public DataSeries<1> {
11 class SCIQLOP_CORE_EXPORT ScalarSeries : public DataSeries<1> {
12 public:
12 public:
13 /**
13 /**
14 * Ctor with two vectors. The vectors must have the same size, otherwise a ScalarSeries with no
14 * Ctor with two vectors. The vectors must have the same size, otherwise a ScalarSeries with no
15 * values will be created.
15 * values will be created.
16 * @param xAxisData x-axis data
16 * @param xAxisData x-axis data
17 * @param valuesData values data
17 * @param valuesData values data
18 */
18 */
19 explicit ScalarSeries(QVector<double> xAxisData, QVector<double> valuesData,
19 explicit ScalarSeries(QVector<double> xAxisData, QVector<double> valuesData,
20 const Unit &xAxisUnit, const Unit &valuesUnit);
20 const Unit &xAxisUnit, const Unit &valuesUnit);
21
21
22 std::unique_ptr<IDataSeries> clone() const override;
22 std::unique_ptr<IDataSeries> clone() const override;
23
23
24 std::shared_ptr<IDataSeries> subData(const SqpRange &range) override;
24 std::shared_ptr<IDataSeries> subDataSeries(const SqpRange &range) override;
25 };
25 };
26
26
27 #endif // SCIQLOP_SCALARSERIES_H
27 #endif // SCIQLOP_SCALARSERIES_H
@@ -1,41 +1,41
1 #include <Data/ScalarSeries.h>
1 #include <Data/ScalarSeries.h>
2
2
3 ScalarSeries::ScalarSeries(QVector<double> xAxisData, QVector<double> valuesData,
3 ScalarSeries::ScalarSeries(QVector<double> xAxisData, QVector<double> valuesData,
4 const Unit &xAxisUnit, const Unit &valuesUnit)
4 const Unit &xAxisUnit, const Unit &valuesUnit)
5 : DataSeries{std::make_shared<ArrayData<1> >(std::move(xAxisData)), xAxisUnit,
5 : DataSeries{std::make_shared<ArrayData<1> >(std::move(xAxisData)), xAxisUnit,
6 std::make_shared<ArrayData<1> >(std::move(valuesData)), valuesUnit}
6 std::make_shared<ArrayData<1> >(std::move(valuesData)), valuesUnit}
7 {
7 {
8 }
8 }
9
9
10 std::unique_ptr<IDataSeries> ScalarSeries::clone() const
10 std::unique_ptr<IDataSeries> ScalarSeries::clone() const
11 {
11 {
12 return std::make_unique<ScalarSeries>(*this);
12 return std::make_unique<ScalarSeries>(*this);
13 }
13 }
14
14
15 std::shared_ptr<IDataSeries> ScalarSeries::subData(const SqpRange &range)
15 std::shared_ptr<IDataSeries> ScalarSeries::subDataSeries(const SqpRange &range)
16 {
16 {
17 auto subXAxisData = QVector<double>();
17 auto subXAxisData = QVector<double>();
18 auto subValuesData = QVector<double>();
18 auto subValuesData = QVector<double>();
19 this->lockRead();
19 this->lockRead();
20 {
20 {
21 const auto &currentXData = this->xAxisData()->cdata();
21 const auto &currentXData = this->xAxisData()->cdata();
22 const auto &currentValuesData = this->valuesData()->cdata();
22 const auto &currentValuesData = this->valuesData()->cdata();
23
23
24 auto xDataBegin = currentXData.cbegin();
24 auto xDataBegin = currentXData.cbegin();
25 auto xDataEnd = currentXData.cend();
25 auto xDataEnd = currentXData.cend();
26
26
27 auto lowerIt = std::lower_bound(xDataBegin, xDataEnd, range.m_TStart);
27 auto lowerIt = std::lower_bound(xDataBegin, xDataEnd, range.m_TStart);
28 auto upperIt = std::upper_bound(xDataBegin, xDataEnd, range.m_TEnd);
28 auto upperIt = std::upper_bound(xDataBegin, xDataEnd, range.m_TEnd);
29 auto distance = std::distance(xDataBegin, lowerIt);
29 auto distance = std::distance(xDataBegin, lowerIt);
30
30
31 auto valuesDataIt = currentValuesData.cbegin() + distance;
31 auto valuesDataIt = currentValuesData.cbegin() + distance;
32 for (auto xAxisDataIt = lowerIt; xAxisDataIt != upperIt; ++xAxisDataIt, ++valuesDataIt) {
32 for (auto xAxisDataIt = lowerIt; xAxisDataIt != upperIt; ++xAxisDataIt, ++valuesDataIt) {
33 subXAxisData.append(*xAxisDataIt);
33 subXAxisData.append(*xAxisDataIt);
34 subValuesData.append(*valuesDataIt);
34 subValuesData.append(*valuesDataIt);
35 }
35 }
36 }
36 }
37 this->unlock();
37 this->unlock();
38
38
39 return std::make_shared<ScalarSeries>(subXAxisData, subValuesData, this->xAxisUnit(),
39 return std::make_shared<ScalarSeries>(subXAxisData, subValuesData, this->xAxisUnit(),
40 this->valuesUnit());
40 this->valuesUnit());
41 }
41 }
@@ -1,211 +1,211
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}, m_Range{dateTime}, m_Metadata{metadata}, m_DataSeries{nullptr}
15 : m_Name{name}, m_Range{dateTime}, m_Metadata{metadata}, m_DataSeries{nullptr}
16 {
16 {
17 }
17 }
18
18
19 void lockRead() { m_Lock.lockForRead(); }
19 void lockRead() { m_Lock.lockForRead(); }
20 void lockWrite() { m_Lock.lockForWrite(); }
20 void lockWrite() { m_Lock.lockForWrite(); }
21 void unlock() { m_Lock.unlock(); }
21 void unlock() { m_Lock.unlock(); }
22
22
23 QString m_Name;
23 QString m_Name;
24
24
25 SqpRange m_Range;
25 SqpRange m_Range;
26 SqpRange m_CacheRange;
26 SqpRange m_CacheRange;
27 QVariantHash m_Metadata;
27 QVariantHash m_Metadata;
28 std::shared_ptr<IDataSeries> m_DataSeries;
28 std::shared_ptr<IDataSeries> m_DataSeries;
29
29
30 QReadWriteLock m_Lock;
30 QReadWriteLock m_Lock;
31 };
31 };
32
32
33 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
33 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
34 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
34 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
35 {
35 {
36 }
36 }
37
37
38 QString Variable::name() const noexcept
38 QString Variable::name() const noexcept
39 {
39 {
40 impl->lockRead();
40 impl->lockRead();
41 auto name = impl->m_Name;
41 auto name = impl->m_Name;
42 impl->unlock();
42 impl->unlock();
43 return name;
43 return name;
44 }
44 }
45
45
46 SqpRange Variable::range() const noexcept
46 SqpRange Variable::range() const noexcept
47 {
47 {
48 impl->lockRead();
48 impl->lockRead();
49 auto range = impl->m_Range;
49 auto range = impl->m_Range;
50 impl->unlock();
50 impl->unlock();
51 return range;
51 return range;
52 }
52 }
53
53
54 void Variable::setRange(const SqpRange &range) noexcept
54 void Variable::setRange(const SqpRange &range) noexcept
55 {
55 {
56 impl->lockWrite();
56 impl->lockWrite();
57 impl->m_Range = range;
57 impl->m_Range = range;
58 impl->unlock();
58 impl->unlock();
59 }
59 }
60
60
61 SqpRange Variable::cacheRange() const noexcept
61 SqpRange Variable::cacheRange() const noexcept
62 {
62 {
63 impl->lockRead();
63 impl->lockRead();
64 auto cacheRange = impl->m_CacheRange;
64 auto cacheRange = impl->m_CacheRange;
65 impl->unlock();
65 impl->unlock();
66 return cacheRange;
66 return cacheRange;
67 }
67 }
68
68
69 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
69 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
70 {
70 {
71 impl->lockWrite();
71 impl->lockWrite();
72 impl->m_CacheRange = cacheRange;
72 impl->m_CacheRange = cacheRange;
73 impl->unlock();
73 impl->unlock();
74 }
74 }
75
75
76 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
76 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
77 {
77 {
78 qCDebug(LOG_Variable()) << "TORM Variable::setDataSeries"
78 qCDebug(LOG_Variable()) << "TORM Variable::setDataSeries"
79 << QThread::currentThread()->objectName();
79 << QThread::currentThread()->objectName();
80 if (!dataSeries) {
80 if (!dataSeries) {
81 /// @todo ALX : log
81 /// @todo ALX : log
82 return;
82 return;
83 }
83 }
84 impl->lockWrite();
84 impl->lockWrite();
85 impl->m_DataSeries = dataSeries->clone();
85 impl->m_DataSeries = dataSeries->clone();
86 impl->unlock();
86 impl->unlock();
87 }
87 }
88
88
89 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
89 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
90 {
90 {
91 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
91 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
92 << QThread::currentThread()->objectName();
92 << QThread::currentThread()->objectName();
93 if (!dataSeries) {
93 if (!dataSeries) {
94 /// @todo ALX : log
94 /// @todo ALX : log
95 return;
95 return;
96 }
96 }
97
97
98 // Add or merge the data
98 // Add or merge the data
99 // Inits the data series of the variable
99 // Inits the data series of the variable
100 impl->lockWrite();
100 impl->lockWrite();
101 if (!impl->m_DataSeries) {
101 if (!impl->m_DataSeries) {
102 impl->m_DataSeries = dataSeries->clone();
102 impl->m_DataSeries = dataSeries->clone();
103 }
103 }
104 else {
104 else {
105 impl->m_DataSeries->merge(dataSeries.get());
105 impl->m_DataSeries->merge(dataSeries.get());
106 }
106 }
107 impl->unlock();
107 impl->unlock();
108
108
109 // sub the data
109 // sub the data
110 auto subData = this->dataSeries()->subData(this->cacheRange());
110 auto subData = this->dataSeries()->subDataSeries(this->cacheRange());
111 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries sub" << subData->range();
111 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries sub" << subData->range();
112 this->setDataSeries(subData);
112 this->setDataSeries(subData);
113 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries set" << this->dataSeries()->range();
113 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries set" << this->dataSeries()->range();
114 }
114 }
115
115
116 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
116 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
117 {
117 {
118 impl->lockRead();
118 impl->lockRead();
119 auto dataSeries = impl->m_DataSeries;
119 auto dataSeries = impl->m_DataSeries;
120 impl->unlock();
120 impl->unlock();
121
121
122 return dataSeries;
122 return dataSeries;
123 }
123 }
124
124
125 QVariantHash Variable::metadata() const noexcept
125 QVariantHash Variable::metadata() const noexcept
126 {
126 {
127 impl->lockRead();
127 impl->lockRead();
128 auto metadata = impl->m_Metadata;
128 auto metadata = impl->m_Metadata;
129 impl->unlock();
129 impl->unlock();
130 return metadata;
130 return metadata;
131 }
131 }
132
132
133 bool Variable::contains(const SqpRange &range) const noexcept
133 bool Variable::contains(const SqpRange &range) const noexcept
134 {
134 {
135 impl->lockRead();
135 impl->lockRead();
136 auto res = impl->m_Range.contains(range);
136 auto res = impl->m_Range.contains(range);
137 impl->unlock();
137 impl->unlock();
138 return res;
138 return res;
139 }
139 }
140
140
141 bool Variable::intersect(const SqpRange &range) const noexcept
141 bool Variable::intersect(const SqpRange &range) const noexcept
142 {
142 {
143
143
144 impl->lockRead();
144 impl->lockRead();
145 auto res = impl->m_Range.intersect(range);
145 auto res = impl->m_Range.intersect(range);
146 impl->unlock();
146 impl->unlock();
147 return res;
147 return res;
148 }
148 }
149
149
150 bool Variable::isInside(const SqpRange &range) const noexcept
150 bool Variable::isInside(const SqpRange &range) const noexcept
151 {
151 {
152 impl->lockRead();
152 impl->lockRead();
153 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
153 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
154 impl->unlock();
154 impl->unlock();
155 return res;
155 return res;
156 }
156 }
157
157
158 bool Variable::cacheContains(const SqpRange &range) const noexcept
158 bool Variable::cacheContains(const SqpRange &range) const noexcept
159 {
159 {
160 impl->lockRead();
160 impl->lockRead();
161 auto res = impl->m_CacheRange.contains(range);
161 auto res = impl->m_CacheRange.contains(range);
162 impl->unlock();
162 impl->unlock();
163 return res;
163 return res;
164 }
164 }
165
165
166 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
166 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
167 {
167 {
168 impl->lockRead();
168 impl->lockRead();
169 auto res = impl->m_CacheRange.intersect(range);
169 auto res = impl->m_CacheRange.intersect(range);
170 impl->unlock();
170 impl->unlock();
171 return res;
171 return res;
172 }
172 }
173
173
174 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
174 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
175 {
175 {
176 impl->lockRead();
176 impl->lockRead();
177 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
177 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
178 impl->unlock();
178 impl->unlock();
179 return res;
179 return res;
180 }
180 }
181
181
182
182
183 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
183 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
184 {
184 {
185 auto notInCache = QVector<SqpRange>{};
185 auto notInCache = QVector<SqpRange>{};
186
186
187 if (!this->cacheContains(range)) {
187 if (!this->cacheContains(range)) {
188 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
188 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
189 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
189 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
190 notInCache << range;
190 notInCache << range;
191 }
191 }
192 else if (range.m_TStart < impl->m_CacheRange.m_TStart
192 else if (range.m_TStart < impl->m_CacheRange.m_TStart
193 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
193 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
194 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
194 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
195 }
195 }
196 else if (range.m_TStart < impl->m_CacheRange.m_TStart
196 else if (range.m_TStart < impl->m_CacheRange.m_TStart
197 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
197 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
198 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
198 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
199 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
199 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
200 }
200 }
201 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
201 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
202 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
202 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
203 }
203 }
204 else {
204 else {
205 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
205 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
206 << QThread::currentThread();
206 << QThread::currentThread();
207 }
207 }
208 }
208 }
209
209
210 return notInCache;
210 return notInCache;
211 }
211 }
@@ -1,541 +1,541
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableAcquisitionWorker.h>
2 #include <Variable/VariableAcquisitionWorker.h>
3 #include <Variable/VariableCacheController.h>
3 #include <Variable/VariableCacheController.h>
4 #include <Variable/VariableCacheStrategy.h>
4 #include <Variable/VariableCacheStrategy.h>
5 #include <Variable/VariableController.h>
5 #include <Variable/VariableController.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7 #include <Variable/VariableSynchronizationGroup.h>
7 #include <Variable/VariableSynchronizationGroup.h>
8
8
9 #include <Data/DataProviderParameters.h>
9 #include <Data/DataProviderParameters.h>
10 #include <Data/IDataProvider.h>
10 #include <Data/IDataProvider.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <Time/TimeController.h>
12 #include <Time/TimeController.h>
13
13
14 #include <QMutex>
14 #include <QMutex>
15 #include <QThread>
15 #include <QThread>
16 #include <QUuid>
16 #include <QUuid>
17 #include <QtCore/QItemSelectionModel>
17 #include <QtCore/QItemSelectionModel>
18
18
19 #include <set>
19 #include <set>
20 #include <unordered_map>
20 #include <unordered_map>
21
21
22 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
22 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
23
23
24 namespace {
24 namespace {
25
25
26 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
26 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
27 const SqpRange &oldGraphRange)
27 const SqpRange &oldGraphRange)
28 {
28 {
29 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
29 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
30
30
31 auto varRangeRequested = varRange;
31 auto varRangeRequested = varRange;
32 switch (zoomType) {
32 switch (zoomType) {
33 case AcquisitionZoomType::ZoomIn: {
33 case AcquisitionZoomType::ZoomIn: {
34 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
34 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
35 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
35 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
36 varRangeRequested.m_TStart += deltaLeft;
36 varRangeRequested.m_TStart += deltaLeft;
37 varRangeRequested.m_TEnd -= deltaRight;
37 varRangeRequested.m_TEnd -= deltaRight;
38 break;
38 break;
39 }
39 }
40
40
41 case AcquisitionZoomType::ZoomOut: {
41 case AcquisitionZoomType::ZoomOut: {
42 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
42 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
43 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
43 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
44 varRangeRequested.m_TStart -= deltaLeft;
44 varRangeRequested.m_TStart -= deltaLeft;
45 varRangeRequested.m_TEnd += deltaRight;
45 varRangeRequested.m_TEnd += deltaRight;
46 break;
46 break;
47 }
47 }
48 case AcquisitionZoomType::PanRight: {
48 case AcquisitionZoomType::PanRight: {
49 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
49 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
50 varRangeRequested.m_TStart += deltaRight;
50 varRangeRequested.m_TStart += deltaRight;
51 varRangeRequested.m_TEnd += deltaRight;
51 varRangeRequested.m_TEnd += deltaRight;
52 break;
52 break;
53 }
53 }
54 case AcquisitionZoomType::PanLeft: {
54 case AcquisitionZoomType::PanLeft: {
55 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
55 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
56 varRangeRequested.m_TStart -= deltaLeft;
56 varRangeRequested.m_TStart -= deltaLeft;
57 varRangeRequested.m_TEnd -= deltaLeft;
57 varRangeRequested.m_TEnd -= deltaLeft;
58 break;
58 break;
59 }
59 }
60 case AcquisitionZoomType::Unknown: {
60 case AcquisitionZoomType::Unknown: {
61 qCCritical(LOG_VariableController())
61 qCCritical(LOG_VariableController())
62 << VariableController::tr("Impossible to synchronize: zoom type unknown");
62 << VariableController::tr("Impossible to synchronize: zoom type unknown");
63 break;
63 break;
64 }
64 }
65 default:
65 default:
66 qCCritical(LOG_VariableController()) << VariableController::tr(
66 qCCritical(LOG_VariableController()) << VariableController::tr(
67 "Impossible to synchronize: zoom type not take into account");
67 "Impossible to synchronize: zoom type not take into account");
68 // No action
68 // No action
69 break;
69 break;
70 }
70 }
71
71
72 return varRangeRequested;
72 return varRangeRequested;
73 }
73 }
74 }
74 }
75
75
76 struct VariableController::VariableControllerPrivate {
76 struct VariableController::VariableControllerPrivate {
77 explicit VariableControllerPrivate(VariableController *parent)
77 explicit VariableControllerPrivate(VariableController *parent)
78 : m_WorkingMutex{},
78 : m_WorkingMutex{},
79 m_VariableModel{new VariableModel{parent}},
79 m_VariableModel{new VariableModel{parent}},
80 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
80 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
81 m_VariableCacheController{std::make_unique<VariableCacheController>()},
81 m_VariableCacheController{std::make_unique<VariableCacheController>()},
82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()}
83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()}
84 {
84 {
85
85
86 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
86 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
87 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
87 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
88 }
88 }
89
89
90
90
91 virtual ~VariableControllerPrivate()
91 virtual ~VariableControllerPrivate()
92 {
92 {
93 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
93 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
94 m_VariableAcquisitionWorkerThread.quit();
94 m_VariableAcquisitionWorkerThread.quit();
95 m_VariableAcquisitionWorkerThread.wait();
95 m_VariableAcquisitionWorkerThread.wait();
96 }
96 }
97
97
98
98
99 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested);
99 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested);
100
100
101 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
101 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
102 const SqpRange &dateTime);
102 const SqpRange &dateTime);
103
103
104 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
104 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
105 std::shared_ptr<IDataSeries>
105 std::shared_ptr<IDataSeries>
106 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
106 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
107
107
108 void registerProvider(std::shared_ptr<IDataProvider> provider);
108 void registerProvider(std::shared_ptr<IDataProvider> provider);
109
109
110 QMutex m_WorkingMutex;
110 QMutex m_WorkingMutex;
111 /// Variable model. The VariableController has the ownership
111 /// Variable model. The VariableController has the ownership
112 VariableModel *m_VariableModel;
112 VariableModel *m_VariableModel;
113 QItemSelectionModel *m_VariableSelectionModel;
113 QItemSelectionModel *m_VariableSelectionModel;
114
114
115
115
116 TimeController *m_TimeController{nullptr};
116 TimeController *m_TimeController{nullptr};
117 std::unique_ptr<VariableCacheController> m_VariableCacheController;
117 std::unique_ptr<VariableCacheController> m_VariableCacheController;
118 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
118 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
119 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
119 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
120 QThread m_VariableAcquisitionWorkerThread;
120 QThread m_VariableAcquisitionWorkerThread;
121
121
122 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
122 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
123 m_VariableToProviderMap;
123 m_VariableToProviderMap;
124 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
124 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
125 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
125 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
126 m_GroupIdToVariableSynchronizationGroupMap;
126 m_GroupIdToVariableSynchronizationGroupMap;
127 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
127 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
128 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
128 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
129 };
129 };
130
130
131
131
132 VariableController::VariableController(QObject *parent)
132 VariableController::VariableController(QObject *parent)
133 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
133 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
134 {
134 {
135 qCDebug(LOG_VariableController()) << tr("VariableController construction")
135 qCDebug(LOG_VariableController()) << tr("VariableController construction")
136 << QThread::currentThread();
136 << QThread::currentThread();
137
137
138 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
138 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
139 &VariableController::onAbortProgressRequested);
139 &VariableController::onAbortProgressRequested);
140
140
141 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
141 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
142 &VariableController::onDataProvided);
142 &VariableController::onDataProvided);
143 connect(impl->m_VariableAcquisitionWorker.get(),
143 connect(impl->m_VariableAcquisitionWorker.get(),
144 &VariableAcquisitionWorker::variableRequestInProgress, this,
144 &VariableAcquisitionWorker::variableRequestInProgress, this,
145 &VariableController::onVariableRetrieveDataInProgress);
145 &VariableController::onVariableRetrieveDataInProgress);
146
146
147 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
147 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
148 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
148 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
149 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
149 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
150 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
150 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
151
151
152
152
153 impl->m_VariableAcquisitionWorkerThread.start();
153 impl->m_VariableAcquisitionWorkerThread.start();
154 }
154 }
155
155
156 VariableController::~VariableController()
156 VariableController::~VariableController()
157 {
157 {
158 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
158 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
159 << QThread::currentThread();
159 << QThread::currentThread();
160 this->waitForFinish();
160 this->waitForFinish();
161 }
161 }
162
162
163 VariableModel *VariableController::variableModel() noexcept
163 VariableModel *VariableController::variableModel() noexcept
164 {
164 {
165 return impl->m_VariableModel;
165 return impl->m_VariableModel;
166 }
166 }
167
167
168 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
168 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
169 {
169 {
170 return impl->m_VariableSelectionModel;
170 return impl->m_VariableSelectionModel;
171 }
171 }
172
172
173 void VariableController::setTimeController(TimeController *timeController) noexcept
173 void VariableController::setTimeController(TimeController *timeController) noexcept
174 {
174 {
175 impl->m_TimeController = timeController;
175 impl->m_TimeController = timeController;
176 }
176 }
177
177
178 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
178 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
179 {
179 {
180 if (!variable) {
180 if (!variable) {
181 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
181 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
182 return;
182 return;
183 }
183 }
184
184
185 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
185 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
186 // make some treatments before the deletion
186 // make some treatments before the deletion
187 emit variableAboutToBeDeleted(variable);
187 emit variableAboutToBeDeleted(variable);
188
188
189 // Deletes identifier
189 // Deletes identifier
190 impl->m_VariableToIdentifierMap.erase(variable);
190 impl->m_VariableToIdentifierMap.erase(variable);
191
191
192 // Deletes provider
192 // Deletes provider
193 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
193 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
194 qCDebug(LOG_VariableController())
194 qCDebug(LOG_VariableController())
195 << tr("Number of providers deleted for variable %1: %2")
195 << tr("Number of providers deleted for variable %1: %2")
196 .arg(variable->name(), QString::number(nbProvidersDeleted));
196 .arg(variable->name(), QString::number(nbProvidersDeleted));
197
197
198 // Clears cache
198 // Clears cache
199 impl->m_VariableCacheController->clear(variable);
199 impl->m_VariableCacheController->clear(variable);
200
200
201 // Deletes from model
201 // Deletes from model
202 impl->m_VariableModel->deleteVariable(variable);
202 impl->m_VariableModel->deleteVariable(variable);
203 }
203 }
204
204
205 void VariableController::deleteVariables(
205 void VariableController::deleteVariables(
206 const QVector<std::shared_ptr<Variable> > &variables) noexcept
206 const QVector<std::shared_ptr<Variable> > &variables) noexcept
207 {
207 {
208 for (auto variable : qAsConst(variables)) {
208 for (auto variable : qAsConst(variables)) {
209 deleteVariable(variable);
209 deleteVariable(variable);
210 }
210 }
211 }
211 }
212
212
213 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
213 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
214 {
214 {
215 }
215 }
216
216
217 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
217 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
218 std::shared_ptr<IDataProvider> provider) noexcept
218 std::shared_ptr<IDataProvider> provider) noexcept
219 {
219 {
220
220
221 if (!impl->m_TimeController) {
221 if (!impl->m_TimeController) {
222 qCCritical(LOG_VariableController())
222 qCCritical(LOG_VariableController())
223 << tr("Impossible to create variable: The time controller is null");
223 << tr("Impossible to create variable: The time controller is null");
224 return;
224 return;
225 }
225 }
226
226
227 auto range = impl->m_TimeController->dateTime();
227 auto range = impl->m_TimeController->dateTime();
228
228
229 if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) {
229 if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) {
230 auto identifier = QUuid::createUuid();
230 auto identifier = QUuid::createUuid();
231
231
232 // store the provider
232 // store the provider
233 impl->registerProvider(provider);
233 impl->registerProvider(provider);
234
234
235 // Associate the provider
235 // Associate the provider
236 impl->m_VariableToProviderMap[newVariable] = provider;
236 impl->m_VariableToProviderMap[newVariable] = provider;
237 impl->m_VariableToIdentifierMap[newVariable] = identifier;
237 impl->m_VariableToIdentifierMap[newVariable] = identifier;
238
238
239
239
240 impl->processRequest(newVariable, range);
240 impl->processRequest(newVariable, range);
241 }
241 }
242 }
242 }
243
243
244 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
244 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
245 {
245 {
246 // TODO check synchronisation
246 // TODO check synchronisation
247 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
247 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
248 << QThread::currentThread()->objectName();
248 << QThread::currentThread()->objectName();
249 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
249 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
250
250
251 for (const auto &selectedRow : qAsConst(selectedRows)) {
251 for (const auto &selectedRow : qAsConst(selectedRows)) {
252 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
252 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
253 selectedVariable->setRange(dateTime);
253 selectedVariable->setRange(dateTime);
254 impl->processRequest(selectedVariable, dateTime);
254 impl->processRequest(selectedVariable, dateTime);
255
255
256 // notify that rescale operation has to be done
256 // notify that rescale operation has to be done
257 emit rangeChanged(selectedVariable, dateTime);
257 emit rangeChanged(selectedVariable, dateTime);
258 }
258 }
259 }
259 }
260 }
260 }
261
261
262 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
262 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
263 const SqpRange &cacheRangeRequested,
263 const SqpRange &cacheRangeRequested,
264 QVector<AcquisitionDataPacket> dataAcquired)
264 QVector<AcquisitionDataPacket> dataAcquired)
265 {
265 {
266 if (auto var = impl->findVariable(vIdentifier)) {
266 if (auto var = impl->findVariable(vIdentifier)) {
267 var->setRange(rangeRequested);
267 var->setRange(rangeRequested);
268 var->setCacheRange(cacheRangeRequested);
268 var->setCacheRange(cacheRangeRequested);
269 qCDebug(LOG_VariableController()) << tr("1: onDataProvided") << rangeRequested;
269 qCDebug(LOG_VariableController()) << tr("1: onDataProvided") << rangeRequested;
270 qCDebug(LOG_VariableController()) << tr("2: onDataProvided") << cacheRangeRequested;
270 qCDebug(LOG_VariableController()) << tr("2: onDataProvided") << cacheRangeRequested;
271
271
272 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
272 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
273 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
273 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
274 << retrievedDataSeries->range();
274 << retrievedDataSeries->range();
275 var->mergeDataSeries(retrievedDataSeries);
275 var->mergeDataSeries(retrievedDataSeries);
276 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
276 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
277 emit var->updated();
277 emit var->updated();
278 }
278 }
279 else {
279 else {
280 qCCritical(LOG_VariableController()) << tr("Impossible to provide data to a null variable");
280 qCCritical(LOG_VariableController()) << tr("Impossible to provide data to a null variable");
281 }
281 }
282 }
282 }
283
283
284 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
284 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
285 {
285 {
286 if (auto var = impl->findVariable(identifier)) {
286 if (auto var = impl->findVariable(identifier)) {
287 impl->m_VariableModel->setDataProgress(var, progress);
287 impl->m_VariableModel->setDataProgress(var, progress);
288 }
288 }
289 else {
289 else {
290 qCCritical(LOG_VariableController())
290 qCCritical(LOG_VariableController())
291 << tr("Impossible to notify progression of a null variable");
291 << tr("Impossible to notify progression of a null variable");
292 }
292 }
293 }
293 }
294
294
295 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
295 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
296 {
296 {
297 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
297 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
298 << QThread::currentThread()->objectName();
298 << QThread::currentThread()->objectName();
299
299
300 auto it = impl->m_VariableToIdentifierMap.find(variable);
300 auto it = impl->m_VariableToIdentifierMap.find(variable);
301 if (it != impl->m_VariableToIdentifierMap.cend()) {
301 if (it != impl->m_VariableToIdentifierMap.cend()) {
302 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
302 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
303 }
303 }
304 else {
304 else {
305 qCWarning(LOG_VariableController())
305 qCWarning(LOG_VariableController())
306 << tr("Aborting progression of inexistant variable detected !!!")
306 << tr("Aborting progression of inexistant variable detected !!!")
307 << QThread::currentThread()->objectName();
307 << QThread::currentThread()->objectName();
308 }
308 }
309 }
309 }
310
310
311 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
311 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
312 {
312 {
313 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
313 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
314 << QThread::currentThread()->objectName()
314 << QThread::currentThread()->objectName()
315 << synchronizationGroupId;
315 << synchronizationGroupId;
316 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
316 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
317 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
317 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
318 std::make_pair(synchronizationGroupId, vSynchroGroup));
318 std::make_pair(synchronizationGroupId, vSynchroGroup));
319 }
319 }
320
320
321 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
321 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
322 {
322 {
323 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
323 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
324 }
324 }
325
325
326 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
326 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
327 QUuid synchronizationGroupId)
327 QUuid synchronizationGroupId)
328
328
329 {
329 {
330 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
330 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
331 << synchronizationGroupId;
331 << synchronizationGroupId;
332 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
332 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
333 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
333 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
334 auto groupIdToVSGIt
334 auto groupIdToVSGIt
335 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
335 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
336 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
336 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
337 impl->m_VariableIdGroupIdMap.insert(
337 impl->m_VariableIdGroupIdMap.insert(
338 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
338 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
339 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
339 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
340 }
340 }
341 else {
341 else {
342 qCCritical(LOG_VariableController())
342 qCCritical(LOG_VariableController())
343 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
343 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
344 << variable->name();
344 << variable->name();
345 }
345 }
346 }
346 }
347 else {
347 else {
348 qCCritical(LOG_VariableController())
348 qCCritical(LOG_VariableController())
349 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
349 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
350 }
350 }
351 }
351 }
352
352
353
353
354 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
354 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
355 const SqpRange &range, const SqpRange &oldRange,
355 const SqpRange &range, const SqpRange &oldRange,
356 bool synchronise)
356 bool synchronise)
357 {
357 {
358 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
358 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
359
359
360 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
360 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
361 << QThread::currentThread()->objectName();
361 << QThread::currentThread()->objectName();
362 // we want to load data of the variable for the dateTime.
362 // we want to load data of the variable for the dateTime.
363 // First we check if the cache contains some of them.
363 // First we check if the cache contains some of them.
364 // For the other, we ask the provider to give them.
364 // For the other, we ask the provider to give them.
365
365
366 for (const auto &var : variables) {
366 for (const auto &var : variables) {
367 qCDebug(LOG_VariableController()) << "processRequest for" << var->name();
367 qCDebug(LOG_VariableController()) << "processRequest for" << var->name();
368 impl->processRequest(var, range);
368 impl->processRequest(var, range);
369 }
369 }
370
370
371 if (synchronise) {
371 if (synchronise) {
372 // Get the group ids
372 // Get the group ids
373 qCDebug(LOG_VariableController())
373 qCDebug(LOG_VariableController())
374 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
374 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
375 auto groupIds = std::set<QUuid>();
375 auto groupIds = std::set<QUuid>();
376 for (const auto &var : variables) {
376 for (const auto &var : variables) {
377 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
377 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
378 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
378 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
379 auto vId = varToVarIdIt->second;
379 auto vId = varToVarIdIt->second;
380 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
380 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
381 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
381 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
382 auto gId = varIdToGroupIdIt->second;
382 auto gId = varIdToGroupIdIt->second;
383 if (groupIds.find(gId) == groupIds.cend()) {
383 if (groupIds.find(gId) == groupIds.cend()) {
384 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
384 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
385 groupIds.insert(gId);
385 groupIds.insert(gId);
386 }
386 }
387 }
387 }
388 }
388 }
389 }
389 }
390
390
391 // We assume here all group ids exist
391 // We assume here all group ids exist
392 for (const auto &gId : groupIds) {
392 for (const auto &gId : groupIds) {
393 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
393 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
394 auto vSyncIds = vSynchronizationGroup->getIds();
394 auto vSyncIds = vSynchronizationGroup->getIds();
395 qCDebug(LOG_VariableController()) << "Var in synchro group ";
395 qCDebug(LOG_VariableController()) << "Var in synchro group ";
396 for (auto vId : vSyncIds) {
396 for (auto vId : vSyncIds) {
397 auto var = impl->findVariable(vId);
397 auto var = impl->findVariable(vId);
398
398
399 // Don't process already processed var
399 // Don't process already processed var
400 if (!variables.contains(var)) {
400 if (!variables.contains(var)) {
401 if (var != nullptr) {
401 if (var != nullptr) {
402 qCDebug(LOG_VariableController()) << "processRequest synchro for"
402 qCDebug(LOG_VariableController()) << "processRequest synchro for"
403 << var->name();
403 << var->name();
404 auto vSyncRangeRequested
404 auto vSyncRangeRequested
405 = computeSynchroRangeRequested(var->range(), range, oldRange);
405 = computeSynchroRangeRequested(var->range(), range, oldRange);
406 impl->processRequest(var, vSyncRangeRequested);
406 impl->processRequest(var, vSyncRangeRequested);
407 }
407 }
408 else {
408 else {
409 qCCritical(LOG_VariableController())
409 qCCritical(LOG_VariableController())
410
410
411 << tr("Impossible to synchronize a null variable");
411 << tr("Impossible to synchronize a null variable");
412 }
412 }
413 }
413 }
414 }
414 }
415 }
415 }
416 }
416 }
417 }
417 }
418
418
419
419
420 void VariableController::initialize()
420 void VariableController::initialize()
421 {
421 {
422 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
422 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
423 impl->m_WorkingMutex.lock();
423 impl->m_WorkingMutex.lock();
424 qCDebug(LOG_VariableController()) << tr("VariableController init END");
424 qCDebug(LOG_VariableController()) << tr("VariableController init END");
425 }
425 }
426
426
427 void VariableController::finalize()
427 void VariableController::finalize()
428 {
428 {
429 impl->m_WorkingMutex.unlock();
429 impl->m_WorkingMutex.unlock();
430 }
430 }
431
431
432 void VariableController::waitForFinish()
432 void VariableController::waitForFinish()
433 {
433 {
434 QMutexLocker locker{&impl->m_WorkingMutex};
434 QMutexLocker locker{&impl->m_WorkingMutex};
435 }
435 }
436
436
437 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
437 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
438 {
438 {
439 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
439 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
440 auto zoomType = AcquisitionZoomType::Unknown;
440 auto zoomType = AcquisitionZoomType::Unknown;
441 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
441 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
442 zoomType = AcquisitionZoomType::ZoomOut;
442 zoomType = AcquisitionZoomType::ZoomOut;
443 }
443 }
444 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
444 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
445 zoomType = AcquisitionZoomType::PanRight;
445 zoomType = AcquisitionZoomType::PanRight;
446 }
446 }
447 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
447 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
448 zoomType = AcquisitionZoomType::PanLeft;
448 zoomType = AcquisitionZoomType::PanLeft;
449 }
449 }
450 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
450 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
451 zoomType = AcquisitionZoomType::ZoomIn;
451 zoomType = AcquisitionZoomType::ZoomIn;
452 }
452 }
453 else {
453 else {
454 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
454 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
455 }
455 }
456 return zoomType;
456 return zoomType;
457 }
457 }
458
458
459 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
459 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
460 const SqpRange &rangeRequested)
460 const SqpRange &rangeRequested)
461 {
461 {
462
462
463 auto varRangesRequested
463 auto varRangesRequested
464 = m_VariableCacheStrategy->computeCacheRange(var->range(), rangeRequested);
464 = m_VariableCacheStrategy->computeCacheRange(var->range(), rangeRequested);
465 auto notInCacheRangeList = var->provideNotInCacheRangeList(varRangesRequested.second);
465 auto notInCacheRangeList = var->provideNotInCacheRangeList(varRangesRequested.second);
466
466
467 if (!notInCacheRangeList.empty()) {
467 if (!notInCacheRangeList.empty()) {
468 auto identifier = m_VariableToIdentifierMap.at(var);
468 auto identifier = m_VariableToIdentifierMap.at(var);
469 auto varProvider = m_VariableToProviderMap.at(var);
469 auto varProvider = m_VariableToProviderMap.at(var);
470 if (varProvider != nullptr) {
470 if (varProvider != nullptr) {
471 m_VariableAcquisitionWorker->pushVariableRequest(
471 m_VariableAcquisitionWorker->pushVariableRequest(
472 identifier, varRangesRequested.first, varRangesRequested.second,
472 identifier, varRangesRequested.first, varRangesRequested.second,
473 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
473 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
474 varProvider);
474 varProvider);
475 }
475 }
476 else {
476 else {
477 qCCritical(LOG_VariableController())
477 qCCritical(LOG_VariableController())
478 << "Impossible to provide data with a null provider";
478 << "Impossible to provide data with a null provider";
479 }
479 }
480 }
480 }
481 else {
481 else {
482 var->setRange(rangeRequested);
482 var->setRange(rangeRequested);
483 var->setCacheRange(varRangesRequested.second);
483 var->setCacheRange(varRangesRequested.second);
484 var->setDataSeries(var->dataSeries()->subData(varRangesRequested.second));
484 var->setDataSeries(var->dataSeries()->subDataSeries(varRangesRequested.second));
485 emit var->updated();
485 emit var->updated();
486 }
486 }
487 }
487 }
488
488
489 std::shared_ptr<Variable>
489 std::shared_ptr<Variable>
490 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
490 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
491 {
491 {
492 std::shared_ptr<Variable> var;
492 std::shared_ptr<Variable> var;
493 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
493 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
494
494
495 auto end = m_VariableToIdentifierMap.cend();
495 auto end = m_VariableToIdentifierMap.cend();
496 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
496 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
497 if (it != end) {
497 if (it != end) {
498 var = it->first;
498 var = it->first;
499 }
499 }
500 else {
500 else {
501 qCCritical(LOG_VariableController())
501 qCCritical(LOG_VariableController())
502 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
502 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
503 }
503 }
504
504
505 return var;
505 return var;
506 }
506 }
507
507
508 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
508 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
509 const QVector<AcquisitionDataPacket> acqDataPacketVector)
509 const QVector<AcquisitionDataPacket> acqDataPacketVector)
510 {
510 {
511 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
511 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
512 << acqDataPacketVector.size();
512 << acqDataPacketVector.size();
513 std::shared_ptr<IDataSeries> dataSeries;
513 std::shared_ptr<IDataSeries> dataSeries;
514 if (!acqDataPacketVector.isEmpty()) {
514 if (!acqDataPacketVector.isEmpty()) {
515 dataSeries = acqDataPacketVector[0].m_DateSeries;
515 dataSeries = acqDataPacketVector[0].m_DateSeries;
516 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
516 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
517 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
517 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
518 }
518 }
519 }
519 }
520 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
520 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
521 << acqDataPacketVector.size();
521 << acqDataPacketVector.size();
522 return dataSeries;
522 return dataSeries;
523 }
523 }
524
524
525 void VariableController::VariableControllerPrivate::registerProvider(
525 void VariableController::VariableControllerPrivate::registerProvider(
526 std::shared_ptr<IDataProvider> provider)
526 std::shared_ptr<IDataProvider> provider)
527 {
527 {
528 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
528 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
529 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
529 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
530 << provider->objectName();
530 << provider->objectName();
531 m_ProviderSet.insert(provider);
531 m_ProviderSet.insert(provider);
532 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
532 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
533 &VariableAcquisitionWorker::onVariableDataAcquired);
533 &VariableAcquisitionWorker::onVariableDataAcquired);
534 connect(provider.get(), &IDataProvider::dataProvidedProgress,
534 connect(provider.get(), &IDataProvider::dataProvidedProgress,
535 m_VariableAcquisitionWorker.get(),
535 m_VariableAcquisitionWorker.get(),
536 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
536 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
537 }
537 }
538 else {
538 else {
539 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
539 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
540 }
540 }
541 }
541 }
@@ -1,18 +1,44
1 # On ignore toutes les règles vera++ pour le fichier spimpl
1 # On ignore toutes les règles vera++ pour le fichier spimpl
2 Common/spimpl\.h:\d+:.*
2 Common/spimpl\.h:\d+:.*
3
3
4 # Ignore false positive relative to two class definitions in a same file
4 # Ignore false positive relative to two class definitions in a same file
5 DataSourceItem\.h:\d+:.*IPSIS_S01.*
5 DataSourceItem\.h:\d+:.*IPSIS_S01.*
6
6
7 # Ignore false positive relative to a template class
7 # Ignore false positive relative to a template class
8 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (D)
8 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (D)
9 ArrayData\.h:\d+:.*IPSIS_S04_NAMESPACE.*found: (arraydata_detail)
9 ArrayData\.h:\d+:.*IPSIS_S04_NAMESPACE.*found: (arraydata_detail)
10 ArrayData\.h:\d+:.*IPSIS_S06.*found: (D)
10 ArrayData\.h:\d+:.*IPSIS_S06.*found: (D)
11 ArrayData\.h:\d+:.*IPSIS_S06.*found: (Dim)
11 ArrayData\.h:\d+:.*IPSIS_S06.*found: (Dim)
12 DataSeries\.h:\d+:.*IPSIS_S04_VARIABLE.*
12 DataSeries\.h:\d+:.*IPSIS_S04_VARIABLE.*
13
13
14 # Ignore false positive relative to iterators
15 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (forward_iterator_tag)
16 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (IteratorValue)
17 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (ptrdiff_t)
18 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (value_type)
19 ArrayData\.h:\d+:.*IPSIS_S05.*
20 ArrayData\.h:\d+:.*IPSIS_S06.*found: (iterator_category)
21 ArrayData\.h:\d+:.*IPSIS_S06.*found: (forward_iterator_tag)
22 ArrayData\.h:\d+:.*IPSIS_S06.*found: (value_type)
23 ArrayData\.h:\d+:.*IPSIS_S06.*found: (IteratorValue)
24 ArrayData\.h:\d+:.*IPSIS_S06.*found: (difference_type)
25 ArrayData\.h:\d+:.*IPSIS_S06.*found: (ptrdiff_t)
26 ArrayData\.h:\d+:.*IPSIS_S06.*found: (pointer)
27 ArrayData\.h:\d+:.*IPSIS_S06.*found: (reference)
28 ArrayData\.h:\d+:.*IPSIS_S06.*found: (value_type)
29 DataSeries\.h:\d+:.*IPSIS_S05.*
30 DataSeries\.h:\d+:.*IPSIS_S06.*found: (iterator_category)
31 DataSeries\.h:\d+:.*IPSIS_S06.*found: (forward_iterator_tag)
32 DataSeries\.h:\d+:.*IPSIS_S06.*found: (value_type)
33 DataSeries\.h:\d+:.*IPSIS_S06.*found: (IteratorValue)
34 DataSeries\.h:\d+:.*IPSIS_S06.*found: (difference_type)
35 DataSeries\.h:\d+:.*IPSIS_S06.*found: (ptrdiff_t)
36 DataSeries\.h:\d+:.*IPSIS_S06.*found: (pointer)
37 DataSeries\.h:\d+:.*IPSIS_S06.*found: (reference)
38 DataSeries\.h:\d+:.*IPSIS_S06.*found: (value_type)
39
14 # Ignore false positive relative to an alias
40 # Ignore false positive relative to an alias
15 DataSourceItemAction\.h:\d+:.*IPSIS_S06.*found: (ExecuteFunction)
41 DataSourceItemAction\.h:\d+:.*IPSIS_S06.*found: (ExecuteFunction)
16
42
17 # Ignore false positive relative to unnamed namespace
43 # Ignore false positive relative to unnamed namespace
18 VariableController\.cpp:\d+:.*IPSIS_F13.*
44 VariableController\.cpp:\d+:.*IPSIS_F13.*
General Comments 0
You need to be logged in to leave comments. Login now