##// END OF EJS Templates
Merge pull request 223 from SCIQLOP-Initialisation develop...
leroux -
r549:d2d58fbc7625 merge
parent child
Show More
@@ -1,225 +1,225
1 #include "Variable/VariableAcquisitionWorker.h"
1 #include "Variable/VariableAcquisitionWorker.h"
2
2
3 #include "Variable/Variable.h"
3 #include "Variable/Variable.h"
4
4
5 #include <Data/AcquisitionRequest.h>
5 #include <Data/AcquisitionRequest.h>
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <unordered_map>
8 #include <unordered_map>
9 #include <utility>
9 #include <utility>
10
10
11 #include <QMutex>
11 #include <QMutex>
12 #include <QReadWriteLock>
12 #include <QReadWriteLock>
13 #include <QThread>
13 #include <QThread>
14
14
15 Q_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker, "VariableAcquisitionWorker")
15 Q_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker, "VariableAcquisitionWorker")
16
16
17 struct VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate {
17 struct VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate {
18
18
19 explicit VariableAcquisitionWorkerPrivate() : m_Lock{QReadWriteLock::Recursive} {}
19 explicit VariableAcquisitionWorkerPrivate() : m_Lock{QReadWriteLock::Recursive} {}
20
20
21 void lockRead() { m_Lock.lockForRead(); }
21 void lockRead() { m_Lock.lockForRead(); }
22 void lockWrite() { m_Lock.lockForWrite(); }
22 void lockWrite() { m_Lock.lockForWrite(); }
23 void unlock() { m_Lock.unlock(); }
23 void unlock() { m_Lock.unlock(); }
24
24
25 void removeVariableRequest(QUuid vIdentifier);
25 void removeVariableRequest(QUuid vIdentifier);
26
26
27 QMutex m_WorkingMutex;
27 QMutex m_WorkingMutex;
28 QReadWriteLock m_Lock;
28 QReadWriteLock m_Lock;
29
29
30 std::map<QUuid, QVector<AcquisitionDataPacket> > m_AcqIdentifierToAcqDataPacketVectorMap;
30 std::map<QUuid, QVector<AcquisitionDataPacket> > m_AcqIdentifierToAcqDataPacketVectorMap;
31 std::map<QUuid, AcquisitionRequest> m_AcqIdentifierToAcqRequestMap;
31 std::map<QUuid, AcquisitionRequest> m_AcqIdentifierToAcqRequestMap;
32 std::map<QUuid, std::pair<QUuid, QUuid> > m_VIdentifierToCurrrentAcqIdNextIdPairMap;
32 std::map<QUuid, std::pair<QUuid, QUuid> > m_VIdentifierToCurrrentAcqIdNextIdPairMap;
33 };
33 };
34
34
35
35
36 VariableAcquisitionWorker::VariableAcquisitionWorker(QObject *parent)
36 VariableAcquisitionWorker::VariableAcquisitionWorker(QObject *parent)
37 : QObject{parent}, impl{spimpl::make_unique_impl<VariableAcquisitionWorkerPrivate>()}
37 : QObject{parent}, impl{spimpl::make_unique_impl<VariableAcquisitionWorkerPrivate>()}
38 {
38 {
39 }
39 }
40
40
41 VariableAcquisitionWorker::~VariableAcquisitionWorker()
41 VariableAcquisitionWorker::~VariableAcquisitionWorker()
42 {
42 {
43 qCInfo(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker destruction")
43 qCInfo(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker destruction")
44 << QThread::currentThread();
44 << QThread::currentThread();
45 this->waitForFinish();
45 this->waitForFinish();
46 }
46 }
47
47
48
48
49 void VariableAcquisitionWorker::pushVariableRequest(QUuid vIdentifier, SqpRange rangeRequested,
49 void VariableAcquisitionWorker::pushVariableRequest(QUuid vIdentifier, SqpRange rangeRequested,
50 SqpRange cacheRangeRequested,
50 SqpRange cacheRangeRequested,
51 DataProviderParameters parameters,
51 DataProviderParameters parameters,
52 std::shared_ptr<IDataProvider> provider)
52 std::shared_ptr<IDataProvider> provider)
53 {
53 {
54 qCInfo(LOG_VariableAcquisitionWorker())
54 qCInfo(LOG_VariableAcquisitionWorker())
55 << tr("TORM VariableAcquisitionWorker::pushVariableRequest ") << cacheRangeRequested;
55 << tr("TORM VariableAcquisitionWorker::pushVariableRequest ") << cacheRangeRequested;
56
56
57 // Request creation
57 // Request creation
58 auto acqRequest = AcquisitionRequest{};
58 auto acqRequest = AcquisitionRequest{};
59 acqRequest.m_vIdentifier = vIdentifier;
59 acqRequest.m_vIdentifier = vIdentifier;
60 acqRequest.m_DataProviderParameters = parameters;
60 acqRequest.m_DataProviderParameters = parameters;
61 acqRequest.m_RangeRequested = rangeRequested;
61 acqRequest.m_RangeRequested = rangeRequested;
62 acqRequest.m_CacheRangeRequested = cacheRangeRequested;
62 acqRequest.m_CacheRangeRequested = cacheRangeRequested;
63 acqRequest.m_Size = parameters.m_Times.size();
63 acqRequest.m_Size = parameters.m_Times.size();
64 acqRequest.m_Provider = provider;
64 acqRequest.m_Provider = provider;
65
65
66 // Register request
66 // Register request
67 impl->lockWrite();
67 impl->lockWrite();
68 impl->m_AcqIdentifierToAcqRequestMap.insert(
68 impl->m_AcqIdentifierToAcqRequestMap.insert(
69 std::make_pair(acqRequest.m_AcqIdentifier, acqRequest));
69 std::make_pair(acqRequest.m_AcqIdentifier, acqRequest));
70
70
71 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
71 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
72 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
72 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
73 // A current request already exists, we can replace the next one
73 // A current request already exists, we can replace the next one
74 it->second.second = acqRequest.m_AcqIdentifier;
74 it->second.second = acqRequest.m_AcqIdentifier;
75 impl->unlock();
75 impl->unlock();
76 }
76 }
77 else {
77 else {
78 // First request for the variable, it must be stored and executed
78 // First request for the variable, it must be stored and executed
79 impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.insert(
79 impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.insert(
80 std::make_pair(vIdentifier, std::make_pair(acqRequest.m_AcqIdentifier, QUuid())));
80 std::make_pair(vIdentifier, std::make_pair(acqRequest.m_AcqIdentifier, QUuid())));
81 impl->unlock();
81 impl->unlock();
82
82
83 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
83 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
84 Q_ARG(QUuid, acqRequest.m_AcqIdentifier));
84 Q_ARG(QUuid, acqRequest.m_AcqIdentifier));
85 }
85 }
86 }
86 }
87
87
88 void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier)
88 void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier)
89 {
89 {
90 // TODO
90 // TODO
91 }
91 }
92
92
93 void VariableAcquisitionWorker::onVariableRetrieveDataInProgress(QUuid acqIdentifier,
93 void VariableAcquisitionWorker::onVariableRetrieveDataInProgress(QUuid acqIdentifier,
94 double progress)
94 double progress)
95 {
95 {
96 // TODO
96 // TODO
97 }
97 }
98
98
99 void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier,
99 void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier,
100 std::shared_ptr<IDataSeries> dataSeries,
100 std::shared_ptr<IDataSeries> dataSeries,
101 SqpRange dataRangeAcquired)
101 SqpRange dataRangeAcquired)
102 {
102 {
103 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onVariableDataAcquired on range ")
103 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onVariableDataAcquired on range ")
104 << acqIdentifier << dataRangeAcquired;
104 << acqIdentifier << dataRangeAcquired;
105 impl->lockWrite();
105 impl->lockWrite();
106 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
106 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
107 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
107 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
108 // Store the result
108 // Store the result
109 auto dataPacket = AcquisitionDataPacket{};
109 auto dataPacket = AcquisitionDataPacket{};
110 dataPacket.m_Range = dataRangeAcquired;
110 dataPacket.m_Range = dataRangeAcquired;
111 dataPacket.m_DateSeries = dataSeries;
111 dataPacket.m_DateSeries = dataSeries;
112
112
113 auto aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
113 auto aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
114 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
114 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
115 // A current request result already exists, we can update it
115 // A current request result already exists, we can update it
116 aIdToADPVit->second.push_back(dataPacket);
116 aIdToADPVit->second.push_back(dataPacket);
117 }
117 }
118 else {
118 else {
119 // First request result for the variable, it must be stored
119 // First request result for the variable, it must be stored
120 impl->m_AcqIdentifierToAcqDataPacketVectorMap.insert(
120 impl->m_AcqIdentifierToAcqDataPacketVectorMap.insert(
121 std::make_pair(acqIdentifier, QVector<AcquisitionDataPacket>() << dataPacket));
121 std::make_pair(acqIdentifier, QVector<AcquisitionDataPacket>() << dataPacket));
122 }
122 }
123
123
124
124
125 // Decrement the counter of the request
125 // Decrement the counter of the request
126 auto &acqRequest = aIdToARit->second;
126 auto &acqRequest = aIdToARit->second;
127 acqRequest.m_Size = acqRequest.m_Size - 1;
127 acqRequest.m_Size = acqRequest.m_Size - 1;
128
128
129 // if the counter is 0, we can return data then run the next request if it exists and
129 // if the counter is 0, we can return data then run the next request if it exists and
130 // removed the finished request
130 // removed the finished request
131 if (acqRequest.m_Size == 0) {
131 if (acqRequest.m_Size == 0) {
132 // Return the data
132 // Return the data
133 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
133 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
134 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
134 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
135 emit dataProvided(acqRequest.m_vIdentifier, acqRequest.m_RangeRequested,
135 emit dataProvided(acqRequest.m_vIdentifier, acqRequest.m_RangeRequested,
136 acqRequest.m_CacheRangeRequested, aIdToADPVit->second);
136 acqRequest.m_CacheRangeRequested, aIdToADPVit->second);
137 }
137 }
138
138
139 // Execute the next one
139 // Execute the next one
140 auto it
140 auto it
141 = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(acqRequest.m_vIdentifier);
141 = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(acqRequest.m_vIdentifier);
142
142
143 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
143 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
144 if (it->second.second.isNull()) {
144 if (it->second.second.isNull()) {
145 // There is no next request, we can remove the varibale request
145 // There is no next request, we can remove the variable request
146 impl->removeVariableRequest(acqRequest.m_vIdentifier);
146 impl->removeVariableRequest(acqRequest.m_vIdentifier);
147 }
147 }
148 else {
148 else {
149 auto acqIdentifierToRemove = it->second.first;
149 auto acqIdentifierToRemove = it->second.first;
150 // Move the next request to the current request
150 // Move the next request to the current request
151 it->second.first = it->second.second;
151 it->second.first = it->second.second;
152 it->second.second = QUuid();
152 it->second.second = QUuid();
153 // Remove AcquisitionRequest and results;
153 // Remove AcquisitionRequest and results;
154 impl->m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
154 impl->m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
155 impl->m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
155 impl->m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
156 // Execute the current request
156 // Execute the current request
157 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
157 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
158 Q_ARG(QUuid, it->second.first));
158 Q_ARG(QUuid, it->second.first));
159 }
159 }
160 }
160 }
161 else {
161 else {
162 qCCritical(LOG_VariableAcquisitionWorker())
162 qCCritical(LOG_VariableAcquisitionWorker())
163 << tr("Impossible to execute the acquisition on an unfound variable ");
163 << tr("Impossible to execute the acquisition on an unfound variable ");
164 }
164 }
165 }
165 }
166 }
166 }
167 else {
167 else {
168 qCCritical(LOG_VariableAcquisitionWorker())
168 qCCritical(LOG_VariableAcquisitionWorker())
169 << tr("Impossible to retrieve AcquisitionRequest for the incoming data");
169 << tr("Impossible to retrieve AcquisitionRequest for the incoming data");
170 }
170 }
171 impl->unlock();
171 impl->unlock();
172 }
172 }
173
173
174 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
174 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
175 {
175 {
176 qCInfo(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread();
176 qCInfo(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread();
177 impl->lockRead();
177 impl->lockRead();
178 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
178 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
179 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
179 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
180 auto request = it->second;
180 auto request = it->second;
181 impl->unlock();
181 impl->unlock();
182 request.m_Provider->requestDataLoading(acqIdentifier, request.m_DataProviderParameters);
182 request.m_Provider->requestDataLoading(acqIdentifier, request.m_DataProviderParameters);
183 }
183 }
184 else {
184 else {
185 impl->unlock();
185 impl->unlock();
186 // TODO log no acqIdentifier recognized
186 // TODO log no acqIdentifier recognized
187 }
187 }
188 }
188 }
189
189
190 void VariableAcquisitionWorker::initialize()
190 void VariableAcquisitionWorker::initialize()
191 {
191 {
192 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init")
192 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init")
193 << QThread::currentThread();
193 << QThread::currentThread();
194 impl->m_WorkingMutex.lock();
194 impl->m_WorkingMutex.lock();
195 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init END");
195 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init END");
196 }
196 }
197
197
198 void VariableAcquisitionWorker::finalize()
198 void VariableAcquisitionWorker::finalize()
199 {
199 {
200 impl->m_WorkingMutex.unlock();
200 impl->m_WorkingMutex.unlock();
201 }
201 }
202
202
203 void VariableAcquisitionWorker::waitForFinish()
203 void VariableAcquisitionWorker::waitForFinish()
204 {
204 {
205 QMutexLocker locker{&impl->m_WorkingMutex};
205 QMutexLocker locker{&impl->m_WorkingMutex};
206 }
206 }
207
207
208 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariableRequest(
208 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariableRequest(
209 QUuid vIdentifier)
209 QUuid vIdentifier)
210 {
210 {
211 lockWrite();
211 lockWrite();
212 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
212 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
213
213
214 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
214 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
215 // A current request already exists, we can replace the next one
215 // A current request already exists, we can replace the next one
216
216
217 m_AcqIdentifierToAcqRequestMap.erase(it->second.first);
217 m_AcqIdentifierToAcqRequestMap.erase(it->second.first);
218 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.first);
218 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.first);
219
219
220 m_AcqIdentifierToAcqRequestMap.erase(it->second.second);
220 m_AcqIdentifierToAcqRequestMap.erase(it->second.second);
221 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.second);
221 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.second);
222 }
222 }
223 m_VIdentifierToCurrrentAcqIdNextIdPairMap.erase(vIdentifier);
223 m_VIdentifierToCurrrentAcqIdNextIdPairMap.erase(vIdentifier);
224 unlock();
224 unlock();
225 }
225 }
@@ -1,543 +1,541
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableAcquisitionWorker.h>
2 #include <Variable/VariableAcquisitionWorker.h>
3 #include <Variable/VariableCacheController.h>
3 #include <Variable/VariableCacheController.h>
4 #include <Variable/VariableCacheStrategy.h>
4 #include <Variable/VariableCacheStrategy.h>
5 #include <Variable/VariableController.h>
5 #include <Variable/VariableController.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7 #include <Variable/VariableSynchronizationGroup.h>
7 #include <Variable/VariableSynchronizationGroup.h>
8
8
9 #include <Data/DataProviderParameters.h>
9 #include <Data/DataProviderParameters.h>
10 #include <Data/IDataProvider.h>
10 #include <Data/IDataProvider.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <Time/TimeController.h>
12 #include <Time/TimeController.h>
13
13
14 #include <QMutex>
14 #include <QMutex>
15 #include <QThread>
15 #include <QThread>
16 #include <QUuid>
16 #include <QUuid>
17 #include <QtCore/QItemSelectionModel>
17 #include <QtCore/QItemSelectionModel>
18
18
19 #include <set>
19 #include <set>
20 #include <unordered_map>
20 #include <unordered_map>
21
21
22 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
22 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
23
23
24 namespace {
24 namespace {
25
25
26 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &grapheRange,
26 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
27 const SqpRange &oldGraphRange)
27 const SqpRange &oldGraphRange)
28 {
28 {
29 auto zoomType = VariableController::getZoomType(grapheRange, oldGraphRange);
29 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
30
30
31 auto varRangeRequested = varRange;
31 auto varRangeRequested = varRange;
32 switch (zoomType) {
32 switch (zoomType) {
33 case AcquisitionZoomType::ZoomIn: {
33 case AcquisitionZoomType::ZoomIn: {
34 auto deltaLeft = grapheRange.m_TStart - oldGraphRange.m_TStart;
34 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
35 auto deltaRight = oldGraphRange.m_TEnd - grapheRange.m_TEnd;
35 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
36 varRangeRequested.m_TStart += deltaLeft;
36 varRangeRequested.m_TStart += deltaLeft;
37 varRangeRequested.m_TEnd -= deltaRight;
37 varRangeRequested.m_TEnd -= deltaRight;
38 break;
38 break;
39 }
39 }
40
40
41 case AcquisitionZoomType::ZoomOut: {
41 case AcquisitionZoomType::ZoomOut: {
42 auto deltaLeft = oldGraphRange.m_TStart - grapheRange.m_TStart;
42 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
43 auto deltaRight = grapheRange.m_TEnd - oldGraphRange.m_TEnd;
43 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
44 varRangeRequested.m_TStart -= deltaLeft;
44 varRangeRequested.m_TStart -= deltaLeft;
45 varRangeRequested.m_TEnd += deltaRight;
45 varRangeRequested.m_TEnd += deltaRight;
46 break;
46 break;
47 }
47 }
48 case AcquisitionZoomType::PanRight: {
48 case AcquisitionZoomType::PanRight: {
49 auto deltaRight = grapheRange.m_TEnd - oldGraphRange.m_TEnd;
49 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
50 varRangeRequested.m_TStart += deltaRight;
50 varRangeRequested.m_TStart += deltaRight;
51 varRangeRequested.m_TEnd += deltaRight;
51 varRangeRequested.m_TEnd += deltaRight;
52 break;
52 break;
53 }
53 }
54 case AcquisitionZoomType::PanLeft: {
54 case AcquisitionZoomType::PanLeft: {
55 auto deltaLeft = oldGraphRange.m_TStart - grapheRange.m_TStart;
55 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
56 varRangeRequested.m_TStart -= deltaLeft;
56 varRangeRequested.m_TStart -= deltaLeft;
57 varRangeRequested.m_TEnd -= deltaLeft;
57 varRangeRequested.m_TEnd -= deltaLeft;
58 break;
58 break;
59 }
59 }
60 case AcquisitionZoomType::Unknown: {
60 case AcquisitionZoomType::Unknown: {
61 qCCritical(LOG_VariableController())
61 qCCritical(LOG_VariableController())
62 << VariableController::tr("Impossible to synchronize: zoom type unknown");
62 << VariableController::tr("Impossible to synchronize: zoom type unknown");
63 break;
63 break;
64 }
64 }
65 default:
65 default:
66 qCCritical(LOG_VariableController()) << VariableController::tr(
66 qCCritical(LOG_VariableController()) << VariableController::tr(
67 "Impossible to synchronize: zoom type not take into account");
67 "Impossible to synchronize: zoom type not take into account");
68 // No action
68 // No action
69 break;
69 break;
70 }
70 }
71
71
72 return varRangeRequested;
72 return varRangeRequested;
73 }
73 }
74 }
74 }
75
75
76 struct VariableController::VariableControllerPrivate {
76 struct VariableController::VariableControllerPrivate {
77 explicit VariableControllerPrivate(VariableController *parent)
77 explicit VariableControllerPrivate(VariableController *parent)
78 : m_WorkingMutex{},
78 : m_WorkingMutex{},
79 m_VariableModel{new VariableModel{parent}},
79 m_VariableModel{new VariableModel{parent}},
80 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
80 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
81 m_VariableCacheController{std::make_unique<VariableCacheController>()},
81 m_VariableCacheController{std::make_unique<VariableCacheController>()},
82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
82 m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()}
83 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()}
84 {
84 {
85
85
86 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
86 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
87 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
87 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
88 }
88 }
89
89
90
90
91 virtual ~VariableControllerPrivate()
91 virtual ~VariableControllerPrivate()
92 {
92 {
93 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
93 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
94 m_VariableAcquisitionWorkerThread.quit();
94 m_VariableAcquisitionWorkerThread.quit();
95 m_VariableAcquisitionWorkerThread.wait();
95 m_VariableAcquisitionWorkerThread.wait();
96 }
96 }
97
97
98
98
99 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested);
99 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested);
100
100
101 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
101 QVector<SqpRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
102 const SqpRange &dateTime);
102 const SqpRange &dateTime);
103
103
104 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
104 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
105 std::shared_ptr<IDataSeries>
105 std::shared_ptr<IDataSeries>
106 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
106 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
107
107
108 void registerProvider(std::shared_ptr<IDataProvider> provider);
108 void registerProvider(std::shared_ptr<IDataProvider> provider);
109
109
110 QMutex m_WorkingMutex;
110 QMutex m_WorkingMutex;
111 /// Variable model. The VariableController has the ownership
111 /// Variable model. The VariableController has the ownership
112 VariableModel *m_VariableModel;
112 VariableModel *m_VariableModel;
113 QItemSelectionModel *m_VariableSelectionModel;
113 QItemSelectionModel *m_VariableSelectionModel;
114
114
115
115
116 TimeController *m_TimeController{nullptr};
116 TimeController *m_TimeController{nullptr};
117 std::unique_ptr<VariableCacheController> m_VariableCacheController;
117 std::unique_ptr<VariableCacheController> m_VariableCacheController;
118 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
118 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
119 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
119 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
120 QThread m_VariableAcquisitionWorkerThread;
120 QThread m_VariableAcquisitionWorkerThread;
121
121
122 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
122 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
123 m_VariableToProviderMap;
123 m_VariableToProviderMap;
124 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
124 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
125 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
125 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
126 m_GroupIdToVariableSynchronizationGroupMap;
126 m_GroupIdToVariableSynchronizationGroupMap;
127 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
127 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
128 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
128 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
129 };
129 };
130
130
131
131
132 VariableController::VariableController(QObject *parent)
132 VariableController::VariableController(QObject *parent)
133 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
133 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
134 {
134 {
135 qCDebug(LOG_VariableController()) << tr("VariableController construction")
135 qCDebug(LOG_VariableController()) << tr("VariableController construction")
136 << QThread::currentThread();
136 << QThread::currentThread();
137
137
138 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
138 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
139 &VariableController::onAbortProgressRequested);
139 &VariableController::onAbortProgressRequested);
140
140
141 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
141 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
142 &VariableController::onDataProvided);
142 &VariableController::onDataProvided);
143 connect(impl->m_VariableAcquisitionWorker.get(),
143 connect(impl->m_VariableAcquisitionWorker.get(),
144 &VariableAcquisitionWorker::variableRequestInProgress, this,
144 &VariableAcquisitionWorker::variableRequestInProgress, this,
145 &VariableController::onVariableRetrieveDataInProgress);
145 &VariableController::onVariableRetrieveDataInProgress);
146
146
147 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
147 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
148 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
148 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
149 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
149 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
150 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
150 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
151
151
152
152
153 impl->m_VariableAcquisitionWorkerThread.start();
153 impl->m_VariableAcquisitionWorkerThread.start();
154 }
154 }
155
155
156 VariableController::~VariableController()
156 VariableController::~VariableController()
157 {
157 {
158 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
158 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
159 << QThread::currentThread();
159 << QThread::currentThread();
160 this->waitForFinish();
160 this->waitForFinish();
161 }
161 }
162
162
163 VariableModel *VariableController::variableModel() noexcept
163 VariableModel *VariableController::variableModel() noexcept
164 {
164 {
165 return impl->m_VariableModel;
165 return impl->m_VariableModel;
166 }
166 }
167
167
168 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
168 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
169 {
169 {
170 return impl->m_VariableSelectionModel;
170 return impl->m_VariableSelectionModel;
171 }
171 }
172
172
173 void VariableController::setTimeController(TimeController *timeController) noexcept
173 void VariableController::setTimeController(TimeController *timeController) noexcept
174 {
174 {
175 impl->m_TimeController = timeController;
175 impl->m_TimeController = timeController;
176 }
176 }
177
177
178 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
178 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
179 {
179 {
180 if (!variable) {
180 if (!variable) {
181 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
181 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
182 return;
182 return;
183 }
183 }
184
184
185 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
185 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
186 // make some treatments before the deletion
186 // make some treatments before the deletion
187 emit variableAboutToBeDeleted(variable);
187 emit variableAboutToBeDeleted(variable);
188
188
189 // Deletes identifier
189 // Deletes identifier
190 impl->m_VariableToIdentifierMap.erase(variable);
190 impl->m_VariableToIdentifierMap.erase(variable);
191
191
192 // Deletes provider
192 // Deletes provider
193 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
193 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
194 qCDebug(LOG_VariableController())
194 qCDebug(LOG_VariableController())
195 << tr("Number of providers deleted for variable %1: %2")
195 << tr("Number of providers deleted for variable %1: %2")
196 .arg(variable->name(), QString::number(nbProvidersDeleted));
196 .arg(variable->name(), QString::number(nbProvidersDeleted));
197
197
198 // Clears cache
198 // Clears cache
199 impl->m_VariableCacheController->clear(variable);
199 impl->m_VariableCacheController->clear(variable);
200
200
201 // Deletes from model
201 // Deletes from model
202 impl->m_VariableModel->deleteVariable(variable);
202 impl->m_VariableModel->deleteVariable(variable);
203 }
203 }
204
204
205 void VariableController::deleteVariables(
205 void VariableController::deleteVariables(
206 const QVector<std::shared_ptr<Variable> > &variables) noexcept
206 const QVector<std::shared_ptr<Variable> > &variables) noexcept
207 {
207 {
208 for (auto variable : qAsConst(variables)) {
208 for (auto variable : qAsConst(variables)) {
209 deleteVariable(variable);
209 deleteVariable(variable);
210 }
210 }
211 }
211 }
212
212
213 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
213 void VariableController::abortProgress(std::shared_ptr<Variable> variable)
214 {
214 {
215 }
215 }
216
216
217 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
217 void VariableController::createVariable(const QString &name, const QVariantHash &metadata,
218 std::shared_ptr<IDataProvider> provider) noexcept
218 std::shared_ptr<IDataProvider> provider) noexcept
219 {
219 {
220
220
221 if (!impl->m_TimeController) {
221 if (!impl->m_TimeController) {
222 qCCritical(LOG_VariableController())
222 qCCritical(LOG_VariableController())
223 << tr("Impossible to create variable: The time controller is null");
223 << tr("Impossible to create variable: The time controller is null");
224 return;
224 return;
225 }
225 }
226
226
227 auto range = impl->m_TimeController->dateTime();
227 auto range = impl->m_TimeController->dateTime();
228
228
229 if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) {
229 if (auto newVariable = impl->m_VariableModel->createVariable(name, range, metadata)) {
230 auto identifier = QUuid::createUuid();
230 auto identifier = QUuid::createUuid();
231
231
232 // store the provider
232 // store the provider
233 impl->registerProvider(provider);
233 impl->registerProvider(provider);
234
234
235 // Associate the provider
235 // Associate the provider
236 impl->m_VariableToProviderMap[newVariable] = provider;
236 impl->m_VariableToProviderMap[newVariable] = provider;
237 impl->m_VariableToIdentifierMap[newVariable] = identifier;
237 impl->m_VariableToIdentifierMap[newVariable] = identifier;
238
238
239
239
240 impl->processRequest(newVariable, range);
240 impl->processRequest(newVariable, range);
241 }
241 }
242 }
242 }
243
243
244 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
244 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
245 {
245 {
246 // TODO check synchronisation
246 // TODO check synchronisation
247 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
247 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
248 << QThread::currentThread()->objectName();
248 << QThread::currentThread()->objectName();
249 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
249 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
250
250
251 for (const auto &selectedRow : qAsConst(selectedRows)) {
251 for (const auto &selectedRow : qAsConst(selectedRows)) {
252 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
252 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
253 selectedVariable->setRange(dateTime);
253 selectedVariable->setRange(dateTime);
254 impl->processRequest(selectedVariable, dateTime);
254 impl->processRequest(selectedVariable, dateTime);
255
255
256 // notify that rescale operation has to be done
256 // notify that rescale operation has to be done
257 emit rangeChanged(selectedVariable, dateTime);
257 emit rangeChanged(selectedVariable, dateTime);
258 }
258 }
259 }
259 }
260 }
260 }
261
261
262 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
262 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
263 const SqpRange &cacheRangeRequested,
263 const SqpRange &cacheRangeRequested,
264 QVector<AcquisitionDataPacket> dataAcquired)
264 QVector<AcquisitionDataPacket> dataAcquired)
265 {
265 {
266 auto var = impl->findVariable(vIdentifier);
266 if (auto var = impl->findVariable(vIdentifier)) {
267 if (var != nullptr) {
268 var->setRange(rangeRequested);
267 var->setRange(rangeRequested);
269 var->setCacheRange(cacheRangeRequested);
268 var->setCacheRange(cacheRangeRequested);
270 qCDebug(LOG_VariableController()) << tr("1: onDataProvided") << rangeRequested;
269 qCDebug(LOG_VariableController()) << tr("1: onDataProvided") << rangeRequested;
271 qCDebug(LOG_VariableController()) << tr("2: onDataProvided") << cacheRangeRequested;
270 qCDebug(LOG_VariableController()) << tr("2: onDataProvided") << cacheRangeRequested;
272
271
273 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
272 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
274 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
273 qCDebug(LOG_VariableController()) << tr("3: onDataProvided")
275 << retrievedDataSeries->range();
274 << retrievedDataSeries->range();
276 var->mergeDataSeries(retrievedDataSeries);
275 var->mergeDataSeries(retrievedDataSeries);
277 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
276 qCDebug(LOG_VariableController()) << tr("4: onDataProvided");
278 emit var->updated();
277 emit var->updated();
279 }
278 }
280 else {
279 else {
281 qCCritical(LOG_VariableController()) << tr("Impossible to provide data to a null variable");
280 qCCritical(LOG_VariableController()) << tr("Impossible to provide data to a null variable");
282 }
281 }
283 }
282 }
284
283
285 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
284 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
286 {
285 {
287 auto var = impl->findVariable(identifier);
286 if (auto var = impl->findVariable(identifier)) {
288 if (var != nullptr) {
289 impl->m_VariableModel->setDataProgress(var, progress);
287 impl->m_VariableModel->setDataProgress(var, progress);
290 }
288 }
291 else {
289 else {
292 qCCritical(LOG_VariableController())
290 qCCritical(LOG_VariableController())
293 << tr("Impossible to notify progression of a null variable");
291 << tr("Impossible to notify progression of a null variable");
294 }
292 }
295 }
293 }
296
294
297 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
295 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
298 {
296 {
299 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
297 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAbortProgressRequested"
300 << QThread::currentThread()->objectName();
298 << QThread::currentThread()->objectName();
301
299
302 auto it = impl->m_VariableToIdentifierMap.find(variable);
300 auto it = impl->m_VariableToIdentifierMap.find(variable);
303 if (it != impl->m_VariableToIdentifierMap.cend()) {
301 if (it != impl->m_VariableToIdentifierMap.cend()) {
304 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
302 impl->m_VariableToProviderMap.at(variable)->requestDataAborting(it->second);
305 }
303 }
306 else {
304 else {
307 qCWarning(LOG_VariableController())
305 qCWarning(LOG_VariableController())
308 << tr("Aborting progression of inexistant variable detected !!!")
306 << tr("Aborting progression of inexistant variable detected !!!")
309 << QThread::currentThread()->objectName();
307 << QThread::currentThread()->objectName();
310 }
308 }
311 }
309 }
312
310
313 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
311 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
314 {
312 {
315 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
313 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
316 << QThread::currentThread()->objectName()
314 << QThread::currentThread()->objectName()
317 << synchronizationGroupId;
315 << synchronizationGroupId;
318 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
316 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
319 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
317 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
320 std::make_pair(synchronizationGroupId, vSynchroGroup));
318 std::make_pair(synchronizationGroupId, vSynchroGroup));
321 }
319 }
322
320
323 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
321 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
324 {
322 {
325 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
323 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
326 }
324 }
327
325
328 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
326 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
329 QUuid synchronizationGroupId)
327 QUuid synchronizationGroupId)
330
328
331 {
329 {
332 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
330 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
333 << synchronizationGroupId;
331 << synchronizationGroupId;
334 auto vToVIdit = impl->m_VariableToIdentifierMap.find(variable);
332 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
335 if (vToVIdit != impl->m_VariableToIdentifierMap.cend()) {
333 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
336 auto itSynchroGroup
334 auto groupIdToVSGIt
337 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
335 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
338 if (itSynchroGroup != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
336 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
339 impl->m_VariableIdGroupIdMap.insert(
337 impl->m_VariableIdGroupIdMap.insert(
340 std::make_pair(vToVIdit->second, synchronizationGroupId));
338 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
341 itSynchroGroup->second->addVariableId(vToVIdit->second);
339 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
342 }
340 }
343 else {
341 else {
344 qCCritical(LOG_VariableController())
342 qCCritical(LOG_VariableController())
345 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
343 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
346 << variable->name();
344 << variable->name();
347 }
345 }
348 }
346 }
349 else {
347 else {
350 qCCritical(LOG_VariableController())
348 qCCritical(LOG_VariableController())
351 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
349 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
352 }
350 }
353 }
351 }
354
352
355
353
356 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
354 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
357 const SqpRange &range, const SqpRange &oldRange,
355 const SqpRange &range, const SqpRange &oldRange,
358 bool synchronise)
356 bool synchronise)
359 {
357 {
360 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
358 // NOTE: oldRange isn't really necessary since oldRange == variable->range().
361
359
362 qCInfo(LOG_VariableController()) << "VariableController::onRequestDataLoading"
360 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
363 << QThread::currentThread()->objectName();
361 << QThread::currentThread()->objectName();
364 // we want to load data of the variable for the dateTime.
362 // we want to load data of the variable for the dateTime.
365 // First we check if the cache contains some of them.
363 // First we check if the cache contains some of them.
366 // For the other, we ask the provider to give them.
364 // For the other, we ask the provider to give them.
367
365
368 foreach (auto var, variables) {
366 for (const auto &var : variables) {
369 qCDebug(LOG_VariableController()) << "processRequest for" << var->name();
367 qCDebug(LOG_VariableController()) << "processRequest for" << var->name();
370 impl->processRequest(var, range);
368 impl->processRequest(var, range);
371 }
369 }
372
370
373 if (synchronise) {
371 if (synchronise) {
374 // Get the group ids
372 // Get the group ids
375 qCDebug(LOG_VariableController())
373 qCDebug(LOG_VariableController())
376 << "VariableController::onRequestDataLoading for synchro var ENABLE";
374 << "TORM VariableController::onRequestDataLoading for synchro var ENABLE";
377 auto groupIds = std::set<QUuid>();
375 auto groupIds = std::set<QUuid>();
378 foreach (auto var, variables) {
376 for (const auto &var : variables) {
379 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
377 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(var);
380 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
378 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
381 auto vId = varToVarIdIt->second;
379 auto vId = varToVarIdIt->second;
382 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
380 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
383 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
381 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
384 auto gId = varIdToGroupIdIt->second;
382 auto gId = varIdToGroupIdIt->second;
385 if (groupIds.find(gId) == groupIds.cend()) {
383 if (groupIds.find(gId) == groupIds.cend()) {
386 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
384 qCDebug(LOG_VariableController()) << "Synchro detect group " << gId;
387 groupIds.insert(gId);
385 groupIds.insert(gId);
388 }
386 }
389 }
387 }
390 }
388 }
391 }
389 }
392
390
393 // We assume here all group ids exist
391 // We assume here all group ids exist
394 foreach (auto gId, groupIds) {
392 for (const auto &gId : groupIds) {
395 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
393 auto vSynchronizationGroup = impl->m_GroupIdToVariableSynchronizationGroupMap.at(gId);
396 auto vSyncIds = vSynchronizationGroup->getIds();
394 auto vSyncIds = vSynchronizationGroup->getIds();
397 qCDebug(LOG_VariableController()) << "Var in synchro group ";
395 qCDebug(LOG_VariableController()) << "Var in synchro group ";
398 for (auto vId : vSyncIds) {
396 for (auto vId : vSyncIds) {
399 auto var = impl->findVariable(vId);
397 auto var = impl->findVariable(vId);
400
398
401 // Don't process already processed var
399 // Don't process already processed var
402 if (!variables.contains(var)) {
400 if (!variables.contains(var)) {
403 if (var != nullptr) {
401 if (var != nullptr) {
404 qCDebug(LOG_VariableController()) << "processRequest synchro for"
402 qCDebug(LOG_VariableController()) << "processRequest synchro for"
405 << var->name();
403 << var->name();
406 auto vSyncRangeRequested
404 auto vSyncRangeRequested
407 = computeSynchroRangeRequested(var->range(), range, oldRange);
405 = computeSynchroRangeRequested(var->range(), range, oldRange);
408 impl->processRequest(var, vSyncRangeRequested);
406 impl->processRequest(var, vSyncRangeRequested);
409 }
407 }
410 else {
408 else {
411 qCCritical(LOG_VariableController())
409 qCCritical(LOG_VariableController())
412
410
413 << tr("Impossible to synchronize a null variable");
411 << tr("Impossible to synchronize a null variable");
414 }
412 }
415 }
413 }
416 }
414 }
417 }
415 }
418 }
416 }
419 }
417 }
420
418
421
419
422 void VariableController::initialize()
420 void VariableController::initialize()
423 {
421 {
424 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
422 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
425 impl->m_WorkingMutex.lock();
423 impl->m_WorkingMutex.lock();
426 qCDebug(LOG_VariableController()) << tr("VariableController init END");
424 qCDebug(LOG_VariableController()) << tr("VariableController init END");
427 }
425 }
428
426
429 void VariableController::finalize()
427 void VariableController::finalize()
430 {
428 {
431 impl->m_WorkingMutex.unlock();
429 impl->m_WorkingMutex.unlock();
432 }
430 }
433
431
434 void VariableController::waitForFinish()
432 void VariableController::waitForFinish()
435 {
433 {
436 QMutexLocker locker{&impl->m_WorkingMutex};
434 QMutexLocker locker{&impl->m_WorkingMutex};
437 }
435 }
438
436
439 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
437 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
440 {
438 {
441 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
439 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
442 auto zoomType = AcquisitionZoomType::Unknown;
440 auto zoomType = AcquisitionZoomType::Unknown;
443 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
441 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
444 zoomType = AcquisitionZoomType::ZoomOut;
442 zoomType = AcquisitionZoomType::ZoomOut;
445 }
443 }
446 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
444 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
447 zoomType = AcquisitionZoomType::PanRight;
445 zoomType = AcquisitionZoomType::PanRight;
448 }
446 }
449 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
447 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
450 zoomType = AcquisitionZoomType::PanLeft;
448 zoomType = AcquisitionZoomType::PanLeft;
451 }
449 }
452 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
450 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
453 zoomType = AcquisitionZoomType::ZoomIn;
451 zoomType = AcquisitionZoomType::ZoomIn;
454 }
452 }
455 else {
453 else {
456 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
454 qCCritical(LOG_VariableController()) << "getZoomType: Unknown type detected";
457 }
455 }
458 return zoomType;
456 return zoomType;
459 }
457 }
460
458
461 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
459 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
462 const SqpRange &rangeRequested)
460 const SqpRange &rangeRequested)
463 {
461 {
464
462
465 auto varRangesRequested
463 auto varRangesRequested
466 = m_VariableCacheStrategy->computeCacheRange(var->range(), rangeRequested);
464 = m_VariableCacheStrategy->computeCacheRange(var->range(), rangeRequested);
467 auto notInCacheRangeList = var->provideNotInCacheRangeList(varRangesRequested.second);
465 auto notInCacheRangeList = var->provideNotInCacheRangeList(varRangesRequested.second);
468
466
469 if (!notInCacheRangeList.empty()) {
467 if (!notInCacheRangeList.empty()) {
470 auto identifier = m_VariableToIdentifierMap.at(var);
468 auto identifier = m_VariableToIdentifierMap.at(var);
471 auto varProvider = m_VariableToProviderMap.at(var);
469 auto varProvider = m_VariableToProviderMap.at(var);
472 if (varProvider != nullptr) {
470 if (varProvider != nullptr) {
473 m_VariableAcquisitionWorker->pushVariableRequest(
471 m_VariableAcquisitionWorker->pushVariableRequest(
474 identifier, varRangesRequested.first, varRangesRequested.second,
472 identifier, varRangesRequested.first, varRangesRequested.second,
475 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
473 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
476 varProvider);
474 varProvider);
477 }
475 }
478 else {
476 else {
479 qCCritical(LOG_VariableController())
477 qCCritical(LOG_VariableController())
480 << "Impossible to provide data with a null provider";
478 << "Impossible to provide data with a null provider";
481 }
479 }
482 }
480 }
483 else {
481 else {
484 var->setRange(rangeRequested);
482 var->setRange(rangeRequested);
485 var->setCacheRange(varRangesRequested.second);
483 var->setCacheRange(varRangesRequested.second);
486 var->setDataSeries(var->dataSeries()->subData(varRangesRequested.second));
484 var->setDataSeries(var->dataSeries()->subData(varRangesRequested.second));
487 emit var->updated();
485 emit var->updated();
488 }
486 }
489 }
487 }
490
488
491 std::shared_ptr<Variable>
489 std::shared_ptr<Variable>
492 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
490 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
493 {
491 {
494 std::shared_ptr<Variable> var;
492 std::shared_ptr<Variable> var;
495 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
493 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
496
494
497 auto end = m_VariableToIdentifierMap.cend();
495 auto end = m_VariableToIdentifierMap.cend();
498 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
496 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
499 if (it != end) {
497 if (it != end) {
500 var = it->first;
498 var = it->first;
501 }
499 }
502 else {
500 else {
503 qCCritical(LOG_VariableController())
501 qCCritical(LOG_VariableController())
504 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
502 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
505 }
503 }
506
504
507 return var;
505 return var;
508 }
506 }
509
507
510 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
508 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
511 const QVector<AcquisitionDataPacket> acqDataPacketVector)
509 const QVector<AcquisitionDataPacket> acqDataPacketVector)
512 {
510 {
513 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
511 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
514 << acqDataPacketVector.size();
512 << acqDataPacketVector.size();
515 std::shared_ptr<IDataSeries> dataSeries;
513 std::shared_ptr<IDataSeries> dataSeries;
516 if (!acqDataPacketVector.isEmpty()) {
514 if (!acqDataPacketVector.isEmpty()) {
517 dataSeries = acqDataPacketVector[0].m_DateSeries;
515 dataSeries = acqDataPacketVector[0].m_DateSeries;
518 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
516 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
519 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
517 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
520 }
518 }
521 }
519 }
522 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
520 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
523 << acqDataPacketVector.size();
521 << acqDataPacketVector.size();
524 return dataSeries;
522 return dataSeries;
525 }
523 }
526
524
527 void VariableController::VariableControllerPrivate::registerProvider(
525 void VariableController::VariableControllerPrivate::registerProvider(
528 std::shared_ptr<IDataProvider> provider)
526 std::shared_ptr<IDataProvider> provider)
529 {
527 {
530 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
528 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
531 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
529 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
532 << provider->objectName();
530 << provider->objectName();
533 m_ProviderSet.insert(provider);
531 m_ProviderSet.insert(provider);
534 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
532 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
535 &VariableAcquisitionWorker::onVariableDataAcquired);
533 &VariableAcquisitionWorker::onVariableDataAcquired);
536 connect(provider.get(), &IDataProvider::dataProvidedProgress,
534 connect(provider.get(), &IDataProvider::dataProvidedProgress,
537 m_VariableAcquisitionWorker.get(),
535 m_VariableAcquisitionWorker.get(),
538 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
536 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
539 }
537 }
540 else {
538 else {
541 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
539 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
542 }
540 }
543 }
541 }
@@ -1,38 +1,40
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 static QVector<QCPAbstractPlottable *> createV2(std::shared_ptr<Variable> variable,
34 QCustomPlot &plot) noexcept;
33
35
34 static void updateData(QVector<QCPAbstractPlottable *> plotableVect,
36 static void updateData(QVector<QCPAbstractPlottable *> plotableVect,
35 std::shared_ptr<IDataSeries> dataSeries, const SqpRange &dateTime);
37 std::shared_ptr<IDataSeries> dataSeries, const SqpRange &dateTime);
36 };
38 };
37
39
38 #endif // SCIQLOP_VISUALIZATIONGRAPHHELPER_H
40 #endif // SCIQLOP_VISUALIZATIONGRAPHHELPER_H
@@ -1,83 +1,84
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 namespace Ui {
19 namespace Ui {
20 class VisualizationGraphWidget;
20 class VisualizationGraphWidget;
21 } // namespace Ui
21 } // namespace Ui
22
22
23 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
23 class VisualizationGraphWidget : public QWidget, public IVisualizationWidget {
24 Q_OBJECT
24 Q_OBJECT
25
25
26 public:
26 public:
27 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
27 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
28 virtual ~VisualizationGraphWidget();
28 virtual ~VisualizationGraphWidget();
29
29
30 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
30 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
31 void enableAcquisition(bool enable);
31 void enableAcquisition(bool enable);
32
32
33 void addVariable(std::shared_ptr<Variable> variable);
33 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
34 void addVariableUsingGraph(std::shared_ptr<Variable> variable);
34
35 /// Removes a variable from the graph
35 /// Removes a variable from the graph
36 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
36 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
37
37
38 void setRange(std::shared_ptr<Variable> variable, const SqpRange &range);
38 void setRange(std::shared_ptr<Variable> variable, const SqpRange &range);
39 void setYRange(const SqpRange &range);
39 SqpRange graphRange() const noexcept;
40 SqpRange graphRange() const noexcept;
40 void setGraphRange(const SqpRange &range);
41 void setGraphRange(const SqpRange &range);
41
42
42 // IVisualizationWidget interface
43 // IVisualizationWidget interface
43 void accept(IVisualizationWidgetVisitor *visitor) override;
44 void accept(IVisualizationWidgetVisitor *visitor) override;
44 bool canDrop(const Variable &variable) const override;
45 bool canDrop(const Variable &variable) const override;
45 bool contains(const Variable &variable) const override;
46 bool contains(const Variable &variable) const override;
46 QString name() const override;
47 QString name() const override;
47
48
48
49
49 signals:
50 signals:
50 void synchronize(const SqpRange &range, const SqpRange &oldRange);
51 void synchronize(const SqpRange &range, const SqpRange &oldRange);
51 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
52 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
52 const SqpRange &oldRange, bool synchronise);
53 const SqpRange &oldRange, bool synchronise);
53
54
54
55
55 void variableAdded(std::shared_ptr<Variable> var);
56 void variableAdded(std::shared_ptr<Variable> var);
56
57
57
58
58 private:
59 private:
59 Ui::VisualizationGraphWidget *ui;
60 Ui::VisualizationGraphWidget *ui;
60
61
61 class VisualizationGraphWidgetPrivate;
62 class VisualizationGraphWidgetPrivate;
62 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
63 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
63
64
64 private slots:
65 private slots:
65 /// Slot called when right clicking on the graph (displays a menu)
66 /// Slot called when right clicking on the graph (displays a menu)
66 void onGraphMenuRequested(const QPoint &pos) noexcept;
67 void onGraphMenuRequested(const QPoint &pos) noexcept;
67
68
68 /// Rescale the X axe to range parameter
69 /// Rescale the X axe to range parameter
69 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
70 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
70
71
71 /// Slot called when a mouse move was made
72 /// Slot called when a mouse move was made
72 void onMouseMove(QMouseEvent *event) noexcept;
73 void onMouseMove(QMouseEvent *event) noexcept;
73 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
74 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
74 void onMouseWheel(QWheelEvent *event) noexcept;
75 void onMouseWheel(QWheelEvent *event) noexcept;
75 /// Slot called when a mouse press was made, to activate the calibration of a graph
76 /// Slot called when a mouse press was made, to activate the calibration of a graph
76 void onMousePress(QMouseEvent *event) noexcept;
77 void onMousePress(QMouseEvent *event) noexcept;
77 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
78 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
78 void onMouseRelease(QMouseEvent *event) noexcept;
79 void onMouseRelease(QMouseEvent *event) noexcept;
79
80
80 void onDataCacheVariableUpdated();
81 void onDataCacheVariableUpdated();
81 };
82 };
82
83
83 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
84 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,163 +1,210
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, std::shared_ptr<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()) << "TODEBUG: 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()) << "TODEBUG: 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 *createScalarSeriesComponentV2(std::shared_ptr<ScalarSeries> scalarSeries,
83 QCustomPlot &plot)
84 {
85 auto component = plot.addGraph();
86
87 if (component) {
88 // Axes properties
89 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
90 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
91
92 auto setAxisProperties = [](auto axis, const auto &unit) {
93 // label (unit name)
94 axis->setLabel(unit.m_Name);
95
96 // ticker (depending on the type of unit)
97 axis->setTicker(axisTicker(unit.m_TimeUnit));
98 };
99 setAxisProperties(plot.xAxis, scalarSeries->xAxisUnit());
100 setAxisProperties(plot.yAxis, scalarSeries->valuesUnit());
101 }
102 return component;
103 }
104
82 QCPAbstractPlottable *createScalarSeriesComponent(std::shared_ptr<ScalarSeries> scalarSeries,
105 QCPAbstractPlottable *createScalarSeriesComponent(std::shared_ptr<ScalarSeries> scalarSeries,
83 QCustomPlot &plot, const SqpRange &dateTime)
106 QCustomPlot &plot, const SqpRange &dateTime)
84 {
107 {
85 auto component = plot.addGraph();
108 auto component = plot.addGraph();
86
109
87 if (component) {
110 if (component) {
88 // // Graph data
111 // // Graph data
89 component->setData(scalarSeries->xAxisData()->data(), scalarSeries->valuesData()->data(),
112 component->setData(scalarSeries->xAxisData()->data(), scalarSeries->valuesData()->data(),
90 true);
113 true);
91
114
92 updateScalarData(component, scalarSeries, dateTime);
115 updateScalarData(component, scalarSeries, dateTime);
93
116
94 // Axes properties
117 // Axes properties
95 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
118 /// @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
119 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
97
120
98 auto setAxisProperties = [](auto axis, const auto &unit) {
121 auto setAxisProperties = [](auto axis, const auto &unit) {
99 // label (unit name)
122 // label (unit name)
100 axis->setLabel(unit.m_Name);
123 axis->setLabel(unit.m_Name);
101
124
102 // ticker (depending on the type of unit)
125 // ticker (depending on the type of unit)
103 axis->setTicker(axisTicker(unit.m_TimeUnit));
126 axis->setTicker(axisTicker(unit.m_TimeUnit));
104 };
127 };
105 setAxisProperties(plot.xAxis, scalarSeries->xAxisUnit());
128 setAxisProperties(plot.xAxis, scalarSeries->xAxisUnit());
106 setAxisProperties(plot.yAxis, scalarSeries->valuesUnit());
129 setAxisProperties(plot.yAxis, scalarSeries->valuesUnit());
107
130
108 // Display all data
131 // Display all data
109 component->rescaleAxes();
132 component->rescaleAxes();
110 plot.replot();
133 plot.replot();
111 }
134 }
112 else {
135 else {
113 qCDebug(LOG_VisualizationGraphHelper())
136 qCDebug(LOG_VisualizationGraphHelper())
114 << QObject::tr("Can't create graph for the scalar series");
137 << QObject::tr("Can't create graph for the scalar series");
115 }
138 }
116
139
117 return component;
140 return component;
118 }
141 }
119
142
120 } // namespace
143 } // namespace
121
144
145 QVector<QCPAbstractPlottable *>
146 VisualizationGraphHelper::createV2(std::shared_ptr<Variable> variable, QCustomPlot &plot) noexcept
147 {
148 auto result = QVector<QCPAbstractPlottable *>{};
149
150 if (variable) {
151 // Gets the data series of the variable to call the creation of the right components
152 // according to its type
153 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(variable->dataSeries())) {
154 result.append(createScalarSeriesComponentV2(scalarSeries, plot));
155 }
156 else {
157 qCDebug(LOG_VisualizationGraphHelper())
158 << QObject::tr("Can't create graph plottables : unmanaged data series type");
159 }
160 }
161 else {
162 qCDebug(LOG_VisualizationGraphHelper())
163 << QObject::tr("Can't create graph plottables : the variable is null");
164 }
165
166 return result;
167 }
168
122 QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
169 QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
123 QCustomPlot &plot) noexcept
170 QCustomPlot &plot) noexcept
124 {
171 {
125 auto result = QVector<QCPAbstractPlottable *>{};
172 auto result = QVector<QCPAbstractPlottable *>{};
126
173
127 if (variable) {
174 if (variable) {
128 // Gets the data series of the variable to call the creation of the right components
175 // Gets the data series of the variable to call the creation of the right components
129 // according to its type
176 // according to its type
130 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(variable->dataSeries())) {
177 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(variable->dataSeries())) {
131 result.append(createScalarSeriesComponent(scalarSeries, plot, variable->range()));
178 result.append(createScalarSeriesComponent(scalarSeries, plot, variable->range()));
132 }
179 }
133 else {
180 else {
134 qCDebug(LOG_VisualizationGraphHelper())
181 qCDebug(LOG_VisualizationGraphHelper())
135 << QObject::tr("Can't create graph plottables : unmanaged data series type");
182 << QObject::tr("Can't create graph plottables : unmanaged data series type");
136 }
183 }
137 }
184 }
138 else {
185 else {
139 qCDebug(LOG_VisualizationGraphHelper())
186 qCDebug(LOG_VisualizationGraphHelper())
140 << QObject::tr("Can't create graph plottables : the variable is null");
187 << QObject::tr("Can't create graph plottables : the variable is null");
141 }
188 }
142
189
143 return result;
190 return result;
144 }
191 }
145
192
146 void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect,
193 void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect,
147 std::shared_ptr<IDataSeries> dataSeries,
194 std::shared_ptr<IDataSeries> dataSeries,
148 const SqpRange &dateTime)
195 const SqpRange &dateTime)
149 {
196 {
150 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
197 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
151 if (plotableVect.size() == 1) {
198 if (plotableVect.size() == 1) {
152 updateScalarData(plotableVect.at(0), scalarSeries, dateTime);
199 updateScalarData(plotableVect.at(0), scalarSeries, dateTime);
153 }
200 }
154 else {
201 else {
155 qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr(
202 qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr(
156 "Can't update Data of a scalarSeries because there is not only one component "
203 "Can't update Data of a scalarSeries because there is not only one component "
157 "associated");
204 "associated");
158 }
205 }
159 }
206 }
160 else {
207 else {
161 /// @todo DEBUG
208 /// @todo DEBUG
162 }
209 }
163 }
210 }
@@ -1,307 +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 } // namespace
26 } // namespace
27
27
28 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
28 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
29
29
30 explicit VisualizationGraphWidgetPrivate()
30 explicit VisualizationGraphWidgetPrivate()
31 : m_DoAcquisition{true}, m_IsCalibration{false}, m_RenderingDelegate{nullptr}
31 : m_DoAcquisition{true}, m_IsCalibration{false}, m_RenderingDelegate{nullptr}
32 {
32 {
33 }
33 }
34
34
35 // 1 variable -> n qcpplot
35 // 1 variable -> n qcpplot
36 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
36 std::multimap<std::shared_ptr<Variable>, QCPAbstractPlottable *> m_VariableToPlotMultiMap;
37 bool m_DoAcquisition;
37 bool m_DoAcquisition;
38 bool m_IsCalibration;
38 bool m_IsCalibration;
39 QCPItemTracer *m_TextTracer;
39 QCPItemTracer *m_TextTracer;
40 /// Delegate used to attach rendering features to the plot
40 /// Delegate used to attach rendering features to the plot
41 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
41 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
42 };
42 };
43
43
44 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
44 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
45 : QWidget{parent},
45 : QWidget{parent},
46 ui{new Ui::VisualizationGraphWidget},
46 ui{new Ui::VisualizationGraphWidget},
47 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
47 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
48 {
48 {
49 ui->setupUi(this);
49 ui->setupUi(this);
50
50
51 // 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
52 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*ui->widget);
52 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*ui->widget);
53
53
54 ui->graphNameLabel->setText(name);
54 ui->graphNameLabel->setText(name);
55
55
56 // 'Close' options : widget is deleted when closed
56 // 'Close' options : widget is deleted when closed
57 setAttribute(Qt::WA_DeleteOnClose);
57 setAttribute(Qt::WA_DeleteOnClose);
58 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
58 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
59 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
59 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
60
60
61 // Set qcpplot properties :
61 // Set qcpplot properties :
62 // - Drag (on x-axis) and zoom are enabled
62 // - Drag (on x-axis) and zoom are enabled
63 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
63 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
64 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
64 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
65 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
65 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
66
66
67 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
67 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
68 connect(ui->widget, &QCustomPlot::mouseRelease, this,
68 connect(ui->widget, &QCustomPlot::mouseRelease, this,
69 &VisualizationGraphWidget::onMouseRelease);
69 &VisualizationGraphWidget::onMouseRelease);
70 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
70 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
71 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
71 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
72 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 &)>(
73 &QCPAxis::rangeChanged),
73 &QCPAxis::rangeChanged),
74 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
74 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
75
75
76 // Activates menu when right clicking on the graph
76 // Activates menu when right clicking on the graph
77 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
77 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
78 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
78 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
79 &VisualizationGraphWidget::onGraphMenuRequested);
79 &VisualizationGraphWidget::onGraphMenuRequested);
80
80
81 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
81 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
82 &VariableController::onRequestDataLoading);
82 &VariableController::onRequestDataLoading);
83 }
83 }
84
84
85
85
86 VisualizationGraphWidget::~VisualizationGraphWidget()
86 VisualizationGraphWidget::~VisualizationGraphWidget()
87 {
87 {
88 delete ui;
88 delete ui;
89 }
89 }
90
90
91 void VisualizationGraphWidget::enableAcquisition(bool enable)
91 void VisualizationGraphWidget::enableAcquisition(bool enable)
92 {
92 {
93 impl->m_DoAcquisition = enable;
93 impl->m_DoAcquisition = enable;
94 }
94 }
95
95
96 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
96 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
97 {
97 {
98 auto calibrationState = impl->m_IsCalibration;
99 impl->m_IsCalibration = true;
100 // Uses delegate to create the qcpplot components according to the variable
98 // Uses delegate to create the qcpplot components according to the variable
101 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
99 auto createdPlottables = VisualizationGraphHelper::createV2(variable, *ui->widget);
102 impl->m_IsCalibration = calibrationState;
103
100
104 for (auto createdPlottable : qAsConst(createdPlottables)) {
101 for (auto createdPlottable : qAsConst(createdPlottables)) {
105 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
102 impl->m_VariableToPlotMultiMap.insert({variable, createdPlottable});
106 }
103 }
107
104
108 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
105 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
109
106
110 emit variableAdded(variable);
107 auto varRange = variable->range();
111 }
112 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
113 {
114 // Uses delegate to create the qcpplot components according to the variable
115 this->addVariable(variable);
116
108
117 // Request range for the variable
109 this->enableAcquisition(false);
118 auto graphRange = ui->widget->xAxis->range();
110 this->setGraphRange(range);
111 this->enableAcquisition(true);
112
113 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, varRange,
114 false);
119
115
120 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable,
116 emit variableAdded(variable);
121 SqpRange{graphRange.lower, graphRange.upper}, variable->range(), false);
122 }
117 }
123
118
124 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
119 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
125 {
120 {
126 // Each component associated to the variable :
121 // Each component associated to the variable :
127 // - is removed from qcpplot (which deletes it)
122 // - is removed from qcpplot (which deletes it)
128 // - is no longer referenced in the map
123 // - is no longer referenced in the map
129 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
124 auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
130 for (auto it = componentsIt.first; it != componentsIt.second;) {
125 for (auto it = componentsIt.first; it != componentsIt.second;) {
131 ui->widget->removePlottable(it->second);
126 ui->widget->removePlottable(it->second);
132 it = impl->m_VariableToPlotMultiMap.erase(it);
127 it = impl->m_VariableToPlotMultiMap.erase(it);
133 }
128 }
134
129
135 // Updates graph
130 // Updates graph
136 ui->widget->replot();
131 ui->widget->replot();
137 }
132 }
138
133
139 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable, const SqpRange &range)
134 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable, const SqpRange &range)
140 {
135 {
141 // Note: in case of different axes that depends on variable, we could start with a code like
136 // Note: in case of different axes that depends on variable, we could start with a code like
142 // that:
137 // that:
143 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
138 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
144 // for (auto it = componentsIt.first; it != componentsIt.second;) {
139 // for (auto it = componentsIt.first; it != componentsIt.second;) {
145 // }
140 // }
146 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
141 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
147 ui->widget->replot();
142 ui->widget->replot();
148 }
143 }
149
144
145 void VisualizationGraphWidget::setYRange(const SqpRange &range)
146 {
147 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
148 }
149
150 SqpRange VisualizationGraphWidget::graphRange() const noexcept
150 SqpRange VisualizationGraphWidget::graphRange() const noexcept
151 {
151 {
152 auto grapheRange = ui->widget->xAxis->range();
152 auto graphRange = ui->widget->xAxis->range();
153 return SqpRange{grapheRange.lower, grapheRange.upper};
153 return SqpRange{graphRange.lower, graphRange.upper};
154 }
154 }
155
155
156 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
156 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
157 {
157 {
158 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
158 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
159 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
159 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
160 ui->widget->replot();
160 ui->widget->replot();
161 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
161 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
162 }
162 }
163
163
164 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
164 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
165 {
165 {
166 if (visitor) {
166 if (visitor) {
167 visitor->visit(this);
167 visitor->visit(this);
168 }
168 }
169 else {
169 else {
170 qCCritical(LOG_VisualizationGraphWidget())
170 qCCritical(LOG_VisualizationGraphWidget())
171 << tr("Can't visit widget : the visitor is null");
171 << tr("Can't visit widget : the visitor is null");
172 }
172 }
173 }
173 }
174
174
175 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
175 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
176 {
176 {
177 /// @todo : for the moment, a graph can always accomodate a variable
177 /// @todo : for the moment, a graph can always accomodate a variable
178 Q_UNUSED(variable);
178 Q_UNUSED(variable);
179 return true;
179 return true;
180 }
180 }
181
181
182 bool VisualizationGraphWidget::contains(const Variable &variable) const
182 bool VisualizationGraphWidget::contains(const Variable &variable) const
183 {
183 {
184 // Finds the variable among the keys of the map
184 // Finds the variable among the keys of the map
185 auto variablePtr = &variable;
185 auto variablePtr = &variable;
186 auto findVariable
186 auto findVariable
187 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
187 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
188
188
189 auto end = impl->m_VariableToPlotMultiMap.cend();
189 auto end = impl->m_VariableToPlotMultiMap.cend();
190 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
190 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
191 return it != end;
191 return it != end;
192 }
192 }
193
193
194 QString VisualizationGraphWidget::name() const
194 QString VisualizationGraphWidget::name() const
195 {
195 {
196 return ui->graphNameLabel->text();
196 return ui->graphNameLabel->text();
197 }
197 }
198
198
199 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
199 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
200 {
200 {
201 QMenu graphMenu{};
201 QMenu graphMenu{};
202
202
203 // Iterates on variables (unique keys)
203 // Iterates on variables (unique keys)
204 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
204 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
205 end = impl->m_VariableToPlotMultiMap.cend();
205 end = impl->m_VariableToPlotMultiMap.cend();
206 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
206 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
207 // 'Remove variable' action
207 // 'Remove variable' action
208 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
208 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
209 [ this, var = it->first ]() { removeVariable(var); });
209 [ this, var = it->first ]() { removeVariable(var); });
210 }
210 }
211
211
212 if (!graphMenu.isEmpty()) {
212 if (!graphMenu.isEmpty()) {
213 graphMenu.exec(mapToGlobal(pos));
213 graphMenu.exec(mapToGlobal(pos));
214 }
214 }
215 }
215 }
216
216
217 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
217 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
218 {
218 {
219 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
219 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
220 << QThread::currentThread()->objectName() << "DoAcqui"
220 << QThread::currentThread()->objectName() << "DoAcqui"
221 << impl->m_DoAcquisition;
221 << impl->m_DoAcquisition;
222
222
223 auto graphRange = SqpRange{t1.lower, t1.upper};
223 auto graphRange = SqpRange{t1.lower, t1.upper};
224 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
224 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
225
225
226 if (impl->m_DoAcquisition) {
226 if (impl->m_DoAcquisition) {
227 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
227 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
228
228
229 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
229 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
230 end = impl->m_VariableToPlotMultiMap.end();
230 end = impl->m_VariableToPlotMultiMap.end();
231 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
231 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
232 variableUnderGraphVector.push_back(it->first);
232 variableUnderGraphVector.push_back(it->first);
233 }
233 }
234 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange, oldGraphRange,
234 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange, oldGraphRange,
235 !impl->m_IsCalibration);
235 !impl->m_IsCalibration);
236
236
237 if (!impl->m_IsCalibration) {
237 if (!impl->m_IsCalibration) {
238 qCDebug(LOG_VisualizationGraphWidget())
238 qCDebug(LOG_VisualizationGraphWidget())
239 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
239 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
240 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
240 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
241 emit synchronize(graphRange, oldGraphRange);
241 emit synchronize(graphRange, oldGraphRange);
242 }
242 }
243 }
243 }
244 }
244 }
245
245
246 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
246 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
247 {
247 {
248 // Handles plot rendering when mouse is moving
248 // Handles plot rendering when mouse is moving
249 impl->m_RenderingDelegate->onMouseMove(event);
249 impl->m_RenderingDelegate->onMouseMove(event);
250 }
250 }
251
251
252 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
252 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
253 {
253 {
254 auto zoomOrientations = QFlags<Qt::Orientation>{};
254 auto zoomOrientations = QFlags<Qt::Orientation>{};
255
255
256 // 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
257 // has
257 // has
258 // been pressed
258 // been pressed
259 auto enableOrientation
259 auto enableOrientation
260 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
260 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
261 auto orientationEnabled = event->modifiers().testFlag(modifier);
261 auto orientationEnabled = event->modifiers().testFlag(modifier);
262 zoomOrientations.setFlag(orientation, orientationEnabled);
262 zoomOrientations.setFlag(orientation, orientationEnabled);
263 };
263 };
264 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
264 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
265 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
265 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
266
266
267 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
267 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
268 }
268 }
269
269
270 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
270 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
271 {
271 {
272 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
272 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
273 }
273 }
274
274
275 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
275 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
276 {
276 {
277 impl->m_IsCalibration = false;
277 impl->m_IsCalibration = false;
278 }
278 }
279
279
280 void VisualizationGraphWidget::onDataCacheVariableUpdated()
280 void VisualizationGraphWidget::onDataCacheVariableUpdated()
281 {
281 {
282 // NOTE:
282 // NOTE:
283 // 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
284 // all
284 // all
285 // 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).
286
286
287 // 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:
288 // - 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
289 // - 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
290
290
291 auto grapheRange = ui->widget->xAxis->range();
291 auto graphRange = ui->widget->xAxis->range();
292 auto dateTime = SqpRange{grapheRange.lower, grapheRange.upper};
292 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
293
293
294 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
294 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
295 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
295 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
296 auto variable = it->first;
296 auto variable = it->first;
297 qCDebug(LOG_VisualizationGraphWidget())
297 qCDebug(LOG_VisualizationGraphWidget())
298 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
298 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
299 qCDebug(LOG_VisualizationGraphWidget())
299 qCDebug(LOG_VisualizationGraphWidget())
300 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
300 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
301 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
301 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
302
302
303 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
303 VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *>{} << it->second,
304 variable->dataSeries(), variable->range());
304 variable->dataSeries(), variable->range());
305 }
305 }
306 }
306 }
307 }
307 }
@@ -1,225 +1,244
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3
3
4 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/IVisualizationWidgetVisitor.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "ui_VisualizationZoneWidget.h"
6 #include "ui_VisualizationZoneWidget.h"
7
7
8 #include <Data/SqpRange.h>
8 #include <Data/SqpRange.h>
9 #include <Variable/Variable.h>
9 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
10
11
11 #include <QUuid>
12 #include <QUuid>
12 #include <SqpApplication.h>
13 #include <SqpApplication.h>
13
14
14 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
15 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
15
16
16 namespace {
17 namespace {
17
18
18 /// Minimum height for graph added in zones (in pixels)
19 /// Minimum height for graph added in zones (in pixels)
19 const auto GRAPH_MINIMUM_HEIGHT = 300;
20 const auto GRAPH_MINIMUM_HEIGHT = 300;
20
21
21 /// Generates a default name for a new graph, according to the number of graphs already displayed in
22 /// Generates a default name for a new graph, according to the number of graphs already displayed in
22 /// the zone
23 /// the zone
23 QString defaultGraphName(const QLayout &layout)
24 QString defaultGraphName(const QLayout &layout)
24 {
25 {
25 auto count = 0;
26 auto count = 0;
26 for (auto i = 0; i < layout.count(); ++i) {
27 for (auto i = 0; i < layout.count(); ++i) {
27 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
28 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
28 count++;
29 count++;
29 }
30 }
30 }
31 }
31
32
32 return QObject::tr("Graph %1").arg(count + 1);
33 return QObject::tr("Graph %1").arg(count + 1);
33 }
34 }
34
35
35 } // namespace
36 } // namespace
36
37
37 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
38 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
38
39
39 explicit VisualizationZoneWidgetPrivate() : m_SynchronisationGroupId{QUuid::createUuid()} {}
40 explicit VisualizationZoneWidgetPrivate() : m_SynchronisationGroupId{QUuid::createUuid()} {}
40 QUuid m_SynchronisationGroupId;
41 QUuid m_SynchronisationGroupId;
41 };
42 };
42
43
43 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
44 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
44 : QWidget{parent},
45 : QWidget{parent},
45 ui{new Ui::VisualizationZoneWidget},
46 ui{new Ui::VisualizationZoneWidget},
46 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
47 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
47 {
48 {
48 ui->setupUi(this);
49 ui->setupUi(this);
49
50
50 ui->zoneNameLabel->setText(name);
51 ui->zoneNameLabel->setText(name);
51
52
52 // 'Close' options : widget is deleted when closed
53 // 'Close' options : widget is deleted when closed
53 setAttribute(Qt::WA_DeleteOnClose);
54 setAttribute(Qt::WA_DeleteOnClose);
54 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
55 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
55 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
56 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
56
57
57 // Synchronisation id
58 // Synchronisation id
58 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
59 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
59 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
60 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
60 }
61 }
61
62
62 VisualizationZoneWidget::~VisualizationZoneWidget()
63 VisualizationZoneWidget::~VisualizationZoneWidget()
63 {
64 {
64 delete ui;
65 delete ui;
65 }
66 }
66
67
67 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
68 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
68 {
69 {
69 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
70 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
70 }
71 }
71
72
72 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
73 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
73 {
74 {
74 auto graphWidget = new VisualizationGraphWidget{
75 auto graphWidget = new VisualizationGraphWidget{
75 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
76 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
76
77
77
78
78 // Set graph properties
79 // Set graph properties
79 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
80 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
80 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
81 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
81
82
82
83
83 // Lambda to synchronize zone widget
84 // Lambda to synchronize zone widget
84 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &grapheRange,
85 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
85 const SqpRange &oldGraphRange) {
86 const SqpRange &oldGraphRange) {
86
87
87 auto zoomType = VariableController::getZoomType(grapheRange, oldGraphRange);
88 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
88 auto frameLayout = ui->visualizationZoneFrame->layout();
89 auto frameLayout = ui->visualizationZoneFrame->layout();
89 for (auto i = 0; i < frameLayout->count(); ++i) {
90 for (auto i = 0; i < frameLayout->count(); ++i) {
90 auto graphChild
91 auto graphChild
91 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
92 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
92 if (graphChild && (graphChild != graphWidget)) {
93 if (graphChild && (graphChild != graphWidget)) {
93
94
94 auto graphChildRange = graphChild->graphRange();
95 auto graphChildRange = graphChild->graphRange();
95 switch (zoomType) {
96 switch (zoomType) {
96 case AcquisitionZoomType::ZoomIn: {
97 case AcquisitionZoomType::ZoomIn: {
97 auto deltaLeft = grapheRange.m_TStart - oldGraphRange.m_TStart;
98 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
98 auto deltaRight = oldGraphRange.m_TEnd - grapheRange.m_TEnd;
99 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
99 graphChildRange.m_TStart += deltaLeft;
100 graphChildRange.m_TStart += deltaLeft;
100 graphChildRange.m_TEnd -= deltaRight;
101 graphChildRange.m_TEnd -= deltaRight;
101 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
102 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
102 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
103 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
103 << deltaLeft;
104 << deltaLeft;
104 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
105 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
105 << deltaRight;
106 << deltaRight;
106 qCCritical(LOG_VisualizationZoneWidget())
107 qCCritical(LOG_VisualizationZoneWidget())
107 << tr("TORM: dt") << grapheRange.m_TEnd - grapheRange.m_TStart;
108 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
108
109
109 break;
110 break;
110 }
111 }
111
112
112 case AcquisitionZoomType::ZoomOut: {
113 case AcquisitionZoomType::ZoomOut: {
113 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
114 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
114 auto deltaLeft = oldGraphRange.m_TStart - grapheRange.m_TStart;
115 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
115 auto deltaRight = grapheRange.m_TEnd - oldGraphRange.m_TEnd;
116 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
116 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
117 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
117 << deltaLeft;
118 << deltaLeft;
118 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
119 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
119 << deltaRight;
120 << deltaRight;
120 qCCritical(LOG_VisualizationZoneWidget())
121 qCCritical(LOG_VisualizationZoneWidget())
121 << tr("TORM: dt") << grapheRange.m_TEnd - grapheRange.m_TStart;
122 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
122 graphChildRange.m_TStart -= deltaLeft;
123 graphChildRange.m_TStart -= deltaLeft;
123 graphChildRange.m_TEnd += deltaRight;
124 graphChildRange.m_TEnd += deltaRight;
124 break;
125 break;
125 }
126 }
126 case AcquisitionZoomType::PanRight: {
127 case AcquisitionZoomType::PanRight: {
127 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
128 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
128 auto deltaRight = grapheRange.m_TEnd - oldGraphRange.m_TEnd;
129 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
129 graphChildRange.m_TStart += deltaRight;
130 graphChildRange.m_TStart += deltaRight;
130 graphChildRange.m_TEnd += deltaRight;
131 graphChildRange.m_TEnd += deltaRight;
131 qCCritical(LOG_VisualizationZoneWidget())
132 qCCritical(LOG_VisualizationZoneWidget())
132 << tr("TORM: dt") << grapheRange.m_TEnd - grapheRange.m_TStart;
133 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
133 break;
134 break;
134 }
135 }
135 case AcquisitionZoomType::PanLeft: {
136 case AcquisitionZoomType::PanLeft: {
136 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
137 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
137 auto deltaLeft = oldGraphRange.m_TStart - grapheRange.m_TStart;
138 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
138 graphChildRange.m_TStart -= deltaLeft;
139 graphChildRange.m_TStart -= deltaLeft;
139 graphChildRange.m_TEnd -= deltaLeft;
140 graphChildRange.m_TEnd -= deltaLeft;
140 break;
141 break;
141 }
142 }
142 case AcquisitionZoomType::Unknown: {
143 case AcquisitionZoomType::Unknown: {
143 qCCritical(LOG_VisualizationZoneWidget())
144 qCCritical(LOG_VisualizationZoneWidget())
144 << tr("Impossible to synchronize: zoom type unknown");
145 << tr("Impossible to synchronize: zoom type unknown");
145 break;
146 break;
146 }
147 }
147 default:
148 default:
148 qCCritical(LOG_VisualizationZoneWidget())
149 qCCritical(LOG_VisualizationZoneWidget())
149 << tr("Impossible to synchronize: zoom type not take into account");
150 << tr("Impossible to synchronize: zoom type not take into account");
150 // No action
151 // No action
151 break;
152 break;
152 }
153 }
153 graphChild->enableAcquisition(false);
154 graphChild->enableAcquisition(false);
154 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
155 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
155 << graphChild->graphRange();
156 << graphChild->graphRange();
156 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
157 qCCritical(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
157 << graphChildRange;
158 << graphChildRange;
158 qCCritical(LOG_VisualizationZoneWidget())
159 qCCritical(LOG_VisualizationZoneWidget())
159 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
160 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
160 graphChild->setGraphRange(graphChildRange);
161 graphChild->setGraphRange(graphChildRange);
161 graphChild->enableAcquisition(true);
162 graphChild->enableAcquisition(true);
162 }
163 }
163 }
164 }
164 };
165 };
165
166
166 // connection for synchronization
167 // connection for synchronization
167 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
168 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
168 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
169 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
169 &VisualizationZoneWidget::onVariableAdded);
170 &VisualizationZoneWidget::onVariableAdded);
170
171
172 auto range = SqpRange{};
173
174 // Apply visitor to graph children
175 auto layout = ui->visualizationZoneFrame->layout();
176 if (layout->count() > 0) {
177 // Case of a new graph in a existant zone
178 if (auto visualizationGraphWidget
179 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
180 range = visualizationGraphWidget->graphRange();
181 }
182 }
183 else {
184 // Case of a new graph as the first of the zone
185 range = variable->range();
186 }
187
171 this->addGraph(graphWidget);
188 this->addGraph(graphWidget);
172
189
173 graphWidget->addVariable(variable);
190 graphWidget->addVariable(variable, range);
191 // TODO: get y using variable range
192 graphWidget->setYRange(SqpRange{-10, 10});
174
193
175 return graphWidget;
194 return graphWidget;
176 }
195 }
177
196
178 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
197 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
179 {
198 {
180 if (visitor) {
199 if (visitor) {
181 visitor->visitEnter(this);
200 visitor->visitEnter(this);
182
201
183 // Apply visitor to graph children
202 // Apply visitor to graph children
184 auto layout = ui->visualizationZoneFrame->layout();
203 auto layout = ui->visualizationZoneFrame->layout();
185 for (auto i = 0; i < layout->count(); ++i) {
204 for (auto i = 0; i < layout->count(); ++i) {
186 if (auto item = layout->itemAt(i)) {
205 if (auto item = layout->itemAt(i)) {
187 // Widgets different from graphs are not visited (no action)
206 // Widgets different from graphs are not visited (no action)
188 if (auto visualizationGraphWidget
207 if (auto visualizationGraphWidget
189 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
208 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
190 visualizationGraphWidget->accept(visitor);
209 visualizationGraphWidget->accept(visitor);
191 }
210 }
192 }
211 }
193 }
212 }
194
213
195 visitor->visitLeave(this);
214 visitor->visitLeave(this);
196 }
215 }
197 else {
216 else {
198 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
217 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
199 }
218 }
200 }
219 }
201
220
202 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
221 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
203 {
222 {
204 // A tab can always accomodate a variable
223 // A tab can always accomodate a variable
205 Q_UNUSED(variable);
224 Q_UNUSED(variable);
206 return true;
225 return true;
207 }
226 }
208
227
209 bool VisualizationZoneWidget::contains(const Variable &variable) const
228 bool VisualizationZoneWidget::contains(const Variable &variable) const
210 {
229 {
211 Q_UNUSED(variable);
230 Q_UNUSED(variable);
212 return false;
231 return false;
213 }
232 }
214
233
215 QString VisualizationZoneWidget::name() const
234 QString VisualizationZoneWidget::name() const
216 {
235 {
217 return ui->zoneNameLabel->text();
236 return ui->zoneNameLabel->text();
218 }
237 }
219
238
220 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
239 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
221 {
240 {
222 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
241 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
223 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
242 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
224 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
243 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
225 }
244 }
@@ -1,200 +1,201
1 #include "Visualization/operations/GenerateVariableMenuOperation.h"
1 #include "Visualization/operations/GenerateVariableMenuOperation.h"
2 #include "Visualization/operations/MenuBuilder.h"
2 #include "Visualization/operations/MenuBuilder.h"
3
3
4 #include "Visualization/VisualizationGraphWidget.h"
4 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationTabWidget.h"
5 #include "Visualization/VisualizationTabWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
7
8 #include <Variable/Variable.h>
8 #include <Variable/Variable.h>
9
9
10 #include <QMenu>
10 #include <QMenu>
11 #include <QStack>
11 #include <QStack>
12
12
13 Q_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation, "GenerateVariableMenuOperation")
13 Q_LOGGING_CATEGORY(LOG_GenerateVariableMenuOperation, "GenerateVariableMenuOperation")
14
14
15 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
15 struct GenerateVariableMenuOperation::GenerateVariableMenuOperationPrivate {
16 explicit GenerateVariableMenuOperationPrivate(QMenu *menu, std::shared_ptr<Variable> variable)
16 explicit GenerateVariableMenuOperationPrivate(QMenu *menu, std::shared_ptr<Variable> variable)
17 : m_Variable{variable}, m_PlotMenuBuilder{menu}, m_UnplotMenuBuilder{menu}
17 : m_Variable{variable}, m_PlotMenuBuilder{menu}, m_UnplotMenuBuilder{menu}
18 {
18 {
19 }
19 }
20
20
21 void visitRootEnter()
21 void visitRootEnter()
22 {
22 {
23 // Creates the root menu
23 // Creates the root menu
24 if (auto plotMenu
24 if (auto plotMenu
25 = m_PlotMenuBuilder.addMenu(QObject::tr("Plot"), QIcon{":/icones/plot.png"})) {
25 = m_PlotMenuBuilder.addMenu(QObject::tr("Plot"), QIcon{":/icones/plot.png"})) {
26 plotMenu->setEnabled(m_Variable && m_Variable->dataSeries() != nullptr);
26 plotMenu->setEnabled(m_Variable && m_Variable->dataSeries() != nullptr);
27 }
27 }
28
28
29 m_UnplotMenuBuilder.addMenu(QObject::tr("Unplot"), QIcon{":/icones/unplot.png"});
29 m_UnplotMenuBuilder.addMenu(QObject::tr("Unplot"), QIcon{":/icones/unplot.png"});
30 }
30 }
31
31
32 void visitRootLeave()
32 void visitRootLeave()
33 {
33 {
34 // Closes the root menu
34 // Closes the root menu
35 m_PlotMenuBuilder.closeMenu();
35 m_PlotMenuBuilder.closeMenu();
36 m_UnplotMenuBuilder.closeMenu();
36 m_UnplotMenuBuilder.closeMenu();
37 }
37 }
38
38
39 void visitNodeEnter(const IVisualizationWidget &container)
39 void visitNodeEnter(const IVisualizationWidget &container)
40 {
40 {
41 // Opens a new menu associated to the node
41 // Opens a new menu associated to the node
42 m_PlotMenuBuilder.addMenu(container.name());
42 m_PlotMenuBuilder.addMenu(container.name());
43 m_UnplotMenuBuilder.addMenu(container.name());
43 m_UnplotMenuBuilder.addMenu(container.name());
44 }
44 }
45
45
46 template <typename ActionFun>
46 template <typename ActionFun>
47 void visitNodeLeavePlot(const IVisualizationWidget &container, const QString &actionName,
47 void visitNodeLeavePlot(const IVisualizationWidget &container, const QString &actionName,
48 ActionFun actionFunction)
48 ActionFun actionFunction)
49 {
49 {
50 if (m_Variable && container.canDrop(*m_Variable)) {
50 if (m_Variable && container.canDrop(*m_Variable)) {
51 m_PlotMenuBuilder.addSeparator();
51 m_PlotMenuBuilder.addSeparator();
52 m_PlotMenuBuilder.addAction(actionName, actionFunction);
52 m_PlotMenuBuilder.addAction(actionName, actionFunction);
53 }
53 }
54
54
55 // Closes the menu associated to the node
55 // Closes the menu associated to the node
56 m_PlotMenuBuilder.closeMenu();
56 m_PlotMenuBuilder.closeMenu();
57 }
57 }
58
58
59 void visitNodeLeaveUnplot()
59 void visitNodeLeaveUnplot()
60 {
60 {
61 // Closes the menu associated to the node
61 // Closes the menu associated to the node
62 m_UnplotMenuBuilder.closeMenu();
62 m_UnplotMenuBuilder.closeMenu();
63 }
63 }
64
64
65 template <typename ActionFun>
65 template <typename ActionFun>
66 void visitLeafPlot(const IVisualizationWidget &container, const QString &actionName,
66 void visitLeafPlot(const IVisualizationWidget &container, const QString &actionName,
67 ActionFun actionFunction)
67 ActionFun actionFunction)
68 {
68 {
69 if (m_Variable && container.canDrop(*m_Variable)) {
69 if (m_Variable && container.canDrop(*m_Variable)) {
70 m_PlotMenuBuilder.addAction(actionName, actionFunction);
70 m_PlotMenuBuilder.addAction(actionName, actionFunction);
71 }
71 }
72 }
72 }
73
73
74 template <typename ActionFun>
74 template <typename ActionFun>
75 void visitLeafUnplot(const IVisualizationWidget &container, const QString &actionName,
75 void visitLeafUnplot(const IVisualizationWidget &container, const QString &actionName,
76 ActionFun actionFunction)
76 ActionFun actionFunction)
77 {
77 {
78 if (m_Variable && container.contains(*m_Variable)) {
78 if (m_Variable && container.contains(*m_Variable)) {
79 m_UnplotMenuBuilder.addAction(actionName, actionFunction);
79 m_UnplotMenuBuilder.addAction(actionName, actionFunction);
80 }
80 }
81 }
81 }
82
82
83 std::shared_ptr<Variable> m_Variable;
83 std::shared_ptr<Variable> m_Variable;
84 MenuBuilder m_PlotMenuBuilder; ///< Builder for the 'Plot' menu
84 MenuBuilder m_PlotMenuBuilder; ///< Builder for the 'Plot' menu
85 MenuBuilder m_UnplotMenuBuilder; ///< Builder for the 'Unplot' menu
85 MenuBuilder m_UnplotMenuBuilder; ///< Builder for the 'Unplot' menu
86 };
86 };
87
87
88 GenerateVariableMenuOperation::GenerateVariableMenuOperation(QMenu *menu,
88 GenerateVariableMenuOperation::GenerateVariableMenuOperation(QMenu *menu,
89 std::shared_ptr<Variable> variable)
89 std::shared_ptr<Variable> variable)
90 : impl{spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(menu, variable)}
90 : impl{spimpl::make_unique_impl<GenerateVariableMenuOperationPrivate>(menu, variable)}
91 {
91 {
92 }
92 }
93
93
94 void GenerateVariableMenuOperation::visitEnter(VisualizationWidget *widget)
94 void GenerateVariableMenuOperation::visitEnter(VisualizationWidget *widget)
95 {
95 {
96 // VisualizationWidget is not intended to accommodate a variable
96 // VisualizationWidget is not intended to accommodate a variable
97 Q_UNUSED(widget)
97 Q_UNUSED(widget)
98
98
99 // 'Plot' and 'Unplot' menus
99 // 'Plot' and 'Unplot' menus
100 impl->visitRootEnter();
100 impl->visitRootEnter();
101 }
101 }
102
102
103 void GenerateVariableMenuOperation::visitLeave(VisualizationWidget *widget)
103 void GenerateVariableMenuOperation::visitLeave(VisualizationWidget *widget)
104 {
104 {
105 // VisualizationWidget is not intended to accommodate a variable
105 // VisualizationWidget is not intended to accommodate a variable
106 Q_UNUSED(widget)
106 Q_UNUSED(widget)
107
107
108 // 'Plot' and 'Unplot' menus
108 // 'Plot' and 'Unplot' menus
109 impl->visitRootLeave();
109 impl->visitRootLeave();
110 }
110 }
111
111
112 void GenerateVariableMenuOperation::visitEnter(VisualizationTabWidget *tabWidget)
112 void GenerateVariableMenuOperation::visitEnter(VisualizationTabWidget *tabWidget)
113 {
113 {
114 if (tabWidget) {
114 if (tabWidget) {
115 // 'Plot' and 'Unplot' menus
115 // 'Plot' and 'Unplot' menus
116 impl->visitNodeEnter(*tabWidget);
116 impl->visitNodeEnter(*tabWidget);
117 }
117 }
118 else {
118 else {
119 qCCritical(LOG_GenerateVariableMenuOperation(),
119 qCCritical(LOG_GenerateVariableMenuOperation(),
120 "Can't visit enter VisualizationTabWidget : the widget is null");
120 "Can't visit enter VisualizationTabWidget : the widget is null");
121 }
121 }
122 }
122 }
123
123
124 void GenerateVariableMenuOperation::visitLeave(VisualizationTabWidget *tabWidget)
124 void GenerateVariableMenuOperation::visitLeave(VisualizationTabWidget *tabWidget)
125 {
125 {
126 if (tabWidget) {
126 if (tabWidget) {
127 // 'Plot' menu
127 // 'Plot' menu
128 impl->visitNodeLeavePlot(*tabWidget, QObject::tr("Open in a new zone"),
128 impl->visitNodeLeavePlot(*tabWidget, QObject::tr("Open in a new zone"),
129 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, tabWidget ]() {
129 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, tabWidget ]() {
130 if (auto var = varW.lock()) {
130 if (auto var = varW.lock()) {
131 tabWidget->createZone(var);
131 tabWidget->createZone(var);
132 }
132 }
133 });
133 });
134
134
135 // 'Unplot' menu
135 // 'Unplot' menu
136 impl->visitNodeLeaveUnplot();
136 impl->visitNodeLeaveUnplot();
137 }
137 }
138 else {
138 else {
139 qCCritical(LOG_GenerateVariableMenuOperation(),
139 qCCritical(LOG_GenerateVariableMenuOperation(),
140 "Can't visit leave VisualizationTabWidget : the widget is null");
140 "Can't visit leave VisualizationTabWidget : the widget is null");
141 }
141 }
142 }
142 }
143
143
144 void GenerateVariableMenuOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
144 void GenerateVariableMenuOperation::visitEnter(VisualizationZoneWidget *zoneWidget)
145 {
145 {
146 if (zoneWidget) {
146 if (zoneWidget) {
147 // 'Plot' and 'Unplot' menus
147 // 'Plot' and 'Unplot' menus
148 impl->visitNodeEnter(*zoneWidget);
148 impl->visitNodeEnter(*zoneWidget);
149 }
149 }
150 else {
150 else {
151 qCCritical(LOG_GenerateVariableMenuOperation(),
151 qCCritical(LOG_GenerateVariableMenuOperation(),
152 "Can't visit enter VisualizationZoneWidget : the widget is null");
152 "Can't visit enter VisualizationZoneWidget : the widget is null");
153 }
153 }
154 }
154 }
155
155
156 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
156 void GenerateVariableMenuOperation::visitLeave(VisualizationZoneWidget *zoneWidget)
157 {
157 {
158 qCCritical(LOG_GenerateVariableMenuOperation(), "Open in a new graph DETECTED !!");
158 if (zoneWidget) {
159 if (zoneWidget) {
159 // 'Plot' menu
160 // 'Plot' menu
160 impl->visitNodeLeavePlot(
161 impl->visitNodeLeavePlot(
161 *zoneWidget, QObject::tr("Open in a new graph"),
162 *zoneWidget, QObject::tr("Open in a new graph"),
162 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, zoneWidget ]() {
163 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, zoneWidget ]() {
163 if (auto var = varW.lock()) {
164 if (auto var = varW.lock()) {
164 zoneWidget->createGraph(var);
165 zoneWidget->createGraph(var);
165 }
166 }
166 });
167 });
167
168
168 // 'Unplot' menu
169 // 'Unplot' menu
169 impl->visitNodeLeaveUnplot();
170 impl->visitNodeLeaveUnplot();
170 }
171 }
171 else {
172 else {
172 qCCritical(LOG_GenerateVariableMenuOperation(),
173 qCCritical(LOG_GenerateVariableMenuOperation(),
173 "Can't visit leave VisualizationZoneWidget : the widget is null");
174 "Can't visit leave VisualizationZoneWidget : the widget is null");
174 }
175 }
175 }
176 }
176
177
177 void GenerateVariableMenuOperation::visit(VisualizationGraphWidget *graphWidget)
178 void GenerateVariableMenuOperation::visit(VisualizationGraphWidget *graphWidget)
178 {
179 {
179 if (graphWidget) {
180 if (graphWidget) {
180 // 'Plot' menu
181 // 'Plot' menu
181 impl->visitLeafPlot(*graphWidget, QObject::tr("Open in %1").arg(graphWidget->name()),
182 impl->visitLeafPlot(*graphWidget, QObject::tr("Open in %1").arg(graphWidget->name()),
182 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
183 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
183 if (auto var = varW.lock()) {
184 if (auto var = varW.lock()) {
184 graphWidget->addVariableUsingGraph(var);
185 graphWidget->addVariable(var, graphWidget->graphRange());
185 }
186 }
186 });
187 });
187
188
188 // 'Unplot' menu
189 // 'Unplot' menu
189 impl->visitLeafUnplot(*graphWidget, QObject::tr("Remove from %1").arg(graphWidget->name()),
190 impl->visitLeafUnplot(*graphWidget, QObject::tr("Remove from %1").arg(graphWidget->name()),
190 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
191 [ varW = std::weak_ptr<Variable>{impl->m_Variable}, graphWidget ]() {
191 if (auto var = varW.lock()) {
192 if (auto var = varW.lock()) {
192 graphWidget->removeVariable(var);
193 graphWidget->removeVariable(var);
193 }
194 }
194 });
195 });
195 }
196 }
196 else {
197 else {
197 qCCritical(LOG_GenerateVariableMenuOperation(),
198 qCCritical(LOG_GenerateVariableMenuOperation(),
198 "Can't visit VisualizationGraphWidget : the widget is null");
199 "Can't visit VisualizationGraphWidget : the widget is null");
199 }
200 }
200 }
201 }
@@ -1,148 +1,150
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 acqIdentifier, 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 this->retrieveData(acqIdentifier, dateTime, data);
64 this->retrieveData(acqIdentifier, dateTime, data);
65 QThread::msleep(200);
65
66 // TORM
67 // QThread::msleep(200);
66 }
68 }
67 }
69 }
68
70
69 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
71 void AmdaProvider::requestDataAborting(QUuid acqIdentifier)
70 {
72 {
71 if (auto app = sqpApp) {
73 if (auto app = sqpApp) {
72 auto &networkController = app->networkController();
74 auto &networkController = app->networkController();
73 networkController.onReplyCanceled(acqIdentifier);
75 networkController.onReplyCanceled(acqIdentifier);
74 }
76 }
75 }
77 }
76
78
77 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
79 void AmdaProvider::retrieveData(QUuid token, const SqpRange &dateTime, const QVariantHash &data)
78 {
80 {
79 // Retrieves product ID from data: if the value is invalid, no request is made
81 // Retrieves product ID from data: if the value is invalid, no request is made
80 auto productId = data.value(AMDA_XML_ID_KEY).toString();
82 auto productId = data.value(AMDA_XML_ID_KEY).toString();
81 if (productId.isNull()) {
83 if (productId.isNull()) {
82 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
84 qCCritical(LOG_AmdaProvider()) << tr("Can't retrieve data: unknown product id");
83 return;
85 return;
84 }
86 }
85 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
87 qCDebug(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData") << dateTime;
86
88
87 // /////////// //
89 // /////////// //
88 // Creates URL //
90 // Creates URL //
89 // /////////// //
91 // /////////// //
90
92
91 auto startDate = dateFormat(dateTime.m_TStart);
93 auto startDate = dateFormat(dateTime.m_TStart);
92 auto endDate = dateFormat(dateTime.m_TEnd);
94 auto endDate = dateFormat(dateTime.m_TEnd);
93
95
94 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
96 auto url = QUrl{QString{AMDA_URL_FORMAT}.arg(startDate, endDate, productId)};
95 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData url:") << url;
97 qCInfo(LOG_AmdaProvider()) << tr("TORM AmdaProvider::retrieveData url:") << url;
96 auto tempFile = std::make_shared<QTemporaryFile>();
98 auto tempFile = std::make_shared<QTemporaryFile>();
97
99
98 // LAMBDA
100 // LAMBDA
99 auto httpDownloadFinished
101 auto httpDownloadFinished
100 = [this, dateTime, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
102 = [this, dateTime, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
101
103
102 // Don't do anything if the reply was abort
104 // Don't do anything if the reply was abort
103 if (reply->error() != QNetworkReply::OperationCanceledError) {
105 if (reply->error() != QNetworkReply::OperationCanceledError) {
104
106
105 if (tempFile) {
107 if (tempFile) {
106 auto replyReadAll = reply->readAll();
108 auto replyReadAll = reply->readAll();
107 if (!replyReadAll.isEmpty()) {
109 if (!replyReadAll.isEmpty()) {
108 tempFile->write(replyReadAll);
110 tempFile->write(replyReadAll);
109 }
111 }
110 tempFile->close();
112 tempFile->close();
111
113
112 // Parse results file
114 // Parse results file
113 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
115 if (auto dataSeries = AmdaResultParser::readTxt(tempFile->fileName())) {
114 emit dataProvided(dataId, dataSeries, dateTime);
116 emit dataProvided(dataId, dataSeries, dateTime);
115 }
117 }
116 else {
118 else {
117 /// @todo ALX : debug
119 /// @todo ALX : debug
118 }
120 }
119 }
121 }
120 }
122 }
121
123
122 };
124 };
123 auto httpFinishedLambda
125 auto httpFinishedLambda
124 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
126 = [this, httpDownloadFinished, tempFile](QNetworkReply *reply, QUuid dataId) noexcept {
125
127
126 // Don't do anything if the reply was abort
128 // Don't do anything if the reply was abort
127 if (reply->error() != QNetworkReply::OperationCanceledError) {
129 if (reply->error() != QNetworkReply::OperationCanceledError) {
128 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
130 auto downloadFileUrl = QUrl{QString{reply->readAll()}};
129
131
130
132
131 qCInfo(LOG_AmdaProvider()) << tr("AmdaProvider::retrieveData downloadFileUrl:")
133 qCInfo(LOG_AmdaProvider())
132 << downloadFileUrl;
134 << tr("TORM AmdaProvider::retrieveData downloadFileUrl:") << downloadFileUrl;
133 // Executes request for downloading file //
135 // Executes request for downloading file //
134
136
135 // Creates destination file
137 // Creates destination file
136 if (tempFile->open()) {
138 if (tempFile->open()) {
137 // Executes request
139 // Executes request
138 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId,
140 emit requestConstructed(QNetworkRequest{downloadFileUrl}, dataId,
139 httpDownloadFinished);
141 httpDownloadFinished);
140 }
142 }
141 }
143 }
142 };
144 };
143
145
144 // //////////////// //
146 // //////////////// //
145 // Executes request //
147 // Executes request //
146 // //////////////// //
148 // //////////////// //
147 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
149 emit requestConstructed(QNetworkRequest{url}, token, httpFinishedLambda);
148 }
150 }
@@ -1,103 +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 acqIdentifier,
14 std::shared_ptr<IDataSeries> CosinusProvider::retrieveData(QUuid acqIdentifier,
15 const SqpRange &dataRangeRequested)
15 const SqpRange &dataRangeRequested)
16 {
16 {
17 // TODO: Add Mutex
17 // TODO: Add Mutex
18 auto dataIndex = 0;
18 auto dataIndex = 0;
19
19
20 // Gets the timerange from the parameters
20 // Gets the timerange from the parameters
21 double freq = 100.0;
21 double freq = 100.0;
22 double start = std::ceil(dataRangeRequested.m_TStart * freq); // 100 htz
22 double start = std::ceil(dataRangeRequested.m_TStart * freq); // 100 htz
23 double end = std::floor(dataRangeRequested.m_TEnd * freq); // 100 htz
23 double end = std::floor(dataRangeRequested.m_TEnd * freq); // 100 htz
24
24
25 // We assure that timerange is valid
25 // We assure that timerange is valid
26 if (end < start) {
26 if (end < start) {
27 std::swap(start, end);
27 std::swap(start, end);
28 }
28 }
29
29
30 // Generates scalar series containing cosinus values (one value per second)
30 // Generates scalar series containing cosinus values (one value per second)
31 auto dataCount = end - start;
31 auto dataCount = end - start;
32
32
33 auto xAxisData = QVector<double>{};
33 auto xAxisData = QVector<double>{};
34 xAxisData.resize(dataCount);
34 xAxisData.resize(dataCount);
35
35
36 auto valuesData = QVector<double>{};
36 auto valuesData = QVector<double>{};
37 valuesData.resize(dataCount);
37 valuesData.resize(dataCount);
38
38
39 int progress = 0;
39 int progress = 0;
40 auto progressEnd = dataCount;
40 auto progressEnd = dataCount;
41 for (auto time = start; time < end; ++time, ++dataIndex) {
41 for (auto time = start; time < end; ++time, ++dataIndex) {
42 auto it = m_VariableToEnableProvider.find(acqIdentifier);
42 auto it = m_VariableToEnableProvider.find(acqIdentifier);
43 if (it != m_VariableToEnableProvider.end() && it.value()) {
43 if (it != m_VariableToEnableProvider.end() && it.value()) {
44 const auto timeOnFreq = time / freq;
44 const auto timeOnFreq = time / freq;
45
45
46 xAxisData.replace(dataIndex, timeOnFreq);
46 xAxisData.replace(dataIndex, timeOnFreq);
47 valuesData.replace(dataIndex, std::cos(timeOnFreq));
47 valuesData.replace(dataIndex, std::cos(timeOnFreq));
48
48
49 // progression
49 // progression
50 int currentProgress = (time - start) * 100.0 / progressEnd;
50 int currentProgress = (time - start) * 100.0 / progressEnd;
51 if (currentProgress != progress) {
51 if (currentProgress != progress) {
52 progress = currentProgress;
52 progress = currentProgress;
53
53
54 emit dataProvidedProgress(acqIdentifier, progress);
54 emit dataProvidedProgress(acqIdentifier, progress);
55 }
55 }
56 }
56 }
57 else {
57 else {
58 if (!it.value()) {
58 if (!it.value()) {
59 qCDebug(LOG_CosinusProvider())
59 qCDebug(LOG_CosinusProvider())
60 << "CosinusProvider::retrieveData: ARRET De l'acquisition detectΓ©"
60 << "CosinusProvider::retrieveData: ARRET De l'acquisition detectΓ©"
61 << end - time;
61 << end - time;
62 }
62 }
63 }
63 }
64 }
64 }
65 emit dataProvidedProgress(acqIdentifier, 0.0);
65 emit dataProvidedProgress(acqIdentifier, 0.0);
66
66
67 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
67 return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData),
68 Unit{QStringLiteral("t"), true}, Unit{});
68 Unit{QStringLiteral("t"), true}, Unit{});
69 }
69 }
70
70
71 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
71 void CosinusProvider::requestDataLoading(QUuid acqIdentifier,
72 const DataProviderParameters &parameters)
72 const DataProviderParameters &parameters)
73 {
73 {
74 // TODO: Add Mutex
74 // TODO: Add Mutex
75 m_VariableToEnableProvider[acqIdentifier] = true;
75 m_VariableToEnableProvider[acqIdentifier] = true;
76 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
76 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::requestDataLoading"
77 << QThread::currentThread()->objectName();
77 << QThread::currentThread()->objectName();
78 // NOTE: Try to use multithread if possible
78 // NOTE: Try to use multithread if possible
79 const auto times = parameters.m_Times;
79 const auto times = parameters.m_Times;
80
80
81 for (const auto &dateTime : qAsConst(times)) {
81 for (const auto &dateTime : qAsConst(times)) {
82 if (m_VariableToEnableProvider[acqIdentifier]) {
82 if (m_VariableToEnableProvider[acqIdentifier]) {
83 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime);
83 auto scalarSeries = this->retrieveData(acqIdentifier, dateTime);
84 qCCritical(LOG_CosinusProvider()) << "CosinusProvider::dataProvided";
84 qCDebug(LOG_CosinusProvider()) << "TORM: CosinusProvider::dataProvided";
85 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
85 emit dataProvided(acqIdentifier, scalarSeries, dateTime);
86 }
86 }
87 }
87 }
88 }
88 }
89
89
90 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
90 void CosinusProvider::requestDataAborting(QUuid acqIdentifier)
91 {
91 {
92 // TODO: Add Mutex
92 // TODO: Add Mutex
93 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
93 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataAborting" << acqIdentifier
94 << QThread::currentThread()->objectName();
94 << QThread::currentThread()->objectName();
95 auto it = m_VariableToEnableProvider.find(acqIdentifier);
95 auto it = m_VariableToEnableProvider.find(acqIdentifier);
96 if (it != m_VariableToEnableProvider.end()) {
96 if (it != m_VariableToEnableProvider.end()) {
97 it.value() = false;
97 it.value() = false;
98 }
98 }
99 else {
99 else {
100 qCWarning(LOG_CosinusProvider())
100 qCWarning(LOG_CosinusProvider())
101 << tr("Aborting progression of inexistant identifier detected !!!");
101 << tr("Aborting progression of inexistant identifier detected !!!");
102 }
102 }
103 }
103 }
General Comments 0
You need to be logged in to leave comments. Login now