##// END OF EJS Templates
Merge pull request 222 from SCIQLOP-Initialisation develop...
leroux -
r547:9a7b9cf5359e merge
parent child
Show More
@@ -0,0 +1,25
1 #ifndef SCIQLOP_ACQUISITIONDATAPACKET_H
2 #define SCIQLOP_ACQUISITIONDATAPACKET_H
3
4 #include <QObject>
5
6 #include <Common/DateUtils.h>
7 #include <Common/MetaTypes.h>
8 #include <Data/IDataSeries.h>
9 #include <Data/SqpRange.h>
10
11 #include <memory>
12
13 /**
14 * @brief The AcquisitionDataPacket struct holds the information of an acquisition request result
15 * part.
16 */
17 struct AcquisitionDataPacket {
18 std::shared_ptr<IDataSeries> m_DateSeries;
19 SqpRange m_Range;
20 };
21
22 SCIQLOP_REGISTER_META_TYPE(ACQUISITIONDATAPACKET_REGISTRY, AcquisitionDataPacket)
23 SCIQLOP_REGISTER_META_TYPE(ACQUISITIONDATAPACKETVECTOR_REGISTRY, QVector<AcquisitionDataPacket>)
24
25 #endif // SCIQLOP_ACQUISITIONREQUEST_H
@@ -0,0 +1,38
1 #ifndef SCIQLOP_ACQUISITIONREQUEST_H
2 #define SCIQLOP_ACQUISITIONREQUEST_H
3
4 #include <QObject>
5
6 #include <QUuid>
7
8 #include <Common/DateUtils.h>
9 #include <Common/MetaTypes.h>
10 #include <Data/DataProviderParameters.h>
11 #include <Data/IDataProvider.h>
12 #include <Data/SqpRange.h>
13
14 #include <memory>
15
16 /**
17 * @brief The AcquisitionRequest struct holds the information of an acquisition request
18 */
19 struct AcquisitionRequest {
20 AcquisitionRequest()
21 {
22
23 m_AcqIdentifier = QUuid::createUuid();
24 m_Size = 0;
25 }
26
27 QUuid m_AcqIdentifier;
28 QUuid m_vIdentifier;
29 DataProviderParameters m_DataProviderParameters;
30 SqpRange m_RangeRequested;
31 SqpRange m_CacheRangeRequested;
32 int m_Size;
33 std::shared_ptr<IDataProvider> m_Provider;
34 };
35
36 SCIQLOP_REGISTER_META_TYPE(ACQUISITIONREQUEST_REGISTRY, AcquisitionRequest)
37
38 #endif // SCIQLOP_ACQUISITIONREQUEST_H
@@ -0,0 +1,61
1 #ifndef SCIQLOP_VARIABLEACQUISITIONWORKER_H
2 #define SCIQLOP_VARIABLEACQUISITIONWORKER_H
3
4 #include "CoreGlobal.h"
5
6 #include <Data/DataProviderParameters.h>
7 #include <QLoggingCategory>
8 #include <QObject>
9 #include <QUuid>
10
11 #include <Data/AcquisitionDataPacket.h>
12 #include <Data/IDataSeries.h>
13 #include <Data/SqpRange.h>
14
15 #include <QLoggingCategory>
16
17 #include <Common/spimpl.h>
18
19 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker)
20
21 class Variable;
22 class IDataProvider;
23
24 /// This class aims to handle all acquisition request
25 class SCIQLOP_CORE_EXPORT VariableAcquisitionWorker : public QObject {
26 Q_OBJECT
27 public:
28 explicit VariableAcquisitionWorker(QObject *parent = 0);
29 virtual ~VariableAcquisitionWorker();
30
31 void pushVariableRequest(QUuid vIdentifier, SqpRange rangeRequested,
32 SqpRange cacheRangeRequested, DataProviderParameters parameters,
33 std::shared_ptr<IDataProvider> provider);
34
35 void abortProgressRequested(QUuid vIdentifier);
36
37 void initialize();
38 void finalize();
39 signals:
40 void dataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
41 const SqpRange &cacheRangeRequested,
42 QVector<AcquisitionDataPacket> dataAcquired);
43
44 void variableRequestInProgress(QUuid vIdentifier, double progress);
45
46 public slots:
47 void onVariableDataAcquired(QUuid acqIdentifier, std::shared_ptr<IDataSeries> dataSeries,
48 SqpRange dataRangeAcquired);
49 void onVariableRetrieveDataInProgress(QUuid acqIdentifier, double progress);
50
51 private slots:
52 void onExecuteRequest(QUuid acqIdentifier);
53
54 private:
55 void waitForFinish();
56
57 class VariableAcquisitionWorkerPrivate;
58 spimpl::unique_impl_ptr<VariableAcquisitionWorkerPrivate> impl;
59 };
60
61 #endif // SCIQLOP_VARIABLEACQUISITIONWORKER_H
@@ -0,0 +1,40
1 #ifndef SCIQLOP_VARIABLECACHESTRATEGY_H
2 #define SCIQLOP_VARIABLECACHESTRATEGY_H
3
4 #include "CoreGlobal.h"
5
6 #include <QLoggingCategory>
7 #include <QObject>
8
9 #include <Data/SqpRange.h>
10
11 #include <QLoggingCategory>
12
13 #include <Common/spimpl.h>
14 #include <utility>
15
16
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableCacheStrategy)
18
19 class Variable;
20
21 /**
22 * Possible types of zoom operation
23 */
24 enum class CacheStrategy { FixedTolerance, TwoThreashold };
25
26 /// This class aims to hande the cache strategy.
27 class SCIQLOP_CORE_EXPORT VariableCacheStrategy : public QObject {
28 Q_OBJECT
29 public:
30 explicit VariableCacheStrategy(QObject *parent = 0);
31
32 std::pair<SqpRange, SqpRange> computeCacheRange(const SqpRange &vRange,
33 const SqpRange &rangeRequested);
34
35 private:
36 class VariableCacheStrategyPrivate;
37 spimpl::unique_impl_ptr<VariableCacheStrategyPrivate> impl;
38 };
39
40 #endif // SCIQLOP_VARIABLECACHESTRATEGY_H
@@ -0,0 +1,38
1 #ifndef SCIQLOP_VARIABLESYNCHRONIZATIONGROUP_H
2 #define SCIQLOP_VARIABLESYNCHRONIZATIONGROUP_H
3
4 #include "CoreGlobal.h"
5
6 #include <QLoggingCategory>
7 #include <QObject>
8 #include <QUuid>
9
10 #include <Data/SqpRange.h>
11
12 #include <set>
13
14 #include <QLoggingCategory>
15
16 #include <Common/spimpl.h>
17
18 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableSynchronizationGroup)
19
20 class Variable;
21
22 /// This class aims to hande the cache strategy.
23 class SCIQLOP_CORE_EXPORT VariableSynchronizationGroup : public QObject {
24 Q_OBJECT
25 public:
26 explicit VariableSynchronizationGroup(QObject *parent = 0);
27
28 void addVariableId(QUuid vIdentifier);
29 void removeVariableId(QUuid vIdentifier);
30
31 const std::set<QUuid> &getIds() const noexcept;
32
33 private:
34 class VariableSynchronizationGroupPrivate;
35 spimpl::unique_impl_ptr<VariableSynchronizationGroupPrivate> impl;
36 };
37
38 #endif // SCIQLOP_VARIABLESYNCHRONIZATIONGROUP_H
@@ -0,0 +1,225
1 #include "Variable/VariableAcquisitionWorker.h"
2
3 #include "Variable/Variable.h"
4
5 #include <Data/AcquisitionRequest.h>
6 #include <Data/SqpRange.h>
7
8 #include <unordered_map>
9 #include <utility>
10
11 #include <QMutex>
12 #include <QReadWriteLock>
13 #include <QThread>
14
15 Q_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker, "VariableAcquisitionWorker")
16
17 struct VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate {
18
19 explicit VariableAcquisitionWorkerPrivate() : m_Lock{QReadWriteLock::Recursive} {}
20
21 void lockRead() { m_Lock.lockForRead(); }
22 void lockWrite() { m_Lock.lockForWrite(); }
23 void unlock() { m_Lock.unlock(); }
24
25 void removeVariableRequest(QUuid vIdentifier);
26
27 QMutex m_WorkingMutex;
28 QReadWriteLock m_Lock;
29
30 std::map<QUuid, QVector<AcquisitionDataPacket> > m_AcqIdentifierToAcqDataPacketVectorMap;
31 std::map<QUuid, AcquisitionRequest> m_AcqIdentifierToAcqRequestMap;
32 std::map<QUuid, std::pair<QUuid, QUuid> > m_VIdentifierToCurrrentAcqIdNextIdPairMap;
33 };
34
35
36 VariableAcquisitionWorker::VariableAcquisitionWorker(QObject *parent)
37 : QObject{parent}, impl{spimpl::make_unique_impl<VariableAcquisitionWorkerPrivate>()}
38 {
39 }
40
41 VariableAcquisitionWorker::~VariableAcquisitionWorker()
42 {
43 qCInfo(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker destruction")
44 << QThread::currentThread();
45 this->waitForFinish();
46 }
47
48
49 void VariableAcquisitionWorker::pushVariableRequest(QUuid vIdentifier, SqpRange rangeRequested,
50 SqpRange cacheRangeRequested,
51 DataProviderParameters parameters,
52 std::shared_ptr<IDataProvider> provider)
53 {
54 qCInfo(LOG_VariableAcquisitionWorker())
55 << tr("TORM VariableAcquisitionWorker::pushVariableRequest ") << cacheRangeRequested;
56
57 // Request creation
58 auto acqRequest = AcquisitionRequest{};
59 acqRequest.m_vIdentifier = vIdentifier;
60 acqRequest.m_DataProviderParameters = parameters;
61 acqRequest.m_RangeRequested = rangeRequested;
62 acqRequest.m_CacheRangeRequested = cacheRangeRequested;
63 acqRequest.m_Size = parameters.m_Times.size();
64 acqRequest.m_Provider = provider;
65
66 // Register request
67 impl->lockWrite();
68 impl->m_AcqIdentifierToAcqRequestMap.insert(
69 std::make_pair(acqRequest.m_AcqIdentifier, acqRequest));
70
71 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
72 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
73 // A current request already exists, we can replace the next one
74 it->second.second = acqRequest.m_AcqIdentifier;
75 impl->unlock();
76 }
77 else {
78 // First request for the variable, it must be stored and executed
79 impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.insert(
80 std::make_pair(vIdentifier, std::make_pair(acqRequest.m_AcqIdentifier, QUuid())));
81 impl->unlock();
82
83 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
84 Q_ARG(QUuid, acqRequest.m_AcqIdentifier));
85 }
86 }
87
88 void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier)
89 {
90 // TODO
91 }
92
93 void VariableAcquisitionWorker::onVariableRetrieveDataInProgress(QUuid acqIdentifier,
94 double progress)
95 {
96 // TODO
97 }
98
99 void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier,
100 std::shared_ptr<IDataSeries> dataSeries,
101 SqpRange dataRangeAcquired)
102 {
103 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onVariableDataAcquired on range ")
104 << acqIdentifier << dataRangeAcquired;
105 impl->lockWrite();
106 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
107 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
108 // Store the result
109 auto dataPacket = AcquisitionDataPacket{};
110 dataPacket.m_Range = dataRangeAcquired;
111 dataPacket.m_DateSeries = dataSeries;
112
113 auto aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
114 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
115 // A current request result already exists, we can update it
116 aIdToADPVit->second.push_back(dataPacket);
117 }
118 else {
119 // First request result for the variable, it must be stored
120 impl->m_AcqIdentifierToAcqDataPacketVectorMap.insert(
121 std::make_pair(acqIdentifier, QVector<AcquisitionDataPacket>() << dataPacket));
122 }
123
124
125 // Decrement the counter of the request
126 auto &acqRequest = aIdToARit->second;
127 acqRequest.m_Size = acqRequest.m_Size - 1;
128
129 // if the counter is 0, we can return data then run the next request if it exists and
130 // removed the finished request
131 if (acqRequest.m_Size == 0) {
132 // Return the data
133 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
134 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
135 emit dataProvided(acqRequest.m_vIdentifier, acqRequest.m_RangeRequested,
136 acqRequest.m_CacheRangeRequested, aIdToADPVit->second);
137 }
138
139 // Execute the next one
140 auto it
141 = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(acqRequest.m_vIdentifier);
142
143 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
144 if (it->second.second.isNull()) {
145 // There is no next request, we can remove the varibale request
146 impl->removeVariableRequest(acqRequest.m_vIdentifier);
147 }
148 else {
149 auto acqIdentifierToRemove = it->second.first;
150 // Move the next request to the current request
151 it->second.first = it->second.second;
152 it->second.second = QUuid();
153 // Remove AcquisitionRequest and results;
154 impl->m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
155 impl->m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
156 // Execute the current request
157 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
158 Q_ARG(QUuid, it->second.first));
159 }
160 }
161 else {
162 qCCritical(LOG_VariableAcquisitionWorker())
163 << tr("Impossible to execute the acquisition on an unfound variable ");
164 }
165 }
166 }
167 else {
168 qCCritical(LOG_VariableAcquisitionWorker())
169 << tr("Impossible to retrieve AcquisitionRequest for the incoming data");
170 }
171 impl->unlock();
172 }
173
174 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
175 {
176 qCInfo(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread();
177 impl->lockRead();
178 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
179 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
180 auto request = it->second;
181 impl->unlock();
182 request.m_Provider->requestDataLoading(acqIdentifier, request.m_DataProviderParameters);
183 }
184 else {
185 impl->unlock();
186 // TODO log no acqIdentifier recognized
187 }
188 }
189
190 void VariableAcquisitionWorker::initialize()
191 {
192 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init")
193 << QThread::currentThread();
194 impl->m_WorkingMutex.lock();
195 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init END");
196 }
197
198 void VariableAcquisitionWorker::finalize()
199 {
200 impl->m_WorkingMutex.unlock();
201 }
202
203 void VariableAcquisitionWorker::waitForFinish()
204 {
205 QMutexLocker locker{&impl->m_WorkingMutex};
206 }
207
208 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariableRequest(
209 QUuid vIdentifier)
210 {
211 lockWrite();
212 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
213
214 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
215 // A current request already exists, we can replace the next one
216
217 m_AcqIdentifierToAcqRequestMap.erase(it->second.first);
218 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.first);
219
220 m_AcqIdentifierToAcqRequestMap.erase(it->second.second);
221 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.second);
222 }
223 m_VIdentifierToCurrrentAcqIdNextIdPairMap.erase(vIdentifier);
224 unlock();
225 }
@@ -0,0 +1,52
1 #include "Variable/VariableCacheStrategy.h"
2
3 #include "Settings/SqpSettingsDefs.h"
4
5 #include "Variable/Variable.h"
6 #include "Variable/VariableController.h"
7
8 Q_LOGGING_CATEGORY(LOG_VariableCacheStrategy, "VariableCacheStrategy")
9
10 struct VariableCacheStrategy::VariableCacheStrategyPrivate {
11 VariableCacheStrategyPrivate() : m_CacheStrategy{CacheStrategy::FixedTolerance} {}
12
13 CacheStrategy m_CacheStrategy;
14 };
15
16
17 VariableCacheStrategy::VariableCacheStrategy(QObject *parent)
18 : QObject{parent}, impl{spimpl::make_unique_impl<VariableCacheStrategyPrivate>()}
19 {
20 }
21
22 std::pair<SqpRange, SqpRange>
23 VariableCacheStrategy::computeCacheRange(const SqpRange &vRange, const SqpRange &rangeRequested)
24 {
25
26 auto varRanges = std::pair<SqpRange, SqpRange>{};
27
28 auto toleranceFactor = SqpSettings::toleranceValue(GENERAL_TOLERANCE_AT_UPDATE_KEY,
29 GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE);
30 auto tolerance = toleranceFactor * (rangeRequested.m_TEnd - rangeRequested.m_TStart);
31
32 switch (impl->m_CacheStrategy) {
33 case CacheStrategy::FixedTolerance: {
34 varRanges.first = rangeRequested;
35 varRanges.second
36 = SqpRange{rangeRequested.m_TStart - tolerance, rangeRequested.m_TEnd + tolerance};
37 break;
38 }
39
40 case CacheStrategy::TwoThreashold: {
41 // TODO Implement
42 break;
43 }
44 default:
45 qCCritical(LOG_VariableCacheStrategy())
46 << tr("Impossible to use compute the cache range with an unknow cache strategy");
47 // No action
48 break;
49 }
50
51 return varRanges;
52 }
@@ -0,0 +1,32
1 #include "Variable/VariableSynchronizationGroup.h"
2
3 #include "Variable/Variable.h"
4
5
6 Q_LOGGING_CATEGORY(LOG_VariableSynchronizationGroup, "VariableSynchronizationGroup")
7
8 struct VariableSynchronizationGroup::VariableSynchronizationGroupPrivate {
9
10 std::set<QUuid> m_VariableIdSet;
11 };
12
13
14 VariableSynchronizationGroup::VariableSynchronizationGroup(QObject *parent)
15 : QObject{parent}, impl{spimpl::make_unique_impl<VariableSynchronizationGroupPrivate>()}
16 {
17 }
18
19 void VariableSynchronizationGroup::addVariableId(QUuid vIdentifier)
20 {
21 impl->m_VariableIdSet.insert(vIdentifier);
22 }
23
24 void VariableSynchronizationGroup::removeVariableId(QUuid vIdentifier)
25 {
26 impl->m_VariableIdSet.erase(vIdentifier);
27 }
28
29 const std::set<QUuid> &VariableSynchronizationGroup::getIds() const noexcept
30 {
31 return impl->m_VariableIdSet;
32 }
@@ -1,180 +1,190
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 /// @sa IDataSeries::xAxisData()
32 /// @sa IDataSeries::xAxisData()
33 std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
33 std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
34 const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; }
34 const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; }
35
35
36 /// @sa IDataSeries::xAxisUnit()
36 /// @sa IDataSeries::xAxisUnit()
37 Unit xAxisUnit() const override { return m_XAxisUnit; }
37 Unit xAxisUnit() const override { return m_XAxisUnit; }
38
38
39 /// @return the values dataset
39 /// @return the values dataset
40 std::shared_ptr<ArrayData<Dim> > valuesData() { return m_ValuesData; }
40 std::shared_ptr<ArrayData<Dim> > valuesData() { return m_ValuesData; }
41 const std::shared_ptr<ArrayData<Dim> > valuesData() const { return m_ValuesData; }
41 const std::shared_ptr<ArrayData<Dim> > valuesData() const { return m_ValuesData; }
42
42
43 /// @sa IDataSeries::valuesUnit()
43 /// @sa IDataSeries::valuesUnit()
44 Unit valuesUnit() const override { return m_ValuesUnit; }
44 Unit valuesUnit() const override { return m_ValuesUnit; }
45
45
46
47 SqpRange range() const override
48 {
49 if (!m_XAxisData->cdata().isEmpty()) {
50 return SqpRange{m_XAxisData->cdata().first(), m_XAxisData->cdata().last()};
51 }
52
53 return SqpRange{};
54 }
55
46 void clear()
56 void clear()
47 {
57 {
48 m_XAxisData->clear();
58 m_XAxisData->clear();
49 m_ValuesData->clear();
59 m_ValuesData->clear();
50 }
60 }
51
61
52 /// Merges into the data series an other data series
62 /// Merges into the data series an other data series
53 /// @remarks the data series to merge with is cleared after the operation
63 /// @remarks the data series to merge with is cleared after the operation
54 void merge(IDataSeries *dataSeries) override
64 void merge(IDataSeries *dataSeries) override
55 {
65 {
56 dataSeries->lockWrite();
66 dataSeries->lockWrite();
57 lockWrite();
67 lockWrite();
58
68
59 if (auto other = dynamic_cast<DataSeries<Dim> *>(dataSeries)) {
69 if (auto other = dynamic_cast<DataSeries<Dim> *>(dataSeries)) {
60 const auto &otherXAxisData = other->xAxisData()->cdata();
70 const auto &otherXAxisData = other->xAxisData()->cdata();
61 const auto &xAxisData = m_XAxisData->cdata();
71 const auto &xAxisData = m_XAxisData->cdata();
62
72
63 // As data series are sorted, we can improve performances of merge, by call the sort
73 // As data series are sorted, we can improve performances of merge, by call the sort
64 // method only if the two data series overlap.
74 // method only if the two data series overlap.
65 if (!otherXAxisData.empty()) {
75 if (!otherXAxisData.empty()) {
66 auto firstValue = otherXAxisData.front();
76 auto firstValue = otherXAxisData.front();
67 auto lastValue = otherXAxisData.back();
77 auto lastValue = otherXAxisData.back();
68
78
69 auto xAxisDataBegin = xAxisData.cbegin();
79 auto xAxisDataBegin = xAxisData.cbegin();
70 auto xAxisDataEnd = xAxisData.cend();
80 auto xAxisDataEnd = xAxisData.cend();
71
81
72 bool prepend;
82 bool prepend;
73 bool sortNeeded;
83 bool sortNeeded;
74
84
75 if (std::lower_bound(xAxisDataBegin, xAxisDataEnd, firstValue) == xAxisDataEnd) {
85 if (std::lower_bound(xAxisDataBegin, xAxisDataEnd, firstValue) == xAxisDataEnd) {
76 // Other data series if after data series
86 // Other data series if after data series
77 prepend = false;
87 prepend = false;
78 sortNeeded = false;
88 sortNeeded = false;
79 }
89 }
80 else if (std::upper_bound(xAxisDataBegin, xAxisDataEnd, lastValue)
90 else if (std::upper_bound(xAxisDataBegin, xAxisDataEnd, lastValue)
81 == xAxisDataBegin) {
91 == xAxisDataBegin) {
82 // Other data series if before data series
92 // Other data series if before data series
83 prepend = true;
93 prepend = true;
84 sortNeeded = false;
94 sortNeeded = false;
85 }
95 }
86 else {
96 else {
87 // The two data series overlap
97 // The two data series overlap
88 prepend = false;
98 prepend = false;
89 sortNeeded = true;
99 sortNeeded = true;
90 }
100 }
91
101
92 // Makes the merge
102 // Makes the merge
93 m_XAxisData->add(*other->xAxisData(), prepend);
103 m_XAxisData->add(*other->xAxisData(), prepend);
94 m_ValuesData->add(*other->valuesData(), prepend);
104 m_ValuesData->add(*other->valuesData(), prepend);
95
105
96 if (sortNeeded) {
106 if (sortNeeded) {
97 sort();
107 sort();
98 }
108 }
99 }
109 }
100
110
101 // Clears the other data series
111 // Clears the other data series
102 other->clear();
112 other->clear();
103 }
113 }
104 else {
114 else {
105 qCWarning(LOG_DataSeries())
115 qCWarning(LOG_DataSeries())
106 << QObject::tr("Detection of a type of IDataSeries we cannot merge with !");
116 << QObject::tr("Detection of a type of IDataSeries we cannot merge with !");
107 }
117 }
108 unlock();
118 unlock();
109 dataSeries->unlock();
119 dataSeries->unlock();
110 }
120 }
111
121
112 virtual void lockRead() { m_Lock.lockForRead(); }
122 virtual void lockRead() { m_Lock.lockForRead(); }
113 virtual void lockWrite() { m_Lock.lockForWrite(); }
123 virtual void lockWrite() { m_Lock.lockForWrite(); }
114 virtual void unlock() { m_Lock.unlock(); }
124 virtual void unlock() { m_Lock.unlock(); }
115
125
116 protected:
126 protected:
117 /// Protected ctor (DataSeries is abstract). The vectors must have the same size, otherwise a
127 /// Protected ctor (DataSeries is abstract). The vectors must have the same size, otherwise a
118 /// DataSeries with no values will be created.
128 /// DataSeries with no values will be created.
119 /// @remarks data series is automatically sorted on its x-axis data
129 /// @remarks data series is automatically sorted on its x-axis data
120 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit,
130 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit,
121 std::shared_ptr<ArrayData<Dim> > valuesData, const Unit &valuesUnit)
131 std::shared_ptr<ArrayData<Dim> > valuesData, const Unit &valuesUnit)
122 : m_XAxisData{xAxisData},
132 : m_XAxisData{xAxisData},
123 m_XAxisUnit{xAxisUnit},
133 m_XAxisUnit{xAxisUnit},
124 m_ValuesData{valuesData},
134 m_ValuesData{valuesData},
125 m_ValuesUnit{valuesUnit}
135 m_ValuesUnit{valuesUnit}
126 {
136 {
127 if (m_XAxisData->size() != m_ValuesData->size()) {
137 if (m_XAxisData->size() != m_ValuesData->size()) {
128 clear();
138 clear();
129 }
139 }
130
140
131 // Sorts data if it's not the case
141 // Sorts data if it's not the case
132 const auto &xAxisCData = m_XAxisData->cdata();
142 const auto &xAxisCData = m_XAxisData->cdata();
133 if (!std::is_sorted(xAxisCData.cbegin(), xAxisCData.cend())) {
143 if (!std::is_sorted(xAxisCData.cbegin(), xAxisCData.cend())) {
134 sort();
144 sort();
135 }
145 }
136 }
146 }
137
147
138 /// Copy ctor
148 /// Copy ctor
139 explicit DataSeries(const DataSeries<Dim> &other)
149 explicit DataSeries(const DataSeries<Dim> &other)
140 : m_XAxisData{std::make_shared<ArrayData<1> >(*other.m_XAxisData)},
150 : m_XAxisData{std::make_shared<ArrayData<1> >(*other.m_XAxisData)},
141 m_XAxisUnit{other.m_XAxisUnit},
151 m_XAxisUnit{other.m_XAxisUnit},
142 m_ValuesData{std::make_shared<ArrayData<Dim> >(*other.m_ValuesData)},
152 m_ValuesData{std::make_shared<ArrayData<Dim> >(*other.m_ValuesData)},
143 m_ValuesUnit{other.m_ValuesUnit}
153 m_ValuesUnit{other.m_ValuesUnit}
144 {
154 {
145 // Since a series is ordered from its construction and is always ordered, it is not
155 // Since a series is ordered from its construction and is always ordered, it is not
146 // necessary to call the sort method here ('other' is sorted)
156 // necessary to call the sort method here ('other' is sorted)
147 }
157 }
148
158
149 /// Assignment operator
159 /// Assignment operator
150 template <int D>
160 template <int D>
151 DataSeries &operator=(DataSeries<D> other)
161 DataSeries &operator=(DataSeries<D> other)
152 {
162 {
153 std::swap(m_XAxisData, other.m_XAxisData);
163 std::swap(m_XAxisData, other.m_XAxisData);
154 std::swap(m_XAxisUnit, other.m_XAxisUnit);
164 std::swap(m_XAxisUnit, other.m_XAxisUnit);
155 std::swap(m_ValuesData, other.m_ValuesData);
165 std::swap(m_ValuesData, other.m_ValuesData);
156 std::swap(m_ValuesUnit, other.m_ValuesUnit);
166 std::swap(m_ValuesUnit, other.m_ValuesUnit);
157
167
158 return *this;
168 return *this;
159 }
169 }
160
170
161 private:
171 private:
162 /**
172 /**
163 * Sorts data series on its x-axis data
173 * Sorts data series on its x-axis data
164 */
174 */
165 void sort() noexcept
175 void sort() noexcept
166 {
176 {
167 auto permutation = SortUtils::sortPermutation(*m_XAxisData, std::less<double>());
177 auto permutation = SortUtils::sortPermutation(*m_XAxisData, std::less<double>());
168 m_XAxisData = m_XAxisData->sort(permutation);
178 m_XAxisData = m_XAxisData->sort(permutation);
169 m_ValuesData = m_ValuesData->sort(permutation);
179 m_ValuesData = m_ValuesData->sort(permutation);
170 }
180 }
171
181
172 std::shared_ptr<ArrayData<1> > m_XAxisData;
182 std::shared_ptr<ArrayData<1> > m_XAxisData;
173 Unit m_XAxisUnit;
183 Unit m_XAxisUnit;
174 std::shared_ptr<ArrayData<Dim> > m_ValuesData;
184 std::shared_ptr<ArrayData<Dim> > m_ValuesData;
175 Unit m_ValuesUnit;
185 Unit m_ValuesUnit;
176
186
177 QReadWriteLock m_Lock;
187 QReadWriteLock m_Lock;
178 };
188 };
179
189
180 #endif // SCIQLOP_DATASERIES_H
190 #endif // SCIQLOP_DATASERIES_H
@@ -1,74 +1,76
1 #ifndef SCIQLOP_IDATAPROVIDER_H
1 #ifndef SCIQLOP_IDATAPROVIDER_H
2 #define SCIQLOP_IDATAPROVIDER_H
2 #define SCIQLOP_IDATAPROVIDER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <memory>
6 #include <memory>
7
7
8 #include <QObject>
8 #include <QObject>
9 #include <QUuid>
9 #include <QUuid>
10
10
11 #include <Common/MetaTypes.h>
11 #include <Common/MetaTypes.h>
12
12
13 #include <Data/SqpRange.h>
13 #include <Data/SqpRange.h>
14
14
15 #include <functional>
15 #include <functional>
16
16
17 class DataProviderParameters;
17 class DataProviderParameters;
18 class IDataSeries;
18 class IDataSeries;
19 class QNetworkReply;
19 class QNetworkReply;
20 class QNetworkRequest;
20 class QNetworkRequest;
21
21
22 /**
22 /**
23 * @brief The IDataProvider interface aims to declare a data provider.
23 * @brief The IDataProvider interface aims to declare a data provider.
24 *
24 *
25 * A data provider is an entity that generates data and returns it according to various parameters
25 * A data provider is an entity that generates data and returns it according to various parameters
26 * (time interval, product to retrieve the data, etc.)
26 * (time interval, product to retrieve the data, etc.)
27 *
27 *
28 * @sa IDataSeries
28 * @sa IDataSeries
29 */
29 */
30 class SCIQLOP_CORE_EXPORT IDataProvider : public QObject {
30 class SCIQLOP_CORE_EXPORT IDataProvider : public QObject {
31
31
32 Q_OBJECT
32 Q_OBJECT
33 public:
33 public:
34 virtual ~IDataProvider() noexcept = default;
34 virtual ~IDataProvider() noexcept = default;
35
35
36 /**
36 /**
37 * @brief requestDataLoading provide datas for the data identified by identifier and parameters
37 * @brief requestDataLoading provide datas for the data identified by acqIdentifier and
38 * parameters
38 */
39 */
39 virtual void requestDataLoading(QUuid identifier, const DataProviderParameters &parameters) = 0;
40 virtual void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
41 = 0;
40
42
41 /**
43 /**
42 * @brief requestDataAborting stop data loading of the data identified by identifier
44 * @brief requestDataAborting stop data loading of the data identified by acqIdentifier
43 */
45 */
44 virtual void requestDataAborting(QUuid identifier) = 0;
46 virtual void requestDataAborting(QUuid acqIdentifier) = 0;
45
47
46 signals:
48 signals:
47 /**
49 /**
48 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
50 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
49 * identified by identifier
51 * identified by acqIdentifier
50 */
52 */
51 void dataProvided(QUuid identifier, std::shared_ptr<IDataSeries> dateSerie,
53 void dataProvided(QUuid acqIdentifier, std::shared_ptr<IDataSeries> dateSeriesAcquired,
52 const SqpRange &dateTime);
54 const SqpRange &dataRangeAcquired);
53
55
54 /**
56 /**
55 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
57 * @brief dataProvided send dataSeries under dateTime and that corresponds of the data
56 * identified by identifier
58 * identified by identifier
57 */
59 */
58 void dataProvidedProgress(QUuid identifier, double progress);
60 void dataProvidedProgress(QUuid acqIdentifier, double progress);
59
61
60
62
61 /**
63 /**
62 * @brief requestConstructed send a request for the data identified by identifier
64 * @brief requestConstructed send a request for the data identified by acqIdentifier
63 * @callback is the methode call by the reply of the request when it is finished.
65 * @callback is the methode call by the reply of the request when it is finished.
64 */
66 */
65 void requestConstructed(const QNetworkRequest &request, QUuid identifier,
67 void requestConstructed(const QNetworkRequest &request, QUuid acqIdentifier,
66 std::function<void(QNetworkReply *, QUuid)> callback);
68 std::function<void(QNetworkReply *, QUuid)> callback);
67 };
69 };
68
70
69 // Required for using shared_ptr in signals/slots
71 // Required for using shared_ptr in signals/slots
70 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
72 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
71 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
73 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
72 std::function<void(QNetworkReply *, QUuid)>)
74 std::function<void(QNetworkReply *, QUuid)>)
73
75
74 #endif // SCIQLOP_IDATAPROVIDER_H
76 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -1,69 +1,72
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
6
6 #include <memory>
7 #include <memory>
7
8
8 #include <QString>
9 #include <QString>
9
10
10 template <int Dim>
11 template <int Dim>
11 class ArrayData;
12 class ArrayData;
12
13
13 struct Unit {
14 struct Unit {
14 explicit Unit(const QString &name = {}, bool timeUnit = false)
15 explicit Unit(const QString &name = {}, bool timeUnit = false)
15 : m_Name{name}, m_TimeUnit{timeUnit}
16 : m_Name{name}, m_TimeUnit{timeUnit}
16 {
17 {
17 }
18 }
18
19
19 inline bool operator==(const Unit &other) const
20 inline bool operator==(const Unit &other) const
20 {
21 {
21 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);
22 }
23 }
23 inline bool operator!=(const Unit &other) const { return !(*this == other); }
24 inline bool operator!=(const Unit &other) const { return !(*this == other); }
24
25
25 QString m_Name; ///< Unit name
26 QString m_Name; ///< Unit name
26 bool m_TimeUnit; ///< The unit is a unit of time (UTC)
27 bool m_TimeUnit; ///< The unit is a unit of time (UTC)
27 };
28 };
28
29
29 /**
30 /**
30 * @brief The IDataSeries aims to declare a data series.
31 * @brief The IDataSeries aims to declare a data series.
31 *
32 *
32 * A data series is an entity that contains at least :
33 * A data series is an entity that contains at least :
33 * - one dataset representing the x-axis
34 * - one dataset representing the x-axis
34 * - one dataset representing the values
35 * - one dataset representing the values
35 *
36 *
36 * 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.
37 *
38 *
38 * 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
39 * IDataSeries. The x-axis dataset is always unidimensional.
40 * IDataSeries. The x-axis dataset is always unidimensional.
40 *
41 *
41 * @sa ArrayData
42 * @sa ArrayData
42 */
43 */
43 class IDataSeries {
44 class IDataSeries {
44 public:
45 public:
45 virtual ~IDataSeries() noexcept = default;
46 virtual ~IDataSeries() noexcept = default;
46
47
47 /// Returns the x-axis dataset
48 /// Returns the x-axis dataset
48 virtual std::shared_ptr<ArrayData<1> > xAxisData() = 0;
49 virtual std::shared_ptr<ArrayData<1> > xAxisData() = 0;
49
50
50 /// Returns the x-axis dataset (as const)
51 /// Returns the x-axis dataset (as const)
51 virtual const std::shared_ptr<ArrayData<1> > xAxisData() const = 0;
52 virtual const std::shared_ptr<ArrayData<1> > xAxisData() const = 0;
52
53
53 virtual Unit xAxisUnit() const = 0;
54 virtual Unit xAxisUnit() const = 0;
54
55
55 virtual Unit valuesUnit() const = 0;
56 virtual Unit valuesUnit() const = 0;
56
57
57 virtual void merge(IDataSeries *dataSeries) = 0;
58 virtual void merge(IDataSeries *dataSeries) = 0;
59 virtual std::shared_ptr<IDataSeries> subData(const SqpRange &range) = 0;
58
60
59 virtual std::unique_ptr<IDataSeries> clone() const = 0;
61 virtual std::unique_ptr<IDataSeries> clone() const = 0;
62 virtual SqpRange range() const = 0;
60
63
61 virtual void lockRead() = 0;
64 virtual void lockRead() = 0;
62 virtual void lockWrite() = 0;
65 virtual void lockWrite() = 0;
63 virtual void unlock() = 0;
66 virtual void unlock() = 0;
64 };
67 };
65
68
66 // Required for using shared_ptr in signals/slots
69 // Required for using shared_ptr in signals/slots
67 SCIQLOP_REGISTER_META_TYPE(IDATASERIES_PTR_REGISTRY, std::shared_ptr<IDataSeries>)
70 SCIQLOP_REGISTER_META_TYPE(IDATASERIES_PTR_REGISTRY, std::shared_ptr<IDataSeries>)
68
71
69 #endif // SCIQLOP_IDATASERIES_H
72 #endif // SCIQLOP_IDATASERIES_H
@@ -1,25 +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;
22 std::unique_ptr<IDataSeries> clone() const override;
23
24 std::shared_ptr<IDataSeries> subData(const SqpRange &range) override;
23 };
25 };
24
26
25 #endif // SCIQLOP_SCALARSERIES_H
27 #endif // SCIQLOP_SCALARSERIES_H
@@ -1,18 +1,22
1 #ifndef SCIQLOP_SQPSETTINGSDEFS_H
1 #ifndef SCIQLOP_SQPSETTINGSDEFS_H
2 #define SCIQLOP_SQPSETTINGSDEFS_H
2 #define SCIQLOP_SQPSETTINGSDEFS_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <QString>
6 #include <QString>
7
7
8 // //////////////// //
8 // //////////////// //
9 // General settings //
9 // General settings //
10 // //////////////// //
10 // //////////////// //
11
11
12
13 struct SCIQLOP_CORE_EXPORT SqpSettings {
14 static double toleranceValue(const QString &key, double defaultValue) noexcept;
15 };
12 extern SCIQLOP_CORE_EXPORT const QString GENERAL_TOLERANCE_AT_INIT_KEY;
16 extern SCIQLOP_CORE_EXPORT const QString GENERAL_TOLERANCE_AT_INIT_KEY;
13 extern SCIQLOP_CORE_EXPORT const double GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE;
17 extern SCIQLOP_CORE_EXPORT const double GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE;
14
18
15 extern SCIQLOP_CORE_EXPORT const QString GENERAL_TOLERANCE_AT_UPDATE_KEY;
19 extern SCIQLOP_CORE_EXPORT const QString GENERAL_TOLERANCE_AT_UPDATE_KEY;
16 extern SCIQLOP_CORE_EXPORT const double GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE;
20 extern SCIQLOP_CORE_EXPORT const double GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE;
17
21
18 #endif // SCIQLOP_SQPSETTINGSDEFS_H
22 #endif // SCIQLOP_SQPSETTINGSDEFS_H
@@ -1,57 +1,65
1 #ifndef SCIQLOP_VARIABLE_H
1 #ifndef SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QObject>
9 #include <QObject>
10
10
11 #include <Common/MetaTypes.h>
11 #include <Common/MetaTypes.h>
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
15
15
16 class IDataSeries;
16 class IDataSeries;
17 class QString;
17 class QString;
18
18
19 /**
19 /**
20 * @brief The Variable class represents a variable in SciQlop.
20 * @brief The Variable class represents a variable in SciQlop.
21 */
21 */
22 class SCIQLOP_CORE_EXPORT Variable : public QObject {
22 class SCIQLOP_CORE_EXPORT Variable : public QObject {
23
23
24 Q_OBJECT
24 Q_OBJECT
25
25
26 public:
26 public:
27 explicit Variable(const QString &name, const SqpRange &dateTime,
27 explicit Variable(const QString &name, const SqpRange &dateTime,
28 const QVariantHash &metadata = {});
28 const QVariantHash &metadata = {});
29
29
30 QString name() const noexcept;
30 QString name() const noexcept;
31 SqpRange dateTime() const noexcept;
31 SqpRange range() const noexcept;
32 void setDateTime(const SqpRange &dateTime) noexcept;
32 void setRange(const SqpRange &range) noexcept;
33 SqpRange cacheRange() const noexcept;
34 void setCacheRange(const SqpRange &cacheRange) noexcept;
33
35
34 /// @return the data of the variable, nullptr if there is no data
36 /// @return the data of the variable, nullptr if there is no data
35 IDataSeries *dataSeries() const noexcept;
37 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
36
38
37 QVariantHash metadata() const noexcept;
39 QVariantHash metadata() const noexcept;
38
40
39 bool contains(const SqpRange &dateTime) const noexcept;
41 bool contains(const SqpRange &range) const noexcept;
40 bool intersect(const SqpRange &dateTime) const noexcept;
42 bool intersect(const SqpRange &range) const noexcept;
41 bool isInside(const SqpRange &dateTime) const noexcept;
43 bool isInside(const SqpRange &range) const noexcept;
42
44
43 public slots:
45 bool cacheContains(const SqpRange &range) const noexcept;
46 bool cacheIntersect(const SqpRange &range) const noexcept;
47 bool cacheIsInside(const SqpRange &range) const noexcept;
48
49 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
44 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
50 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
51 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
45
52
46 signals:
53 signals:
47 void updated();
54 void updated();
48
55
49 private:
56 private:
50 class VariablePrivate;
57 class VariablePrivate;
51 spimpl::unique_impl_ptr<VariablePrivate> impl;
58 spimpl::unique_impl_ptr<VariablePrivate> impl;
52 };
59 };
53
60
54 // Required for using shared_ptr in signals/slots
61 // Required for using shared_ptr in signals/slots
55 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
62 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
63 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
56
64
57 #endif // SCIQLOP_VARIABLE_H
65 #endif // SCIQLOP_VARIABLE_H
@@ -1,97 +1,117
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/AcquisitionDataPacket.h>
6 #include <Data/SqpRange.h>
7 #include <Data/SqpRange.h>
7
8
8 #include <QLoggingCategory>
9 #include <QLoggingCategory>
9 #include <QObject>
10 #include <QObject>
10
11
11 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
12
13
13 class IDataProvider;
14 class IDataProvider;
14 class QItemSelectionModel;
15 class QItemSelectionModel;
15 class TimeController;
16 class TimeController;
16 class Variable;
17 class Variable;
17 class VariableModel;
18 class VariableModel;
18
19
19 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
20 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
20
21
22
23 /**
24 * Possible types of zoom operation
25 */
26 enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
27
28
21 /**
29 /**
22 * @brief The VariableController class aims to handle the variables in SciQlop.
30 * @brief The VariableController class aims to handle the variables in SciQlop.
23 */
31 */
24 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
32 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
25 Q_OBJECT
33 Q_OBJECT
26 public:
34 public:
27 explicit VariableController(QObject *parent = 0);
35 explicit VariableController(QObject *parent = 0);
28 virtual ~VariableController();
36 virtual ~VariableController();
29
37
30 VariableModel *variableModel() noexcept;
38 VariableModel *variableModel() noexcept;
31 QItemSelectionModel *variableSelectionModel() noexcept;
39 QItemSelectionModel *variableSelectionModel() noexcept;
32
40
33 void setTimeController(TimeController *timeController) noexcept;
41 void setTimeController(TimeController *timeController) noexcept;
34
42
35 /**
43 /**
36 * Deletes from the controller the variable passed in parameter.
44 * Deletes from the controller the variable passed in parameter.
37 *
45 *
38 * Delete a variable includes:
46 * Delete a variable includes:
39 * - the deletion of the various references to the variable in SciQlop
47 * - the deletion of the various references to the variable in SciQlop
40 * - the deletion of the model variable
48 * - the deletion of the model variable
41 * - the deletion of the provider associated with the variable
49 * - the deletion of the provider associated with the variable
42 * - removing the cache associated with the variable
50 * - removing the cache associated with the variable
43 *
51 *
44 * @param variable the variable to delete from the controller.
52 * @param variable the variable to delete from the controller.
45 */
53 */
46 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
54 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
47
55
48 /**
56 /**
49 * Deletes from the controller the variables passed in parameter.
57 * Deletes from the controller the variables passed in parameter.
50 * @param variables the variables to delete from the controller.
58 * @param variables the variables to delete from the controller.
51 * @sa deleteVariable()
59 * @sa deleteVariable()
52 */
60 */
53 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
61 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
54
62
55 /**
63 /**
56 * @brief abort the variable retrieve data progression
64 * @brief abort the variable retrieve data progression
57 */
65 */
58 void abortProgress(std::shared_ptr<Variable> variable);
66 void abortProgress(std::shared_ptr<Variable> variable);
59
67
68 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
60 signals:
69 signals:
61 /// Signal emitted when a variable is about to be deleted from the controller
70 /// Signal emitted when a variable is about to be deleted from the controller
62 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
71 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
63
72
64 /// Signal emitted when a data acquisition is requested on a range for a variable
73 /// Signal emitted when a data acquisition is requested on a range for a variable
65 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
74 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
66
75
67 public slots:
76 public slots:
68 /// Request the data loading of the variable whithin dateTime
77 /// Request the data loading of the variable whithin range
69 void onRequestDataLoading(std::shared_ptr<Variable> variable, const SqpRange &dateTime);
78 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
79 const SqpRange &oldRange, bool synchronise);
70 /**
80 /**
71 * Creates a new variable and adds it to the model
81 * Creates a new variable and adds it to the model
72 * @param name the name of the new variable
82 * @param name the name of the new variable
73 * @param metadata the metadata of the new variable
83 * @param metadata the metadata of the new variable
74 * @param provider the data provider for the new variable
84 * @param provider the data provider for the new variable
75 */
85 */
76 void createVariable(const QString &name, const QVariantHash &metadata,
86 void createVariable(const QString &name, const QVariantHash &metadata,
77 std::shared_ptr<IDataProvider> provider) noexcept;
87 std::shared_ptr<IDataProvider> provider) noexcept;
78
88
79 /// Update the temporal parameters of every selected variable to dateTime
89 /// Update the temporal parameters of every selected variable to dateTime
80 void onDateTimeOnSelection(const SqpRange &dateTime);
90 void onDateTimeOnSelection(const SqpRange &dateTime);
81
91
82
92
93 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
94 const SqpRange &cacheRangeRequested,
95 QVector<AcquisitionDataPacket> dataAcquired);
96
83 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
97 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
84
98
99 /// Cancel the current request for the variable
85 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
100 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
86
101
102 /// synchronization group methods
103 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
104 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
105 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
106
87 void initialize();
107 void initialize();
88 void finalize();
108 void finalize();
89
109
90 private:
110 private:
91 void waitForFinish();
111 void waitForFinish();
92
112
93 class VariableControllerPrivate;
113 class VariableControllerPrivate;
94 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
114 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
95 };
115 };
96
116
97 #endif // SCIQLOP_VARIABLECONTROLLER_H
117 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,13 +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
15 std::shared_ptr<IDataSeries> ScalarSeries::subData(const SqpRange &range)
16 {
17 auto subXAxisData = QVector<double>();
18 auto subValuesData = QVector<double>();
19 this->lockRead();
20 {
21 const auto &currentXData = this->xAxisData()->cdata();
22 const auto &currentValuesData = this->valuesData()->cdata();
23
24 auto xDataBegin = currentXData.cbegin();
25 auto xDataEnd = currentXData.cend();
26
27 auto lowerIt = std::lower_bound(xDataBegin, xDataEnd, range.m_TStart);
28 auto upperIt = std::upper_bound(xDataBegin, xDataEnd, range.m_TEnd);
29 auto distance = std::distance(xDataBegin, lowerIt);
30
31 auto valuesDataIt = currentValuesData.cbegin() + distance;
32 for (auto xAxisDataIt = lowerIt; xAxisDataIt != upperIt; ++xAxisDataIt, ++valuesDataIt) {
33 subXAxisData.append(*xAxisDataIt);
34 subValuesData.append(*valuesDataIt);
35 }
36 }
37 this->unlock();
38
39 return std::make_shared<ScalarSeries>(subXAxisData, subValuesData, this->xAxisUnit(),
40 this->valuesUnit());
41 }
@@ -1,133 +1,134
1 #include "Network/NetworkController.h"
1 #include "Network/NetworkController.h"
2
2
3 #include <QMutex>
3 #include <QMutex>
4 #include <QNetworkAccessManager>
4 #include <QNetworkAccessManager>
5 #include <QNetworkReply>
5 #include <QNetworkReply>
6 #include <QNetworkRequest>
6 #include <QNetworkRequest>
7 #include <QReadWriteLock>
7 #include <QReadWriteLock>
8 #include <QThread>
8 #include <QThread>
9
9
10 #include <unordered_map>
10 #include <unordered_map>
11
11
12 Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController")
12 Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController")
13
13
14 struct NetworkController::NetworkControllerPrivate {
14 struct NetworkController::NetworkControllerPrivate {
15 explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {}
15 explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {}
16
17 void lockRead() { m_Lock.lockForRead(); }
18 void lockWrite() { m_Lock.lockForWrite(); }
19 void unlock() { m_Lock.unlock(); }
20
16 QMutex m_WorkingMutex;
21 QMutex m_WorkingMutex;
17
22
18 QReadWriteLock m_Lock;
23 QReadWriteLock m_Lock;
19 std::unordered_map<QNetworkReply *, QUuid> m_NetworkReplyToVariableId;
24 std::unordered_map<QNetworkReply *, QUuid> m_NetworkReplyToVariableId;
20 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
25 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
21
22 void lockRead() { m_Lock.lockForRead(); }
23 void lockWrite() { m_Lock.lockForWrite(); }
24 void unlock() { m_Lock.unlock(); }
25 };
26 };
26
27
27 NetworkController::NetworkController(QObject *parent)
28 NetworkController::NetworkController(QObject *parent)
28 : QObject(parent), impl{spimpl::make_unique_impl<NetworkControllerPrivate>(this)}
29 : QObject(parent), impl{spimpl::make_unique_impl<NetworkControllerPrivate>(this)}
29 {
30 {
30 }
31 }
31
32
32 void NetworkController::onProcessRequested(const QNetworkRequest &request, QUuid identifier,
33 void NetworkController::onProcessRequested(const QNetworkRequest &request, QUuid identifier,
33 std::function<void(QNetworkReply *, QUuid)> callback)
34 std::function<void(QNetworkReply *, QUuid)> callback)
34 {
35 {
35 qCDebug(LOG_NetworkController()) << tr("NetworkController registered")
36 qCDebug(LOG_NetworkController()) << tr("NetworkController registered")
36 << QThread::currentThread()->objectName();
37 << QThread::currentThread()->objectName();
37 auto reply = impl->m_AccessManager->get(request);
38 auto reply = impl->m_AccessManager->get(request);
38
39
39 // Store the couple reply id
40 // Store the couple reply id
40 impl->lockWrite();
41 impl->lockWrite();
41 impl->m_NetworkReplyToVariableId[reply] = identifier;
42 impl->m_NetworkReplyToVariableId[reply] = identifier;
42 impl->unlock();
43 impl->unlock();
43
44
44 auto onReplyFinished = [reply, this, identifier, callback]() {
45 auto onReplyFinished = [reply, this, identifier, callback]() {
45
46
46 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished")
47 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished")
47 << QThread::currentThread() << reply;
48 << QThread::currentThread() << reply;
48 impl->lockRead();
49 impl->lockRead();
49 auto it = impl->m_NetworkReplyToVariableId.find(reply);
50 auto it = impl->m_NetworkReplyToVariableId.find(reply);
50 impl->unlock();
51 impl->unlock();
51 if (it != impl->m_NetworkReplyToVariableId.cend()) {
52 if (it != impl->m_NetworkReplyToVariableId.cend()) {
52 impl->lockWrite();
53 impl->lockWrite();
53 impl->m_NetworkReplyToVariableId.erase(reply);
54 impl->m_NetworkReplyToVariableId.erase(reply);
54 impl->unlock();
55 impl->unlock();
55 // Deletes reply
56 // Deletes reply
56 callback(reply, identifier);
57 callback(reply, identifier);
57 reply->deleteLater();
58 reply->deleteLater();
58
59
59 emit this->replyDownloadProgress(identifier, 0);
60 emit this->replyDownloadProgress(identifier, 0);
60 }
61 }
61
62
62 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished END")
63 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished END")
63 << QThread::currentThread() << reply;
64 << QThread::currentThread() << reply;
64 };
65 };
65
66
66 auto onReplyProgress = [reply, this](qint64 bytesRead, qint64 totalBytes) {
67 auto onReplyProgress = [reply, this](qint64 bytesRead, qint64 totalBytes) {
67
68
68 double progress = (bytesRead * 100.0) / totalBytes;
69 double progress = (bytesRead * 100.0) / totalBytes;
69 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress") << progress
70 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress") << progress
70 << QThread::currentThread() << reply;
71 << QThread::currentThread() << reply;
71 impl->lockRead();
72 impl->lockRead();
72 auto it = impl->m_NetworkReplyToVariableId.find(reply);
73 auto it = impl->m_NetworkReplyToVariableId.find(reply);
73 impl->unlock();
74 impl->unlock();
74 if (it != impl->m_NetworkReplyToVariableId.cend()) {
75 if (it != impl->m_NetworkReplyToVariableId.cend()) {
75 emit this->replyDownloadProgress(it->second, progress);
76 emit this->replyDownloadProgress(it->second, progress);
76 }
77 }
77 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress END")
78 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress END")
78 << QThread::currentThread() << reply;
79 << QThread::currentThread() << reply;
79 };
80 };
80
81
81
82
82 connect(reply, &QNetworkReply::finished, this, onReplyFinished);
83 connect(reply, &QNetworkReply::finished, this, onReplyFinished);
83 connect(reply, &QNetworkReply::downloadProgress, this, onReplyProgress);
84 connect(reply, &QNetworkReply::downloadProgress, this, onReplyProgress);
84 qCDebug(LOG_NetworkController()) << tr("NetworkController registered END")
85 qCDebug(LOG_NetworkController()) << tr("NetworkController registered END")
85 << QThread::currentThread()->objectName() << reply;
86 << QThread::currentThread()->objectName() << reply;
86 }
87 }
87
88
88 void NetworkController::initialize()
89 void NetworkController::initialize()
89 {
90 {
90 qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread();
91 qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread();
91 impl->m_WorkingMutex.lock();
92 impl->m_WorkingMutex.lock();
92 impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
93 impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
93
94
94
95
95 auto onReplyErrors = [this](QNetworkReply *reply, const QList<QSslError> &errors) {
96 auto onReplyErrors = [this](QNetworkReply *reply, const QList<QSslError> &errors) {
96
97
97 qCCritical(LOG_NetworkController()) << tr("NetworkAcessManager errors: ") << errors;
98 qCCritical(LOG_NetworkController()) << tr("NetworkAcessManager errors: ") << errors;
98
99
99 };
100 };
100
101
101
102
102 connect(impl->m_AccessManager.get(), &QNetworkAccessManager::sslErrors, this, onReplyErrors);
103 connect(impl->m_AccessManager.get(), &QNetworkAccessManager::sslErrors, this, onReplyErrors);
103
104
104 qCDebug(LOG_NetworkController()) << tr("NetworkController init END");
105 qCDebug(LOG_NetworkController()) << tr("NetworkController init END");
105 }
106 }
106
107
107 void NetworkController::finalize()
108 void NetworkController::finalize()
108 {
109 {
109 impl->m_WorkingMutex.unlock();
110 impl->m_WorkingMutex.unlock();
110 }
111 }
111
112
112 void NetworkController::onReplyCanceled(QUuid identifier)
113 void NetworkController::onReplyCanceled(QUuid identifier)
113 {
114 {
114 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
115 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
115 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled")
116 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled")
116 << QThread::currentThread();
117 << QThread::currentThread();
117
118
118
119
119 impl->lockRead();
120 impl->lockRead();
120 auto end = impl->m_NetworkReplyToVariableId.cend();
121 auto end = impl->m_NetworkReplyToVariableId.cend();
121 auto it = std::find_if(impl->m_NetworkReplyToVariableId.cbegin(), end, findReply);
122 auto it = std::find_if(impl->m_NetworkReplyToVariableId.cbegin(), end, findReply);
122 impl->unlock();
123 impl->unlock();
123 if (it != end) {
124 if (it != end) {
124 it->first->abort();
125 it->first->abort();
125 }
126 }
126 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled END")
127 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled END")
127 << QThread::currentThread();
128 << QThread::currentThread();
128 }
129 }
129
130
130 void NetworkController::waitForFinish()
131 void NetworkController::waitForFinish()
131 {
132 {
132 QMutexLocker locker{&impl->m_WorkingMutex};
133 QMutexLocker locker{&impl->m_WorkingMutex};
133 }
134 }
@@ -1,7 +1,18
1 #include "Settings/SqpSettingsDefs.h"
1 #include "Settings/SqpSettingsDefs.h"
2
2
3 #include <QSettings>
4
5
6 /// Gets a tolerance value from application settings. If the setting can't be found, the default
7 /// value passed in parameter is returned
8 double SqpSettings::toleranceValue(const QString &key, double defaultValue) noexcept
9 {
10 return QSettings{}.value(key, defaultValue).toDouble();
11 }
12
13
3 const QString GENERAL_TOLERANCE_AT_INIT_KEY = QStringLiteral("toleranceInit");
14 const QString GENERAL_TOLERANCE_AT_INIT_KEY = QStringLiteral("toleranceInit");
4 const double GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE = 0.2;
15 const double GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE = 0.2;
5
16
6 const QString GENERAL_TOLERANCE_AT_UPDATE_KEY = QStringLiteral("toleranceUpdate");
17 const QString GENERAL_TOLERANCE_AT_UPDATE_KEY = QStringLiteral("toleranceUpdate");
7 const double GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE = 0.2;
18 const double GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE = 0.2;
@@ -1,86 +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 <QReadWriteLock>
7 #include <QReadWriteLock>
7 #include <QThread>
8 #include <QThread>
8
9
9 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
10
11
11 struct Variable::VariablePrivate {
12 struct Variable::VariablePrivate {
12 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
13 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
13 const QVariantHash &metadata)
14 const QVariantHash &metadata)
14 : m_Name{name}, m_DateTime{dateTime}, m_Metadata{metadata}, m_DataSeries{nullptr}
15 : m_Name{name}, m_Range{dateTime}, m_Metadata{metadata}, m_DataSeries{nullptr}
15 {
16 {
16 }
17 }
17
18
19 void lockRead() { m_Lock.lockForRead(); }
20 void lockWrite() { m_Lock.lockForWrite(); }
21 void unlock() { m_Lock.unlock(); }
22
18 QString m_Name;
23 QString m_Name;
19
24
20 SqpRange m_DateTime; // The dateTime available in the view and loaded. not the cache.
25 SqpRange m_Range;
26 SqpRange m_CacheRange;
21 QVariantHash m_Metadata;
27 QVariantHash m_Metadata;
22 std::unique_ptr<IDataSeries> m_DataSeries;
28 std::shared_ptr<IDataSeries> m_DataSeries;
29
30 QReadWriteLock m_Lock;
23 };
31 };
24
32
25 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
33 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
26 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
34 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
27 {
35 {
28 }
36 }
29
37
30 QString Variable::name() const noexcept
38 QString Variable::name() const noexcept
31 {
39 {
32 return impl->m_Name;
40 impl->lockRead();
41 auto name = impl->m_Name;
42 impl->unlock();
43 return name;
44 }
45
46 SqpRange Variable::range() const noexcept
47 {
48 impl->lockRead();
49 auto range = impl->m_Range;
50 impl->unlock();
51 return range;
33 }
52 }
34
53
35 SqpRange Variable::dateTime() const noexcept
54 void Variable::setRange(const SqpRange &range) noexcept
36 {
55 {
37 return impl->m_DateTime;
56 impl->lockWrite();
57 impl->m_Range = range;
58 impl->unlock();
38 }
59 }
39
60
40 void Variable::setDateTime(const SqpRange &dateTime) noexcept
61 SqpRange Variable::cacheRange() const noexcept
41 {
62 {
42 impl->m_DateTime = dateTime;
63 impl->lockRead();
64 auto cacheRange = impl->m_CacheRange;
65 impl->unlock();
66 return cacheRange;
67 }
68
69 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
70 {
71 impl->lockWrite();
72 impl->m_CacheRange = cacheRange;
73 impl->unlock();
43 }
74 }
44
75
45 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
76 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
46 {
77 {
47 qCDebug(LOG_Variable()) << "Variable::setDataSeries" << QThread::currentThread()->objectName();
78 qCDebug(LOG_Variable()) << "TORM Variable::setDataSeries"
79 << QThread::currentThread()->objectName();
48 if (!dataSeries) {
80 if (!dataSeries) {
49 /// @todo ALX : log
81 /// @todo ALX : log
50 return;
82 return;
51 }
83 }
84 impl->lockWrite();
85 impl->m_DataSeries = dataSeries->clone();
86 impl->unlock();
87 }
52
88
89 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
90 {
91 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
92 << QThread::currentThread()->objectName();
93 if (!dataSeries) {
94 /// @todo ALX : log
95 return;
96 }
97
98 // Add or merge the data
53 // Inits the data series of the variable
99 // Inits the data series of the variable
100 impl->lockWrite();
54 if (!impl->m_DataSeries) {
101 if (!impl->m_DataSeries) {
55 impl->m_DataSeries = dataSeries->clone();
102 impl->m_DataSeries = dataSeries->clone();
56 }
103 }
57 else {
104 else {
58 impl->m_DataSeries->merge(dataSeries.get());
105 impl->m_DataSeries->merge(dataSeries.get());
59 // emit updated();
60 }
106 }
107 impl->unlock();
108
109 // sub the data
110 auto subData = this->dataSeries()->subData(this->cacheRange());
111 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries sub" << subData->range();
112 this->setDataSeries(subData);
113 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries set" << this->dataSeries()->range();
61 }
114 }
62
115
63 IDataSeries *Variable::dataSeries() const noexcept
116 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
64 {
117 {
65 return impl->m_DataSeries.get();
118 impl->lockRead();
119 auto dataSeries = impl->m_DataSeries;
120 impl->unlock();
121
122 return dataSeries;
66 }
123 }
67
124
68 QVariantHash Variable::metadata() const noexcept
125 QVariantHash Variable::metadata() const noexcept
69 {
126 {
70 return impl->m_Metadata;
127 impl->lockRead();
128 auto metadata = impl->m_Metadata;
129 impl->unlock();
130 return metadata;
71 }
131 }
72
132
73 bool Variable::contains(const SqpRange &dateTime) const noexcept
133 bool Variable::contains(const SqpRange &range) const noexcept
74 {
134 {
75 return impl->m_DateTime.contains(dateTime);
135 impl->lockRead();
136 auto res = impl->m_Range.contains(range);
137 impl->unlock();
138 return res;
76 }
139 }
77
140
78 bool Variable::intersect(const SqpRange &dateTime) const noexcept
141 bool Variable::intersect(const SqpRange &range) const noexcept
79 {
142 {
80 return impl->m_DateTime.intersect(dateTime);
143
144 impl->lockRead();
145 auto res = impl->m_Range.intersect(range);
146 impl->unlock();
147 return res;
148 }
149
150 bool Variable::isInside(const SqpRange &range) const noexcept
151 {
152 impl->lockRead();
153 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
154 impl->unlock();
155 return res;
156 }
157
158 bool Variable::cacheContains(const SqpRange &range) const noexcept
159 {
160 impl->lockRead();
161 auto res = impl->m_CacheRange.contains(range);
162 impl->unlock();
163 return res;
164 }
165
166 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
167 {
168 impl->lockRead();
169 auto res = impl->m_CacheRange.intersect(range);
170 impl->unlock();
171 return res;
172 }
173
174 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
175 {
176 impl->lockRead();
177 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
178 impl->unlock();
179 return res;
81 }
180 }
82
181
83 bool Variable::isInside(const SqpRange &dateTime) const noexcept
182
183 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
84 {
184 {
85 return dateTime.contains(SqpRange{impl->m_DateTime.m_TStart, impl->m_DateTime.m_TEnd});
185 auto notInCache = QVector<SqpRange>{};
186
187 if (!this->cacheContains(range)) {
188 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
189 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
190 notInCache << range;
191 }
192 else if (range.m_TStart < impl->m_CacheRange.m_TStart
193 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
194 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
195 }
196 else if (range.m_TStart < impl->m_CacheRange.m_TStart
197 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
198 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
199 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
200 }
201 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
202 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
203 }
204 else {
205 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
206 << QThread::currentThread();
207 }
208 }
209
210 return notInCache;
86 }
211 }
@@ -1,243 +1,543
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableAcquisitionWorker.h>
2 #include <Variable/VariableCacheController.h>
3 #include <Variable/VariableCacheController.h>
4 #include <Variable/VariableCacheStrategy.h>
3 #include <Variable/VariableController.h>
5 #include <Variable/VariableController.h>
4 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7 #include <Variable/VariableSynchronizationGroup.h>
5
8
6 #include <Data/DataProviderParameters.h>
9 #include <Data/DataProviderParameters.h>
7 #include <Data/IDataProvider.h>
10 #include <Data/IDataProvider.h>
8 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
9 #include <Time/TimeController.h>
12 #include <Time/TimeController.h>
10
13
11 #include <QMutex>
14 #include <QMutex>
12 #include <QThread>
15 #include <QThread>
13 #include <QUuid>
16 #include <QUuid>
14 #include <QtCore/QItemSelectionModel>
17 #include <QtCore/QItemSelectionModel>
15
18
19 #include <set>
16 #include <unordered_map>
20 #include <unordered_map>
17
21
18 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
22 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
19
23
24 namespace {
25
26 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &grapheRange,
27 const SqpRange &oldGraphRange)
28 {
29 auto zoomType = VariableController::getZoomType(grapheRange, oldGraphRange);
30
31 auto varRangeRequested = varRange;
32 switch (zoomType) {
33 case AcquisitionZoomType::ZoomIn: {
34 auto deltaLeft = grapheRange.m_TStart - oldGraphRange.m_TStart;
35 auto deltaRight = oldGraphRange.m_TEnd - grapheRange.m_TEnd;
36 varRangeRequested.m_TStart += deltaLeft;
37 varRangeRequested.m_TEnd -= deltaRight;
38 break;
39 }
40
41 case AcquisitionZoomType::ZoomOut: {
42 auto deltaLeft = oldGraphRange.m_TStart - grapheRange.m_TStart;
43 auto deltaRight = grapheRange.m_TEnd - oldGraphRange.m_TEnd;
44 varRangeRequested.m_TStart -= deltaLeft;
45 varRangeRequested.m_TEnd += deltaRight;
46 break;
47 }
48 case AcquisitionZoomType::PanRight: {
49 auto deltaRight = grapheRange.m_TEnd - oldGraphRange.m_TEnd;
50 varRangeRequested.m_TStart += deltaRight;
51 varRangeRequested.m_TEnd += deltaRight;
52 break;
53 }
54 case AcquisitionZoomType::PanLeft: {
55 auto deltaLeft = oldGraphRange.m_TStart - grapheRange.m_TStart;
56 varRangeRequested.m_TStart -= deltaLeft;
57 varRangeRequested.m_TEnd -= deltaLeft;
58 break;
59 }
60 case AcquisitionZoomType::Unknown: {
61 qCCritical(LOG_VariableController())
62 << VariableController::tr("Impossible to synchronize: zoom type unknown");
63 break;
64 }
65 default:
66 qCCritical(LOG_VariableController()) << VariableController::tr(
67 "Impossible to synchronize: zoom type not take into account");
68 // No action
69 break;
70 }
71
72 return varRangeRequested;
73 }
74 }
75
20 struct VariableController::VariableControllerPrivate {
76 struct VariableController::VariableControllerPrivate {
21 explicit VariableControllerPrivate(VariableController *parent)
77 explicit VariableControllerPrivate(VariableController *parent)
22 : m_WorkingMutex{},
78 : m_WorkingMutex{},
23 m_VariableModel{new VariableModel{parent}},
79 m_VariableModel{new VariableModel{parent}},
24 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
80 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
25 m_VariableCacheController{std::make_unique<VariableCacheController>()}
81 m_VariableCacheController{std::make_unique<VariableCacheController>()},
82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()}
84 {
85
86 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
87 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
88 }
89
90
91 virtual ~VariableControllerPrivate()
26 {
92 {
93 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
94 m_VariableAcquisitionWorkerThread.quit();
95 m_VariableAcquisitionWorkerThread.wait();
27 }
96 }
28
97
98
99 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested);
100
101 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
102 const SqpRange &dateTime);
103
104 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
105 std::shared_ptr<IDataSeries>
106 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
107
108 void registerProvider(std::shared_ptr<IDataProvider> provider);
109
29 QMutex m_WorkingMutex;
110 QMutex m_WorkingMutex;
30 /// Variable model. The VariableController has the ownership
111 /// Variable model. The VariableController has the ownership
31 VariableModel *m_VariableModel;
112 VariableModel *m_VariableModel;
32 QItemSelectionModel *m_VariableSelectionModel;
113 QItemSelectionModel *m_VariableSelectionModel;
33
114
34
115
35 TimeController *m_TimeController{nullptr};
116 TimeController *m_TimeController{nullptr};
36 std::unique_ptr<VariableCacheController> m_VariableCacheController;
117 std::unique_ptr<VariableCacheController> m_VariableCacheController;
118 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
119 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
120 QThread m_VariableAcquisitionWorkerThread;
37
121
38 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
122 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
39 m_VariableToProviderMap;
123 m_VariableToProviderMap;
40 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> >
126 m_GroupIdToVariableSynchronizationGroupMap;
127 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
128 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
41 };
129 };
42
130
131
43 VariableController::VariableController(QObject *parent)
132 VariableController::VariableController(QObject *parent)
44 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
133 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
45 {
134 {
46 qCDebug(LOG_VariableController()) << tr("VariableController construction")
135 qCDebug(LOG_VariableController()) << tr("VariableController construction")
47 << QThread::currentThread();
136 << QThread::currentThread();
48
137
49 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
138 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
50 &VariableController::onAbortProgressRequested);
139 &VariableController::onAbortProgressRequested);
140
141 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
142 &VariableController::onDataProvided);
143 connect(impl->m_VariableAcquisitionWorker.get(),
144 &VariableAcquisitionWorker::variableRequestInProgress, this,
145 &VariableController::onVariableRetrieveDataInProgress);
146
147 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
148 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
149 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
150 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
151
152
153 impl->m_VariableAcquisitionWorkerThread.start();
51 }
154 }
52
155
53 VariableController::~VariableController()
156 VariableController::~VariableController()
54 {
157 {
55 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
158 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
56 << QThread::currentThread();
159 << QThread::currentThread();
57 this->waitForFinish();
160 this->waitForFinish();
58 }
161 }
59
162
60 VariableModel *VariableController::variableModel() noexcept
163 VariableModel *VariableController::variableModel() noexcept
61 {
164 {
62 return impl->m_VariableModel;
165 return impl->m_VariableModel;
63 }
166 }
64
167
65 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
168 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
66 {
169 {
67 return impl->m_VariableSelectionModel;
170 return impl->m_VariableSelectionModel;
68 }
171 }
69
172
70 void VariableController::setTimeController(TimeController *timeController) noexcept
173 void VariableController::setTimeController(TimeController *timeController) noexcept
71 {
174 {
72 impl->m_TimeController = timeController;
175 impl->m_TimeController = timeController;
73 }
176 }
74
177
75 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
178 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
76 {
179 {
77 if (!variable) {
180 if (!variable) {
78 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
181 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
79 return;
182 return;
80 }
183 }
81
184
82 // 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
83 // make some treatments before the deletion
186 // make some treatments before the deletion
84 emit variableAboutToBeDeleted(variable);
187 emit variableAboutToBeDeleted(variable);
85
188
86 // Deletes identifier
189 // Deletes identifier
87 impl->m_VariableToIdentifierMap.erase(variable);
190 impl->m_VariableToIdentifierMap.erase(variable);
88
191
89 // Deletes provider
192 // Deletes provider
90 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
193 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
91 qCDebug(LOG_VariableController())
194 qCDebug(LOG_VariableController())
92 << tr("Number of providers deleted for variable %1: %2")
195 << tr("Number of providers deleted for variable %1: %2")
93 .arg(variable->name(), QString::number(nbProvidersDeleted));
196 .arg(variable->name(), QString::number(nbProvidersDeleted));
94
197
95 // Clears cache
198 // Clears cache
96 impl->m_VariableCacheController->clear(variable);
199 impl->m_VariableCacheController->clear(variable);
97
200
98 // Deletes from model
201 // Deletes from model
99 impl->m_VariableModel->deleteVariable(variable);
202 impl->m_VariableModel->deleteVariable(variable);
100 }
203 }
101
204
102 void VariableController::deleteVariables(
205 void VariableController::deleteVariables(
103 const QVector<std::shared_ptr<Variable> > &variables) noexcept
206 const QVector<std::shared_ptr<Variable> > &variables) noexcept
104 {
207 {
105 for (auto variable : qAsConst(variables)) {
208 for (auto variable : qAsConst(variables)) {
106 deleteVariable(variable);
209 deleteVariable(variable);
107 }
210 }
108 }
211 }
109
212
110 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
213 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
111 {
214 {
112 }
215 }
113
216
114 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
217 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
115 std::shared_ptr<IDataProvider> provider) noexcept
218 std::shared_ptr<IDataProvider> provider) noexcept
116 {
219 {
117
220
118 if (!impl->m_TimeController) {
221 if (!impl->m_TimeController) {
119 qCCritical(LOG_VariableController())
222 qCCritical(LOG_VariableController())
120 << tr("Impossible to create variable: The time controller is null");
223 << tr("Impossible to create variable: The time controller is null");
121 return;
224 return;
122 }
225 }
123
226
124 auto dateTime = impl->m_TimeController->dateTime();
227 auto range = impl->m_TimeController->dateTime();
125
228
126 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime, metadata)) {
229 if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) {
127 auto identifier = QUuid::createUuid();
230 auto identifier = QUuid::createUuid();
128
231
129 // store the provider
232 // store the provider
233 impl->registerProvider(provider);
234
235 // Associate the provider
130 impl->m_VariableToProviderMap[newVariable] = provider;
236 impl->m_VariableToProviderMap[newVariable] = provider;
131 impl->m_VariableToIdentifierMap[newVariable] = identifier;
237 impl->m_VariableToIdentifierMap[newVariable] = identifier;
132
238
133 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
134 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
135 {
136 if (auto variable = varW.lock()) {
137 auto varIdentifier = impl->m_VariableToIdentifierMap.at(variable);
138 if (varIdentifier == identifier) {
139 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
140 variable->setDataSeries(dataSeriesAcquired);
141 emit variable->updated();
142 }
143 }
144 };
145
239
146 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
240 impl->processRequest(newVariable, range);
147 connect(provider.get(), &IDataProvider::dataProvidedProgress, this,
148 &VariableController::onVariableRetrieveDataInProgress);
149 this->onRequestDataLoading(newVariable, dateTime);
150 }
241 }
151 }
242 }
152
243
153 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
244 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
154 {
245 {
246 // TODO check synchronisation
155 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
247 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
156 << QThread::currentThread()->objectName();
248 << QThread::currentThread()->objectName();
157 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
249 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
158
250
159 for (const auto &selectedRow : qAsConst(selectedRows)) {
251 for (const auto &selectedRow : qAsConst(selectedRows)) {
160 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
252 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
161 selectedVariable->setDateTime(dateTime);
253 selectedVariable->setRange(dateTime);
162 this->onRequestDataLoading(selectedVariable, dateTime);
254 impl->processRequest(selectedVariable, dateTime);
163
255
164 // notify that rescale operation has to be done
256 // notify that rescale operation has to be done
165 emit rangeChanged(selectedVariable, dateTime);
257 emit rangeChanged(selectedVariable, dateTime);
166 }
258 }
167 }
259 }
168 }
260 }
169
261
170 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
262 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
263 const SqpRange &cacheRangeRequested,
264 QVector<AcquisitionDataPacket> dataAcquired)
171 {
265 {
172 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
266 auto var = impl->findVariable(vIdentifier);
267 if (var != nullptr) {
268 var->setRange(rangeRequested);
269 var->setCacheRange(cacheRangeRequested);
270 qCDebug(LOG_VariableController()) << tr("1: onDataProvided") << rangeRequested;
271 qCDebug(LOG_VariableController()) << tr("2: onDataProvided") << cacheRangeRequested;
272
273 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
274 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
275 << retrievedDataSeries->range();
276 var->mergeDataSeries(retrievedDataSeries);
277 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
278 emit var->updated();
279 }
280 else {
281 qCCritical(LOG_VariableController()) << tr("Impossible to provide data to a null variable");
282 }
283 }
173
284
174 auto end = impl->m_VariableToIdentifierMap.cend();
285 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
175 auto it = std::find_if(impl->m_VariableToIdentifierMap.cbegin(), end, findReply);
286 {
176 if (it != end) {
287 auto var = impl->findVariable(identifier);
177 impl->m_VariableModel->setDataProgress(it->first, progress);
288 if (var != nullptr) {
289 impl->m_VariableModel->setDataProgress(var, progress);
290 }
291 else {
292 qCCritical(LOG_VariableController())
293 << tr("Impossible to notify progression of a null variable");
178 }
294 }
179 }
295 }
180
296
181 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
297 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
182 {
298 {
183 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
299 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
184 << QThread::currentThread()->objectName();
300 << QThread::currentThread()->objectName();
185
301
186 auto it = impl->m_VariableToIdentifierMap.find(variable);
302 auto it = impl->m_VariableToIdentifierMap.find(variable);
187 if (it != impl->m_VariableToIdentifierMap.cend()) {
303 if (it != impl->m_VariableToIdentifierMap.cend()) {
188 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
304 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
189 }
305 }
190 else {
306 else {
191 qCWarning(LOG_VariableController())
307 qCWarning(LOG_VariableController())
192 << tr("Aborting progression of inexistant variable detected !!!")
308 << tr("Aborting progression of inexistant variable detected !!!")
193 << QThread::currentThread()->objectName();
309 << QThread::currentThread()->objectName();
194 }
310 }
195 }
311 }
196
312
313 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
314 {
315 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
316 << QThread::currentThread()->objectName()
317 << synchronizationGroupId;
318 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
319 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
320 std::make_pair(synchronizationGroupId, vSynchroGroup));
321 }
197
322
198 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
323 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
199 const SqpRange &dateTime)
200 {
324 {
201 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
325 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
202 << QThread::currentThread()->objectName();
326 }
203 // we want to load data of the variable for the dateTime.
204 // First we check if the cache contains some of them.
205 // For the other, we ask the provider to give them.
206 if (variable) {
207
327
208 auto dateTimeListNotInCache
328 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
209 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
329 QUuid synchronizationGroupId)
210
330
211 if (!dateTimeListNotInCache.empty()) {
331 {
212 // Ask the provider for each data on the dateTimeListNotInCache
332 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
213 auto identifier = impl->m_VariableToIdentifierMap.at(variable);
333 << synchronizationGroupId;
214 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
334 auto vToVIdit = impl->m_VariableToIdentifierMap.find(variable);
215 identifier,
335 if (vToVIdit != impl->m_VariableToIdentifierMap.cend()) {
216 DataProviderParameters{std::move(dateTimeListNotInCache), variable->metadata()});
336 auto itSynchroGroup
337 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
338 if (itSynchroGroup != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
339 impl->m_VariableIdGroupIdMap.insert(
340 std::make_pair(vToVIdit->second, synchronizationGroupId));
341 itSynchroGroup->second->addVariableId(vToVIdit->second);
217 }
342 }
218 else {
343 else {
219 emit variable->updated();
344 qCCritical(LOG_VariableController())
345 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
346 << variable->name();
220 }
347 }
221 }
348 }
222 else {
349 else {
223 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
350 qCCritical(LOG_VariableController())
351 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
352 }
353 }
354
355
356 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
357 const SqpRange &range, const SqpRange &oldRange,
358 bool synchronise)
359 {
360 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
361
362 qCInfo(LOG_VariableController()) << "VariableController::onRequestDataLoading"
363 << QThread::currentThread()->objectName();
364 // we want to load data of the variable for the dateTime.
365 // First we check if the cache contains some of them.
366 // For the other, we ask the provider to give them.
367
368 foreach (auto var, variables) {
369 qCDebug(LOG_VariableController()) << "processRequest for" << var->name();
370 impl->processRequest(var, range);
371 }
372
373 if (synchronise) {
374 // Get the group ids
375 qCDebug(LOG_VariableController())
376 << "VariableController::onRequestDataLoading for synchro var ENABLE";
377 auto groupIds = std::set<QUuid>();
378 foreach (auto var, variables) {
379 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
380 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
381 auto vId = varToVarIdIt->second;
382 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
383 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
384 auto gId = varIdToGroupIdIt->second;
385 if (groupIds.find(gId) == groupIds.cend()) {
386 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
387 groupIds.insert(gId);
388 }
389 }
390 }
391 }
392
393 // We assume here all group ids exist
394 foreach (auto gId, groupIds) {
395 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
396 auto vSyncIds = vSynchronizationGroup->getIds();
397 qCDebug(LOG_VariableController()) << "Var in synchro group ";
398 for (auto vId : vSyncIds) {
399 auto var = impl->findVariable(vId);
400
401 // Don't process already processed var
402 if (!variables.contains(var)) {
403 if (var != nullptr) {
404 qCDebug(LOG_VariableController()) << "processRequest synchro for"
405 << var->name();
406 auto vSyncRangeRequested
407 = computeSynchroRangeRequested(var->range(), range, oldRange);
408 impl->processRequest(var, vSyncRangeRequested);
409 }
410 else {
411 qCCritical(LOG_VariableController())
412
413 << tr("Impossible to synchronize a null variable");
414 }
415 }
416 }
417 }
224 }
418 }
225 }
419 }
226
420
227
421
228 void VariableController::initialize()
422 void VariableController::initialize()
229 {
423 {
230 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
424 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
231 impl->m_WorkingMutex.lock();
425 impl->m_WorkingMutex.lock();
232 qCDebug(LOG_VariableController()) << tr("VariableController init END");
426 qCDebug(LOG_VariableController()) << tr("VariableController init END");
233 }
427 }
234
428
235 void VariableController::finalize()
429 void VariableController::finalize()
236 {
430 {
237 impl->m_WorkingMutex.unlock();
431 impl->m_WorkingMutex.unlock();
238 }
432 }
239
433
240 void VariableController::waitForFinish()
434 void VariableController::waitForFinish()
241 {
435 {
242 QMutexLocker locker{&impl->m_WorkingMutex};
436 QMutexLocker locker{&impl->m_WorkingMutex};
243 }
437 }
438
439 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
440 {
441 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
442 auto zoomType = AcquisitionZoomType::Unknown;
443 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
444 zoomType = AcquisitionZoomType::ZoomOut;
445 }
446 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
447 zoomType = AcquisitionZoomType::PanRight;
448 }
449 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
450 zoomType = AcquisitionZoomType::PanLeft;
451 }
452 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
453 zoomType = AcquisitionZoomType::ZoomIn;
454 }
455 else {
456 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
457 }
458 return zoomType;
459 }
460
461 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
462 const SqpRange &rangeRequested)
463 {
464
465 auto varRangesRequested
466 = m_VariableCacheStrategy->computeCacheRange(var->range(), rangeRequested);
467 auto notInCacheRangeList = var->provideNotInCacheRangeList(varRangesRequested.second);
468
469 if (!notInCacheRangeList.empty()) {
470 auto identifier = m_VariableToIdentifierMap.at(var);
471 auto varProvider = m_VariableToProviderMap.at(var);
472 if (varProvider != nullptr) {
473 m_VariableAcquisitionWorker->pushVariableRequest(
474 identifier, varRangesRequested.first, varRangesRequested.second,
475 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
476 varProvider);
477 }
478 else {
479 qCCritical(LOG_VariableController())
480 << "Impossible to provide data with a null provider";
481 }
482 }
483 else {
484 var->setRange(rangeRequested);
485 var->setCacheRange(varRangesRequested.second);
486 var->setDataSeries(var->dataSeries()->subData(varRangesRequested.second));
487 emit var->updated();
488 }
489 }
490
491 std::shared_ptr<Variable>
492 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
493 {
494 std::shared_ptr<Variable> var;
495 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
496
497 auto end = m_VariableToIdentifierMap.cend();
498 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
499 if (it != end) {
500 var = it->first;
501 }
502 else {
503 qCCritical(LOG_VariableController())
504 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
505 }
506
507 return var;
508 }
509
510 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
511 const QVector<AcquisitionDataPacket> acqDataPacketVector)
512 {
513 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
514 << acqDataPacketVector.size();
515 std::shared_ptr<IDataSeries> dataSeries;
516 if (!acqDataPacketVector.isEmpty()) {
517 dataSeries = acqDataPacketVector[0].m_DateSeries;
518 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
519 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
520 }
521 }
522 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
523 << acqDataPacketVector.size();
524 return dataSeries;
525 }
526
527 void VariableController::VariableControllerPrivate::registerProvider(
528 std::shared_ptr<IDataProvider> provider)
529 {
530 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
531 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
532 << provider->objectName();
533 m_ProviderSet.insert(provider);
534 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
535 &VariableAcquisitionWorker::onVariableDataAcquired);
536 connect(provider.get(), &IDataProvider::dataProvidedProgress,
537 m_VariableAcquisitionWorker.get(),
538 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
539 }
540 else {
541 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
542 }
543 }
@@ -1,249 +1,249
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableModel.h>
2 #include <Variable/VariableModel.h>
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5
5
6 #include <Data/IDataSeries.h>
6 #include <Data/IDataSeries.h>
7
7
8 #include <QSize>
8 #include <QSize>
9 #include <unordered_map>
9 #include <unordered_map>
10
10
11 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
11 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
12
12
13 namespace {
13 namespace {
14
14
15 // Column indexes
15 // Column indexes
16 const auto NAME_COLUMN = 0;
16 const auto NAME_COLUMN = 0;
17 const auto TSTART_COLUMN = 1;
17 const auto TSTART_COLUMN = 1;
18 const auto TEND_COLUMN = 2;
18 const auto TEND_COLUMN = 2;
19 const auto NB_COLUMNS = 3;
19 const auto NB_COLUMNS = 3;
20
20
21 // Column properties
21 // Column properties
22 const auto DEFAULT_HEIGHT = 25;
22 const auto DEFAULT_HEIGHT = 25;
23 const auto DEFAULT_WIDTH = 100;
23 const auto DEFAULT_WIDTH = 100;
24
24
25 struct ColumnProperties {
25 struct ColumnProperties {
26 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
26 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
27 int height = DEFAULT_HEIGHT)
27 int height = DEFAULT_HEIGHT)
28 : m_Name{name}, m_Width{width}, m_Height{height}
28 : m_Name{name}, m_Width{width}, m_Height{height}
29 {
29 {
30 }
30 }
31
31
32 QString m_Name;
32 QString m_Name;
33 int m_Width;
33 int m_Width;
34 int m_Height;
34 int m_Height;
35 };
35 };
36
36
37 const auto COLUMN_PROPERTIES
37 const auto COLUMN_PROPERTIES
38 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
38 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
39 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
39 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
40 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
40 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
41
41
42 /// Format for datetimes
42 /// Format for datetimes
43 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
43 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
44
44
45
45
46 } // namespace
46 } // namespace
47
47
48 struct VariableModel::VariableModelPrivate {
48 struct VariableModel::VariableModelPrivate {
49 /// Variables created in SciQlop
49 /// Variables created in SciQlop
50 std::vector<std::shared_ptr<Variable> > m_Variables;
50 std::vector<std::shared_ptr<Variable> > m_Variables;
51 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
51 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
52
52
53 /// Return the row index of the variable. -1 if it's not found
53 /// Return the row index of the variable. -1 if it's not found
54 int indexOfVariable(Variable *variable) const noexcept;
54 int indexOfVariable(Variable *variable) const noexcept;
55 };
55 };
56
56
57 VariableModel::VariableModel(QObject *parent)
57 VariableModel::VariableModel(QObject *parent)
58 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
58 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
59 {
59 {
60 }
60 }
61
61
62 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
62 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
63 const SqpRange &dateTime,
63 const SqpRange &dateTime,
64 const QVariantHash &metadata) noexcept
64 const QVariantHash &metadata) noexcept
65 {
65 {
66 auto insertIndex = rowCount();
66 auto insertIndex = rowCount();
67 beginInsertRows({}, insertIndex, insertIndex);
67 beginInsertRows({}, insertIndex, insertIndex);
68
68
69 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
69 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
70
70
71 impl->m_Variables.push_back(variable);
71 impl->m_Variables.push_back(variable);
72 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
72 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
73
73
74 endInsertRows();
74 endInsertRows();
75
75
76 return variable;
76 return variable;
77 }
77 }
78
78
79 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
79 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
80 {
80 {
81 if (!variable) {
81 if (!variable) {
82 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
82 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
83 return;
83 return;
84 }
84 }
85
85
86 // Finds variable in the model
86 // Finds variable in the model
87 auto begin = impl->m_Variables.cbegin();
87 auto begin = impl->m_Variables.cbegin();
88 auto end = impl->m_Variables.cend();
88 auto end = impl->m_Variables.cend();
89 auto it = std::find(begin, end, variable);
89 auto it = std::find(begin, end, variable);
90 if (it != end) {
90 if (it != end) {
91 auto removeIndex = std::distance(begin, it);
91 auto removeIndex = std::distance(begin, it);
92
92
93 // Deletes variable
93 // Deletes variable
94 beginRemoveRows({}, removeIndex, removeIndex);
94 beginRemoveRows({}, removeIndex, removeIndex);
95 impl->m_Variables.erase(it);
95 impl->m_Variables.erase(it);
96 endRemoveRows();
96 endRemoveRows();
97 }
97 }
98 else {
98 else {
99 qCritical(LOG_VariableModel())
99 qCritical(LOG_VariableModel())
100 << tr("Can't delete variable %1 from the model: the variable is not in the model")
100 << tr("Can't delete variable %1 from the model: the variable is not in the model")
101 .arg(variable->name());
101 .arg(variable->name());
102 }
102 }
103
103
104 // Removes variable from progress map
104 // Removes variable from progress map
105 impl->m_VariableToProgress.erase(variable);
105 impl->m_VariableToProgress.erase(variable);
106 }
106 }
107
107
108
108
109 std::shared_ptr<Variable> VariableModel::variable(int index) const
109 std::shared_ptr<Variable> VariableModel::variable(int index) const
110 {
110 {
111 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
111 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
112 }
112 }
113
113
114 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
114 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
115 {
115 {
116 if (progress > 0.0) {
116 if (progress > 0.0) {
117 impl->m_VariableToProgress[variable] = progress;
117 impl->m_VariableToProgress[variable] = progress;
118 }
118 }
119 else {
119 else {
120 impl->m_VariableToProgress.erase(variable);
120 impl->m_VariableToProgress.erase(variable);
121 }
121 }
122 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
122 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
123
123
124 emit dataChanged(modelIndex, modelIndex);
124 emit dataChanged(modelIndex, modelIndex);
125 }
125 }
126
126
127 int VariableModel::columnCount(const QModelIndex &parent) const
127 int VariableModel::columnCount(const QModelIndex &parent) const
128 {
128 {
129 Q_UNUSED(parent);
129 Q_UNUSED(parent);
130
130
131 return NB_COLUMNS;
131 return NB_COLUMNS;
132 }
132 }
133
133
134 int VariableModel::rowCount(const QModelIndex &parent) const
134 int VariableModel::rowCount(const QModelIndex &parent) const
135 {
135 {
136 Q_UNUSED(parent);
136 Q_UNUSED(parent);
137
137
138 return impl->m_Variables.size();
138 return impl->m_Variables.size();
139 }
139 }
140
140
141 QVariant VariableModel::data(const QModelIndex &index, int role) const
141 QVariant VariableModel::data(const QModelIndex &index, int role) const
142 {
142 {
143 if (!index.isValid()) {
143 if (!index.isValid()) {
144 return QVariant{};
144 return QVariant{};
145 }
145 }
146
146
147 if (index.row() < 0 || index.row() >= rowCount()) {
147 if (index.row() < 0 || index.row() >= rowCount()) {
148 return QVariant{};
148 return QVariant{};
149 }
149 }
150
150
151 if (role == Qt::DisplayRole) {
151 if (role == Qt::DisplayRole) {
152 if (auto variable = impl->m_Variables.at(index.row()).get()) {
152 if (auto variable = impl->m_Variables.at(index.row()).get()) {
153 /// Lambda function that builds the variant to return for a time value
153 /// Lambda function that builds the variant to return for a time value
154 auto dateTimeVariant = [](double secs) {
154 auto dateTimeVariant = [](double secs) {
155 auto dateTime = DateUtils::dateTime(secs);
155 auto dateTime = DateUtils::dateTime(secs);
156 return dateTime.toString(DATETIME_FORMAT);
156 return dateTime.toString(DATETIME_FORMAT);
157 };
157 };
158
158
159 switch (index.column()) {
159 switch (index.column()) {
160 case NAME_COLUMN:
160 case NAME_COLUMN:
161 return variable->name();
161 return variable->name();
162 case TSTART_COLUMN:
162 case TSTART_COLUMN:
163 return dateTimeVariant(variable->dateTime().m_TStart);
163 return dateTimeVariant(variable->range().m_TStart);
164 case TEND_COLUMN:
164 case TEND_COLUMN:
165 return dateTimeVariant(variable->dateTime().m_TEnd);
165 return dateTimeVariant(variable->range().m_TEnd);
166 default:
166 default:
167 // No action
167 // No action
168 break;
168 break;
169 }
169 }
170
170
171 qWarning(LOG_VariableModel())
171 qWarning(LOG_VariableModel())
172 << tr("Can't get data (unknown column %1)").arg(index.column());
172 << tr("Can't get data (unknown column %1)").arg(index.column());
173 }
173 }
174 else {
174 else {
175 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
175 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
176 }
176 }
177 }
177 }
178 else if (role == VariableRoles::ProgressRole) {
178 else if (role == VariableRoles::ProgressRole) {
179 if (auto variable = impl->m_Variables.at(index.row())) {
179 if (auto variable = impl->m_Variables.at(index.row())) {
180
180
181 auto it = impl->m_VariableToProgress.find(variable);
181 auto it = impl->m_VariableToProgress.find(variable);
182 if (it != impl->m_VariableToProgress.cend()) {
182 if (it != impl->m_VariableToProgress.cend()) {
183 return it->second;
183 return it->second;
184 }
184 }
185 }
185 }
186 }
186 }
187
187
188 return QVariant{};
188 return QVariant{};
189 }
189 }
190
190
191 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
191 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
192 {
192 {
193 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
193 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
194 return QVariant{};
194 return QVariant{};
195 }
195 }
196
196
197 if (orientation == Qt::Horizontal) {
197 if (orientation == Qt::Horizontal) {
198 auto propertiesIt = COLUMN_PROPERTIES.find(section);
198 auto propertiesIt = COLUMN_PROPERTIES.find(section);
199 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
199 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
200 // Role is either DisplayRole or SizeHintRole
200 // Role is either DisplayRole or SizeHintRole
201 return (role == Qt::DisplayRole)
201 return (role == Qt::DisplayRole)
202 ? QVariant{propertiesIt->m_Name}
202 ? QVariant{propertiesIt->m_Name}
203 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
203 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
204 }
204 }
205 else {
205 else {
206 qWarning(LOG_VariableModel())
206 qWarning(LOG_VariableModel())
207 << tr("Can't get header data (unknown column %1)").arg(section);
207 << tr("Can't get header data (unknown column %1)").arg(section);
208 }
208 }
209 }
209 }
210
210
211 return QVariant{};
211 return QVariant{};
212 }
212 }
213
213
214 void VariableModel::abortProgress(const QModelIndex &index)
214 void VariableModel::abortProgress(const QModelIndex &index)
215 {
215 {
216 if (auto variable = impl->m_Variables.at(index.row())) {
216 if (auto variable = impl->m_Variables.at(index.row())) {
217 emit abortProgessRequested(variable);
217 emit abortProgessRequested(variable);
218 }
218 }
219 }
219 }
220
220
221 void VariableModel::onVariableUpdated() noexcept
221 void VariableModel::onVariableUpdated() noexcept
222 {
222 {
223 // Finds variable that has been updated in the model
223 // Finds variable that has been updated in the model
224 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
224 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
225 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
225 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
226
226
227 if (updatedVariableIndex > -1) {
227 if (updatedVariableIndex > -1) {
228 emit dataChanged(createIndex(updatedVariableIndex, 0),
228 emit dataChanged(createIndex(updatedVariableIndex, 0),
229 createIndex(updatedVariableIndex, columnCount() - 1));
229 createIndex(updatedVariableIndex, columnCount() - 1));
230 }
230 }
231 }
231 }
232 }
232 }
233
233
234 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
234 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
235 {
235 {
236 auto begin = std::cbegin(m_Variables);
236 auto begin = std::cbegin(m_Variables);
237 auto end = std::cend(m_Variables);
237 auto end = std::cend(m_Variables);
238 auto it
238 auto it
239 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
239 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
240
240
241 if (it != end) {
241 if (it != end) {
242 // Gets the index of the variable in the model: we assume here that views have the same
242 // Gets the index of the variable in the model: we assume here that views have the same
243 // order as the model
243 // order as the model
244 return std::distance(begin, it);
244 return std::distance(begin, it);
245 }
245 }
246 else {
246 else {
247 return -1;
247 return -1;
248 }
248 }
249 }
249 }
@@ -1,199 +1,199
1 #include "Data/ArrayData.h"
1 #include "Data/ArrayData.h"
2 #include <QObject>
2 #include <QObject>
3 #include <QtTest>
3 #include <QtTest>
4
4
5 class TestOneDimArrayData : public QObject {
5 class TestOneDimArrayData : public QObject {
6 Q_OBJECT
6 Q_OBJECT
7 private slots:
7 private slots:
8 /// Tests @sa ArrayData::data()
8 /// Tests @sa ArrayData::data()
9 void testData_data();
9 void testData_data();
10 void testData();
10 void testData();
11
11
12 /// Tests @sa ArrayData::data(int componentIndex)
12 /// Tests @sa ArrayData::data(int componentIndex)
13 void testDataByComponentIndex_data();
13 void testDataByComponentIndex_data();
14 void testDataByComponentIndex();
14 void testDataByComponentIndex();
15
15
16 /// Tests @sa ArrayData::add()
16 /// Tests @sa ArrayData::add()
17 void testAdd_data();
17 void testAdd_data();
18 void testAdd();
18 void testAdd();
19
19
20 /// Tests @sa ArrayData::at(int index)
20 /// Tests @sa ArrayData::at(int index)
21 void testAt_data();
21 void testAt_data();
22 void testAt();
22 void testAt();
23
23
24 /// Tests @sa ArrayData::clear()
24 /// Tests @sa ArrayData::clear()
25 void testClear_data();
25 void testClear_data();
26 void testClear();
26 void testClear();
27
27
28 /// Tests @sa ArrayData::size()
28 /// Tests @sa ArrayData::size()
29 void testSize_data();
29 void testSize_data();
30 void testSize();
30 void testSize();
31
31
32 /// Tests @sa ArrayData::sort()
32 /// Tests @sa ArrayData::sort()
33 void testSort_data();
33 void testSort_data();
34 void testSort();
34 void testSort();
35 };
35 };
36
36
37 void TestOneDimArrayData::testData_data()
37 void TestOneDimArrayData::testData_data()
38 {
38 {
39 // Test structure
39 // Test structure
40 QTest::addColumn<QVector<double> >("inputData"); // array's data input
40 QTest::addColumn<QVector<double> >("inputData"); // array's data input
41 QTest::addColumn<QVector<double> >("expectedData"); // expected data
41 QTest::addColumn<QVector<double> >("expectedData"); // expected data
42
42
43 // Test cases
43 // Test cases
44 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.}
44 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.}
45 << QVector<double>{1., 2., 3., 4., 5.};
45 << QVector<double>{1., 2., 3., 4., 5.};
46 }
46 }
47
47
48 void TestOneDimArrayData::testData()
48 void TestOneDimArrayData::testData()
49 {
49 {
50 QFETCH(QVector<double>, inputData);
50 QFETCH(QVector<double>, inputData);
51 QFETCH(QVector<double>, expectedData);
51 QFETCH(QVector<double>, expectedData);
52
52
53 ArrayData<1> arrayData{inputData};
53 ArrayData<1> arrayData{inputData};
54 QVERIFY(arrayData.data() == expectedData);
54 QVERIFY(arrayData.data() == expectedData);
55 }
55 }
56
56
57 void TestOneDimArrayData::testDataByComponentIndex_data()
57 void TestOneDimArrayData::testDataByComponentIndex_data()
58 {
58 {
59 // Test structure
59 // Test structure
60 QTest::addColumn<QVector<double> >("inputData"); // array data's input
60 QTest::addColumn<QVector<double> >("inputData"); // array data's input
61 QTest::addColumn<int>("componentIndex"); // component index to test
61 QTest::addColumn<int>("componentIndex"); // component index to test
62 QTest::addColumn<QVector<double> >("expectedData"); // expected data
62 QTest::addColumn<QVector<double> >("expectedData"); // expected data
63
63
64 // Test cases
64 // Test cases
65 QTest::newRow("validIndex") << QVector<double>{1., 2., 3., 4., 5.} << 0
65 QTest::newRow("validIndex") << QVector<double>{1., 2., 3., 4., 5.} << 0
66 << QVector<double>{1., 2., 3., 4., 5.};
66 << QVector<double>{1., 2., 3., 4., 5.};
67 QTest::newRow("invalidIndex1")
67 QTest::newRow("invalidIndex1") << QVector<double>{1., 2., 3., 4., 5.} << -1
68 << QVector<double>{1., 2., 3., 4., 5.} << -1 << QVector<double>{};
68 << QVector<double>{};
69 QTest::newRow("invalidIndex2") << QVector<double>{1., 2., 3., 4., 5.} << 1 << QVector<double>{};
69 QTest::newRow("invalidIndex2") << QVector<double>{1., 2., 3., 4., 5.} << 1 << QVector<double>{};
70 }
70 }
71
71
72 void TestOneDimArrayData::testDataByComponentIndex()
72 void TestOneDimArrayData::testDataByComponentIndex()
73 {
73 {
74 QFETCH(QVector<double>, inputData);
74 QFETCH(QVector<double>, inputData);
75 QFETCH(int, componentIndex);
75 QFETCH(int, componentIndex);
76 QFETCH(QVector<double>, expectedData);
76 QFETCH(QVector<double>, expectedData);
77
77
78 ArrayData<1> arrayData{inputData};
78 ArrayData<1> arrayData{inputData};
79 QVERIFY(arrayData.data(componentIndex) == expectedData);
79 QVERIFY(arrayData.data(componentIndex) == expectedData);
80 }
80 }
81
81
82 void TestOneDimArrayData::testAdd_data()
82 void TestOneDimArrayData::testAdd_data()
83 {
83 {
84 // Test structure
84 // Test structure
85 QTest::addColumn<QVector<double> >("inputData"); // array's data input
85 QTest::addColumn<QVector<double> >("inputData"); // array's data input
86 QTest::addColumn<QVector<double> >("otherData"); // array data's input to merge with
86 QTest::addColumn<QVector<double> >("otherData"); // array data's input to merge with
87 QTest::addColumn<bool>("prepend"); // prepend or append merge
87 QTest::addColumn<bool>("prepend"); // prepend or append merge
88 QTest::addColumn<QVector<double> >("expectedData"); // expected data after merge
88 QTest::addColumn<QVector<double> >("expectedData"); // expected data after merge
89
89
90 // Test cases
90 // Test cases
91 QTest::newRow("appendMerge") << QVector<double>{1., 2., 3., 4., 5.}
91 QTest::newRow("appendMerge") << QVector<double>{1., 2., 3., 4., 5.}
92 << QVector<double>{6., 7., 8.} << false
92 << QVector<double>{6., 7., 8.} << false
93 << QVector<double>{1., 2., 3., 4., 5., 6., 7., 8.};
93 << QVector<double>{1., 2., 3., 4., 5., 6., 7., 8.};
94 QTest::newRow("prependMerge") << QVector<double>{1., 2., 3., 4., 5.}
94 QTest::newRow("prependMerge") << QVector<double>{1., 2., 3., 4., 5.}
95 << QVector<double>{6., 7., 8.} << true
95 << QVector<double>{6., 7., 8.} << true
96 << QVector<double>{6., 7., 8., 1., 2., 3., 4., 5.};
96 << QVector<double>{6., 7., 8., 1., 2., 3., 4., 5.};
97 }
97 }
98
98
99 void TestOneDimArrayData::testAdd()
99 void TestOneDimArrayData::testAdd()
100 {
100 {
101 QFETCH(QVector<double>, inputData);
101 QFETCH(QVector<double>, inputData);
102 QFETCH(QVector<double>, otherData);
102 QFETCH(QVector<double>, otherData);
103 QFETCH(bool, prepend);
103 QFETCH(bool, prepend);
104 QFETCH(QVector<double>, expectedData);
104 QFETCH(QVector<double>, expectedData);
105
105
106 ArrayData<1> arrayData{inputData};
106 ArrayData<1> arrayData{inputData};
107 ArrayData<1> other{otherData};
107 ArrayData<1> other{otherData};
108
108
109 arrayData.add(other, prepend);
109 arrayData.add(other, prepend);
110 QVERIFY(arrayData.data() == expectedData);
110 QVERIFY(arrayData.data() == expectedData);
111 }
111 }
112
112
113 void TestOneDimArrayData::testAt_data()
113 void TestOneDimArrayData::testAt_data()
114 {
114 {
115 // Test structure
115 // Test structure
116 QTest::addColumn<QVector<double> >("inputData"); // array data's input
116 QTest::addColumn<QVector<double> >("inputData"); // array data's input
117 QTest::addColumn<int>("index"); // index to retrieve data
117 QTest::addColumn<int>("index"); // index to retrieve data
118 QTest::addColumn<double>("expectedData"); // expected data at index
118 QTest::addColumn<double>("expectedData"); // expected data at index
119
119
120 // Test cases
120 // Test cases
121 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.} << 0 << 1.;
121 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.} << 0 << 1.;
122 QTest::newRow("data2") << QVector<double>{1., 2., 3., 4., 5.} << 3 << 4.;
122 QTest::newRow("data2") << QVector<double>{1., 2., 3., 4., 5.} << 3 << 4.;
123 }
123 }
124
124
125 void TestOneDimArrayData::testAt()
125 void TestOneDimArrayData::testAt()
126 {
126 {
127 QFETCH(QVector<double>, inputData);
127 QFETCH(QVector<double>, inputData);
128 QFETCH(int, index);
128 QFETCH(int, index);
129 QFETCH(double, expectedData);
129 QFETCH(double, expectedData);
130
130
131 ArrayData<1> arrayData{inputData};
131 ArrayData<1> arrayData{inputData};
132 QVERIFY(arrayData.at(index) == expectedData);
132 QVERIFY(arrayData.at(index) == expectedData);
133 }
133 }
134
134
135 void TestOneDimArrayData::testClear_data()
135 void TestOneDimArrayData::testClear_data()
136 {
136 {
137 // Test structure
137 // Test structure
138 QTest::addColumn<QVector<double> >("inputData"); // array data's input
138 QTest::addColumn<QVector<double> >("inputData"); // array data's input
139
139
140 // Test cases
140 // Test cases
141 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.};
141 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.};
142 }
142 }
143
143
144 void TestOneDimArrayData::testClear()
144 void TestOneDimArrayData::testClear()
145 {
145 {
146 QFETCH(QVector<double>, inputData);
146 QFETCH(QVector<double>, inputData);
147
147
148 ArrayData<1> arrayData{inputData};
148 ArrayData<1> arrayData{inputData};
149 arrayData.clear();
149 arrayData.clear();
150 QVERIFY(arrayData.data() == QVector<double>{});
150 QVERIFY(arrayData.data() == QVector<double>{});
151 }
151 }
152
152
153 void TestOneDimArrayData::testSize_data()
153 void TestOneDimArrayData::testSize_data()
154 {
154 {
155 // Test structure
155 // Test structure
156 QTest::addColumn<QVector<double> >("inputData"); // array data's input
156 QTest::addColumn<QVector<double> >("inputData"); // array data's input
157 QTest::addColumn<int>("expectedSize"); // expected array data size
157 QTest::addColumn<int>("expectedSize"); // expected array data size
158
158
159 // Test cases
159 // Test cases
160 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.} << 5;
160 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.} << 5;
161 }
161 }
162
162
163 void TestOneDimArrayData::testSize()
163 void TestOneDimArrayData::testSize()
164 {
164 {
165 QFETCH(QVector<double>, inputData);
165 QFETCH(QVector<double>, inputData);
166 QFETCH(int, expectedSize);
166 QFETCH(int, expectedSize);
167
167
168 ArrayData<1> arrayData{inputData};
168 ArrayData<1> arrayData{inputData};
169 QVERIFY(arrayData.size() == expectedSize);
169 QVERIFY(arrayData.size() == expectedSize);
170 }
170 }
171
171
172 void TestOneDimArrayData::testSort_data()
172 void TestOneDimArrayData::testSort_data()
173 {
173 {
174 // Test structure
174 // Test structure
175 QTest::addColumn<QVector<double> >("inputData"); // array data's input
175 QTest::addColumn<QVector<double> >("inputData"); // array data's input
176 QTest::addColumn<std::vector<int> >("sortPermutation"); // permutation used to sort data
176 QTest::addColumn<std::vector<int> >("sortPermutation"); // permutation used to sort data
177 QTest::addColumn<QVector<double> >("expectedData"); // expected data after sorting
177 QTest::addColumn<QVector<double> >("expectedData"); // expected data after sorting
178
178
179 // Test cases
179 // Test cases
180 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.} << std::vector<int>{0, 2, 3, 1, 4}
180 QTest::newRow("data1") << QVector<double>{1., 2., 3., 4., 5.} << std::vector<int>{0, 2, 3, 1, 4}
181 << QVector<double>{1., 3., 4., 2., 5.};
181 << QVector<double>{1., 3., 4., 2., 5.};
182 QTest::newRow("data2") << QVector<double>{1., 2., 3., 4., 5.} << std::vector<int>{4, 1, 2, 3, 0}
182 QTest::newRow("data2") << QVector<double>{1., 2., 3., 4., 5.} << std::vector<int>{4, 1, 2, 3, 0}
183 << QVector<double>{5., 2., 3., 4., 1.};
183 << QVector<double>{5., 2., 3., 4., 1.};
184 }
184 }
185
185
186 void TestOneDimArrayData::testSort()
186 void TestOneDimArrayData::testSort()
187 {
187 {
188 QFETCH(QVector<double>, inputData);
188 QFETCH(QVector<double>, inputData);
189 QFETCH(std::vector<int>, sortPermutation);
189 QFETCH(std::vector<int>, sortPermutation);
190 QFETCH(QVector<double>, expectedData);
190 QFETCH(QVector<double>, expectedData);
191
191
192 ArrayData<1> arrayData{inputData};
192 ArrayData<1> arrayData{inputData};
193 auto sortedArrayData = arrayData.sort(sortPermutation);
193 auto sortedArrayData = arrayData.sort(sortPermutation);
194 QVERIFY(sortedArrayData != nullptr);
194 QVERIFY(sortedArrayData != nullptr);
195 QVERIFY(sortedArrayData->data() == expectedData);
195 QVERIFY(sortedArrayData->data() == expectedData);
196 }
196 }
197
197
198 QTEST_MAIN(TestOneDimArrayData)
198 QTEST_MAIN(TestOneDimArrayData)
199 #include "TestOneDimArrayData.moc"
199 #include "TestOneDimArrayData.moc"
@@ -1,224 +1,224
1 #include "Data/ArrayData.h"
1 #include "Data/ArrayData.h"
2 #include <QObject>
2 #include <QObject>
3 #include <QtTest>
3 #include <QtTest>
4
4
5 using DataContainer = QVector<QVector<double> >;
5 using DataContainer = QVector<QVector<double> >;
6
6
7 class TestTwoDimArrayData : public QObject {
7 class TestTwoDimArrayData : public QObject {
8 Q_OBJECT
8 Q_OBJECT
9 private slots:
9 private slots:
10 /// Tests @sa ArrayData::data(int componentIndex)
10 /// Tests @sa ArrayData::data(int componentIndex)
11 void testDataByComponentIndex_data();
11 void testDataByComponentIndex_data();
12 void testDataByComponentIndex();
12 void testDataByComponentIndex();
13
13
14 /// Tests @sa ArrayData ctor
14 /// Tests @sa ArrayData ctor
15 void testCtor_data();
15 void testCtor_data();
16 void testCtor();
16 void testCtor();
17
17
18 /// Tests @sa ArrayData::add()
18 /// Tests @sa ArrayData::add()
19 void testAdd_data();
19 void testAdd_data();
20 void testAdd();
20 void testAdd();
21
21
22 /// Tests @sa ArrayData::clear()
22 /// Tests @sa ArrayData::clear()
23 void testClear_data();
23 void testClear_data();
24 void testClear();
24 void testClear();
25
25
26 /// Tests @sa ArrayData::size()
26 /// Tests @sa ArrayData::size()
27 void testSize_data();
27 void testSize_data();
28 void testSize();
28 void testSize();
29
29
30 /// Tests @sa ArrayData::sort()
30 /// Tests @sa ArrayData::sort()
31 void testSort_data();
31 void testSort_data();
32 void testSort();
32 void testSort();
33 };
33 };
34
34
35 void TestTwoDimArrayData::testDataByComponentIndex_data()
35 void TestTwoDimArrayData::testDataByComponentIndex_data()
36 {
36 {
37 // Test structure
37 // Test structure
38 QTest::addColumn<DataContainer>("inputData"); // array data's input
38 QTest::addColumn<DataContainer>("inputData"); // array data's input
39 QTest::addColumn<int>("componentIndex"); // component index to test
39 QTest::addColumn<int>("componentIndex"); // component index to test
40 QTest::addColumn<QVector<double> >("expectedData"); // expected data
40 QTest::addColumn<QVector<double> >("expectedData"); // expected data
41
41
42 // Test cases
42 // Test cases
43 auto inputData
43 auto inputData
44 = DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}};
44 = DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}};
45
45
46 QTest::newRow("validIndex1") << inputData << 0 << QVector<double>{1., 2., 3., 4., 5.};
46 QTest::newRow("validIndex1") << inputData << 0 << QVector<double>{1., 2., 3., 4., 5.};
47 QTest::newRow("validIndex2") << inputData << 1 << QVector<double>{6., 7., 8., 9., 10.};
47 QTest::newRow("validIndex2") << inputData << 1 << QVector<double>{6., 7., 8., 9., 10.};
48 QTest::newRow("validIndex3") << inputData << 2 << QVector<double>{11., 12., 13., 14., 15.};
48 QTest::newRow("validIndex3") << inputData << 2 << QVector<double>{11., 12., 13., 14., 15.};
49 QTest::newRow("invalidIndex1") << inputData << -1 << QVector<double>{};
49 QTest::newRow("invalidIndex1") << inputData << -1 << QVector<double>{};
50 QTest::newRow("invalidIndex2") << inputData << 3 << QVector<double>{};
50 QTest::newRow("invalidIndex2") << inputData << 3 << QVector<double>{};
51 }
51 }
52
52
53 void TestTwoDimArrayData::testDataByComponentIndex()
53 void TestTwoDimArrayData::testDataByComponentIndex()
54 {
54 {
55 QFETCH(DataContainer, inputData);
55 QFETCH(DataContainer, inputData);
56 QFETCH(int, componentIndex);
56 QFETCH(int, componentIndex);
57 QFETCH(QVector<double>, expectedData);
57 QFETCH(QVector<double>, expectedData);
58
58
59 ArrayData<2> arrayData{inputData};
59 ArrayData<2> arrayData{inputData};
60 QVERIFY(arrayData.data(componentIndex) == expectedData);
60 QVERIFY(arrayData.data(componentIndex) == expectedData);
61 }
61 }
62
62
63 void TestTwoDimArrayData::testCtor_data()
63 void TestTwoDimArrayData::testCtor_data()
64 {
64 {
65 // Test structure
65 // Test structure
66 QTest::addColumn<DataContainer>("inputData"); // array data's input
66 QTest::addColumn<DataContainer>("inputData"); // array data's input
67 QTest::addColumn<bool>("success"); // array data has been successfully constructed
67 QTest::addColumn<bool>("success"); // array data has been successfully constructed
68 QTest::addColumn<DataContainer>("expectedData"); // expected array data (when success)
68 QTest::addColumn<DataContainer>("expectedData"); // expected array data (when success)
69
69
70 // Test cases
70 // Test cases
71 QTest::newRow("validInput")
71 QTest::newRow("validInput")
72 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}
72 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}
73 << true
73 << true
74 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}};
74 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}};
75 QTest::newRow("malformedInput (components of the array data haven't the same size")
75 QTest::newRow("malformedInput (components of the array data haven't the same size")
76 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8.}, {11., 12.}} << true
76 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8.}, {11., 12.}} << true
77 << DataContainer{{}, {}, {}};
77 << DataContainer{{}, {}, {}};
78 QTest::newRow("invalidInput (less than tow components")
78 QTest::newRow("invalidInput (less than tow components") << DataContainer{{1., 2., 3., 4., 5.}}
79 << DataContainer{{1., 2., 3., 4., 5.}} << false << DataContainer{{}, {}, {}};
79 << false << DataContainer{{}, {}, {}};
80 }
80 }
81
81
82 void TestTwoDimArrayData::testCtor()
82 void TestTwoDimArrayData::testCtor()
83 {
83 {
84 QFETCH(DataContainer, inputData);
84 QFETCH(DataContainer, inputData);
85 QFETCH(bool, success);
85 QFETCH(bool, success);
86
86
87 if (success) {
87 if (success) {
88 QFETCH(DataContainer, expectedData);
88 QFETCH(DataContainer, expectedData);
89
89
90 ArrayData<2> arrayData{inputData};
90 ArrayData<2> arrayData{inputData};
91
91
92 for (auto i = 0; i < expectedData.size(); ++i) {
92 for (auto i = 0; i < expectedData.size(); ++i) {
93 QVERIFY(arrayData.data(i) == expectedData.at(i));
93 QVERIFY(arrayData.data(i) == expectedData.at(i));
94 }
94 }
95 }
95 }
96 else {
96 else {
97 QVERIFY_EXCEPTION_THROWN(ArrayData<2> arrayData{inputData}, std::invalid_argument);
97 QVERIFY_EXCEPTION_THROWN(ArrayData<2> arrayData{inputData}, std::invalid_argument);
98 }
98 }
99 }
99 }
100
100
101 void TestTwoDimArrayData::testAdd_data()
101 void TestTwoDimArrayData::testAdd_data()
102 {
102 {
103 // Test structure
103 // Test structure
104 QTest::addColumn<DataContainer>("inputData"); // array's data input
104 QTest::addColumn<DataContainer>("inputData"); // array's data input
105 QTest::addColumn<DataContainer>("otherData"); // array data's input to merge with
105 QTest::addColumn<DataContainer>("otherData"); // array data's input to merge with
106 QTest::addColumn<bool>("prepend"); // prepend or append merge
106 QTest::addColumn<bool>("prepend"); // prepend or append merge
107 QTest::addColumn<DataContainer>("expectedData"); // expected data after merge
107 QTest::addColumn<DataContainer>("expectedData"); // expected data after merge
108
108
109 // Test cases
109 // Test cases
110 auto inputData
110 auto inputData
111 = DataContainer{{1., 2., 3., 4., 5.}, {11., 12., 13., 14., 15.}, {21., 22., 23., 24., 25.}};
111 = DataContainer{{1., 2., 3., 4., 5.}, {11., 12., 13., 14., 15.}, {21., 22., 23., 24., 25.}};
112
112
113 auto vectorContainer = DataContainer{{6., 7., 8.}, {16., 17., 18.}, {26., 27., 28}};
113 auto vectorContainer = DataContainer{{6., 7., 8.}, {16., 17., 18.}, {26., 27., 28}};
114 auto tensorContainer = DataContainer{{6., 7., 8.}, {16., 17., 18.}, {26., 27., 28},
114 auto tensorContainer = DataContainer{{6., 7., 8.}, {16., 17., 18.}, {26., 27., 28},
115 {36., 37., 38.}, {46., 47., 48.}, {56., 57., 58}};
115 {36., 37., 38.}, {46., 47., 48.}, {56., 57., 58}};
116
116
117 QTest::newRow("appendMerge") << inputData << vectorContainer << false
117 QTest::newRow("appendMerge") << inputData << vectorContainer << false
118 << DataContainer{{1., 2., 3., 4., 5., 6., 7., 8.},
118 << DataContainer{{1., 2., 3., 4., 5., 6., 7., 8.},
119 {11., 12., 13., 14., 15., 16., 17., 18.},
119 {11., 12., 13., 14., 15., 16., 17., 18.},
120 {21., 22., 23., 24., 25., 26., 27., 28}};
120 {21., 22., 23., 24., 25., 26., 27., 28}};
121 QTest::newRow("prependMerge") << inputData << vectorContainer << true
121 QTest::newRow("prependMerge") << inputData << vectorContainer << true
122 << DataContainer{{6., 7., 8., 1., 2., 3., 4., 5.},
122 << DataContainer{{6., 7., 8., 1., 2., 3., 4., 5.},
123 {16., 17., 18., 11., 12., 13., 14., 15.},
123 {16., 17., 18., 11., 12., 13., 14., 15.},
124 {26., 27., 28, 21., 22., 23., 24., 25.}};
124 {26., 27., 28, 21., 22., 23., 24., 25.}};
125 QTest::newRow("invalidMerge") << inputData << tensorContainer << false << inputData;
125 QTest::newRow("invalidMerge") << inputData << tensorContainer << false << inputData;
126 }
126 }
127
127
128 void TestTwoDimArrayData::testAdd()
128 void TestTwoDimArrayData::testAdd()
129 {
129 {
130 QFETCH(DataContainer, inputData);
130 QFETCH(DataContainer, inputData);
131 QFETCH(DataContainer, otherData);
131 QFETCH(DataContainer, otherData);
132 QFETCH(bool, prepend);
132 QFETCH(bool, prepend);
133 QFETCH(DataContainer, expectedData);
133 QFETCH(DataContainer, expectedData);
134
134
135 ArrayData<2> arrayData{inputData};
135 ArrayData<2> arrayData{inputData};
136 ArrayData<2> other{otherData};
136 ArrayData<2> other{otherData};
137
137
138 arrayData.add(other, prepend);
138 arrayData.add(other, prepend);
139
139
140 for (auto i = 0; i < expectedData.size(); ++i) {
140 for (auto i = 0; i < expectedData.size(); ++i) {
141 QVERIFY(arrayData.data(i) == expectedData.at(i));
141 QVERIFY(arrayData.data(i) == expectedData.at(i));
142 }
142 }
143 }
143 }
144
144
145 void TestTwoDimArrayData::testClear_data()
145 void TestTwoDimArrayData::testClear_data()
146 {
146 {
147 // Test structure
147 // Test structure
148 QTest::addColumn<DataContainer>("inputData"); // array data's input
148 QTest::addColumn<DataContainer>("inputData"); // array data's input
149
149
150 // Test cases
150 // Test cases
151 QTest::newRow("data1") << DataContainer{
151 QTest::newRow("data1") << DataContainer{
152 {1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}};
152 {1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}};
153 }
153 }
154
154
155 void TestTwoDimArrayData::testClear()
155 void TestTwoDimArrayData::testClear()
156 {
156 {
157 QFETCH(DataContainer, inputData);
157 QFETCH(DataContainer, inputData);
158
158
159 ArrayData<2> arrayData{inputData};
159 ArrayData<2> arrayData{inputData};
160 arrayData.clear();
160 arrayData.clear();
161
161
162 for (auto i = 0; i < inputData.size(); ++i) {
162 for (auto i = 0; i < inputData.size(); ++i) {
163 QVERIFY(arrayData.data(i) == QVector<double>{});
163 QVERIFY(arrayData.data(i) == QVector<double>{});
164 }
164 }
165 }
165 }
166
166
167 void TestTwoDimArrayData::testSize_data()
167 void TestTwoDimArrayData::testSize_data()
168 {
168 {
169 // Test structure
169 // Test structure
170 QTest::addColumn<QVector<QVector<double> > >("inputData"); // array data's input
170 QTest::addColumn<QVector<QVector<double> > >("inputData"); // array data's input
171 QTest::addColumn<int>("expectedSize"); // expected array data size
171 QTest::addColumn<int>("expectedSize"); // expected array data size
172
172
173 // Test cases
173 // Test cases
174 QTest::newRow("data1") << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}} << 5;
174 QTest::newRow("data1") << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}} << 5;
175 QTest::newRow("data2") << DataContainer{{1., 2., 3., 4., 5.},
175 QTest::newRow("data2") << DataContainer{{1., 2., 3., 4., 5.},
176 {6., 7., 8., 9., 10.},
176 {6., 7., 8., 9., 10.},
177 {11., 12., 13., 14., 15.}}
177 {11., 12., 13., 14., 15.}}
178 << 5;
178 << 5;
179 }
179 }
180
180
181 void TestTwoDimArrayData::testSize()
181 void TestTwoDimArrayData::testSize()
182 {
182 {
183 QFETCH(DataContainer, inputData);
183 QFETCH(DataContainer, inputData);
184 QFETCH(int, expectedSize);
184 QFETCH(int, expectedSize);
185
185
186 ArrayData<2> arrayData{inputData};
186 ArrayData<2> arrayData{inputData};
187 QVERIFY(arrayData.size() == expectedSize);
187 QVERIFY(arrayData.size() == expectedSize);
188 }
188 }
189
189
190 void TestTwoDimArrayData::testSort_data()
190 void TestTwoDimArrayData::testSort_data()
191 {
191 {
192 // Test structure
192 // Test structure
193 QTest::addColumn<DataContainer>("inputData"); // array data's input
193 QTest::addColumn<DataContainer>("inputData"); // array data's input
194 QTest::addColumn<std::vector<int> >("sortPermutation"); // permutation used to sort data
194 QTest::addColumn<std::vector<int> >("sortPermutation"); // permutation used to sort data
195 QTest::addColumn<DataContainer>("expectedData"); // expected data after sorting
195 QTest::addColumn<DataContainer>("expectedData"); // expected data after sorting
196
196
197 // Test cases
197 // Test cases
198 QTest::newRow("data1")
198 QTest::newRow("data1")
199 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}
199 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}
200 << std::vector<int>{0, 2, 3, 1, 4}
200 << std::vector<int>{0, 2, 3, 1, 4}
201 << DataContainer{{1., 3., 4., 2., 5.}, {6., 8., 9., 7., 10.}, {11., 13., 14., 12., 15.}};
201 << DataContainer{{1., 3., 4., 2., 5.}, {6., 8., 9., 7., 10.}, {11., 13., 14., 12., 15.}};
202 QTest::newRow("data2")
202 QTest::newRow("data2")
203 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}
203 << DataContainer{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}
204 << std::vector<int>{2, 4, 3, 0, 1}
204 << std::vector<int>{2, 4, 3, 0, 1}
205 << DataContainer{{3., 5., 4., 1., 2.}, {8., 10., 9., 6., 7.}, {13., 15., 14., 11., 12.}};
205 << DataContainer{{3., 5., 4., 1., 2.}, {8., 10., 9., 6., 7.}, {13., 15., 14., 11., 12.}};
206 }
206 }
207
207
208 void TestTwoDimArrayData::testSort()
208 void TestTwoDimArrayData::testSort()
209 {
209 {
210 QFETCH(DataContainer, inputData);
210 QFETCH(DataContainer, inputData);
211 QFETCH(std::vector<int>, sortPermutation);
211 QFETCH(std::vector<int>, sortPermutation);
212 QFETCH(DataContainer, expectedData);
212 QFETCH(DataContainer, expectedData);
213
213
214 ArrayData<2> arrayData{inputData};
214 ArrayData<2> arrayData{inputData};
215 auto sortedArrayData = arrayData.sort(sortPermutation);
215 auto sortedArrayData = arrayData.sort(sortPermutation);
216 QVERIFY(sortedArrayData != nullptr);
216 QVERIFY(sortedArrayData != nullptr);
217
217
218 for (auto i = 0; i < expectedData.size(); ++i) {
218 for (auto i = 0; i < expectedData.size(); ++i) {
219 QVERIFY(sortedArrayData->data(i) == expectedData.at(i));
219 QVERIFY(sortedArrayData->data(i) == expectedData.at(i));
220 }
220 }
221 }
221 }
222
222
223 QTEST_MAIN(TestTwoDimArrayData)
223 QTEST_MAIN(TestTwoDimArrayData)
224 #include "TestTwoDimArrayData.moc"
224 #include "TestTwoDimArrayData.moc"
@@ -1,38 +1,38
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHHELPER_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHHELPER_H
2 #define SCIQLOP_VISUALIZATIONGRAPHHELPER_H
2 #define SCIQLOP_VISUALIZATIONGRAPHHELPER_H
3
3
4 #include <Data/SqpRange.h>
4 #include <Data/SqpRange.h>
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QVector>
7 #include <QVector>
8
8
9 #include <memory>
9 #include <memory>
10
10
11 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphHelper)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphHelper)
12
12
13 class IDataSeries;
13 class IDataSeries;
14 class QCPAbstractPlottable;
14 class QCPAbstractPlottable;
15 class QCustomPlot;
15 class QCustomPlot;
16 class Variable;
16 class Variable;
17
17
18 /**
18 /**
19 * @brief The VisualizationGraphHelper class aims to create the QCustomPlot components relative to a
19 * @brief The VisualizationGraphHelper class aims to create the QCustomPlot components relative to a
20 * variable, depending on the data series of this variable
20 * variable, depending on the data series of this variable
21 */
21 */
22 struct VisualizationGraphHelper {
22 struct VisualizationGraphHelper {
23 /**
23 /**
24 * Creates (if possible) the QCustomPlot components relative to the variable passed in
24 * Creates (if possible) the QCustomPlot components relative to the variable passed in
25 * parameter, and adds these to the plot passed in parameter.
25 * parameter, and adds these to the plot passed in parameter.
26 * @param variable the variable for which to create the components
26 * @param variable the variable for which to create the components
27 * @param plot the plot in which to add the created components. It takes ownership of these
27 * @param plot the plot in which to add the created components. It takes ownership of these
28 * components.
28 * components.
29 * @return the list of the components created
29 * @return the list of the components created
30 */
30 */
31 static QVector<QCPAbstractPlottable *> create(std::shared_ptr<Variable> variable,
31 static QVector<QCPAbstractPlottable *> create(std::shared_ptr<Variable> variable,
32 QCustomPlot &plot) noexcept;
32 QCustomPlot &plot) noexcept;
33
33
34 static void updateData(QVector<QCPAbstractPlottable *> plotableVect, IDataSeries *dataSeries,
34 static void updateData(QVector<QCPAbstractPlottable *> plotableVect,
35 const SqpRange &dateTime);
35 std::shared_ptr<IDataSeries> dataSeries, const SqpRange &dateTime);
36 };
36 };
37
37
38 #endif // SCIQLOP_VISUALIZATIONGRAPHHELPER_H
38 #endif // SCIQLOP_VISUALIZATIONGRAPHHELPER_H
@@ -1,84 +1,83
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QWidget>
7 #include <QWidget>
8
8
9 #include <memory>
9 #include <memory>
10
10
11 #include <Common/spimpl.h>
11 #include <Common/spimpl.h>
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14
14
15 class QCPRange;
15 class QCPRange;
16 class SqpRange;
16 class SqpRange;
17 class Variable;
17 class Variable;
18
18
19 /**
20 * Possible types of zoom operation
21 */
22 enum class VisualizationGraphWidgetZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
23
24 namespace Ui {
19 namespace Ui {
25 class VisualizationGraphWidget;
20 class VisualizationGraphWidget;
26 } // namespace Ui
21 } // namespace Ui
27
22
28 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
23 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
29 Q_OBJECT
24 Q_OBJECT
30
25
31 public:
26 public:
32 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
27 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
33 virtual ~VisualizationGraphWidget();
28 virtual ~VisualizationGraphWidget();
34
29
35 void enableSynchronize(bool enable);
30 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
31 void enableAcquisition(bool enable);
36
32
37 void addVariable(std::shared_ptr<Variable> variable);
33 void addVariable(std::shared_ptr<Variable> variable);
38 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
34 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
39 /// Removes a variable from the graph
35 /// Removes a variable from the graph
40 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
36 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
41
37
42 void setRange(std::shared_ptr<Variable> variable, const SqpRange &range);
38 void setRange(std::shared_ptr<Variable> variable, const SqpRange &range);
43 SqpRange graphRange() const noexcept;
39 SqpRange graphRange() const noexcept;
44 void setGraphRange(const SqpRange &range);
40 void setGraphRange(const SqpRange &range);
45
41
46 // IVisualizationWidget interface
42 // IVisualizationWidget interface
47 void accept(IVisualizationWidgetVisitor *visitor) override;
43 void accept(IVisualizationWidgetVisitor *visitor) override;
48 bool canDrop(const Variable &variable) const override;
44 bool canDrop(const Variable &variable) const override;
49 bool contains(const Variable &variable) const override;
45 bool contains(const Variable &variable) const override;
50 QString name() const override;
46 QString name() const override;
51
47
52
48
53 signals:
49 signals:
54 void requestDataLoading(std::shared_ptr<Variable> variable, const SqpRange &dateTime);
50 void synchronize(const SqpRange &range, const SqpRange &oldRange);
55 void synchronize(const SqpRange &dateTime, const SqpRange &oldDateTime,
51 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
56 VisualizationGraphWidgetZoomType zoomType);
52 const SqpRange &oldRange, bool synchronise);
53
54
55 void variableAdded(std::shared_ptr<Variable> var);
57
56
58
57
59 private:
58 private:
60 Ui::VisualizationGraphWidget *ui;
59 Ui::VisualizationGraphWidget *ui;
61
60
62 class VisualizationGraphWidgetPrivate;
61 class VisualizationGraphWidgetPrivate;
63 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
62 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
64
63
65 private slots:
64 private slots:
66 /// Slot called when right clicking on the graph (displays a menu)
65 /// Slot called when right clicking on the graph (displays a menu)
67 void onGraphMenuRequested(const QPoint &pos) noexcept;
66 void onGraphMenuRequested(const QPoint &pos) noexcept;
68
67
69 /// Rescale the X axe to range parameter
68 /// Rescale the X axe to range parameter
70 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
69 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
71
70
72 /// Slot called when a mouse move was made
71 /// Slot called when a mouse move was made
73 void onMouseMove(QMouseEvent *event) noexcept;
72 void onMouseMove(QMouseEvent *event) noexcept;
74 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
73 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
75 void onMouseWheel(QWheelEvent *event) noexcept;
74 void onMouseWheel(QWheelEvent *event) noexcept;
76 /// Slot called when a mouse press was made, to activate the calibration of a graph
75 /// Slot called when a mouse press was made, to activate the calibration of a graph
77 void onMousePress(QMouseEvent *event) noexcept;
76 void onMousePress(QMouseEvent *event) noexcept;
78 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
77 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
79 void onMouseRelease(QMouseEvent *event) noexcept;
78 void onMouseRelease(QMouseEvent *event) noexcept;
80
79
81 void onDataCacheVariableUpdated();
80 void onDataCacheVariableUpdated();
82 };
81 };
83
82
84 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
83 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,45 +1,56
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QWidget>
7 #include <QWidget>
8
8
9 #include <memory>
10
11 #include <Common/spimpl.h>
12
9 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
10
14
11 namespace Ui {
15 namespace Ui {
12 class VisualizationZoneWidget;
16 class VisualizationZoneWidget;
13 } // Ui
17 } // Ui
14
18
15 class Variable;
19 class Variable;
16 class VisualizationGraphWidget;
20 class VisualizationGraphWidget;
17
21
18 class VisualizationZoneWidget : public QWidget, public IVisualizationWidget {
22 class VisualizationZoneWidget : public QWidget, public IVisualizationWidget {
19 Q_OBJECT
23 Q_OBJECT
20
24
21 public:
25 public:
22 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
26 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
23 virtual ~VisualizationZoneWidget();
27 virtual ~VisualizationZoneWidget();
24
28
25 /// Add a graph widget
29 /// Add a graph widget
26 void addGraph(VisualizationGraphWidget *graphWidget);
30 void addGraph(VisualizationGraphWidget *graphWidget);
27
31
28 /**
32 /**
29 * Creates a graph using a variable. The variable will be displayed in the new graph.
33 * Creates a graph using a variable. The variable will be displayed in the new graph.
30 * @param variable the variable for which to create the graph
34 * @param variable the variable for which to create the graph
31 * @return the pointer to the created graph
35 * @return the pointer to the created graph
32 */
36 */
33 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
37 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
34
38
35 // IVisualizationWidget interface
39 // IVisualizationWidget interface
36 void accept(IVisualizationWidgetVisitor *visitor) override;
40 void accept(IVisualizationWidgetVisitor *visitor) override;
37 bool canDrop(const Variable &variable) const override;
41 bool canDrop(const Variable &variable) const override;
38 bool contains(const Variable &variable) const override;
42 bool contains(const Variable &variable) const override;
39 QString name() const override;
43 QString name() const override;
40
44
45
46 private slots:
47 void onVariableAdded(std::shared_ptr<Variable> variable);
48
41 private:
49 private:
42 Ui::VisualizationZoneWidget *ui;
50 Ui::VisualizationZoneWidget *ui;
51
52 class VisualizationZoneWidgetPrivate;
53 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
43 };
54 };
44
55
45 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
56 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -1,151 +1,151
1 #include "SqpApplication.h"
1 #include "SqpApplication.h"
2
2
3 #include <Data/IDataProvider.h>
3 #include <Data/IDataProvider.h>
4 #include <DataSource/DataSourceController.h>
4 #include <DataSource/DataSourceController.h>
5 #include <Network/NetworkController.h>
5 #include <Network/NetworkController.h>
6 #include <QThread>
6 #include <QThread>
7 #include <Time/TimeController.h>
7 #include <Time/TimeController.h>
8 #include <Variable/Variable.h>
8 #include <Variable/Variable.h>
9 #include <Variable/VariableController.h>
9 #include <Variable/VariableController.h>
10 #include <Visualization/VisualizationController.h>
10 #include <Visualization/VisualizationController.h>
11
11
12 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
12 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
13
13
14 class SqpApplication::SqpApplicationPrivate {
14 class SqpApplication::SqpApplicationPrivate {
15 public:
15 public:
16 SqpApplicationPrivate()
16 SqpApplicationPrivate()
17 : m_DataSourceController{std::make_unique<DataSourceController>()},
17 : m_DataSourceController{std::make_unique<DataSourceController>()},
18 m_NetworkController{std::make_unique<NetworkController>()},
18 m_NetworkController{std::make_unique<NetworkController>()},
19 m_TimeController{std::make_unique<TimeController>()},
19 m_TimeController{std::make_unique<TimeController>()},
20 m_VariableController{std::make_unique<VariableController>()},
20 m_VariableController{std::make_unique<VariableController>()},
21 m_VisualizationController{std::make_unique<VisualizationController>()}
21 m_VisualizationController{std::make_unique<VisualizationController>()}
22 {
22 {
23 // /////////////////////////////// //
23 // /////////////////////////////// //
24 // Connections between controllers //
24 // Connections between controllers //
25 // /////////////////////////////// //
25 // /////////////////////////////// //
26
26
27 // VariableController <-> DataSourceController
27 // VariableController <-> DataSourceController
28 connect(m_DataSourceController.get(),
28 connect(m_DataSourceController.get(),
29 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
29 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
30 std::shared_ptr<IDataProvider>)),
30 std::shared_ptr<IDataProvider>)),
31 m_VariableController.get(),
31 m_VariableController.get(),
32 SLOT(createVariable(const QString &, const QVariantHash &,
32 SLOT(createVariable(const QString &, const QVariantHash &,
33 std::shared_ptr<IDataProvider>)));
33 std::shared_ptr<IDataProvider>)));
34
34
35 // VariableController <-> VisualizationController
35 // VariableController <-> VisualizationController
36 connect(m_VariableController.get(),
36 connect(m_VariableController.get(),
37 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
37 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
38 m_VisualizationController.get(),
38 m_VisualizationController.get(),
39 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
39 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
40
40
41 connect(m_VariableController.get(),
41 connect(m_VariableController.get(),
42 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
42 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
43 m_VisualizationController.get(),
43 m_VisualizationController.get(),
44 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
44 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
45
45
46
46
47 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
47 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
48 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
48 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
49 m_NetworkController->moveToThread(&m_NetworkControllerThread);
49 m_NetworkController->moveToThread(&m_NetworkControllerThread);
50 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
50 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
51 m_VariableController->moveToThread(&m_VariableControllerThread);
51 m_VariableController->moveToThread(&m_VariableControllerThread);
52 m_VariableControllerThread.setObjectName("VariableControllerThread");
52 m_VariableControllerThread.setObjectName("VariableControllerThread");
53 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
53 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
54 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
54 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
55
55
56
56
57 // Additionnal init
57 // Additionnal init
58 m_VariableController->setTimeController(m_TimeController.get());
58 m_VariableController->setTimeController(m_TimeController.get());
59 }
59 }
60
60
61 virtual ~SqpApplicationPrivate()
61 virtual ~SqpApplicationPrivate()
62 {
62 {
63 qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
63 qCDebug(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
64 m_DataSourceControllerThread.quit();
64 m_DataSourceControllerThread.quit();
65 m_DataSourceControllerThread.wait();
65 m_DataSourceControllerThread.wait();
66
66
67 m_NetworkControllerThread.quit();
67 m_NetworkControllerThread.quit();
68 m_NetworkControllerThread.wait();
68 m_NetworkControllerThread.wait();
69
69
70 m_VariableControllerThread.quit();
70 m_VariableControllerThread.quit();
71 m_VariableControllerThread.wait();
71 m_VariableControllerThread.wait();
72
72
73 m_VisualizationControllerThread.quit();
73 m_VisualizationControllerThread.quit();
74 m_VisualizationControllerThread.wait();
74 m_VisualizationControllerThread.wait();
75 }
75 }
76
76
77 std::unique_ptr<DataSourceController> m_DataSourceController;
77 std::unique_ptr<DataSourceController> m_DataSourceController;
78 std::unique_ptr<VariableController> m_VariableController;
78 std::unique_ptr<VariableController> m_VariableController;
79 std::unique_ptr<TimeController> m_TimeController;
79 std::unique_ptr<TimeController> m_TimeController;
80 std::unique_ptr<NetworkController> m_NetworkController;
80 std::unique_ptr<NetworkController> m_NetworkController;
81 std::unique_ptr<VisualizationController> m_VisualizationController;
81 std::unique_ptr<VisualizationController> m_VisualizationController;
82 QThread m_DataSourceControllerThread;
82 QThread m_DataSourceControllerThread;
83 QThread m_NetworkControllerThread;
83 QThread m_NetworkControllerThread;
84 QThread m_VariableControllerThread;
84 QThread m_VariableControllerThread;
85 QThread m_VisualizationControllerThread;
85 QThread m_VisualizationControllerThread;
86 };
86 };
87
87
88
88
89 SqpApplication::SqpApplication(int &argc, char **argv)
89 SqpApplication::SqpApplication(int &argc, char **argv)
90 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
90 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
91 {
91 {
92 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
92 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
93
93
94 connect(&impl->m_DataSourceControllerThread, &QThread::started,
94 connect(&impl->m_DataSourceControllerThread, &QThread::started,
95 impl->m_DataSourceController.get(), &DataSourceController::initialize);
95 impl->m_DataSourceController.get(), &DataSourceController::initialize);
96 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
96 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
97 impl->m_DataSourceController.get(), &DataSourceController::finalize);
97 impl->m_DataSourceController.get(), &DataSourceController::finalize);
98
98
99 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
99 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
100 &NetworkController::initialize);
100 &NetworkController::initialize);
101 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
101 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
102 &NetworkController::finalize);
102 &NetworkController::finalize);
103
103
104 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
104 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
105 &VariableController::initialize);
105 &VariableController::initialize);
106 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
106 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
107 &VariableController::finalize);
107 &VariableController::finalize);
108
108
109 connect(&impl->m_VisualizationControllerThread, &QThread::started,
109 connect(&impl->m_VisualizationControllerThread, &QThread::started,
110 impl->m_VisualizationController.get(), &VisualizationController::initialize);
110 impl->m_VisualizationController.get(), &VisualizationController::initialize);
111 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
111 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
112 impl->m_VisualizationController.get(), &VisualizationController::finalize);
112 impl->m_VisualizationController.get(), &VisualizationController::finalize);
113
113
114 impl->m_DataSourceControllerThread.start();
114 impl->m_DataSourceControllerThread.start();
115 impl->m_NetworkControllerThread.start();
115 impl->m_NetworkControllerThread.start();
116 impl->m_VariableControllerThread.start();
116 impl->m_VariableControllerThread.start();
117 impl->m_VisualizationControllerThread.start();
117 impl->m_VisualizationControllerThread.start();
118 }
118 }
119
119
120 SqpApplication::~SqpApplication()
120 SqpApplication::~SqpApplication()
121 {
121 {
122 }
122 }
123
123
124 void SqpApplication::initialize()
124 void SqpApplication::initialize()
125 {
125 {
126 }
126 }
127
127
128 DataSourceController &SqpApplication::dataSourceController() noexcept
128 DataSourceController &SqpApplication::dataSourceController() noexcept
129 {
129 {
130 return *impl->m_DataSourceController;
130 return *impl->m_DataSourceController;
131 }
131 }
132
132
133 NetworkController &SqpApplication::networkController() noexcept
133 NetworkController &SqpApplication::networkController() noexcept
134 {
134 {
135 return *impl->m_NetworkController;
135 return *impl->m_NetworkController;
136 }
136 }
137
137
138 TimeController &SqpApplication::timeController() noexcept
138 TimeController &SqpApplication::timeController() noexcept
139 {
139 {
140 return *impl->m_TimeController;
140 return *impl->m_TimeController;
141 }
141 }
142
142
143 VariableController &SqpApplication::variableController() noexcept
143 VariableController &SqpApplication::variableController() noexcept
144 {
144 {
145 return *impl->m_VariableController;
145 return *impl->m_VariableController;
146 }
146 }
147
147
148 VisualizationController &SqpApplication::visualizationController() noexcept
148 VisualizationController &SqpApplication::visualizationController() noexcept
149 {
149 {
150 return *impl->m_VisualizationController;
150 return *impl->m_VisualizationController;
151 }
151 }
@@ -1,162 +1,163
1 #include "Visualization/VisualizationGraphHelper.h"
1 #include "Visualization/VisualizationGraphHelper.h"
2 #include "Visualization/qcustomplot.h"
2 #include "Visualization/qcustomplot.h"
3
3
4 #include <Data/ScalarSeries.h>
4 #include <Data/ScalarSeries.h>
5
5
6 #include <Variable/Variable.h>
6 #include <Variable/Variable.h>
7
7
8 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
8 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
9
9
10 namespace {
10 namespace {
11
11
12 class SqpDataContainer : public QCPGraphDataContainer {
12 class SqpDataContainer : public QCPGraphDataContainer {
13 public:
13 public:
14 void appendGraphData(const QCPGraphData &data) { mData.append(data); }
14 void appendGraphData(const QCPGraphData &data) { mData.append(data); }
15 };
15 };
16
16
17
17
18 /// Format for datetimes on a axis
18 /// Format for datetimes on a axis
19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
20
20
21 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
21 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
22 /// non-time data
22 /// non-time data
23 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
23 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
24 {
24 {
25 if (isTimeAxis) {
25 if (isTimeAxis) {
26 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
26 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
27 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
27 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
28 dateTicker->setDateTimeSpec(Qt::UTC);
28 dateTicker->setDateTimeSpec(Qt::UTC);
29
29
30 return dateTicker;
30 return dateTicker;
31 }
31 }
32 else {
32 else {
33 // default ticker
33 // default ticker
34 return QSharedPointer<QCPAxisTicker>::create();
34 return QSharedPointer<QCPAxisTicker>::create();
35 }
35 }
36 }
36 }
37
37
38 void updateScalarData(QCPAbstractPlottable *component, ScalarSeries &scalarSeries,
38 void updateScalarData(QCPAbstractPlottable *component, std::shared_ptr<ScalarSeries> scalarSeries,
39 const SqpRange &dateTime)
39 const SqpRange &dateTime)
40 {
40 {
41 qCDebug(LOG_VisualizationGraphHelper()) << "TORM: updateScalarData"
41 qCDebug(LOG_VisualizationGraphHelper()) << "TORM: updateScalarData"
42 << QThread::currentThread()->objectName();
42 << QThread::currentThread()->objectName();
43 if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) {
43 if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) {
44 scalarSeries.lockRead();
44 scalarSeries->lockRead();
45 {
45 {
46 const auto &xData = scalarSeries.xAxisData()->cdata();
46 const auto &xData = scalarSeries->xAxisData()->cdata();
47 const auto &valuesData = scalarSeries.valuesData()->cdata();
47 const auto &valuesData = scalarSeries->valuesData()->cdata();
48
48
49 auto xDataBegin = xData.cbegin();
49 auto xDataBegin = xData.cbegin();
50 auto xDataEnd = xData.cend();
50 auto xDataEnd = xData.cend();
51
51
52 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points in cache"
52 qCInfo(LOG_VisualizationGraphHelper()) << "TODEBUG: Current points in cache"
53 << xData.count();
53 << xData.count();
54
54
55 auto sqpDataContainer = QSharedPointer<SqpDataContainer>::create();
55 auto sqpDataContainer = QSharedPointer<SqpDataContainer>::create();
56 qcpGraph->setData(sqpDataContainer);
56 qcpGraph->setData(sqpDataContainer);
57
57
58 auto lowerIt = std::lower_bound(xDataBegin, xDataEnd, dateTime.m_TStart);
58 auto lowerIt = std::lower_bound(xDataBegin, xDataEnd, dateTime.m_TStart);
59 auto upperIt = std::upper_bound(xDataBegin, xDataEnd, dateTime.m_TEnd);
59 auto upperIt = std::upper_bound(xDataBegin, xDataEnd, dateTime.m_TEnd);
60 auto distance = std::distance(xDataBegin, lowerIt);
60 auto distance = std::distance(xDataBegin, lowerIt);
61
61
62 auto valuesDataIt = valuesData.cbegin() + distance;
62 auto valuesDataIt = valuesData.cbegin() + distance;
63 for (auto xAxisDataIt = lowerIt; xAxisDataIt != upperIt;
63 for (auto xAxisDataIt = lowerIt; xAxisDataIt != upperIt;
64 ++xAxisDataIt, ++valuesDataIt) {
64 ++xAxisDataIt, ++valuesDataIt) {
65 sqpDataContainer->appendGraphData(QCPGraphData(*xAxisDataIt, *valuesDataIt));
65 sqpDataContainer->appendGraphData(QCPGraphData(*xAxisDataIt, *valuesDataIt));
66 }
66 }
67
67
68 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points displayed"
68 qCInfo(LOG_VisualizationGraphHelper()) << "TODEBUG: Current points displayed"
69 << sqpDataContainer->size();
69 << sqpDataContainer->size();
70 }
70 }
71 scalarSeries.unlock();
71 scalarSeries->unlock();
72
72
73
73
74 // Display all data
74 // Display all data
75 component->parentPlot()->replot();
75 component->parentPlot()->replot();
76 }
76 }
77 else {
77 else {
78 /// @todo DEBUG
78 /// @todo DEBUG
79 }
79 }
80 }
80 }
81
81
82 QCPAbstractPlottable *createScalarSeriesComponent(ScalarSeries &scalarSeries, QCustomPlot &plot,
82 QCPAbstractPlottable *createScalarSeriesComponent(std::shared_ptr<ScalarSeries> scalarSeries,
83 const SqpRange &dateTime)
83 QCustomPlot &plot, const SqpRange &dateTime)
84 {
84 {
85 auto component = plot.addGraph();
85 auto component = plot.addGraph();
86
86
87 if (component) {
87 if (component) {
88 // // Graph data
88 // // Graph data
89 component->setData(scalarSeries.xAxisData()->data(), scalarSeries.valuesData()->data(),
89 component->setData(scalarSeries->xAxisData()->data(), scalarSeries->valuesData()->data(),
90 true);
90 true);
91
91
92 updateScalarData(component, scalarSeries, dateTime);
92 updateScalarData(component, scalarSeries, dateTime);
93
93
94 // Axes properties
94 // Axes properties
95 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
95 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
96 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
96 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
97
97
98 auto setAxisProperties = [](auto axis, const auto &unit) {
98 auto setAxisProperties = [](auto axis, const auto &unit) {
99 // label (unit name)
99 // label (unit name)
100 axis->setLabel(unit.m_Name);
100 axis->setLabel(unit.m_Name);
101
101
102 // ticker (depending on the type of unit)
102 // ticker (depending on the type of unit)
103 axis->setTicker(axisTicker(unit.m_TimeUnit));
103 axis->setTicker(axisTicker(unit.m_TimeUnit));
104 };
104 };
105 setAxisProperties(plot.xAxis, scalarSeries.xAxisUnit());
105 setAxisProperties(plot.xAxis, scalarSeries->xAxisUnit());
106 setAxisProperties(plot.yAxis, scalarSeries.valuesUnit());
106 setAxisProperties(plot.yAxis, scalarSeries->valuesUnit());
107
107
108 // Display all data
108 // Display all data
109 component->rescaleAxes();
109 component->rescaleAxes();
110 plot.replot();
110 plot.replot();
111 }
111 }
112 else {
112 else {
113 qCDebug(LOG_VisualizationGraphHelper())
113 qCDebug(LOG_VisualizationGraphHelper())
114 << QObject::tr("Can't create graph for the scalar series");
114 << QObject::tr("Can't create graph for the scalar series");
115 }
115 }
116
116
117 return component;
117 return component;
118 }
118 }
119
119
120 } // namespace
120 } // namespace
121
121
122 QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
122 QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
123 QCustomPlot &plot) noexcept
123 QCustomPlot &plot) noexcept
124 {
124 {
125 auto result = QVector<QCPAbstractPlottable *>{};
125 auto result = QVector<QCPAbstractPlottable *>{};
126
126
127 if (variable) {
127 if (variable) {
128 // Gets the data series of the variable to call the creation of the right components
128 // Gets the data series of the variable to call the creation of the right components
129 // according to its type
129 // according to its type
130 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(variable->dataSeries())) {
130 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(variable->dataSeries())) {
131 result.append(createScalarSeriesComponent(*scalarSeries, plot, variable->dateTime()));
131 result.append(createScalarSeriesComponent(scalarSeries, plot, variable->range()));
132 }
132 }
133 else {
133 else {
134 qCDebug(LOG_VisualizationGraphHelper())
134 qCDebug(LOG_VisualizationGraphHelper())
135 << QObject::tr("Can't create graph plottables : unmanaged data series type");
135 << QObject::tr("Can't create graph plottables : unmanaged data series type");
136 }
136 }
137 }
137 }
138 else {
138 else {
139 qCDebug(LOG_VisualizationGraphHelper())
139 qCDebug(LOG_VisualizationGraphHelper())
140 << QObject::tr("Can't create graph plottables : the variable is null");
140 << QObject::tr("Can't create graph plottables : the variable is null");
141 }
141 }
142
142
143 return result;
143 return result;
144 }
144 }
145
145
146 void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect,
146 void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect,
147 IDataSeries *dataSeries, const SqpRange &dateTime)
147 std::shared_ptr<IDataSeries> dataSeries,
148 const SqpRange &dateTime)
148 {
149 {
149 if (auto scalarSeries = dynamic_cast<ScalarSeries *>(dataSeries)) {
150 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
150 if (plotableVect.size() == 1) {
151 if (plotableVect.size() == 1) {
151 updateScalarData(plotableVect.at(0), *scalarSeries, dateTime);
152 updateScalarData(plotableVect.at(0), scalarSeries, dateTime);
152 }
153 }
153 else {
154 else {
154 qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr(
155 qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr(
155 "Can't update Data of a scalarSeries because there is not only one component "
156 "Can't update Data of a scalarSeries because there is not only one component "
156 "associated");
157 "associated");
157 }
158 }
158 }
159 }
159 else {
160 else {
160 /// @todo DEBUG
161 /// @todo DEBUG
161 }
162 }
162 }
163 }
@@ -1,427 +1,307
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationGraphHelper.h"
3 #include "Visualization/VisualizationGraphHelper.h"
4 #include "Visualization/VisualizationGraphRenderingDelegate.h"
4 #include "Visualization/VisualizationGraphRenderingDelegate.h"
5 #include "ui_VisualizationGraphWidget.h"
5 #include "ui_VisualizationGraphWidget.h"
6
6
7 #include <Data/ArrayData.h>
7 #include <Data/ArrayData.h>
8 #include <Data/IDataSeries.h>
8 #include <Data/IDataSeries.h>
9 #include <Settings/SqpSettingsDefs.h>
9 #include <Settings/SqpSettingsDefs.h>
10 #include <SqpApplication.h>
10 #include <SqpApplication.h>
11 #include <Variable/Variable.h>
11 #include <Variable/Variable.h>
12 #include <Variable/VariableController.h>
12 #include <Variable/VariableController.h>
13
13
14 #include <unordered_map>
14 #include <unordered_map>
15
15
16 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
16 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
17
17
18 namespace {
18 namespace {
19
19
20 /// Key pressed to enable zoom on horizontal axis
20 /// Key pressed to enable zoom on horizontal axis
21 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
21 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
22
22
23 /// Key pressed to enable zoom on vertical axis
23 /// Key pressed to enable zoom on vertical axis
24 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
24 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
25
25
26 /// Gets a tolerance value from application settings. If the setting can't be found, the default
27 /// value passed in parameter is returned
28 double toleranceValue(const QString &key, double defaultValue) noexcept
29 {
30 return QSettings{}.value(key, defaultValue).toDouble();
31 }
32
33 } // namespace
26 } // namespace
34
27
35 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
28 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
36
29
37 explicit VisualizationGraphWidgetPrivate()
30 explicit VisualizationGraphWidgetPrivate()
38 : m_DoSynchronize{true}, m_IsCalibration{false}, m_RenderingDelegate{nullptr}
31 : m_DoAcquisition{true}, m_IsCalibration{false}, m_RenderingDelegate{nullptr}
39 {
32 {
40 }
33 }
41
34
42 // Return the operation when range changed
43 VisualizationGraphWidgetZoomType getZoomType(const QCPRange &t1, const QCPRange &t2);
44
45 // 1 variable -> n qcpplot
35 // 1 variable -> n qcpplot
46 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
36 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
47 bool m_DoSynchronize;
37 bool m_DoAcquisition;
48 bool m_IsCalibration;
38 bool m_IsCalibration;
49 QCPItemTracer *m_TextTracer;
39 QCPItemTracer *m_TextTracer;
50 /// Delegate used to attach rendering features to the plot
40 /// Delegate used to attach rendering features to the plot
51 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
41 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
52 };
42 };
53
43
54 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
44 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
55 : QWidget{parent},
45 : QWidget{parent},
56 ui{new Ui::VisualizationGraphWidget},
46 ui{new Ui::VisualizationGraphWidget},
57 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
47 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
58 {
48 {
59 ui->setupUi(this);
49 ui->setupUi(this);
60
50
61 // The delegate must be initialized after the ui as it uses the plot
51 // The delegate must be initialized after the ui as it uses the plot
62 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*ui->widget);
52 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*ui->widget);
63
53
64 ui->graphNameLabel->setText(name);
54 ui->graphNameLabel->setText(name);
65
55
66 // 'Close' options : widget is deleted when closed
56 // 'Close' options : widget is deleted when closed
67 setAttribute(Qt::WA_DeleteOnClose);
57 setAttribute(Qt::WA_DeleteOnClose);
68 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
58 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
69 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
59 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
70
60
71 // Set qcpplot properties :
61 // Set qcpplot properties :
72 // - Drag (on x-axis) and zoom are enabled
62 // - Drag (on x-axis) and zoom are enabled
73 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
63 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
74 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
64 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
75 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
65 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
76
66
77 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
67 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
78 connect(ui->widget, &QCustomPlot::mouseRelease, this,
68 connect(ui->widget, &QCustomPlot::mouseRelease, this,
79 &VisualizationGraphWidget::onMouseRelease);
69 &VisualizationGraphWidget::onMouseRelease);
80 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
70 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
81 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
71 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
82 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
72 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
83 &QCPAxis::rangeChanged),
73 &QCPAxis::rangeChanged),
84 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
74 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
85
75
86 // Activates menu when right clicking on the graph
76 // Activates menu when right clicking on the graph
87 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
77 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
88 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
78 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
89 &VisualizationGraphWidget::onGraphMenuRequested);
79 &VisualizationGraphWidget::onGraphMenuRequested);
90
80
91 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
81 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
92 &VariableController::onRequestDataLoading);
82 &VariableController::onRequestDataLoading);
93 }
83 }
94
84
95
85
96 VisualizationGraphWidget::~VisualizationGraphWidget()
86 VisualizationGraphWidget::~VisualizationGraphWidget()
97 {
87 {
98 delete ui;
88 delete ui;
99 }
89 }
100
90
101 void VisualizationGraphWidget::enableSynchronize(bool enable)
91 void VisualizationGraphWidget::enableAcquisition(bool enable)
102 {
92 {
103 impl->m_DoSynchronize = enable;
93 impl->m_DoAcquisition = enable;
104 }
94 }
105
95
106 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
96 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
107 {
97 {
98 auto calibrationState = impl->m_IsCalibration;
99 impl->m_IsCalibration = true;
108 // Uses delegate to create the qcpplot components according to the variable
100 // Uses delegate to create the qcpplot components according to the variable
109 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
101 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
102 impl->m_IsCalibration = calibrationState;
110
103
111 for (auto createdPlottable : qAsConst(createdPlottables)) {
104 for (auto createdPlottable : qAsConst(createdPlottables)) {
112 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
105 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
113 }
106 }
114
107
115 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
108 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
109
110 emit variableAdded(variable);
116 }
111 }
117 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
112 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
118 {
113 {
119
120 // when adding a variable, we need to set its time range to the current graph range
121 auto grapheRange = ui->widget->xAxis->range();
122 auto dateTime = SqpRange{grapheRange.lower, grapheRange.upper};
123 variable->setDateTime(dateTime);
124
125 auto variableDateTimeWithTolerance = dateTime;
126
127 // add tolerance for each side
128 auto toleranceFactor
129 = toleranceValue(GENERAL_TOLERANCE_AT_INIT_KEY, GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE);
130 auto tolerance = toleranceFactor * (dateTime.m_TEnd - dateTime.m_TStart);
131 variableDateTimeWithTolerance.m_TStart -= tolerance;
132 variableDateTimeWithTolerance.m_TEnd += tolerance;
133
134 // Uses delegate to create the qcpplot components according to the variable
114 // Uses delegate to create the qcpplot components according to the variable
135 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
115 this->addVariable(variable);
136
137 for (auto createdPlottable : qAsConst(createdPlottables)) {
138 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
139 }
140
116
141 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
117 // Request range for the variable
118 auto graphRange = ui->widget->xAxis->range();
142
119
143 // CHangement detected, we need to ask controller to request data loading
120 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable,
144 emit requestDataLoading(variable, variableDateTimeWithTolerance);
121 SqpRange{graphRange.lower, graphRange.upper}, variable->range(), false);
145 }
122 }
146
123
147 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
124 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
148 {
125 {
149 // Each component associated to the variable :
126 // Each component associated to the variable :
150 // - is removed from qcpplot (which deletes it)
127 // - is removed from qcpplot (which deletes it)
151 // - is no longer referenced in the map
128 // - is no longer referenced in the map
152 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
129 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
153 for (auto it = componentsIt.first; it != componentsIt.second;) {
130 for (auto it = componentsIt.first; it != componentsIt.second;) {
154 ui->widget->removePlottable(it->second);
131 ui->widget->removePlottable(it->second);
155 it = impl->m_VariableToPlotMultiMap.erase(it);
132 it = impl->m_VariableToPlotMultiMap.erase(it);
156 }
133 }
157
134
158 // Updates graph
135 // Updates graph
159 ui->widget->replot();
136 ui->widget->replot();
160 }
137 }
161
138
162 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable, const SqpRange &range)
139 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable, const SqpRange &range)
163 {
140 {
164 // Note: in case of different axes that depends on variable, we could start with a code like
141 // Note: in case of different axes that depends on variable, we could start with a code like
165 // that:
142 // that:
166 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
143 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
167 // for (auto it = componentsIt.first; it != componentsIt.second;) {
144 // for (auto it = componentsIt.first; it != componentsIt.second;) {
168 // }
145 // }
169 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
146 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
170 ui->widget->replot();
147 ui->widget->replot();
171 }
148 }
172
149
173 SqpRange VisualizationGraphWidget::graphRange() const noexcept
150 SqpRange VisualizationGraphWidget::graphRange() const noexcept
174 {
151 {
175 auto grapheRange = ui->widget->xAxis->range();
152 auto grapheRange = ui->widget->xAxis->range();
176 return SqpRange{grapheRange.lower, grapheRange.upper};
153 return SqpRange{grapheRange.lower, grapheRange.upper};
177 }
154 }
178
155
179 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
156 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
180 {
157 {
181 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
158 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
182 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
159 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
183 ui->widget->replot();
160 ui->widget->replot();
184 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
161 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
185 }
162 }
186
163
187 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
164 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
188 {
165 {
189 if (visitor) {
166 if (visitor) {
190 visitor->visit(this);
167 visitor->visit(this);
191 }
168 }
192 else {
169 else {
193 qCCritical(LOG_VisualizationGraphWidget())
170 qCCritical(LOG_VisualizationGraphWidget())
194 << tr("Can't visit widget : the visitor is null");
171 << tr("Can't visit widget : the visitor is null");
195 }
172 }
196 }
173 }
197
174
198 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
175 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
199 {
176 {
200 /// @todo : for the moment, a graph can always accomodate a variable
177 /// @todo : for the moment, a graph can always accomodate a variable
201 Q_UNUSED(variable);
178 Q_UNUSED(variable);
202 return true;
179 return true;
203 }
180 }
204
181
205 bool VisualizationGraphWidget::contains(const Variable &variable) const
182 bool VisualizationGraphWidget::contains(const Variable &variable) const
206 {
183 {
207 // Finds the variable among the keys of the map
184 // Finds the variable among the keys of the map
208 auto variablePtr = &variable;
185 auto variablePtr = &variable;
209 auto findVariable
186 auto findVariable
210 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
187 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
211
188
212 auto end = impl->m_VariableToPlotMultiMap.cend();
189 auto end = impl->m_VariableToPlotMultiMap.cend();
213 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
190 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
214 return it != end;
191 return it != end;
215 }
192 }
216
193
217 QString VisualizationGraphWidget::name() const
194 QString VisualizationGraphWidget::name() const
218 {
195 {
219 return ui->graphNameLabel->text();
196 return ui->graphNameLabel->text();
220 }
197 }
221
198
222 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
199 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
223 {
200 {
224 QMenu graphMenu{};
201 QMenu graphMenu{};
225
202
226 // Iterates on variables (unique keys)
203 // Iterates on variables (unique keys)
227 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
204 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
228 end = impl->m_VariableToPlotMultiMap.cend();
205 end = impl->m_VariableToPlotMultiMap.cend();
229 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
206 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
230 // 'Remove variable' action
207 // 'Remove variable' action
231 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
208 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
232 [ this, var = it->first ]() { removeVariable(var); });
209 [ this, var = it->first ]() { removeVariable(var); });
233 }
210 }
234
211
235 if (!graphMenu.isEmpty()) {
212 if (!graphMenu.isEmpty()) {
236 graphMenu.exec(mapToGlobal(pos));
213 graphMenu.exec(mapToGlobal(pos));
237 }
214 }
238 }
215 }
239
216
240 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
217 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
241 {
218 {
242 qCInfo(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
219 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
243 << QThread::currentThread()->objectName();
220 << QThread::currentThread()->objectName() << "DoAcqui"
221 << impl->m_DoAcquisition;
244
222
245 auto dateTimeRange = SqpRange{t1.lower, t1.upper};
223 auto graphRange = SqpRange{t1.lower, t1.upper};
224 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
246
225
247 auto zoomType = impl->getZoomType(t1, t2);
226 if (impl->m_DoAcquisition) {
248 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
227 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
249 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
250
228
251 auto variable = it->first;
229 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
252 auto currentDateTime = dateTimeRange;
230 end = impl->m_VariableToPlotMultiMap.end();
253
231 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
254 auto toleranceFactor = toleranceValue(GENERAL_TOLERANCE_AT_UPDATE_KEY,
232 variableUnderGraphVector.push_back(it->first);
255 GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE);
256 auto tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
257 auto variableDateTimeWithTolerance = currentDateTime;
258 variableDateTimeWithTolerance.m_TStart -= tolerance;
259 variableDateTimeWithTolerance.m_TEnd += tolerance;
260
261 qCDebug(LOG_VisualizationGraphWidget()) << "r" << currentDateTime;
262 qCDebug(LOG_VisualizationGraphWidget()) << "t" << variableDateTimeWithTolerance;
263 qCDebug(LOG_VisualizationGraphWidget()) << "v" << variable->dateTime();
264 // If new range with tol is upper than variable datetime parameters. we need to request new
265 // data
266 if (!variable->contains(variableDateTimeWithTolerance)) {
267
268 auto variableDateTimeWithTolerance = currentDateTime;
269 if (!variable->isInside(currentDateTime)) {
270 auto variableDateTime = variable->dateTime();
271 if (variable->contains(variableDateTimeWithTolerance)) {
272 qCDebug(LOG_VisualizationGraphWidget())
273 << tr("TORM: Detection zoom in that need request:");
274 // add tolerance for each side
275 tolerance
276 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
277 variableDateTimeWithTolerance.m_TStart -= tolerance;
278 variableDateTimeWithTolerance.m_TEnd += tolerance;
279 }
280 else if (variableDateTime.m_TStart < currentDateTime.m_TStart) {
281 qCInfo(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to right:");
282
283 auto diffEndToKeepDelta = currentDateTime.m_TEnd - variableDateTime.m_TEnd;
284 currentDateTime.m_TStart = variableDateTime.m_TStart + diffEndToKeepDelta;
285 // Tolerance have to be added to the right
286 // add tolerance for right (end) side
287 tolerance
288 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
289 variableDateTimeWithTolerance.m_TEnd += tolerance;
290 }
291 else if (variableDateTime.m_TEnd > currentDateTime.m_TEnd) {
292 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection pan to left: ");
293 auto diffStartToKeepDelta
294 = variableDateTime.m_TStart - currentDateTime.m_TStart;
295 currentDateTime.m_TEnd = variableDateTime.m_TEnd - diffStartToKeepDelta;
296 // Tolerance have to be added to the left
297 // add tolerance for left (start) side
298 tolerance
299 = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
300 variableDateTimeWithTolerance.m_TStart -= tolerance;
301 }
302 else {
303 qCCritical(LOG_VisualizationGraphWidget())
304 << tr("Detection anormal zoom detection: ");
305 }
306 }
307 else {
308 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Detection zoom out: ");
309 // add tolerance for each side
310 tolerance = toleranceFactor * (currentDateTime.m_TEnd - currentDateTime.m_TStart);
311 variableDateTimeWithTolerance.m_TStart -= tolerance;
312 variableDateTimeWithTolerance.m_TEnd += tolerance;
313 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
314 }
315 if (!variable->contains(dateTimeRange)) {
316 qCDebug(LOG_VisualizationGraphWidget())
317 << "TORM: Modif on variable datetime detected" << currentDateTime;
318 variable->setDateTime(currentDateTime);
319 }
320
321 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: Request data detection: ");
322 // CHangement detected, we need to ask controller to request data loading
323 emit requestDataLoading(variable, variableDateTimeWithTolerance);
324 }
233 }
325 else {
234 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange, oldGraphRange,
326 qCInfo(LOG_VisualizationGraphWidget())
235 !impl->m_IsCalibration);
327 << tr("TORM: Detection zoom in that doesn't need request: ");
236
328 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
237 if (!impl->m_IsCalibration) {
238 qCDebug(LOG_VisualizationGraphWidget())
239 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
240 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
241 emit synchronize(graphRange, oldGraphRange);
329 }
242 }
330 }
243 }
331
332 if (impl->m_DoSynchronize && !impl->m_IsCalibration) {
333 auto oldDateTime = SqpRange{t2.lower, t2.upper};
334 qCDebug(LOG_VisualizationGraphWidget())
335 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
336 << QThread::currentThread()->objectName();
337 emit synchronize(dateTimeRange, oldDateTime, zoomType);
338 }
339 }
244 }
340
245
341 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
246 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
342 {
247 {
343 // Handles plot rendering when mouse is moving
248 // Handles plot rendering when mouse is moving
344 impl->m_RenderingDelegate->onMouseMove(event);
249 impl->m_RenderingDelegate->onMouseMove(event);
345 }
250 }
346
251
347 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
252 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
348 {
253 {
349 auto zoomOrientations = QFlags<Qt::Orientation>{};
254 auto zoomOrientations = QFlags<Qt::Orientation>{};
350
255
351 // Lambda that enables a zoom orientation if the key modifier related to this orientation
256 // Lambda that enables a zoom orientation if the key modifier related to this orientation
352 // has
257 // has
353 // been pressed
258 // been pressed
354 auto enableOrientation
259 auto enableOrientation
355 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
260 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
356 auto orientationEnabled = event->modifiers().testFlag(modifier);
261 auto orientationEnabled = event->modifiers().testFlag(modifier);
357 zoomOrientations.setFlag(orientation, orientationEnabled);
262 zoomOrientations.setFlag(orientation, orientationEnabled);
358 };
263 };
359 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
264 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
360 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
265 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
361
266
362 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
267 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
363 }
268 }
364
269
365 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
270 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
366 {
271 {
367 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
272 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
368 }
273 }
369
274
370 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
275 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
371 {
276 {
372 impl->m_IsCalibration = false;
277 impl->m_IsCalibration = false;
373 }
278 }
374
279
375 void VisualizationGraphWidget::onDataCacheVariableUpdated()
280 void VisualizationGraphWidget::onDataCacheVariableUpdated()
376 {
281 {
377 // NOTE:
282 // NOTE:
378 // We don't want to call the method for each component of a variable unitarily, but for
283 // We don't want to call the method for each component of a variable unitarily, but for
379 // all
284 // all
380 // its components at once (eg its three components in the case of a vector).
285 // its components at once (eg its three components in the case of a vector).
381
286
382 // The unordered_multimap does not do this easily, so the question is whether to:
287 // The unordered_multimap does not do this easily, so the question is whether to:
383 // - use an ordered_multimap and the algos of std to group the values by key
288 // - use an ordered_multimap and the algos of std to group the values by key
384 // - use a map (unique keys) and store as values directly the list of components
289 // - use a map (unique keys) and store as values directly the list of components
385
290
386 auto grapheRange = ui->widget->xAxis->range();
291 auto grapheRange = ui->widget->xAxis->range();
387 auto dateTime = SqpRange{grapheRange.lower, grapheRange.upper};
292 auto dateTime = SqpRange{grapheRange.lower, grapheRange.upper};
388
293
389 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
294 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
390 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
295 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
391 auto variable = it->first;
296 auto variable = it->first;
392 qCDebug(LOG_VisualizationGraphWidget())
297 qCDebug(LOG_VisualizationGraphWidget())
393 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S"
298 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
394 << variable->dateTime();
395 qCDebug(LOG_VisualizationGraphWidget())
299 qCDebug(LOG_VisualizationGraphWidget())
396 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
300 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
397 if (dateTime.contains(variable->dateTime()) || dateTime.intersect(variable->dateTime())) {
301 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
398
302
399 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
303 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
400 variable->dataSeries(), variable->dateTime());
304 variable->dataSeries(), variable->range());
401 }
305 }
402 }
306 }
403 }
307 }
404
405 VisualizationGraphWidgetZoomType
406 VisualizationGraphWidget::VisualizationGraphWidgetPrivate::getZoomType(const QCPRange &t1,
407 const QCPRange &t2)
408 {
409 // t1.lower <= t2.lower && t2.upper <= t1.upper
410 auto zoomType = VisualizationGraphWidgetZoomType::Unknown;
411 if (t1.lower <= t2.lower && t2.upper <= t1.upper) {
412 zoomType = VisualizationGraphWidgetZoomType::ZoomOut;
413 }
414 else if (t1.lower > t2.lower && t1.upper > t2.upper) {
415 zoomType = VisualizationGraphWidgetZoomType::PanRight;
416 }
417 else if (t1.lower < t2.lower && t1.upper < t2.upper) {
418 zoomType = VisualizationGraphWidgetZoomType::PanLeft;
419 }
420 else if (t1.lower > t2.lower && t2.upper > t1.upper) {
421 zoomType = VisualizationGraphWidgetZoomType::ZoomIn;
422 }
423 else {
424 qCCritical(LOG_VisualizationGraphWidget()) << "getZoomType: Unknown type detected";
425 }
426 return zoomType;
427 }
@@ -1,200 +1,225
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Data/SqpRange.h"
4
3
5 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/IVisualizationWidgetVisitor.h"
6 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
6 #include "ui_VisualizationZoneWidget.h"
8
7
8 #include <Data/SqpRange.h>
9 #include <Variable/VariableController.h>
9
10
11 #include <QUuid>
10 #include <SqpApplication.h>
12 #include <SqpApplication.h>
11
13
12 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
14 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
13
15
14 namespace {
16 namespace {
15
17
16 /// Minimum height for graph added in zones (in pixels)
18 /// Minimum height for graph added in zones (in pixels)
17 const auto GRAPH_MINIMUM_HEIGHT = 300;
19 const auto GRAPH_MINIMUM_HEIGHT = 300;
18
20
19 /// Generates a default name for a new graph, according to the number of graphs already displayed in
21 /// Generates a default name for a new graph, according to the number of graphs already displayed in
20 /// the zone
22 /// the zone
21 QString defaultGraphName(const QLayout &layout)
23 QString defaultGraphName(const QLayout &layout)
22 {
24 {
23 auto count = 0;
25 auto count = 0;
24 for (auto i = 0; i < layout.count(); ++i) {
26 for (auto i = 0; i < layout.count(); ++i) {
25 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
27 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
26 count++;
28 count++;
27 }
29 }
28 }
30 }
29
31
30 return QObject::tr("Graph %1").arg(count + 1);
32 return QObject::tr("Graph %1").arg(count + 1);
31 }
33 }
32
34
33 } // namespace
35 } // namespace
34
36
37 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
38
39 explicit VisualizationZoneWidgetPrivate() : m_SynchronisationGroupId{QUuid::createUuid()} {}
40 QUuid m_SynchronisationGroupId;
41 };
42
35 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
43 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
36 : QWidget{parent}, ui{new Ui::VisualizationZoneWidget}
44 : QWidget{parent},
45 ui{new Ui::VisualizationZoneWidget},
46 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
37 {
47 {
38 ui->setupUi(this);
48 ui->setupUi(this);
39
49
40 ui->zoneNameLabel->setText(name);
50 ui->zoneNameLabel->setText(name);
41
51
42 // 'Close' options : widget is deleted when closed
52 // 'Close' options : widget is deleted when closed
43 setAttribute(Qt::WA_DeleteOnClose);
53 setAttribute(Qt::WA_DeleteOnClose);
44 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
54 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
45 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
55 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
56
57 // Synchronisation id
58 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
59 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
46 }
60 }
47
61
48 VisualizationZoneWidget::~VisualizationZoneWidget()
62 VisualizationZoneWidget::~VisualizationZoneWidget()
49 {
63 {
50 delete ui;
64 delete ui;
51 }
65 }
52
66
53 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
67 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
54 {
68 {
55 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
69 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
56 }
70 }
57
71
58 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
72 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
59 {
73 {
60 auto graphWidget = new VisualizationGraphWidget{
74 auto graphWidget = new VisualizationGraphWidget{
61 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
75 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
62
76
63
77
64 // Set graph properties
78 // Set graph properties
65 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
79 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
66 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
80 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
67
81
68 this->addGraph(graphWidget);
69
70 graphWidget->addVariable(variable);
71
82
72 // Lambda to synchronize zone widget
83 // Lambda to synchronize zone widget
73 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &dateTime,
84 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &grapheRange,
74 const SqpRange &oldDateTime,
85 const SqpRange &oldGraphRange) {
75 VisualizationGraphWidgetZoomType zoomType) {
86
87 auto zoomType = VariableController::getZoomType(grapheRange, oldGraphRange);
76 auto frameLayout = ui->visualizationZoneFrame->layout();
88 auto frameLayout = ui->visualizationZoneFrame->layout();
77 for (auto i = 0; i < frameLayout->count(); ++i) {
89 for (auto i = 0; i < frameLayout->count(); ++i) {
78 auto graphChild
90 auto graphChild
79 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
91 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
80 if (graphChild && (graphChild != graphWidget)) {
92 if (graphChild && (graphChild != graphWidget)) {
81
93
82 auto graphChildRange = graphChild->graphRange();
94 auto graphChildRange = graphChild->graphRange();
83 switch (zoomType) {
95 switch (zoomType) {
84 case VisualizationGraphWidgetZoomType::ZoomIn: {
96 case AcquisitionZoomType::ZoomIn: {
85 auto deltaLeft = dateTime.m_TStart - oldDateTime.m_TStart;
97 auto deltaLeft = grapheRange.m_TStart - oldGraphRange.m_TStart;
86 auto deltaRight = oldDateTime.m_TEnd - dateTime.m_TEnd;
98 auto deltaRight = oldGraphRange.m_TEnd - grapheRange.m_TEnd;
87 graphChildRange.m_TStart += deltaLeft;
99 graphChildRange.m_TStart += deltaLeft;
88 graphChildRange.m_TEnd -= deltaRight;
100 graphChildRange.m_TEnd -= deltaRight;
89 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
101 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
90 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
102 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
91 << deltaLeft;
103 << deltaLeft;
92 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
104 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
93 << deltaRight;
105 << deltaRight;
94 qCCritical(LOG_VisualizationZoneWidget())
106 qCCritical(LOG_VisualizationZoneWidget())
95 << tr("TORM: dt") << dateTime.m_TEnd - dateTime.m_TStart;
107 << tr("TORM: dt") << grapheRange.m_TEnd - grapheRange.m_TStart;
96
108
97 break;
109 break;
98 }
110 }
99
111
100 case VisualizationGraphWidgetZoomType::ZoomOut: {
112 case AcquisitionZoomType::ZoomOut: {
101 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
113 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
102 auto deltaLeft = oldDateTime.m_TStart - dateTime.m_TStart;
114 auto deltaLeft = oldGraphRange.m_TStart - grapheRange.m_TStart;
103 auto deltaRight = dateTime.m_TEnd - oldDateTime.m_TEnd;
115 auto deltaRight = grapheRange.m_TEnd - oldGraphRange.m_TEnd;
104 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
116 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
105 << deltaLeft;
117 << deltaLeft;
106 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
118 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
107 << deltaRight;
119 << deltaRight;
108 qCCritical(LOG_VisualizationZoneWidget())
120 qCCritical(LOG_VisualizationZoneWidget())
109 << tr("TORM: dt") << dateTime.m_TEnd - dateTime.m_TStart;
121 << tr("TORM: dt") << grapheRange.m_TEnd - grapheRange.m_TStart;
110 graphChildRange.m_TStart -= deltaLeft;
122 graphChildRange.m_TStart -= deltaLeft;
111 graphChildRange.m_TEnd += deltaRight;
123 graphChildRange.m_TEnd += deltaRight;
112 break;
124 break;
113 }
125 }
114 case VisualizationGraphWidgetZoomType::PanRight: {
126 case AcquisitionZoomType::PanRight: {
115 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
127 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
116 auto deltaRight = dateTime.m_TEnd - oldDateTime.m_TEnd;
128 auto deltaRight = grapheRange.m_TEnd - oldGraphRange.m_TEnd;
117 graphChildRange.m_TStart += deltaRight;
129 graphChildRange.m_TStart += deltaRight;
118 graphChildRange.m_TEnd += deltaRight;
130 graphChildRange.m_TEnd += deltaRight;
119 qCCritical(LOG_VisualizationZoneWidget())
131 qCCritical(LOG_VisualizationZoneWidget())
120 << tr("TORM: dt") << dateTime.m_TEnd - dateTime.m_TStart;
132 << tr("TORM: dt") << grapheRange.m_TEnd - grapheRange.m_TStart;
121 break;
133 break;
122 }
134 }
123 case VisualizationGraphWidgetZoomType::PanLeft: {
135 case AcquisitionZoomType::PanLeft: {
124 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
136 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
125 auto deltaLeft = oldDateTime.m_TStart - dateTime.m_TStart;
137 auto deltaLeft = oldGraphRange.m_TStart - grapheRange.m_TStart;
126 graphChildRange.m_TStart -= deltaLeft;
138 graphChildRange.m_TStart -= deltaLeft;
127 graphChildRange.m_TEnd -= deltaLeft;
139 graphChildRange.m_TEnd -= deltaLeft;
128 break;
140 break;
129 }
141 }
130 case VisualizationGraphWidgetZoomType::Unknown: {
142 case AcquisitionZoomType::Unknown: {
131 qCCritical(LOG_VisualizationZoneWidget())
143 qCCritical(LOG_VisualizationZoneWidget())
132 << tr("Impossible to synchronize: zoom type unknown");
144 << tr("Impossible to synchronize: zoom type unknown");
133 break;
145 break;
134 }
146 }
135 default:
147 default:
136 qCCritical(LOG_VisualizationZoneWidget())
148 qCCritical(LOG_VisualizationZoneWidget())
137 << tr("Impossible to synchronize: zoom type not take into account");
149 << tr("Impossible to synchronize: zoom type not take into account");
138 // No action
150 // No action
139 break;
151 break;
140 }
152 }
141 graphChild->enableSynchronize(false);
153 graphChild->enableAcquisition(false);
142 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
154 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
143 << graphChild->graphRange();
155 << graphChild->graphRange();
144 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
156 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
145 << graphChildRange;
157 << graphChildRange;
146 qCCritical(LOG_VisualizationZoneWidget())
158 qCCritical(LOG_VisualizationZoneWidget())
147 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
159 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
148 graphChild->setGraphRange(graphChildRange);
160 graphChild->setGraphRange(graphChildRange);
149 graphChild->enableSynchronize(true);
161 graphChild->enableAcquisition(true);
150 }
162 }
151 }
163 }
152 };
164 };
153
165
154 // connection for synchronization
166 // connection for synchronization
155 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
167 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
168 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
169 &VisualizationZoneWidget::onVariableAdded);
170
171 this->addGraph(graphWidget);
172
173 graphWidget->addVariable(variable);
156
174
157 return graphWidget;
175 return graphWidget;
158 }
176 }
159
177
160 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
178 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
161 {
179 {
162 if (visitor) {
180 if (visitor) {
163 visitor->visitEnter(this);
181 visitor->visitEnter(this);
164
182
165 // Apply visitor to graph children
183 // Apply visitor to graph children
166 auto layout = ui->visualizationZoneFrame->layout();
184 auto layout = ui->visualizationZoneFrame->layout();
167 for (auto i = 0; i < layout->count(); ++i) {
185 for (auto i = 0; i < layout->count(); ++i) {
168 if (auto item = layout->itemAt(i)) {
186 if (auto item = layout->itemAt(i)) {
169 // Widgets different from graphs are not visited (no action)
187 // Widgets different from graphs are not visited (no action)
170 if (auto visualizationGraphWidget
188 if (auto visualizationGraphWidget
171 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
189 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
172 visualizationGraphWidget->accept(visitor);
190 visualizationGraphWidget->accept(visitor);
173 }
191 }
174 }
192 }
175 }
193 }
176
194
177 visitor->visitLeave(this);
195 visitor->visitLeave(this);
178 }
196 }
179 else {
197 else {
180 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
198 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
181 }
199 }
182 }
200 }
183
201
184 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
202 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
185 {
203 {
186 // A tab can always accomodate a variable
204 // A tab can always accomodate a variable
187 Q_UNUSED(variable);
205 Q_UNUSED(variable);
188 return true;
206 return true;
189 }
207 }
190
208
191 bool VisualizationZoneWidget::contains(const Variable &variable) const
209 bool VisualizationZoneWidget::contains(const Variable &variable) const
192 {
210 {
193 Q_UNUSED(variable);
211 Q_UNUSED(variable);
194 return false;
212 return false;
195 }
213 }
196
214
197 QString VisualizationZoneWidget::name() const
215 QString VisualizationZoneWidget::name() const
198 {
216 {
199 return ui->zoneNameLabel->text();
217 return ui->zoneNameLabel->text();
200 }
218 }
219
220 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
221 {
222 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
223 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
224 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
225 }
@@ -1,60 +1,57
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>VisualizationTabWidget</class>
3 <class>VisualizationTabWidget</class>
4 <widget class="QWidget" name="VisualizationTabWidget">
4 <widget class="QWidget" name="VisualizationTabWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>400</width>
9 <width>400</width>
10 <height>300</height>
10 <height>300</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout">
16 <layout class="QVBoxLayout" name="verticalLayout">
17 <property name="leftMargin">
17 <property name="leftMargin">
18 <number>0</number>
18 <number>0</number>
19 </property>
19 </property>
20 <property name="topMargin">
20 <property name="topMargin">
21 <number>0</number>
21 <number>0</number>
22 </property>
22 </property>
23 <property name="rightMargin">
23 <property name="rightMargin">
24 <number>0</number>
24 <number>0</number>
25 </property>
25 </property>
26 <property name="bottomMargin">
26 <property name="bottomMargin">
27 <number>0</number>
27 <number>0</number>
28 </property>
28 </property>
29 <item>
29 <item>
30 <widget class="QScrollArea" name="scrollArea">
30 <widget class="QScrollArea" name="scrollArea">
31 <property name="styleSheet">
32 <string notr="true">background-color: transparent;</string>
33 </property>
34 <property name="frameShape">
31 <property name="frameShape">
35 <enum>QFrame::NoFrame</enum>
32 <enum>QFrame::NoFrame</enum>
36 </property>
33 </property>
37 <property name="frameShadow">
34 <property name="frameShadow">
38 <enum>QFrame::Sunken</enum>
35 <enum>QFrame::Sunken</enum>
39 </property>
36 </property>
40 <property name="widgetResizable">
37 <property name="widgetResizable">
41 <bool>true</bool>
38 <bool>true</bool>
42 </property>
39 </property>
43 <widget class="QWidget" name="scrollAreaWidgetContents">
40 <widget class="QWidget" name="scrollAreaWidgetContents">
44 <property name="geometry">
41 <property name="geometry">
45 <rect>
42 <rect>
46 <x>0</x>
43 <x>0</x>
47 <y>0</y>
44 <y>0</y>
48 <width>400</width>
45 <width>400</width>
49 <height>300</height>
46 <height>300</height>
50 </rect>
47 </rect>
51 </property>
48 </property>
52 <layout class="QVBoxLayout" name="verticalLayout_3"/>
49 <layout class="QVBoxLayout" name="verticalLayout_3"/>
53 </widget>
50 </widget>
54 </widget>
51 </widget>
55 </item>
52 </item>
56 </layout>
53 </layout>
57 </widget>
54 </widget>
58 <resources/>
55 <resources/>
59 <connections/>
56 <connections/>
60 </ui>
57 </ui>
@@ -1,30 +1,30
1 #ifndef SCIQLOP_AMDAPROVIDER_H
1 #ifndef SCIQLOP_AMDAPROVIDER_H
2 #define SCIQLOP_AMDAPROVIDER_H
2 #define SCIQLOP_AMDAPROVIDER_H
3
3
4 #include "AmdaGlobal.h"
4 #include "AmdaGlobal.h"
5
5
6 #include <Data/IDataProvider.h>
6 #include <Data/IDataProvider.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9
9
10
10
11 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
12
12
13 class QNetworkReply;
13 class QNetworkReply;
14
14
15 /**
15 /**
16 * @brief The AmdaProvider class is an example of how a data provider can generate data
16 * @brief The AmdaProvider class is an example of how a data provider can generate data
17 */
17 */
18 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
18 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
19 public:
19 public:
20 explicit AmdaProvider();
20 explicit AmdaProvider();
21
21
22 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
22 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
23
23
24 void requestDataAborting(QUuid identifier) override;
24 void requestDataAborting(QUuid acqIdentifier) override;
25
25
26 private:
26 private:
27 void retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data);
27 void retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data);
28 };
28 };
29
29
30 #endif // SCIQLOP_AMDAPROVIDER_H
30 #endif // SCIQLOP_AMDAPROVIDER_H
@@ -1,148 +1,148
1 #include "AmdaProvider.h"
1 #include "AmdaProvider.h"
2 #include "AmdaDefs.h"
2 #include "AmdaDefs.h"
3 #include "AmdaResultParser.h"
3 #include "AmdaResultParser.h"
4
4
5 #include <Common/DateUtils.h>
5 #include <Common/DateUtils.h>
6 #include <Data/DataProviderParameters.h>
6 #include <Data/DataProviderParameters.h>
7 #include <Network/NetworkController.h>
7 #include <Network/NetworkController.h>
8 #include <SqpApplication.h>
8 #include <SqpApplication.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10
10
11 #include <QNetworkAccessManager>
11 #include <QNetworkAccessManager>
12 #include <QNetworkReply>
12 #include <QNetworkReply>
13 #include <QTemporaryFile>
13 #include <QTemporaryFile>
14 #include <QThread>
14 #include <QThread>
15
15
16 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
16 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
17
17
18 namespace {
18 namespace {
19
19
20 /// URL format for a request on AMDA server. The parameters are as follows:
20 /// URL format for a request on AMDA server. The parameters are as follows:
21 /// - %1: start date
21 /// - %1: start date
22 /// - %2: end date
22 /// - %2: end date
23 /// - %3: parameter id
23 /// - %3: parameter id
24 const auto AMDA_URL_FORMAT = QStringLiteral(
24 const auto AMDA_URL_FORMAT = QStringLiteral(
25 "http://amda.irap.omp.eu/php/rest/"
25 "http://amda.irap.omp.eu/php/rest/"
26 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&outputFormat=ASCII&"
26 "getParameter.php?startTime=%1&stopTime=%2&parameterID=%3&outputFormat=ASCII&"
27 "timeFormat=ISO8601&gzip=0");
27 "timeFormat=ISO8601&gzip=0");
28
28
29 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
29 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
30 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
30 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
31
31
32 /// Formats a time to a date that can be passed in URL
32 /// Formats a time to a date that can be passed in URL
33 QString dateFormat(double sqpRange) noexcept
33 QString dateFormat(double sqpRange) noexcept
34 {
34 {
35 auto dateTime = DateUtils::dateTime(sqpRange);
35 auto dateTime = DateUtils::dateTime(sqpRange);
36 return dateTime.toString(AMDA_TIME_FORMAT);
36 return dateTime.toString(AMDA_TIME_FORMAT);
37 }
37 }
38
38
39 } // namespace
39 } // namespace
40
40
41 AmdaProvider::AmdaProvider()
41 AmdaProvider::AmdaProvider()
42 {
42 {
43 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
43 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::AmdaProvider") << QThread::currentThread();
44 if (auto app = sqpApp) {
44 if (auto app = sqpApp) {
45 auto &networkController = app->networkController();
45 auto &networkController = app->networkController();
46 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
46 connect(this, SIGNAL(requestConstructed(QNetworkRequest, QUuid,
47 std::function<void(QNetworkReply *, QUuid)>)),
47 std::function<void(QNetworkReply *, QUuid)>)),
48 &networkController,
48 &networkController,
49 SLOT(onProcessRequested(QNetworkRequest, QUuid,
49 SLOT(onProcessRequested(QNetworkRequest, QUuid,
50 std::function<void(QNetworkReply *, QUuid)>)));
50 std::function<void(QNetworkReply *, QUuid)>)));
51
51
52
52
53 connect(&sqpApp->networkController(), SIGNAL(replyDownloadProgress(QUuid, double)), this,
53 connect(&sqpApp->networkController(), SIGNAL(replyDownloadProgress(QUuid, double)), this,
54 SIGNAL(dataProvidedProgress(QUuid, double)));
54 SIGNAL(dataProvidedProgress(QUuid, double)));
55 }
55 }
56 }
56 }
57
57
58 void AmdaProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
58 void AmdaProvider::requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters)
59 {
59 {
60 // NOTE: Try to use multithread if possible
60 // NOTE: Try to use multithread if possible
61 const auto times = parameters.m_Times;
61 const auto times = parameters.m_Times;
62 const auto data = parameters.m_Data;
62 const auto data = parameters.m_Data;
63 for (const auto &dateTime : qAsConst(times)) {
63 for (const auto &dateTime : qAsConst(times)) {
64 retrieveData(token, dateTime, data);
64 this->retrieveData(acqIdentifier, dateTime, data);
65 QThread::msleep(200);
65 }
66 }
66 }
67 }
67
68
68 void AmdaProvider::requestDataAborting(QUuid identifier)
69 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
69 {
70 {
70 if (auto app = sqpApp) {
71 if (auto app = sqpApp) {
71 auto &networkController = app->networkController();
72 auto &networkController = app->networkController();
72 networkController.onReplyCanceled(identifier);
73 networkController.onReplyCanceled(acqIdentifier);
73 }
74 }
74 }
75 }
75
76
76 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
77 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
77 {
78 {
78 // Retrieves product ID from data: if the value is invalid, no request is made
79 // Retrieves product ID from data: if the value is invalid, no request is made
79 auto productId = data.value(AMDA_XML_ID_KEY).toString();
80 auto productId = data.value(AMDA_XML_ID_KEY).toString();
80 if (productId.isNull()) {
81 if (productId.isNull()) {
81 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
82 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
82 return;
83 return;
83 }
84 }
84 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
85 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
85
86
86 // /////////// //
87 // /////////// //
87 // Creates URL //
88 // Creates URL //
88 // /////////// //
89 // /////////// //
89
90
90 auto startDate = dateFormat(dateTime.m_TStart);
91 auto startDate = dateFormat(dateTime.m_TStart);
91 auto endDate = dateFormat(dateTime.m_TEnd);
92 auto endDate = dateFormat(dateTime.m_TEnd);
92
93
93 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
94 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
94 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData url:") << url;
95 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData url:") << url;
95 auto tempFile = std::make_shared<QTemporaryFile>();
96 auto tempFile = std::make_shared<QTemporaryFile>();
96
97
97 // LAMBDA
98 // LAMBDA
98 auto httpDownloadFinished
99 auto httpDownloadFinished
99 = [this, dateTime, tempFile, token](QNetworkReply *reply, QUuid dataId) noexcept {
100 = [this, dateTime, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
100 Q_UNUSED(dataId);
101
101
102 // Don't do anything if the reply was abort
102 // Don't do anything if the reply was abort
103 if (reply->error() != QNetworkReply::OperationCanceledError) {
103 if (reply->error() != QNetworkReply::OperationCanceledError) {
104
104
105 if (tempFile) {
105 if (tempFile) {
106 auto replyReadAll = reply->readAll();
106 auto replyReadAll = reply->readAll();
107 if (!replyReadAll.isEmpty()) {
107 if (!replyReadAll.isEmpty()) {
108 tempFile->write(replyReadAll);
108 tempFile->write(replyReadAll);
109 }
109 }
110 tempFile->close();
110 tempFile->close();
111
111
112 // Parse results file
112 // Parse results file
113 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
113 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
114 emit dataProvided(token, dataSeries, dateTime);
114 emit dataProvided(dataId, dataSeries, dateTime);
115 }
115 }
116 else {
116 else {
117 /// @todo ALX : debug
117 /// @todo ALX : debug
118 }
118 }
119 }
119 }
120 }
120 }
121
121
122 };
122 };
123 auto httpFinishedLambda
123 auto httpFinishedLambda
124 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
124 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
125
125
126 // Don't do anything if the reply was abort
126 // Don't do anything if the reply was abort
127 if (reply->error() != QNetworkReply::OperationCanceledError) {
127 if (reply->error() != QNetworkReply::OperationCanceledError) {
128 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
128 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
129
129
130
130
131 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData downloadFileUrl:")
131 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData downloadFileUrl:")
132 << downloadFileUrl;
132 << downloadFileUrl;
133 // Executes request for downloading file //
133 // Executes request for downloading file //
134
134
135 // Creates destination file
135 // Creates destination file
136 if (tempFile->open()) {
136 if (tempFile->open()) {
137 // Executes request
137 // Executes request
138 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId,
138 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId,
139 httpDownloadFinished);
139 httpDownloadFinished);
140 }
140 }
141 }
141 }
142 };
142 };
143
143
144 // //////////////// //
144 // //////////////// //
145 // Executes request //
145 // Executes request //
146 // //////////////// //
146 // //////////////// //
147 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
147 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
148 }
148 }
@@ -1,33 +1,34
1 #ifndef SCIQLOP_COSINUSPROVIDER_H
1 #ifndef SCIQLOP_COSINUSPROVIDER_H
2 #define SCIQLOP_COSINUSPROVIDER_H
2 #define SCIQLOP_COSINUSPROVIDER_H
3
3
4 #include "MockPluginGlobal.h"
4 #include "MockPluginGlobal.h"
5
5
6 #include <Data/IDataProvider.h>
6 #include <Data/IDataProvider.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QUuid>
9 #include <QUuid>
10
10
11 #include <QHash>
11 #include <QHash>
12 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_CosinusProvider)
13
13
14 /**
14 /**
15 * @brief The CosinusProvider class is an example of how a data provider can generate data
15 * @brief The CosinusProvider class is an example of how a data provider can generate data
16 */
16 */
17 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
17 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
18 public:
18 public:
19 /// @sa IDataProvider::requestDataLoading(). The current impl isn't thread safe.
19 /// @sa IDataProvider::requestDataLoading(). The current impl isn't thread safe.
20 void requestDataLoading(QUuid token, const DataProviderParameters &parameters) override;
20 void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters &parameters) override;
21
21
22
22
23 /// @sa IDataProvider::requestDataAborting(). The current impl isn't thread safe.
23 /// @sa IDataProvider::requestDataAborting(). The current impl isn't thread safe.
24 void requestDataAborting(QUuid identifier) override;
24 void requestDataAborting(QUuid acqIdentifier) override;
25
25
26
26
27 private:
27 private:
28 std::shared_ptr<IDataSeries> retrieveData(QUuid token, const SqpRange &dateTime);
28 std::shared_ptr<IDataSeries> retrieveData(QUuid acqIdentifier,
29 const SqpRange &dataRangeRequested);
29
30
30 QHash<QUuid, bool> m_VariableToEnableProvider;
31 QHash<QUuid, bool> m_VariableToEnableProvider;
31 };
32 };
32
33
33 #endif // SCIQLOP_COSINUSPROVIDER_H
34 #endif // SCIQLOP_COSINUSPROVIDER_H
@@ -1,100 +1,103
1 #include "CosinusProvider.h"
1 #include "CosinusProvider.h"
2
2
3 #include <Data/DataProviderParameters.h>
3 #include <Data/DataProviderParameters.h>
4 #include <Data/ScalarSeries.h>
4 #include <Data/ScalarSeries.h>
5
5
6 #include <cmath>
6 #include <cmath>
7
7
8 #include <QFuture>
8 #include <QFuture>
9 #include <QThread>
9 #include <QThread>
10 #include <QtConcurrent/QtConcurrent>
10 #include <QtConcurrent/QtConcurrent>
11
11
12 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
12 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
13
13
14 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid token, const SqpRange &dateTime)
14 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid acqIdentifier,
15 const SqpRange &dataRangeRequested)
15 {
16 {
16 // TODO: Add Mutex
17 // TODO: Add Mutex
17 auto dataIndex = 0;
18 auto dataIndex = 0;
18
19
19 // Gets the timerange from the parameters
20 // Gets the timerange from the parameters
20 double freq = 100.0;
21 double freq = 100.0;
21 double start = std::ceil(dateTime.m_TStart * freq); // 100 htz
22 double start = std::ceil(dataRangeRequested.m_TStart * freq); // 100 htz
22 double end = std::floor(dateTime.m_TEnd * freq); // 100 htz
23 double end = std::floor(dataRangeRequested.m_TEnd * freq); // 100 htz
23
24
24 // We assure that timerange is valid
25 // We assure that timerange is valid
25 if (end < start) {
26 if (end < start) {
26 std::swap(start, end);
27 std::swap(start, end);
27 }
28 }
28
29
29 // Generates scalar series containing cosinus values (one value per second)
30 // Generates scalar series containing cosinus values (one value per second)
30 auto dataCount = end - start;
31 auto dataCount = end - start;
31
32
32 auto xAxisData = QVector<double>{};
33 auto xAxisData = QVector<double>{};
33 xAxisData.resize(dataCount);
34 xAxisData.resize(dataCount);
34
35
35 auto valuesData = QVector<double>{};
36 auto valuesData = QVector<double>{};
36 valuesData.resize(dataCount);
37 valuesData.resize(dataCount);
37
38
38 int progress = 0;
39 int progress = 0;
39 auto progressEnd = dataCount;
40 auto progressEnd = dataCount;
40 for (auto time = start; time < end; ++time, ++dataIndex) {
41 for (auto time = start; time < end; ++time, ++dataIndex) {
41 auto it = m_VariableToEnableProvider.find(token);
42 auto it = m_VariableToEnableProvider.find(acqIdentifier);
42 if (it != m_VariableToEnableProvider.end() && it.value()) {
43 if (it != m_VariableToEnableProvider.end() && it.value()) {
43 const auto timeOnFreq = time / freq;
44 const auto timeOnFreq = time / freq;
44
45
45 xAxisData.replace(dataIndex, timeOnFreq);
46 xAxisData.replace(dataIndex, timeOnFreq);
46 valuesData.replace(dataIndex, std::cos(timeOnFreq));
47 valuesData.replace(dataIndex, std::cos(timeOnFreq));
47
48
48 // progression
49 // progression
49 int currentProgress = (time - start) * 100.0 / progressEnd;
50 int currentProgress = (time - start) * 100.0 / progressEnd;
50 if (currentProgress != progress) {
51 if (currentProgress != progress) {
51 progress = currentProgress;
52 progress = currentProgress;
52
53
53 emit dataProvidedProgress(token, progress);
54 emit dataProvidedProgress(acqIdentifier, progress);
54 }
55 }
55 }
56 }
56 else {
57 else {
57 if (!it.value()) {
58 if (!it.value()) {
58 qCDebug(LOG_CosinusProvider())
59 qCDebug(LOG_CosinusProvider())
59 << "CosinusProvider::retrieveData: ARRET De l'acquisition detecté"
60 << "CosinusProvider::retrieveData: ARRET De l'acquisition detecté"
60 << end - time;
61 << end - time;
61 }
62 }
62 }
63 }
63 }
64 }
64 emit dataProvidedProgress(token, 0.0);
65 emit dataProvidedProgress(acqIdentifier, 0.0);
65
66
66 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
67 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
67 Unit{QStringLiteral("t"), true}, Unit{});
68 Unit{QStringLiteral("t"), true}, Unit{});
68 }
69 }
69
70
70 void CosinusProvider::requestDataLoading(QUuid token, const DataProviderParameters &parameters)
71 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
72 const DataProviderParameters &parameters)
71 {
73 {
72 // TODO: Add Mutex
74 // TODO: Add Mutex
73 m_VariableToEnableProvider[token] = true;
75 m_VariableToEnableProvider[acqIdentifier] = true;
74 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
76 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
75 << QThread::currentThread()->objectName();
77 << QThread::currentThread()->objectName();
76 // NOTE: Try to use multithread if possible
78 // NOTE: Try to use multithread if possible
77 const auto times = parameters.m_Times;
79 const auto times = parameters.m_Times;
78
80
79 for (const auto &dateTime : qAsConst(times)) {
81 for (const auto &dateTime : qAsConst(times)) {
80 if (m_VariableToEnableProvider[token]) {
82 if (m_VariableToEnableProvider[acqIdentifier]) {
81 auto scalarSeries = this->retrieveData(token, dateTime);
83 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime);
82 emit dataProvided(token, scalarSeries, dateTime);
84 qCCritical(LOG_CosinusProvider()) << "CosinusProvider::dataProvided";
85 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
83 }
86 }
84 }
87 }
85 }
88 }
86
89
87 void CosinusProvider::requestDataAborting(QUuid identifier)
90 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
88 {
91 {
89 // TODO: Add Mutex
92 // TODO: Add Mutex
90 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << identifier
93 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
91 << QThread::currentThread()->objectName();
94 << QThread::currentThread()->objectName();
92 auto it = m_VariableToEnableProvider.find(identifier);
95 auto it = m_VariableToEnableProvider.find(acqIdentifier);
93 if (it != m_VariableToEnableProvider.end()) {
96 if (it != m_VariableToEnableProvider.end()) {
94 it.value() = false;
97 it.value() = false;
95 }
98 }
96 else {
99 else {
97 qCWarning(LOG_CosinusProvider())
100 qCWarning(LOG_CosinusProvider())
98 << tr("Aborting progression of inexistant identifier detected !!!");
101 << tr("Aborting progression of inexistant identifier detected !!!");
99 }
102 }
100 }
103 }
General Comments 0
You need to be logged in to leave comments. Login now