##// END OF EJS Templates
Few methods added to ease integration in existing GUI...
jeandet -
r25:5f4f9560990b
parent child
Show More
@@ -1,65 +1,86
1 #ifndef SCIQLOP_DATETIMERANGEHELPER_H
1 #ifndef SCIQLOP_DATETIMERANGEHELPER_H
2 #define SCIQLOP_DATETIMERANGEHELPER_H
2 #define SCIQLOP_DATETIMERANGEHELPER_H
3
3
4 #include <optional>
4 #include <optional>
5
5
6 #include <cmath>
6 #include <cmath>
7 #include <variant>
7 #include <variant>
8 #include <QObject>
8 #include <QObject>
9
9
10 #include <QDebug>
10 #include <QDebug>
11
11
12 #include <opaque/numeric_typedef.hpp>
12 #include <opaque/numeric_typedef.hpp>
13 #include <Common/DateUtils.h>
13 #include <Common/DateUtils.h>
14 #include <Common/MetaTypes.h>
14 #include <Common/MetaTypes.h>
15 #include <Common/Numeric.h>
15 #include <Common/Numeric.h>
16 #include <Data/DateTimeRange.h>
16 #include <Data/DateTimeRange.h>
17
17
18 enum class TransformationType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
19
18 namespace DateTimeRangeHelper {
20 namespace DateTimeRangeHelper {
19
21
20
22
21 inline bool isnan(const DateTimeRange& range)
23 inline bool isnan(const DateTimeRange& range)
22 {
24 {
23 return std::isnan(range.m_TStart) && std::isnan(range.m_TEnd);
25 return std::isnan(range.m_TStart) && std::isnan(range.m_TEnd);
24 }
26 }
25
27
26 inline bool hasnan(const DateTimeRange& range)
28 inline bool hasnan(const DateTimeRange& range)
27 {
29 {
28 return std::isnan(range.m_TStart) || std::isnan(range.m_TEnd);
30 return std::isnan(range.m_TStart) || std::isnan(range.m_TEnd);
29 }
31 }
30
32
31 inline bool isPureShift(const DateTimeRange& range1, const DateTimeRange& range2)
33 inline bool isPureShift(const DateTimeRange& range1, const DateTimeRange& range2)
32 {
34 {
33 return SciQLop::numeric::almost_equal<double>(range1.delta(), range2.delta(), 1)
35 return SciQLop::numeric::almost_equal<double>(range1.delta(), range2.delta(), 1)
34 && !SciQLop::numeric::almost_equal(range1.m_TStart, range2.m_TStart, 1);
36 && !SciQLop::numeric::almost_equal(range1.m_TStart, range2.m_TStart, 1);
35 }
37 }
36
38
37 inline bool isPureZoom(const DateTimeRange& range1, const DateTimeRange& range2)
39 inline bool isPureZoom(const DateTimeRange& range1, const DateTimeRange& range2)
38 {
40 {
39 return !SciQLop::numeric::almost_equal<double>(range1.delta(),range2.delta(),1)&&
41 return !SciQLop::numeric::almost_equal<double>(range1.delta(),range2.delta(),1)&&
40 SciQLop::numeric::almost_equal<double>(range1.center(), range2.center(),1);
42 SciQLop::numeric::almost_equal<double>(range1.center(), range2.center(),1);
41 }
43 }
42
44
45
43 /**
46 /**
44 * @brief computeTransformation such as range2 = zoom*range1 + shift
47 * @brief computeTransformation such as range2 = zoom*range1 + shift
45 * @param range1
48 * @param range1
46 * @param range2
49 * @param range2
47 * @return trnaformation applied to range1 to get range2 or an object of type
50 * @return trnaformation applied to range1 to get range2 or an object of type
48 * InvalidDateTimeRangeTransformation if the transformation has NaN or forbiden values
51 * InvalidDateTimeRangeTransformation if the transformation has NaN or forbiden values
49 */
52 */
50 inline std::optional<DateTimeRangeTransformation>
53 inline std::optional<DateTimeRangeTransformation>
51 computeTransformation(const DateTimeRange& range1, const DateTimeRange& range2)
54 computeTransformation(const DateTimeRange& range1, const DateTimeRange& range2)
52 {
55 {
53 std::optional<DateTimeRangeTransformation> transformation;
56 std::optional<DateTimeRangeTransformation> transformation;
54 double zoom = range2.delta()/range1.delta();
57 double zoom = range2.delta()/range1.delta();
55 Seconds<double> shift = range2.center() - (range1*zoom).center();
58 Seconds<double> shift = range2.center() - (range1*zoom).center();
56 bool zoomValid = zoom!=0. && !std::isnan(zoom) && !std::isinf(zoom);
59 bool zoomValid = zoom!=0. && !std::isnan(zoom) && !std::isinf(zoom);
57 bool shiftValid = !std::isnan(shift.value) && !std::isinf(shift.value);
60 bool shiftValid = !std::isnan(shift.value) && !std::isinf(shift.value);
58 if(zoomValid && shiftValid)
61 if(zoomValid && shiftValid)
59 transformation = DateTimeRangeTransformation{zoom, shift};
62 transformation = DateTimeRangeTransformation{zoom, shift};
60 return transformation;
63 return transformation;
61 }
64 }
62
65
66 inline TransformationType getTransformationType(const DateTimeRange& range1, const DateTimeRange& range2)
67 {
68 auto transformation = computeTransformation (range1,range2);
69 if(transformation.has_value ())
70 {
71 if(SciQLop::numeric::almost_equal(transformation->zoom,1.))
72 {
73 if(transformation->shift > 0.)
74 return TransformationType::PanRight;
75 return TransformationType::PanLeft;
76 }
77 if(transformation->zoom > 0.)
78 return TransformationType::ZoomOut;
79 return TransformationType::ZoomIn;
80 }
81 return TransformationType::Unknown;
82 }
83
63 }
84 }
64
85
65 #endif // SCIQLOP_DATETIMERANGEHELPER_H
86 #endif // SCIQLOP_DATETIMERANGEHELPER_H
@@ -1,46 +1,52
1 #include <memory>
1 #include <memory>
2 #include <vector>
2 #include <vector>
3 #include <set>
3 #include <set>
4 #include <QHash>
4 #include <QHash>
5 #include <QObject>
5 #include <QObject>
6 #include <QMutexLocker>
6 #include <QMutexLocker>
7 #include <QUuid>
7 #include <QUuid>
8 #include <QByteArray>
8 #include <QByteArray>
9 #include <QItemSelectionModel>
9 #include <QItemSelectionModel>
10 #include <Common/spimpl.h>
10 #include <Common/spimpl.h>
11 #include <Variable/Variable.h>
11 #include <Variable/Variable.h>
12 //#include <Variable/VariableSynchronizationGroup.h>
12 //#include <Variable/VariableSynchronizationGroup.h>
13 #include <Variable/VariableModel.h>
13 #include <Variable/VariableModel.h>
14 #include <Data/IDataProvider.h>
14 #include <Data/IDataProvider.h>
15 #include "Data/DateTimeRange.h"
15 #include "Data/DateTimeRange.h"
16
16
17 class VariableController2: public QObject
17 class VariableController2: public QObject
18 {
18 {
19 class VariableController2Private;
19 class VariableController2Private;
20 Q_OBJECT
20 Q_OBJECT
21
21
22 spimpl::unique_impl_ptr<VariableController2Private> impl;
22 spimpl::unique_impl_ptr<VariableController2Private> impl;
23
23
24 public:
24 public:
25 explicit VariableController2();
25 explicit VariableController2();
26 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
26 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
27 const std::shared_ptr<IDataProvider>& provider,
27 const std::shared_ptr<IDataProvider>& provider,
28 const DateTimeRange &range);
28 const DateTimeRange &range);
29
29
30 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable);
30 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable);
31 void deleteVariable(const std::shared_ptr<Variable>& variable);
31 void deleteVariable(const std::shared_ptr<Variable>& variable);
32 void changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
32 void changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
33 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
33 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r);
34 const std::vector<std::shared_ptr<Variable>> variables();
34 const std::vector<std::shared_ptr<Variable>> variables();
35
35
36 bool isReady(const std::shared_ptr<Variable>& variable);
36 bool isReady(const std::shared_ptr<Variable>& variable);
37
37
38 void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with);
38 void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with);
39
39
40 //This should be somewhere else VC has nothing to do with MIMEData
40 QByteArray mimeData(const std::vector<std::shared_ptr<Variable>> &variables) const;
41 QByteArray mimeData(const std::vector<std::shared_ptr<Variable>> &variables) const;
42 const std::vector<std::shared_ptr<Variable>> variables(QByteArray mimeData);
43
44 const std::shared_ptr<Variable>& operator[] (int index) const;
45 std::shared_ptr<Variable> operator[] (int index);
46
41
47
42 signals:
48 signals:
43 void variableAdded(const std::shared_ptr<Variable>&);
49 void variableAdded(const std::shared_ptr<Variable>&);
44 void variableDeleted(const std::shared_ptr<Variable>&);
50 void variableDeleted(const std::shared_ptr<Variable>&);
45
51
46 };
52 };
@@ -1,358 +1,403
1 #include <QQueue>
1 #include <QQueue>
2 #include <QThreadPool>
2 #include <QThreadPool>
3 #include <QRunnable>
3 #include <QRunnable>
4 #include <QObject>
4 #include <QObject>
5 #include <QDataStream>
5 #include <QDataStream>
6
6
7 #include "Variable/VariableController2.h"
7 #include "Variable/VariableController2.h"
8 #include "Variable/VariableSynchronizationGroup2.h"
8 #include "Variable/VariableSynchronizationGroup2.h"
9 #include <Common/containers.h>
9 #include <Common/containers.h>
10 #include <Common/debug.h>
10 #include <Common/debug.h>
11 #include <Data/DataProviderParameters.h>
11 #include <Data/DataProviderParameters.h>
12 #include <Data/DateTimeRangeHelper.h>
12 #include <Data/DateTimeRangeHelper.h>
13 #include <Data/DateTimeRange.h>
13 #include <Data/DateTimeRange.h>
14 #include <Variable/VariableCacheStrategyFactory.h>
14 #include <Variable/VariableCacheStrategyFactory.h>
15 #include <Variable/private/VCTransaction.h>
15 #include <Variable/private/VCTransaction.h>
16 #include <QCoreApplication>
16 #include <QCoreApplication>
17
17
18
18
19
19
20 class VariableController2::VariableController2Private
20 class VariableController2::VariableController2Private
21 {
21 {
22 struct threadSafeVaraiblesMaps
22 struct threadSafeVaraiblesMaps
23 {
23 {
24 inline void addVariable(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider, const std::shared_ptr<VariableSynchronizationGroup2>& synchronizationGroup)
24 inline void addVariable(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider, const std::shared_ptr<VariableSynchronizationGroup2>& synchronizationGroup)
25 {
25 {
26 QWriteLocker lock{&_lock};
26 QWriteLocker lock{&_lock};
27 _variables[*variable] = variable;
27 _variables[*variable] = variable;
28 _providers[*variable] = provider;
28 _providers[*variable] = provider;
29 _synchronizationGroups[*variable] = synchronizationGroup;
29 _synchronizationGroups[*variable] = synchronizationGroup;
30 }
30 }
31
31
32 inline void removeVariable(const std::shared_ptr<Variable>& variable)
32 inline void removeVariable(const std::shared_ptr<Variable>& variable)
33 {
33 {
34 QWriteLocker lock{&_lock};
34 QWriteLocker lock{&_lock};
35 _variables.remove(*variable);
35 _variables.remove(*variable);
36 _providers.remove(*variable);
36 _providers.remove(*variable);
37 _synchronizationGroups.remove(*variable);
37 _synchronizationGroups.remove(*variable);
38 }
38 }
39
39
40 inline void synchronize(const std::shared_ptr<Variable>& variable, const std::optional<std::shared_ptr<Variable>>& with)
40 inline void synchronize(const std::shared_ptr<Variable>& variable, const std::optional<std::shared_ptr<Variable>>& with)
41 {
41 {
42 QWriteLocker lock{&_lock};
42 QWriteLocker lock{&_lock};
43 if(with.has_value())
43 if(with.has_value())
44 {
44 {
45 auto newGroup = _synchronizationGroups[*with.value()];
45 auto newGroup = _synchronizationGroups[*with.value()];
46 newGroup->addVariable(*variable);
46 newGroup->addVariable(*variable);
47 _synchronizationGroups[*variable] = newGroup;
47 _synchronizationGroups[*variable] = newGroup;
48 }
48 }
49 else
49 else
50 {
50 {
51 _synchronizationGroups[*variable] = std::make_shared<VariableSynchronizationGroup2>(*variable);
51 _synchronizationGroups[*variable] = std::make_shared<VariableSynchronizationGroup2>(*variable);
52 }
52 }
53 }
53 }
54
54
55 inline std::shared_ptr<Variable> variable(QUuid variable)
55 inline std::shared_ptr<Variable> variable(QUuid variable)
56 {
56 {
57 QReadLocker lock{&_lock};
57 QReadLocker lock{&_lock};
58 [[unlikely]]
58 [[unlikely]]
59 if(!_variables.contains(variable))
59 if(!_variables.contains(variable))
60 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
60 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
61 return _variables[variable];
61 return _variables[variable];
62 }
62 }
63
63
64 inline std::shared_ptr<Variable> variable(int index)
65 {
66 QReadLocker lock{&_lock};
67 [[unlikely]]
68 if(!_variables.size() > index)
69 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Index is out of bounds");
70 return _variables.values()[index];
71 }
72
64 inline const std::vector<std::shared_ptr<Variable>> variables()
73 inline const std::vector<std::shared_ptr<Variable>> variables()
65 {
74 {
66 std::vector<std::shared_ptr<Variable>> vars;
75 std::vector<std::shared_ptr<Variable>> vars;
67 QReadLocker lock{&_lock};
76 QReadLocker lock{&_lock};
68 for(const auto &var:_variables)
77 for(const auto &var:_variables)
69 {
78 {
70 vars.push_back(var);
79 vars.push_back(var);
71 }
80 }
72 return vars;
81 return vars;
73 }
82 }
74
83
75 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
84 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
76 {
85 {
77 QReadLocker lock{&_lock};
86 QReadLocker lock{&_lock};
78 [[unlikely]]
87 [[unlikely]]
79 if(!_providers.contains(variable))
88 if(!_providers.contains(variable))
80 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
89 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
81 return _providers[variable];
90 return _providers[variable];
82 }
91 }
83
92
84 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
93 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
85 {
94 {
86 QReadLocker lock{&_lock};
95 QReadLocker lock{&_lock};
87 [[unlikely]]
96 [[unlikely]]
88 if(!_synchronizationGroups.contains(variable))
97 if(!_synchronizationGroups.contains(variable))
89 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
98 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
90 return _synchronizationGroups[variable];
99 return _synchronizationGroups[variable];
91 }
100 }
92
101
93 inline bool has(const std::shared_ptr<Variable>& variable)
102 inline bool has(const std::shared_ptr<Variable>& variable)
94 {
103 {
95 QReadLocker lock{&_lock};
104 QReadLocker lock{&_lock};
96 return _variables.contains(*variable);
105 return _variables.contains(*variable);
97 }
106 }
98
107
99 private:
108 private:
100 QMap<QUuid,std::shared_ptr<Variable>> _variables;
109 QMap<QUuid,std::shared_ptr<Variable>> _variables;
101 QMap<QUuid,std::shared_ptr<IDataProvider>> _providers;
110 QMap<QUuid,std::shared_ptr<IDataProvider>> _providers;
102 QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups;
111 QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups;
103 QReadWriteLock _lock{QReadWriteLock::Recursive};
112 QReadWriteLock _lock{QReadWriteLock::Recursive};
104 }_maps;
113 }_maps;
105 QThreadPool _ThreadPool;
114 QThreadPool _ThreadPool;
106 VCTransactionsQueues _transactions;
115 VCTransactionsQueues _transactions;
107 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
116 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
108
117
109 void _transactionComplete(QUuid group, std::shared_ptr<VCTransaction> transaction)
118 void _transactionComplete(QUuid group, std::shared_ptr<VCTransaction> transaction)
110 {
119 {
111 if(transaction->done())
120 if(transaction->done())
112 {
121 {
113 _transactions.complete(group);
122 _transactions.complete(group);
114 }
123 }
115 this->_processTransactions();
124 this->_processTransactions();
116 }
125 }
117 void _processTransactions()
126 void _processTransactions()
118 {
127 {
119 auto nextTransactions = _transactions.nextTransactions();
128 auto nextTransactions = _transactions.nextTransactions();
120 auto pendingTransactions = _transactions.pendingTransactions();
129 auto pendingTransactions = _transactions.pendingTransactions();
121 for( auto [groupID, newTransaction] : nextTransactions)
130 for( auto [groupID, newTransaction] : nextTransactions)
122 {
131 {
123 if(newTransaction.has_value() && !pendingTransactions[groupID].has_value())
132 if(newTransaction.has_value() && !pendingTransactions[groupID].has_value())
124 {
133 {
125 _transactions.start(groupID);
134 _transactions.start(groupID);
126 auto refVar = _maps.variable(newTransaction.value()->refVar);
135 auto refVar = _maps.variable(newTransaction.value()->refVar);
127 auto ranges = _computeAllRangesInGroup(refVar,newTransaction.value()->range);
136 auto ranges = _computeAllRangesInGroup(refVar,newTransaction.value()->range);
128 for( auto const& [ID, range] : ranges)
137 for( auto const& [ID, range] : ranges)
129 {
138 {
130 auto provider = _maps.provider(ID);
139 auto provider = _maps.provider(ID);
131 auto variable = _maps.variable(ID);
140 auto variable = _maps.variable(ID);
132 auto [missingRanges, newCacheRange] = _computeMissingRanges(variable,range);
141 auto [missingRanges, newCacheRange] = _computeMissingRanges(variable,range);
133 auto exe = new TransactionExe(variable, provider, missingRanges, range, newCacheRange);
142 auto exe = new TransactionExe(variable, provider, missingRanges, range, newCacheRange);
134 QObject::connect(exe,
143 QObject::connect(exe,
135 &TransactionExe::transactionComplete,
144 &TransactionExe::transactionComplete,
136 [groupID=groupID,transaction=newTransaction.value(),this]()
145 [groupID=groupID,transaction=newTransaction.value(),this]()
137 {
146 {
138 this->_transactionComplete(groupID, transaction);
147 this->_transactionComplete(groupID, transaction);
139 }
148 }
140 );
149 );
141 _ThreadPool.start(exe);
150 _ThreadPool.start(exe);
142 }
151 }
143 }
152 }
144 }
153 }
145 }
154 }
146
155
147 std::map<QUuid,DateTimeRange> _computeAllRangesInGroup(const std::shared_ptr<Variable>& refVar, DateTimeRange r)
156 std::map<QUuid,DateTimeRange> _computeAllRangesInGroup(const std::shared_ptr<Variable>& refVar, DateTimeRange r)
148 {
157 {
149 std::map<QUuid,DateTimeRange> ranges;
158 std::map<QUuid,DateTimeRange> ranges;
150 if(!DateTimeRangeHelper::hasnan(r))
159 if(!DateTimeRangeHelper::hasnan(r))
151 {
160 {
152 auto group = _maps.group(*refVar);
161 auto group = _maps.group(*refVar);
153 if(auto transformation = DateTimeRangeHelper::computeTransformation(refVar->range(),r);
162 if(auto transformation = DateTimeRangeHelper::computeTransformation(refVar->range(),r);
154 transformation.has_value())
163 transformation.has_value())
155 {
164 {
156 for(auto varId:group->variables())
165 for(auto varId:group->variables())
157 {
166 {
158 auto var = _maps.variable(varId);
167 auto var = _maps.variable(varId);
159 auto newRange = var->range().transform(transformation.value());
168 auto newRange = var->range().transform(transformation.value());
160 ranges[varId] = newRange;
169 ranges[varId] = newRange;
161 }
170 }
162 }
171 }
163 else // force new range to all variables -> may be weird if more than one var in the group
172 else // force new range to all variables -> may be weird if more than one var in the group
164 // @TODO ensure that there is no side effects
173 // @TODO ensure that there is no side effects
165 {
174 {
166 for(auto varId:group->variables())
175 for(auto varId:group->variables())
167 {
176 {
168 auto var = _maps.variable(varId);
177 auto var = _maps.variable(varId);
169 ranges[varId] = r;
178 ranges[varId] = r;
170 }
179 }
171 }
180 }
172 }
181 }
173 else
182 else
174 {
183 {
175 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
184 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
176 }
185 }
177 return ranges;
186 return ranges;
178 }
187 }
179
188
180 std::pair<std::vector<DateTimeRange>,DateTimeRange> _computeMissingRanges(const std::shared_ptr<Variable>& var, DateTimeRange r)
189 std::pair<std::vector<DateTimeRange>,DateTimeRange> _computeMissingRanges(const std::shared_ptr<Variable>& var, DateTimeRange r)
181 {
190 {
182 DateTimeRange newCacheRange;
191 DateTimeRange newCacheRange;
183 std::vector<DateTimeRange> missingRanges;
192 std::vector<DateTimeRange> missingRanges;
184 if(DateTimeRangeHelper::hasnan(var->cacheRange()))
193 if(DateTimeRangeHelper::hasnan(var->cacheRange()))
185 {
194 {
186 newCacheRange = _cacheStrategy->computeRange(r,r);
195 newCacheRange = _cacheStrategy->computeRange(r,r);
187 missingRanges = {newCacheRange};
196 missingRanges = {newCacheRange};
188 }
197 }
189 else
198 else
190 {
199 {
191 newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r);
200 newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r);
192 missingRanges = newCacheRange - var->cacheRange();
201 missingRanges = newCacheRange - var->cacheRange();
193 }
202 }
194 return {missingRanges,newCacheRange};
203 return {missingRanges,newCacheRange};
195 }
204 }
196
205
197 void _changeRange(QUuid id, DateTimeRange r)
206 void _changeRange(QUuid id, DateTimeRange r)
198 {
207 {
199 _changeRange(_maps.variable(id) ,r);
208 _changeRange(_maps.variable(id) ,r);
200 }
209 }
201 void _changeRange(const std::shared_ptr<Variable>& var, DateTimeRange r)
210 void _changeRange(const std::shared_ptr<Variable>& var, DateTimeRange r)
202 {
211 {
203 auto provider = _maps.provider(*var);
212 auto provider = _maps.provider(*var);
204 auto [missingRanges, newCacheRange] = _computeMissingRanges(var,r);
213 auto [missingRanges, newCacheRange] = _computeMissingRanges(var,r);
205 std::vector<IDataSeries*> data;
214 std::vector<IDataSeries*> data;
206 for(auto range:missingRanges)
215 for(auto range:missingRanges)
207 {
216 {
208 data.push_back(provider->getData(DataProviderParameters{{range}, var->metadata()}));
217 data.push_back(provider->getData(DataProviderParameters{{range}, var->metadata()}));
209 }
218 }
210 var->updateData(data, r, newCacheRange, true);
219 var->updateData(data, r, newCacheRange, true);
211 }
220 }
212 public:
221 public:
213 VariableController2Private(QObject* parent=Q_NULLPTR)
222 VariableController2Private(QObject* parent=Q_NULLPTR)
214 :_cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(CacheStrategy::SingleThreshold))
223 :_cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(CacheStrategy::SingleThreshold))
215 {
224 {
216 Q_UNUSED(parent);
225 Q_UNUSED(parent);
217 this->_ThreadPool.setMaxThreadCount(32);
226 this->_ThreadPool.setMaxThreadCount(32);
218 }
227 }
219
228
220 /*
229 /*
221 * This dtor has to like this even if this is ugly, because default dtor would rely on
230 * This dtor has to like this even if this is ugly, because default dtor would rely on
222 * declaration order to destruct members and that would always lead to regressions when
231 * declaration order to destruct members and that would always lead to regressions when
223 * modifying class members
232 * modifying class members
224 */
233 */
225 ~VariableController2Private()
234 ~VariableController2Private()
226 {
235 {
227 while (this->_ThreadPool.activeThreadCount())
236 while (this->_ThreadPool.activeThreadCount())
228 {
237 {
229 this->_ThreadPool.waitForDone(100);
238 this->_ThreadPool.waitForDone(100);
230 }
239 }
231 }
240 }
232
241
233 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider)
242 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider)
234 {
243 {
235 auto newVar = std::make_shared<Variable>(name,metadata);
244 auto newVar = std::make_shared<Variable>(name,metadata);
236 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
245 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
237 _maps.addVariable(newVar,std::move(provider),group);
246 _maps.addVariable(newVar,std::move(provider),group);
238 this->_transactions.addEntry(*group);
247 this->_transactions.addEntry(*group);
239 return newVar;
248 return newVar;
240 }
249 }
241
250
251 std::shared_ptr<Variable> variable(QUuid ID)
252 {
253 return _maps.variable(ID);
254 }
255
256 std::shared_ptr<Variable> variable(int index)
257 {
258 return _maps.variable(index);
259 }
260
242 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable)
261 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable)
243 {
262 {
244 auto newVar = variable->clone();
263 auto newVar = variable->clone();
245 _maps.synchronize(newVar,std::nullopt);
264 _maps.synchronize(newVar,std::nullopt);
246 _maps.addVariable(newVar,_maps.provider(*variable),_maps.group(*newVar));
265 _maps.addVariable(newVar,_maps.provider(*variable),_maps.group(*newVar));
247 this->_transactions.addEntry(*_maps.group(*newVar));
266 this->_transactions.addEntry(*_maps.group(*newVar));
248 return newVar;
267 return newVar;
249 }
268 }
250
269
251 bool hasPendingTransactions(const std::shared_ptr<Variable>& variable)
270 bool hasPendingTransactions(const std::shared_ptr<Variable>& variable)
252 {
271 {
253 return _transactions.active(*_maps.group(*variable));
272 return _transactions.active(*_maps.group(*variable));
254 }
273 }
255
274
256 void deleteVariable(const std::shared_ptr<Variable>& variable)
275 void deleteVariable(const std::shared_ptr<Variable>& variable)
257 {
276 {
258 _maps.removeVariable(variable);
277 _maps.removeVariable(variable);
259 }
278 }
260
279
261 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
280 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
262 {
281 {
263 if(!DateTimeRangeHelper::hasnan(r))
282 if(!DateTimeRangeHelper::hasnan(r))
264 {
283 {
265 auto group = _maps.group(*variable);
284 auto group = _maps.group(*variable);
266 // Just overwrite next transaction
285 // Just overwrite next transaction
267 {
286 {
268 _transactions.enqueue(*group,std::make_shared<VCTransaction>(variable->ID(), r, static_cast<int>(group->variables().size())));
287 _transactions.enqueue(*group,std::make_shared<VCTransaction>(variable->ID(), r, static_cast<int>(group->variables().size())));
269 }
288 }
270 _processTransactions();
289 _processTransactions();
271 }
290 }
272 else
291 else
273 {
292 {
274 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
293 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
275 }
294 }
276 }
295 }
277
296
278 void changeRange(const std::shared_ptr<Variable>& variable, DateTimeRange r)
297 void changeRange(const std::shared_ptr<Variable>& variable, DateTimeRange r)
279 {
298 {
280 asyncChangeRange(variable,r);
299 asyncChangeRange(variable,r);
281 while (hasPendingTransactions(variable))
300 while (hasPendingTransactions(variable))
282 {
301 {
283 QCoreApplication::processEvents();
302 QCoreApplication::processEvents();
284 }
303 }
285 }
304 }
286
305
287 inline void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with)
306 inline void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with)
288 {
307 {
289 _maps.synchronize(var, with);
308 _maps.synchronize(var, with);
290 }
309 }
291
310
292 inline const std::vector<std::shared_ptr<Variable>> variables()
311 inline const std::vector<std::shared_ptr<Variable>> variables()
293 {
312 {
294 return _maps.variables();
313 return _maps.variables();
295 }
314 }
296
315
297 };
316 };
298
317
299 VariableController2::VariableController2()
318 VariableController2::VariableController2()
300 :impl{spimpl::make_unique_impl<VariableController2Private>()}
319 :impl{spimpl::make_unique_impl<VariableController2Private>()}
301 {}
320 {}
302
321
303 std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, const std::shared_ptr<IDataProvider>& provider, const DateTimeRange &range)
322 std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, const std::shared_ptr<IDataProvider>& provider, const DateTimeRange &range)
304 {
323 {
305 auto var = impl->createVariable(name, metadata, provider);
324 auto var = impl->createVariable(name, metadata, provider);
306 emit variableAdded(var);
325 emit variableAdded(var);
307 if(!DateTimeRangeHelper::hasnan(range))
326 if(!DateTimeRangeHelper::hasnan(range))
308 impl->changeRange(var,range);
327 impl->changeRange(var,range);
309 else
328 else
310 SCIQLOP_ERROR(VariableController2, "Creating a variable with default constructed DateTimeRange is an error");
329 SCIQLOP_ERROR(VariableController2, "Creating a variable with default constructed DateTimeRange is an error");
311 return var;
330 return var;
312 }
331 }
313
332
314 std::shared_ptr<Variable> VariableController2::cloneVariable(const std::shared_ptr<Variable> &variable)
333 std::shared_ptr<Variable> VariableController2::cloneVariable(const std::shared_ptr<Variable> &variable)
315 {
334 {
316 return impl->cloneVariable(variable);
335 return impl->cloneVariable(variable);
317 }
336 }
318
337
319 void VariableController2::deleteVariable(const std::shared_ptr<Variable>& variable)
338 void VariableController2::deleteVariable(const std::shared_ptr<Variable>& variable)
320 {
339 {
321 impl->deleteVariable(variable);
340 impl->deleteVariable(variable);
322 emit variableDeleted(variable);
341 emit variableDeleted(variable);
323 }
342 }
324
343
325 void VariableController2::changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
344 void VariableController2::changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
326 {
345 {
327 impl->changeRange(variable, r);
346 impl->changeRange(variable, r);
328 }
347 }
329
348
330 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &variable, const DateTimeRange &r)
349 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &variable, const DateTimeRange &r)
331 {
350 {
332 impl->asyncChangeRange(variable, r);
351 impl->asyncChangeRange(variable, r);
333 }
352 }
334
353
335 const std::vector<std::shared_ptr<Variable> > VariableController2::variables()
354 const std::vector<std::shared_ptr<Variable> > VariableController2::variables()
336 {
355 {
337 return impl->variables();
356 return impl->variables();
338 }
357 }
339
358
340 bool VariableController2::isReady(const std::shared_ptr<Variable> &variable)
359 bool VariableController2::isReady(const std::shared_ptr<Variable> &variable)
341 {
360 {
342 return impl->hasPendingTransactions(variable);
361 return impl->hasPendingTransactions(variable);
343 }
362 }
344
363
345 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, const std::shared_ptr<Variable> &with)
364 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, const std::shared_ptr<Variable> &with)
346 {
365 {
347 impl->synchronize(var, with);
366 impl->synchronize(var, with);
348 }
367 }
349
368
350 QByteArray VariableController2::mimeData(const std::vector<std::shared_ptr<Variable> > &variables) const
369 QByteArray VariableController2::mimeData(const std::vector<std::shared_ptr<Variable> > &variables) const
351 {
370 {
352 auto encodedData = QByteArray{};
371 auto encodedData = QByteArray{};
353 QDataStream stream{&encodedData, QIODevice::WriteOnly};
372 QDataStream stream{&encodedData, QIODevice::WriteOnly};
354 for (auto &var : variables) {
373 for (auto &var : variables) {
355 stream << var->ID().toByteArray();
374 stream << var->ID().toByteArray();
356 }
375 }
357 return encodedData;
376 return encodedData;
358 }
377 }
378
379 const std::vector<std::shared_ptr<Variable>> VariableController2::variables(QByteArray mimeData)
380 {
381 std::vector<std::shared_ptr<Variable>> variables;
382 QDataStream stream{mimeData};
383
384 QVariantList ids;
385 stream >> ids;
386
387 for (const auto& id : ids) {
388 auto uuid = QUuid{id.toByteArray()};
389 variables.push_back (impl->variable(uuid));
390 }
391
392 return variables;
393 }
394
395 const std::shared_ptr<Variable> &VariableController2::operator[](int index) const
396 {
397 return impl->variable (index);
398 }
399
400 std::shared_ptr<Variable> VariableController2::operator[](int index)
401 {
402 return impl->variable (index);
403 }
General Comments 0
You need to be logged in to leave comments. Login now