##// END OF EJS Templates
Merge branch 'feature/ImprovePerf' into develop
Alexandre Leroux -
r615:4575ac2a0a6a merge
parent child
Show More
@@ -1,43 +1,56
1 #ifndef SCIQLOP_SQPRANGE_H
1 #ifndef SCIQLOP_SQPRANGE_H
2 #define SCIQLOP_SQPRANGE_H
2 #define SCIQLOP_SQPRANGE_H
3
3
4 #include <QObject>
4 #include <QObject>
5
5
6 #include <QDebug>
6 #include <QDebug>
7
7
8 #include <Common/DateUtils.h>
8 #include <Common/DateUtils.h>
9 #include <Common/MetaTypes.h>
9 #include <Common/MetaTypes.h>
10
10
11 /**
11 /**
12 * @brief The SqpRange struct holds the information of time parameters
12 * @brief The SqpRange struct holds the information of time parameters
13 */
13 */
14 struct SqpRange {
14 struct SqpRange {
15 /// Start time (UTC)
15 /// Start time (UTC)
16 double m_TStart;
16 double m_TStart;
17 /// End time (UTC)
17 /// End time (UTC)
18 double m_TEnd;
18 double m_TEnd;
19
19
20 bool contains(const SqpRange &dateTime) const noexcept
20 bool contains(const SqpRange &dateTime) const noexcept
21 {
21 {
22 return (m_TStart <= dateTime.m_TStart && m_TEnd >= dateTime.m_TEnd);
22 return (m_TStart <= dateTime.m_TStart && m_TEnd >= dateTime.m_TEnd);
23 }
23 }
24
24
25 bool intersect(const SqpRange &dateTime) const noexcept
25 bool intersect(const SqpRange &dateTime) const noexcept
26 {
26 {
27 return (m_TEnd >= dateTime.m_TStart && m_TStart <= dateTime.m_TEnd);
27 return (m_TEnd >= dateTime.m_TStart && m_TStart <= dateTime.m_TEnd);
28 }
28 }
29
30 bool operator==(const SqpRange &other) const
31 {
32 auto equals = [](const auto &v1, const auto &v2) {
33 return (std::isnan(v1) && std::isnan(v2)) || v1 == v2;
34 };
35
36 return equals(m_TStart, other.m_TStart) && equals(m_TEnd, other.m_TEnd);
37 }
38 bool operator!=(const SqpRange &other) const { return !(*this == other); }
29 };
39 };
30
40
41 const auto INVALID_RANGE
42 = SqpRange{std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()};
43
31 inline QDebug operator<<(QDebug d, SqpRange obj)
44 inline QDebug operator<<(QDebug d, SqpRange obj)
32 {
45 {
33 auto tendDateTimeStart = DateUtils::dateTime(obj.m_TStart);
46 auto tendDateTimeStart = DateUtils::dateTime(obj.m_TStart);
34 auto tendDateTimeEnd = DateUtils::dateTime(obj.m_TEnd);
47 auto tendDateTimeEnd = DateUtils::dateTime(obj.m_TEnd);
35
48
36 d << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd;
49 d << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd;
37 return d;
50 return d;
38 }
51 }
39
52
40 // Required for using shared_ptr in signals/slots
53 // Required for using shared_ptr in signals/slots
41 SCIQLOP_REGISTER_META_TYPE(SQPRANGE_REGISTRY, SqpRange)
54 SCIQLOP_REGISTER_META_TYPE(SQPRANGE_REGISTRY, SqpRange)
42
55
43 #endif // SCIQLOP_SQPRANGE_H
56 #endif // SCIQLOP_SQPRANGE_H
@@ -1,66 +1,75
1 #ifndef SCIQLOP_VARIABLE_H
1 #ifndef SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
2 #define SCIQLOP_VARIABLE_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/DataSeriesIterator.h>
6 #include <Data/SqpRange.h>
7 #include <Data/SqpRange.h>
7
8
8 #include <QLoggingCategory>
9 #include <QLoggingCategory>
9 #include <QObject>
10 #include <QObject>
10
11
11 #include <Common/MetaTypes.h>
12 #include <Common/MetaTypes.h>
12 #include <Common/spimpl.h>
13 #include <Common/spimpl.h>
13
14
14 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
15 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
15
16
16 class IDataSeries;
17 class IDataSeries;
17 class QString;
18 class QString;
18
19
19 /**
20 /**
20 * @brief The Variable class represents a variable in SciQlop.
21 * @brief The Variable class represents a variable in SciQlop.
21 */
22 */
22 class SCIQLOP_CORE_EXPORT Variable : public QObject {
23 class SCIQLOP_CORE_EXPORT Variable : public QObject {
23
24
24 Q_OBJECT
25 Q_OBJECT
25
26
26 public:
27 public:
27 explicit Variable(const QString &name, const SqpRange &dateTime,
28 explicit Variable(const QString &name, const SqpRange &dateTime,
28 const QVariantHash &metadata = {});
29 const QVariantHash &metadata = {});
29
30
30 QString name() const noexcept;
31 QString name() const noexcept;
31 SqpRange range() const noexcept;
32 SqpRange range() const noexcept;
32 void setRange(const SqpRange &range) noexcept;
33 void setRange(const SqpRange &range) noexcept;
33 SqpRange cacheRange() const noexcept;
34 SqpRange cacheRange() const noexcept;
34 void setCacheRange(const SqpRange &cacheRange) noexcept;
35 void setCacheRange(const SqpRange &cacheRange) noexcept;
35
36
37 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
38 /// series between the range of the variable. The real range is updated each time the variable
39 /// range or the data series changed
40 /// @return the real range, invalid range if the data series is null or empty
41 /// @sa setDataSeries()
42 /// @sa setRange()
43 SqpRange realRange() const noexcept;
44
36 /// @return the data of the variable, nullptr if there is no data
45 /// @return the data of the variable, nullptr if there is no data
37 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
46 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
38
47
39 QVariantHash metadata() const noexcept;
48 QVariantHash metadata() const noexcept;
40
49
41 bool contains(const SqpRange &range) const noexcept;
50 bool contains(const SqpRange &range) const noexcept;
42 bool intersect(const SqpRange &range) const noexcept;
51 bool intersect(const SqpRange &range) const noexcept;
43 bool isInside(const SqpRange &range) const noexcept;
52 bool isInside(const SqpRange &range) const noexcept;
44
53
45 bool cacheContains(const SqpRange &range) const noexcept;
54 bool cacheContains(const SqpRange &range) const noexcept;
46 bool cacheIntersect(const SqpRange &range) const noexcept;
55 bool cacheIntersect(const SqpRange &range) const noexcept;
47 bool cacheIsInside(const SqpRange &range) const noexcept;
56 bool cacheIsInside(const SqpRange &range) const noexcept;
48
57
49 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
58 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
50 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
59 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
51 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
60 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
52 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
61 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
53
62
54 signals:
63 signals:
55 void updated();
64 void updated();
56
65
57 private:
66 private:
58 class VariablePrivate;
67 class VariablePrivate;
59 spimpl::unique_impl_ptr<VariablePrivate> impl;
68 spimpl::unique_impl_ptr<VariablePrivate> impl;
60 };
69 };
61
70
62 // Required for using shared_ptr in signals/slots
71 // Required for using shared_ptr in signals/slots
63 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
72 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
64 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
73 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
65
74
66 #endif // SCIQLOP_VARIABLE_H
75 #endif // SCIQLOP_VARIABLE_H
@@ -1,61 +1,61
1 #ifndef SCIQLOP_VARIABLEACQUISITIONWORKER_H
1 #ifndef SCIQLOP_VARIABLEACQUISITIONWORKER_H
2 #define SCIQLOP_VARIABLEACQUISITIONWORKER_H
2 #define SCIQLOP_VARIABLEACQUISITIONWORKER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/DataProviderParameters.h>
6 #include <Data/DataProviderParameters.h>
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8 #include <QObject>
8 #include <QObject>
9 #include <QUuid>
9 #include <QUuid>
10
10
11 #include <Data/AcquisitionDataPacket.h>
11 #include <Data/AcquisitionDataPacket.h>
12 #include <Data/IDataSeries.h>
12 #include <Data/IDataSeries.h>
13 #include <Data/SqpRange.h>
13 #include <Data/SqpRange.h>
14
14
15 #include <QLoggingCategory>
15 #include <QLoggingCategory>
16
16
17 #include <Common/spimpl.h>
17 #include <Common/spimpl.h>
18
18
19 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker)
19 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker)
20
20
21 class Variable;
21 class Variable;
22 class IDataProvider;
22 class IDataProvider;
23
23
24 /// This class aims to handle all acquisition request
24 /// This class aims to handle all acquisition request
25 class SCIQLOP_CORE_EXPORT VariableAcquisitionWorker : public QObject {
25 class SCIQLOP_CORE_EXPORT VariableAcquisitionWorker : public QObject {
26 Q_OBJECT
26 Q_OBJECT
27 public:
27 public:
28 explicit VariableAcquisitionWorker(QObject *parent = 0);
28 explicit VariableAcquisitionWorker(QObject *parent = 0);
29 virtual ~VariableAcquisitionWorker();
29 virtual ~VariableAcquisitionWorker();
30
30
31 QUuid pushVariableRequest(QUuid varRequestId, QUuid vIdentifier, SqpRange rangeRequested,
31 QUuid pushVariableRequest(QUuid varRequestId, QUuid vIdentifier, SqpRange rangeRequested,
32 SqpRange cacheRangeRequested, DataProviderParameters parameters,
32 SqpRange cacheRangeRequested, DataProviderParameters parameters,
33 std::shared_ptr<IDataProvider> provider);
33 std::shared_ptr<IDataProvider> provider);
34
34
35 void abortProgressRequested(QUuid vIdentifier);
35 void abortProgressRequested(QUuid vIdentifier);
36
36
37 void initialize();
37 void initialize();
38 void finalize();
38 void finalize();
39 signals:
39 signals:
40 void dataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
40 void dataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
41 const SqpRange &cacheRangeRequested,
41 const SqpRange &cacheRangeRequested,
42 QVector<AcquisitionDataPacket> dataAcquired);
42 QVector<AcquisitionDataPacket> dataAcquired);
43
43
44 void variableRequestInProgress(QUuid vIdentifier, double progress);
44 void variableRequestInProgress(QUuid vIdentifier, double progress);
45
45
46 public slots:
46 public slots:
47 void onVariableDataAcquired(QUuid acqIdentifier, std::shared_ptr<IDataSeries> dataSeries,
47 void onVariableDataAcquired(QUuid acqIdentifier, std::shared_ptr<IDataSeries> dataSeries,
48 SqpRange dataRangeAcquired);
48 SqpRange dataRangeAcquired);
49 void onVariableRetrieveDataInProgress(QUuid acqIdentifier, double progress);
49 void onVariableRetrieveDataInProgress(QUuid acqIdentifier, double progress);
50
50
51 private slots:
52 void onExecuteRequest(QUuid acqIdentifier);
53
54 private:
51 private:
55 void waitForFinish();
52 void waitForFinish();
56
53
57 class VariableAcquisitionWorkerPrivate;
54 class VariableAcquisitionWorkerPrivate;
58 spimpl::unique_impl_ptr<VariableAcquisitionWorkerPrivate> impl;
55 spimpl::unique_impl_ptr<VariableAcquisitionWorkerPrivate> impl;
56
57 private slots:
58 void onExecuteRequest(QUuid acqIdentifier);
59 };
59 };
60
60
61 #endif // SCIQLOP_VARIABLEACQUISITIONWORKER_H
61 #endif // SCIQLOP_VARIABLEACQUISITIONWORKER_H
@@ -1,248 +1,279
1 #include "Variable/Variable.h"
1 #include "Variable/Variable.h"
2
2
3 #include <Data/IDataSeries.h>
3 #include <Data/IDataSeries.h>
4 #include <Data/SqpRange.h>
4 #include <Data/SqpRange.h>
5
5
6 #include <QMutex>
6 #include <QMutex>
7 #include <QReadWriteLock>
7 #include <QReadWriteLock>
8 #include <QThread>
8 #include <QThread>
9
9
10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
11
11
12 struct Variable::VariablePrivate {
12 struct Variable::VariablePrivate {
13 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
13 explicit VariablePrivate(const QString &name, const SqpRange &dateTime,
14 const QVariantHash &metadata)
14 const QVariantHash &metadata)
15 : m_Name{name}, m_Range{dateTime}, m_Metadata{metadata}, m_DataSeries{nullptr}
15 : m_Name{name},
16 m_Range{dateTime},
17 m_Metadata{metadata},
18 m_DataSeries{nullptr},
19 m_RealRange{INVALID_RANGE}
16 {
20 {
17 }
21 }
18
22
19 void lockRead() { m_Lock.lockForRead(); }
23 void lockRead() { m_Lock.lockForRead(); }
20 void lockWrite() { m_Lock.lockForWrite(); }
24 void lockWrite() { m_Lock.lockForWrite(); }
21 void unlock() { m_Lock.unlock(); }
25 void unlock() { m_Lock.unlock(); }
22
26
27 /// Updates real range according to current variable range and data series
28 void updateRealRange()
29 {
30 if (m_DataSeries) {
31 m_DataSeries->lockRead();
32 auto end = m_DataSeries->cend();
33 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
34 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
35
36 m_RealRange = (minXAxisIt != end && maxXAxisIt != end)
37 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
38 : INVALID_RANGE;
39 m_DataSeries->unlock();
40 }
41 else {
42 m_RealRange = INVALID_RANGE;
43 }
44 }
45
23 QString m_Name;
46 QString m_Name;
24
47
25 SqpRange m_Range;
48 SqpRange m_Range;
26 SqpRange m_CacheRange;
49 SqpRange m_CacheRange;
27 QVariantHash m_Metadata;
50 QVariantHash m_Metadata;
28 std::shared_ptr<IDataSeries> m_DataSeries;
51 std::shared_ptr<IDataSeries> m_DataSeries;
52 SqpRange m_RealRange;
29
53
30 QReadWriteLock m_Lock;
54 QReadWriteLock m_Lock;
31 };
55 };
32
56
33 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
57 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
34 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
58 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
35 {
59 {
36 }
60 }
37
61
38 QString Variable::name() const noexcept
62 QString Variable::name() const noexcept
39 {
63 {
40 impl->lockRead();
64 impl->lockRead();
41 auto name = impl->m_Name;
65 auto name = impl->m_Name;
42 impl->unlock();
66 impl->unlock();
43 return name;
67 return name;
44 }
68 }
45
69
46 SqpRange Variable::range() const noexcept
70 SqpRange Variable::range() const noexcept
47 {
71 {
48 impl->lockRead();
72 impl->lockRead();
49 auto range = impl->m_Range;
73 auto range = impl->m_Range;
50 impl->unlock();
74 impl->unlock();
51 return range;
75 return range;
52 }
76 }
53
77
54 void Variable::setRange(const SqpRange &range) noexcept
78 void Variable::setRange(const SqpRange &range) noexcept
55 {
79 {
56 impl->lockWrite();
80 impl->lockWrite();
57 impl->m_Range = range;
81 impl->m_Range = range;
82 impl->updateRealRange();
58 impl->unlock();
83 impl->unlock();
59 }
84 }
60
85
61 SqpRange Variable::cacheRange() const noexcept
86 SqpRange Variable::cacheRange() const noexcept
62 {
87 {
63 impl->lockRead();
88 impl->lockRead();
64 auto cacheRange = impl->m_CacheRange;
89 auto cacheRange = impl->m_CacheRange;
65 impl->unlock();
90 impl->unlock();
66 return cacheRange;
91 return cacheRange;
67 }
92 }
68
93
69 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
94 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
70 {
95 {
71 impl->lockWrite();
96 impl->lockWrite();
72 impl->m_CacheRange = cacheRange;
97 impl->m_CacheRange = cacheRange;
73 impl->unlock();
98 impl->unlock();
74 }
99 }
75
100
101 SqpRange Variable::realRange() const noexcept
102 {
103 return impl->m_RealRange;
104 }
105
76 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
106 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
77 {
107 {
78 qCDebug(LOG_Variable()) << "TORM Variable::setDataSeries"
108 qCDebug(LOG_Variable()) << "TORM Variable::setDataSeries"
79 << QThread::currentThread()->objectName();
109 << QThread::currentThread()->objectName();
80 if (!dataSeries) {
110 if (!dataSeries) {
81 /// @todo ALX : log
111 /// @todo ALX : log
82 return;
112 return;
83 }
113 }
84 impl->lockWrite();
114 impl->lockWrite();
85 impl->m_DataSeries = dataSeries->clone();
115 impl->m_DataSeries = dataSeries->clone();
116 impl->updateRealRange();
86 impl->unlock();
117 impl->unlock();
87 }
118 }
88
119
89 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
120 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
90 {
121 {
91 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
122 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
92 << QThread::currentThread()->objectName();
123 << QThread::currentThread()->objectName();
93 if (!dataSeries) {
124 if (!dataSeries) {
94 /// @todo ALX : log
125 /// @todo ALX : log
95 return;
126 return;
96 }
127 }
97
128
98 // Add or merge the data
129 // Add or merge the data
99 // Inits the data series of the variable
130 // Inits the data series of the variable
100 impl->lockWrite();
131 impl->lockWrite();
101 if (!impl->m_DataSeries) {
132 if (!impl->m_DataSeries) {
102 impl->m_DataSeries = dataSeries->clone();
133 impl->m_DataSeries = dataSeries->clone();
103 }
134 }
104 else {
135 else {
105 impl->m_DataSeries->merge(dataSeries.get());
136 impl->m_DataSeries->merge(dataSeries.get());
106 }
137 }
107 impl->unlock();
138 impl->unlock();
108
139
109 // sub the data
140 // sub the data
110 auto subData = this->dataSeries()->subDataSeries(this->cacheRange());
141 auto subData = this->dataSeries()->subDataSeries(this->cacheRange());
111 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries sub" << subData->range();
142 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries sub" << subData->range();
112 this->setDataSeries(subData);
143 this->setDataSeries(subData);
113 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries set" << this->dataSeries()->range();
144 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries set" << this->dataSeries()->range();
114 }
145 }
115
146
116 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
147 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
117 {
148 {
118 impl->lockRead();
149 impl->lockRead();
119 auto dataSeries = impl->m_DataSeries;
150 auto dataSeries = impl->m_DataSeries;
120 impl->unlock();
151 impl->unlock();
121
152
122 return dataSeries;
153 return dataSeries;
123 }
154 }
124
155
125 QVariantHash Variable::metadata() const noexcept
156 QVariantHash Variable::metadata() const noexcept
126 {
157 {
127 impl->lockRead();
158 impl->lockRead();
128 auto metadata = impl->m_Metadata;
159 auto metadata = impl->m_Metadata;
129 impl->unlock();
160 impl->unlock();
130 return metadata;
161 return metadata;
131 }
162 }
132
163
133 bool Variable::contains(const SqpRange &range) const noexcept
164 bool Variable::contains(const SqpRange &range) const noexcept
134 {
165 {
135 impl->lockRead();
166 impl->lockRead();
136 auto res = impl->m_Range.contains(range);
167 auto res = impl->m_Range.contains(range);
137 impl->unlock();
168 impl->unlock();
138 return res;
169 return res;
139 }
170 }
140
171
141 bool Variable::intersect(const SqpRange &range) const noexcept
172 bool Variable::intersect(const SqpRange &range) const noexcept
142 {
173 {
143
174
144 impl->lockRead();
175 impl->lockRead();
145 auto res = impl->m_Range.intersect(range);
176 auto res = impl->m_Range.intersect(range);
146 impl->unlock();
177 impl->unlock();
147 return res;
178 return res;
148 }
179 }
149
180
150 bool Variable::isInside(const SqpRange &range) const noexcept
181 bool Variable::isInside(const SqpRange &range) const noexcept
151 {
182 {
152 impl->lockRead();
183 impl->lockRead();
153 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
184 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
154 impl->unlock();
185 impl->unlock();
155 return res;
186 return res;
156 }
187 }
157
188
158 bool Variable::cacheContains(const SqpRange &range) const noexcept
189 bool Variable::cacheContains(const SqpRange &range) const noexcept
159 {
190 {
160 impl->lockRead();
191 impl->lockRead();
161 auto res = impl->m_CacheRange.contains(range);
192 auto res = impl->m_CacheRange.contains(range);
162 impl->unlock();
193 impl->unlock();
163 return res;
194 return res;
164 }
195 }
165
196
166 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
197 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
167 {
198 {
168 impl->lockRead();
199 impl->lockRead();
169 auto res = impl->m_CacheRange.intersect(range);
200 auto res = impl->m_CacheRange.intersect(range);
170 impl->unlock();
201 impl->unlock();
171 return res;
202 return res;
172 }
203 }
173
204
174 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
205 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
175 {
206 {
176 impl->lockRead();
207 impl->lockRead();
177 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
208 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
178 impl->unlock();
209 impl->unlock();
179 return res;
210 return res;
180 }
211 }
181
212
182
213
183 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
214 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
184 {
215 {
185 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
216 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
186
217
187 auto notInCache = QVector<SqpRange>{};
218 auto notInCache = QVector<SqpRange>{};
188
219
189 if (!this->cacheContains(range)) {
220 if (!this->cacheContains(range)) {
190 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
221 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
191 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
222 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
192 notInCache << range;
223 notInCache << range;
193 }
224 }
194 else if (range.m_TStart < impl->m_CacheRange.m_TStart
225 else if (range.m_TStart < impl->m_CacheRange.m_TStart
195 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
226 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
196 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
227 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
197 }
228 }
198 else if (range.m_TStart < impl->m_CacheRange.m_TStart
229 else if (range.m_TStart < impl->m_CacheRange.m_TStart
199 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
230 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
200 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
231 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
201 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
232 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
202 }
233 }
203 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
234 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
204 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
235 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
205 }
236 }
206 else {
237 else {
207 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
238 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
208 << QThread::currentThread();
239 << QThread::currentThread();
209 }
240 }
210 }
241 }
211
242
212 return notInCache;
243 return notInCache;
213 }
244 }
214
245
215 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
246 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
216 {
247 {
217 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
248 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
218
249
219 auto inCache = QVector<SqpRange>{};
250 auto inCache = QVector<SqpRange>{};
220
251
221
252
222 if (this->intersect(range)) {
253 if (this->intersect(range)) {
223 if (range.m_TStart <= impl->m_CacheRange.m_TStart
254 if (range.m_TStart <= impl->m_CacheRange.m_TStart
224 && range.m_TEnd >= impl->m_CacheRange.m_TStart
255 && range.m_TEnd >= impl->m_CacheRange.m_TStart
225 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
256 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
226 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
257 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
227 }
258 }
228
259
229 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
260 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
230 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
261 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
231 inCache << range;
262 inCache << range;
232 }
263 }
233 else if (range.m_TStart > impl->m_CacheRange.m_TStart
264 else if (range.m_TStart > impl->m_CacheRange.m_TStart
234 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
265 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
235 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
266 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
236 }
267 }
237 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
268 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
238 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
269 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
239 inCache << impl->m_CacheRange;
270 inCache << impl->m_CacheRange;
240 }
271 }
241 else {
272 else {
242 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
273 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
243 << QThread::currentThread();
274 << QThread::currentThread();
244 }
275 }
245 }
276 }
246
277
247 return inCache;
278 return inCache;
248 }
279 }
@@ -1,238 +1,238
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 QUuid VariableAcquisitionWorker::pushVariableRequest(QUuid varRequestId, QUuid vIdentifier,
49 QUuid VariableAcquisitionWorker::pushVariableRequest(QUuid varRequestId, QUuid vIdentifier,
50 SqpRange rangeRequested,
50 SqpRange rangeRequested,
51 SqpRange cacheRangeRequested,
51 SqpRange cacheRangeRequested,
52 DataProviderParameters parameters,
52 DataProviderParameters parameters,
53 std::shared_ptr<IDataProvider> provider)
53 std::shared_ptr<IDataProvider> provider)
54 {
54 {
55 qCDebug(LOG_VariableAcquisitionWorker())
55 qCDebug(LOG_VariableAcquisitionWorker())
56 << tr("TORM VariableAcquisitionWorker::pushVariableRequest ") << cacheRangeRequested;
56 << tr("TORM VariableAcquisitionWorker::pushVariableRequest ") << cacheRangeRequested;
57 auto varRequestIdCanceled = QUuid();
57 auto varRequestIdCanceled = QUuid();
58
58
59 // Request creation
59 // Request creation
60 auto acqRequest = AcquisitionRequest{};
60 auto acqRequest = AcquisitionRequest{};
61 acqRequest.m_VarRequestId = varRequestId;
61 acqRequest.m_VarRequestId = varRequestId;
62 acqRequest.m_vIdentifier = vIdentifier;
62 acqRequest.m_vIdentifier = vIdentifier;
63 acqRequest.m_DataProviderParameters = parameters;
63 acqRequest.m_DataProviderParameters = parameters;
64 acqRequest.m_RangeRequested = rangeRequested;
64 acqRequest.m_RangeRequested = rangeRequested;
65 acqRequest.m_CacheRangeRequested = cacheRangeRequested;
65 acqRequest.m_CacheRangeRequested = cacheRangeRequested;
66 acqRequest.m_Size = parameters.m_Times.size();
66 acqRequest.m_Size = parameters.m_Times.size();
67 acqRequest.m_Provider = provider;
67 acqRequest.m_Provider = provider;
68
68
69
69
70 // Register request
70 // Register request
71 impl->lockWrite();
71 impl->lockWrite();
72 impl->m_AcqIdentifierToAcqRequestMap.insert(
72 impl->m_AcqIdentifierToAcqRequestMap.insert(
73 std::make_pair(acqRequest.m_AcqIdentifier, acqRequest));
73 std::make_pair(acqRequest.m_AcqIdentifier, acqRequest));
74
74
75 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
75 auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
76 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
76 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
77 // A current request already exists, we can replace the next one
77 // A current request already exists, we can replace the next one
78 auto nextAcqId = it->second.second;
78 auto nextAcqId = it->second.second;
79 auto acqIdentifierToAcqRequestMapIt = impl->m_AcqIdentifierToAcqRequestMap.find(nextAcqId);
79 auto acqIdentifierToAcqRequestMapIt = impl->m_AcqIdentifierToAcqRequestMap.find(nextAcqId);
80 if (acqIdentifierToAcqRequestMapIt != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
80 if (acqIdentifierToAcqRequestMapIt != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
81 auto request = acqIdentifierToAcqRequestMapIt->second;
81 auto request = acqIdentifierToAcqRequestMapIt->second;
82 varRequestIdCanceled = request.m_VarRequestId;
82 varRequestIdCanceled = request.m_VarRequestId;
83 }
83 }
84
84
85 it->second.second = acqRequest.m_AcqIdentifier;
85 it->second.second = acqRequest.m_AcqIdentifier;
86 impl->unlock();
86 impl->unlock();
87 }
87 }
88 else {
88 else {
89 // First request for the variable, it must be stored and executed
89 // First request for the variable, it must be stored and executed
90 impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.insert(
90 impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.insert(
91 std::make_pair(vIdentifier, std::make_pair(acqRequest.m_AcqIdentifier, QUuid())));
91 std::make_pair(vIdentifier, std::make_pair(acqRequest.m_AcqIdentifier, QUuid())));
92 impl->unlock();
92 impl->unlock();
93
93
94 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
94 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
95 Q_ARG(QUuid, acqRequest.m_AcqIdentifier));
95 Q_ARG(QUuid, acqRequest.m_AcqIdentifier));
96 }
96 }
97
97
98 return varRequestIdCanceled;
98 return varRequestIdCanceled;
99 }
99 }
100
100
101 void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier)
101 void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier)
102 {
102 {
103 // TODO
103 // TODO
104 }
104 }
105
105
106 void VariableAcquisitionWorker::onVariableRetrieveDataInProgress(QUuid acqIdentifier,
106 void VariableAcquisitionWorker::onVariableRetrieveDataInProgress(QUuid acqIdentifier,
107 double progress)
107 double progress)
108 {
108 {
109 // TODO
109 // TODO
110 }
110 }
111
111
112 void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier,
112 void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier,
113 std::shared_ptr<IDataSeries> dataSeries,
113 std::shared_ptr<IDataSeries> dataSeries,
114 SqpRange dataRangeAcquired)
114 SqpRange dataRangeAcquired)
115 {
115 {
116 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onVariableDataAcquired on range ")
116 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onVariableDataAcquired on range ")
117 << acqIdentifier << dataRangeAcquired;
117 << acqIdentifier << dataRangeAcquired;
118 impl->lockWrite();
118 impl->lockWrite();
119 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
119 auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
120 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
120 if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
121 // Store the result
121 // Store the result
122 auto dataPacket = AcquisitionDataPacket{};
122 auto dataPacket = AcquisitionDataPacket{};
123 dataPacket.m_Range = dataRangeAcquired;
123 dataPacket.m_Range = dataRangeAcquired;
124 dataPacket.m_DateSeries = dataSeries;
124 dataPacket.m_DateSeries = dataSeries;
125
125
126 auto aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
126 auto aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
127 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
127 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
128 // A current request result already exists, we can update it
128 // A current request result already exists, we can update it
129 aIdToADPVit->second.push_back(dataPacket);
129 aIdToADPVit->second.push_back(dataPacket);
130 }
130 }
131 else {
131 else {
132 // First request result for the variable, it must be stored
132 // First request result for the variable, it must be stored
133 impl->m_AcqIdentifierToAcqDataPacketVectorMap.insert(
133 impl->m_AcqIdentifierToAcqDataPacketVectorMap.insert(
134 std::make_pair(acqIdentifier, QVector<AcquisitionDataPacket>() << dataPacket));
134 std::make_pair(acqIdentifier, QVector<AcquisitionDataPacket>() << dataPacket));
135 }
135 }
136
136
137
137
138 // Decrement the counter of the request
138 // Decrement the counter of the request
139 auto &acqRequest = aIdToARit->second;
139 auto &acqRequest = aIdToARit->second;
140 acqRequest.m_Size = acqRequest.m_Size - 1;
140 acqRequest.m_Size = acqRequest.m_Size - 1;
141
141
142 // if the counter is 0, we can return data then run the next request if it exists and
142 // if the counter is 0, we can return data then run the next request if it exists and
143 // removed the finished request
143 // removed the finished request
144 if (acqRequest.m_Size == 0) {
144 if (acqRequest.m_Size == 0) {
145 // Return the data
145 // Return the data
146 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
146 aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier);
147 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
147 if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) {
148 emit dataProvided(acqRequest.m_vIdentifier, acqRequest.m_RangeRequested,
148 emit dataProvided(acqRequest.m_vIdentifier, acqRequest.m_RangeRequested,
149 acqRequest.m_CacheRangeRequested, aIdToADPVit->second);
149 acqRequest.m_CacheRangeRequested, aIdToADPVit->second);
150 }
150 }
151
151
152 // Execute the next one
152 // Execute the next one
153 auto it
153 auto it
154 = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(acqRequest.m_vIdentifier);
154 = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(acqRequest.m_vIdentifier);
155
155
156 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
156 if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
157 if (it->second.second.isNull()) {
157 if (it->second.second.isNull()) {
158 // There is no next request, we can remove the variable request
158 // There is no next request, we can remove the variable request
159 impl->removeVariableRequest(acqRequest.m_vIdentifier);
159 impl->removeVariableRequest(acqRequest.m_vIdentifier);
160 }
160 }
161 else {
161 else {
162 auto acqIdentifierToRemove = it->second.first;
162 auto acqIdentifierToRemove = it->second.first;
163 // Move the next request to the current request
163 // Move the next request to the current request
164 it->second.first = it->second.second;
164 it->second.first = it->second.second;
165 it->second.second = QUuid();
165 it->second.second = QUuid();
166 // Remove AcquisitionRequest and results;
166 // Remove AcquisitionRequest and results;
167 impl->m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
167 impl->m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove);
168 impl->m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
168 impl->m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove);
169 // Execute the current request
169 // Execute the current request
170 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
170 QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection,
171 Q_ARG(QUuid, it->second.first));
171 Q_ARG(QUuid, it->second.first));
172 }
172 }
173 }
173 }
174 else {
174 else {
175 qCCritical(LOG_VariableAcquisitionWorker())
175 qCCritical(LOG_VariableAcquisitionWorker())
176 << tr("Impossible to execute the acquisition on an unfound variable ");
176 << tr("Impossible to execute the acquisition on an unfound variable ");
177 }
177 }
178 }
178 }
179 }
179 }
180 else {
180 else {
181 qCCritical(LOG_VariableAcquisitionWorker())
181 qCCritical(LOG_VariableAcquisitionWorker())
182 << tr("Impossible to retrieve AcquisitionRequest for the incoming data");
182 << tr("Impossible to retrieve AcquisitionRequest for the incoming data");
183 }
183 }
184 impl->unlock();
184 impl->unlock();
185 }
185 }
186
186
187 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
188 {
189 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread();
190 impl->lockRead();
191 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
192 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
193 auto request = it->second;
194 impl->unlock();
195 request.m_Provider->requestDataLoading(acqIdentifier, request.m_DataProviderParameters);
196 }
197 else {
198 impl->unlock();
199 // TODO log no acqIdentifier recognized
200 }
201 }
202
203 void VariableAcquisitionWorker::initialize()
187 void VariableAcquisitionWorker::initialize()
204 {
188 {
205 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init")
189 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init")
206 << QThread::currentThread();
190 << QThread::currentThread();
207 impl->m_WorkingMutex.lock();
191 impl->m_WorkingMutex.lock();
208 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init END");
192 qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init END");
209 }
193 }
210
194
211 void VariableAcquisitionWorker::finalize()
195 void VariableAcquisitionWorker::finalize()
212 {
196 {
213 impl->m_WorkingMutex.unlock();
197 impl->m_WorkingMutex.unlock();
214 }
198 }
215
199
216 void VariableAcquisitionWorker::waitForFinish()
200 void VariableAcquisitionWorker::waitForFinish()
217 {
201 {
218 QMutexLocker locker{&impl->m_WorkingMutex};
202 QMutexLocker locker{&impl->m_WorkingMutex};
219 }
203 }
220
204
221 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariableRequest(
205 void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariableRequest(
222 QUuid vIdentifier)
206 QUuid vIdentifier)
223 {
207 {
224 lockWrite();
208 lockWrite();
225 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
209 auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier);
226
210
227 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
211 if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) {
228 // A current request already exists, we can replace the next one
212 // A current request already exists, we can replace the next one
229
213
230 m_AcqIdentifierToAcqRequestMap.erase(it->second.first);
214 m_AcqIdentifierToAcqRequestMap.erase(it->second.first);
231 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.first);
215 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.first);
232
216
233 m_AcqIdentifierToAcqRequestMap.erase(it->second.second);
217 m_AcqIdentifierToAcqRequestMap.erase(it->second.second);
234 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.second);
218 m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.second);
235 }
219 }
236 m_VIdentifierToCurrrentAcqIdNextIdPairMap.erase(vIdentifier);
220 m_VIdentifierToCurrrentAcqIdNextIdPairMap.erase(vIdentifier);
237 unlock();
221 unlock();
238 }
222 }
223
224 void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier)
225 {
226 qCDebug(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread();
227 impl->lockRead();
228 auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier);
229 if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) {
230 auto request = it->second;
231 impl->unlock();
232 request.m_Provider->requestDataLoading(acqIdentifier, request.m_DataProviderParameters);
233 }
234 else {
235 impl->unlock();
236 // TODO log no acqIdentifier recognized
237 }
238 }
@@ -1,274 +1,260
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableModel.h>
2 #include <Variable/VariableModel.h>
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5
5
6 #include <Data/IDataSeries.h>
6 #include <Data/IDataSeries.h>
7
7
8 #include <QSize>
8 #include <QSize>
9 #include <unordered_map>
9 #include <unordered_map>
10
10
11 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
11 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
12
12
13 namespace {
13 namespace {
14
14
15 // Column indexes
15 // Column indexes
16 const auto NAME_COLUMN = 0;
16 const auto NAME_COLUMN = 0;
17 const auto TSTART_COLUMN = 1;
17 const auto TSTART_COLUMN = 1;
18 const auto TEND_COLUMN = 2;
18 const auto TEND_COLUMN = 2;
19 const auto UNIT_COLUMN = 3;
19 const auto UNIT_COLUMN = 3;
20 const auto MISSION_COLUMN = 4;
20 const auto MISSION_COLUMN = 4;
21 const auto PLUGIN_COLUMN = 5;
21 const auto PLUGIN_COLUMN = 5;
22 const auto NB_COLUMNS = 6;
22 const auto NB_COLUMNS = 6;
23
23
24 // Column properties
24 // Column properties
25 const auto DEFAULT_HEIGHT = 25;
25 const auto DEFAULT_HEIGHT = 25;
26 const auto DEFAULT_WIDTH = 100;
26 const auto DEFAULT_WIDTH = 100;
27
27
28 struct ColumnProperties {
28 struct ColumnProperties {
29 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
29 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
30 int height = DEFAULT_HEIGHT)
30 int height = DEFAULT_HEIGHT)
31 : m_Name{name}, m_Width{width}, m_Height{height}
31 : m_Name{name}, m_Width{width}, m_Height{height}
32 {
32 {
33 }
33 }
34
34
35 QString m_Name;
35 QString m_Name;
36 int m_Width;
36 int m_Width;
37 int m_Height;
37 int m_Height;
38 };
38 };
39
39
40 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
40 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
41 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
41 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
42 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {UNIT_COLUMN, {QObject::tr("Unit")}},
42 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {UNIT_COLUMN, {QObject::tr("Unit")}},
43 {MISSION_COLUMN, {QObject::tr("Mission")}}, {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
43 {MISSION_COLUMN, {QObject::tr("Mission")}}, {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
44
44
45 /// Format for datetimes
45 /// Format for datetimes
46 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
46 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
47
47
48
48
49 } // namespace
49 } // namespace
50
50
51 struct VariableModel::VariableModelPrivate {
51 struct VariableModel::VariableModelPrivate {
52 /// Variables created in SciQlop
52 /// Variables created in SciQlop
53 std::vector<std::shared_ptr<Variable> > m_Variables;
53 std::vector<std::shared_ptr<Variable> > m_Variables;
54 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
54 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
55
55
56 /// Return the row index of the variable. -1 if it's not found
56 /// Return the row index of the variable. -1 if it's not found
57 int indexOfVariable(Variable *variable) const noexcept;
57 int indexOfVariable(Variable *variable) const noexcept;
58 };
58 };
59
59
60 VariableModel::VariableModel(QObject *parent)
60 VariableModel::VariableModel(QObject *parent)
61 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
61 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
62 {
62 {
63 }
63 }
64
64
65 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
65 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
66 const SqpRange &dateTime,
66 const SqpRange &dateTime,
67 const QVariantHash &metadata) noexcept
67 const QVariantHash &metadata) noexcept
68 {
68 {
69 auto insertIndex = rowCount();
69 auto insertIndex = rowCount();
70 beginInsertRows({}, insertIndex, insertIndex);
70 beginInsertRows({}, insertIndex, insertIndex);
71
71
72 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
72 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
73
73
74 impl->m_Variables.push_back(variable);
74 impl->m_Variables.push_back(variable);
75 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
75 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
76
76
77 endInsertRows();
77 endInsertRows();
78
78
79 return variable;
79 return variable;
80 }
80 }
81
81
82 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
82 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
83 {
83 {
84 if (!variable) {
84 if (!variable) {
85 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
85 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
86 return;
86 return;
87 }
87 }
88
88
89 // Finds variable in the model
89 // Finds variable in the model
90 auto begin = impl->m_Variables.cbegin();
90 auto begin = impl->m_Variables.cbegin();
91 auto end = impl->m_Variables.cend();
91 auto end = impl->m_Variables.cend();
92 auto it = std::find(begin, end, variable);
92 auto it = std::find(begin, end, variable);
93 if (it != end) {
93 if (it != end) {
94 auto removeIndex = std::distance(begin, it);
94 auto removeIndex = std::distance(begin, it);
95
95
96 // Deletes variable
96 // Deletes variable
97 beginRemoveRows({}, removeIndex, removeIndex);
97 beginRemoveRows({}, removeIndex, removeIndex);
98 impl->m_Variables.erase(it);
98 impl->m_Variables.erase(it);
99 endRemoveRows();
99 endRemoveRows();
100 }
100 }
101 else {
101 else {
102 qCritical(LOG_VariableModel())
102 qCritical(LOG_VariableModel())
103 << tr("Can't delete variable %1 from the model: the variable is not in the model")
103 << tr("Can't delete variable %1 from the model: the variable is not in the model")
104 .arg(variable->name());
104 .arg(variable->name());
105 }
105 }
106
106
107 // Removes variable from progress map
107 // Removes variable from progress map
108 impl->m_VariableToProgress.erase(variable);
108 impl->m_VariableToProgress.erase(variable);
109 }
109 }
110
110
111
111
112 std::shared_ptr<Variable> VariableModel::variable(int index) const
112 std::shared_ptr<Variable> VariableModel::variable(int index) const
113 {
113 {
114 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
114 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
115 }
115 }
116
116
117 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
117 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
118 {
118 {
119 if (progress > 0.0) {
119 if (progress > 0.0) {
120 impl->m_VariableToProgress[variable] = progress;
120 impl->m_VariableToProgress[variable] = progress;
121 }
121 }
122 else {
122 else {
123 impl->m_VariableToProgress.erase(variable);
123 impl->m_VariableToProgress.erase(variable);
124 }
124 }
125 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
125 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
126
126
127 emit dataChanged(modelIndex, modelIndex);
127 emit dataChanged(modelIndex, modelIndex);
128 }
128 }
129
129
130 int VariableModel::columnCount(const QModelIndex &parent) const
130 int VariableModel::columnCount(const QModelIndex &parent) const
131 {
131 {
132 Q_UNUSED(parent);
132 Q_UNUSED(parent);
133
133
134 return NB_COLUMNS;
134 return NB_COLUMNS;
135 }
135 }
136
136
137 int VariableModel::rowCount(const QModelIndex &parent) const
137 int VariableModel::rowCount(const QModelIndex &parent) const
138 {
138 {
139 Q_UNUSED(parent);
139 Q_UNUSED(parent);
140
140
141 return impl->m_Variables.size();
141 return impl->m_Variables.size();
142 }
142 }
143
143
144 QVariant VariableModel::data(const QModelIndex &index, int role) const
144 QVariant VariableModel::data(const QModelIndex &index, int role) const
145 {
145 {
146 if (!index.isValid()) {
146 if (!index.isValid()) {
147 return QVariant{};
147 return QVariant{};
148 }
148 }
149
149
150 if (index.row() < 0 || index.row() >= rowCount()) {
150 if (index.row() < 0 || index.row() >= rowCount()) {
151 return QVariant{};
151 return QVariant{};
152 }
152 }
153
153
154 if (role == Qt::DisplayRole) {
154 if (role == Qt::DisplayRole) {
155 if (auto variable = impl->m_Variables.at(index.row()).get()) {
155 if (auto variable = impl->m_Variables.at(index.row()).get()) {
156 /// Lambda function that builds the variant to return for a time value
157 /// @param getValueFun function used to get for a data series the iterator on the entry
158 /// that contains the time value to display
159 auto dateTimeVariant = [variable](const auto &getValueFun) {
160 if (auto dataSeries = variable->dataSeries()) {
161 dataSeries->lockRead();
162 auto it = getValueFun(*dataSeries);
163 auto resVariant = (it != dataSeries->cend())
164 ? DateUtils::dateTime(it->x()).toString(DATETIME_FORMAT)
165 : QVariant{};
166 dataSeries->unlock();
167 return resVariant;
168 }
169 else {
170 return QVariant{};
171 }
172 };
173
174 switch (index.column()) {
156 switch (index.column()) {
175 case NAME_COLUMN:
157 case NAME_COLUMN:
176 return variable->name();
158 return variable->name();
177 case TSTART_COLUMN:
159 case TSTART_COLUMN: {
178 // Shows the min value of the data series above the range tstart
160 auto range = variable->realRange();
179 return dateTimeVariant([min = variable->range().m_TStart](
161 return range != INVALID_RANGE
180 const auto &dataSeries) { return dataSeries.minXAxisData(min); });
162 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
181 case TEND_COLUMN:
163 : QVariant{};
182 // Shows the max value of the data series under the range tend
164 }
183 return dateTimeVariant([max = variable->range().m_TEnd](
165 case TEND_COLUMN: {
184 const auto &dataSeries) { return dataSeries.maxXAxisData(max); });
166 auto range = variable->realRange();
167 return range != INVALID_RANGE
168 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
169 : QVariant{};
170 }
185 case UNIT_COLUMN:
171 case UNIT_COLUMN:
186 return variable->metadata().value(QStringLiteral("units"));
172 return variable->metadata().value(QStringLiteral("units"));
187 case MISSION_COLUMN:
173 case MISSION_COLUMN:
188 return variable->metadata().value(QStringLiteral("mission"));
174 return variable->metadata().value(QStringLiteral("mission"));
189 case PLUGIN_COLUMN:
175 case PLUGIN_COLUMN:
190 return variable->metadata().value(QStringLiteral("plugin"));
176 return variable->metadata().value(QStringLiteral("plugin"));
191 default:
177 default:
192 // No action
178 // No action
193 break;
179 break;
194 }
180 }
195
181
196 qWarning(LOG_VariableModel())
182 qWarning(LOG_VariableModel())
197 << tr("Can't get data (unknown column %1)").arg(index.column());
183 << tr("Can't get data (unknown column %1)").arg(index.column());
198 }
184 }
199 else {
185 else {
200 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
186 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
201 }
187 }
202 }
188 }
203 else if (role == VariableRoles::ProgressRole) {
189 else if (role == VariableRoles::ProgressRole) {
204 if (auto variable = impl->m_Variables.at(index.row())) {
190 if (auto variable = impl->m_Variables.at(index.row())) {
205
191
206 auto it = impl->m_VariableToProgress.find(variable);
192 auto it = impl->m_VariableToProgress.find(variable);
207 if (it != impl->m_VariableToProgress.cend()) {
193 if (it != impl->m_VariableToProgress.cend()) {
208 return it->second;
194 return it->second;
209 }
195 }
210 }
196 }
211 }
197 }
212
198
213 return QVariant{};
199 return QVariant{};
214 }
200 }
215
201
216 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
202 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
217 {
203 {
218 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
204 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
219 return QVariant{};
205 return QVariant{};
220 }
206 }
221
207
222 if (orientation == Qt::Horizontal) {
208 if (orientation == Qt::Horizontal) {
223 auto propertiesIt = COLUMN_PROPERTIES.find(section);
209 auto propertiesIt = COLUMN_PROPERTIES.find(section);
224 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
210 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
225 // Role is either DisplayRole or SizeHintRole
211 // Role is either DisplayRole or SizeHintRole
226 return (role == Qt::DisplayRole)
212 return (role == Qt::DisplayRole)
227 ? QVariant{propertiesIt->m_Name}
213 ? QVariant{propertiesIt->m_Name}
228 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
214 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
229 }
215 }
230 else {
216 else {
231 qWarning(LOG_VariableModel())
217 qWarning(LOG_VariableModel())
232 << tr("Can't get header data (unknown column %1)").arg(section);
218 << tr("Can't get header data (unknown column %1)").arg(section);
233 }
219 }
234 }
220 }
235
221
236 return QVariant{};
222 return QVariant{};
237 }
223 }
238
224
239 void VariableModel::abortProgress(const QModelIndex &index)
225 void VariableModel::abortProgress(const QModelIndex &index)
240 {
226 {
241 if (auto variable = impl->m_Variables.at(index.row())) {
227 if (auto variable = impl->m_Variables.at(index.row())) {
242 emit abortProgessRequested(variable);
228 emit abortProgessRequested(variable);
243 }
229 }
244 }
230 }
245
231
246 void VariableModel::onVariableUpdated() noexcept
232 void VariableModel::onVariableUpdated() noexcept
247 {
233 {
248 // Finds variable that has been updated in the model
234 // Finds variable that has been updated in the model
249 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
235 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
250 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
236 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
251
237
252 if (updatedVariableIndex > -1) {
238 if (updatedVariableIndex > -1) {
253 emit dataChanged(createIndex(updatedVariableIndex, 0),
239 emit dataChanged(createIndex(updatedVariableIndex, 0),
254 createIndex(updatedVariableIndex, columnCount() - 1));
240 createIndex(updatedVariableIndex, columnCount() - 1));
255 }
241 }
256 }
242 }
257 }
243 }
258
244
259 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
245 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
260 {
246 {
261 auto begin = std::cbegin(m_Variables);
247 auto begin = std::cbegin(m_Variables);
262 auto end = std::cend(m_Variables);
248 auto end = std::cend(m_Variables);
263 auto it
249 auto it
264 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
250 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
265
251
266 if (it != end) {
252 if (it != end) {
267 // Gets the index of the variable in the model: we assume here that views have the same
253 // Gets the index of the variable in the model: we assume here that views have the same
268 // order as the model
254 // order as the model
269 return std::distance(begin, it);
255 return std::distance(begin, it);
270 }
256 }
271 else {
257 else {
272 return -1;
258 return -1;
273 }
259 }
274 }
260 }
@@ -1,52 +1,39
1 # On ignore toutes les règles vera++ pour le fichier spimpl
1 # On ignore toutes les règles vera++ pour le fichier spimpl
2 Common/spimpl\.h:\d+:.*
2 Common/spimpl\.h:\d+:.*
3
3
4 # Ignore false positive relative to two class definitions in a same file
4 # Ignore false positive relative to two class definitions in a same file
5 ArrayData\.h:\d+:.*IPSIS_S01.*
6 ArrayDataIterator\.h:\d+:.*IPSIS_S01.*
5 DataSourceItem\.h:\d+:.*IPSIS_S01.*
7 DataSourceItem\.h:\d+:.*IPSIS_S01.*
6 DataSeries\.h:\d+:.*IPSIS_S01.*
8 DataSeries\.h:\d+:.*IPSIS_S01.*
7 DataSeriesIterator\.h:\d+:.*IPSIS_S01.*
9 DataSeriesIterator\.h:\d+:.*IPSIS_S01.*
8
10
9 # Ignore false positive relative to a template class
11 # Ignore false positive relative to a template class
10 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (D)
12 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (D)
11 ArrayData\.h:\d+:.*IPSIS_S04_NAMESPACE.*found: (arraydata_detail)
13 ArrayData\.h:\d+:.*IPSIS_S04_NAMESPACE.*found: (arraydata_detail)
12 ArrayData\.h:\d+:.*IPSIS_S06.*found: (D)
14 ArrayData\.h:\d+:.*IPSIS_S06.*found: (D)
13 ArrayData\.h:\d+:.*IPSIS_S06.*found: (Dim)
15 ArrayData\.h:\d+:.*IPSIS_S06.*found: (Dim)
14 DataSeries\.h:\d+:.*IPSIS_S04_METHOD.*found: LOG_DataSeries
16 DataSeries\.h:\d+:.*IPSIS_S04_METHOD.*found: LOG_DataSeries
15 DataSeries\.h:\d+:.*IPSIS_S04_VARIABLE.*
17 DataSeries\.h:\d+:.*IPSIS_S04_VARIABLE.*
16 DataSeries\.h:\d+:.*IPSIS_S04_NAMESPACE.*found: (dataseries_detail)
18 DataSeries\.h:\d+:.*IPSIS_S04_NAMESPACE.*found: (dataseries_detail)
17
19
18 # Ignore false positive relative to iterators
20 # Ignore false positive relative to iterators
19 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (forward_iterator_tag)
21 SqpIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (forward_iterator_tag)
20 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (IteratorValue)
22 SqpIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (T)
21 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (ptrdiff_t)
23 SqpIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (ptrdiff_t)
22 ArrayData\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (value_type)
24 SqpIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (value_type)
23 ArrayData\.h:\d+:.*IPSIS_S05.*
25 SqpIterator\.h:\d+:.*IPSIS_S06.*found: (iterator_category)
24 ArrayData\.h:\d+:.*IPSIS_S06.*found: (iterator_category)
26 SqpIterator\.h:\d+:.*IPSIS_S06.*found: (forward_iterator_tag)
25 ArrayData\.h:\d+:.*IPSIS_S06.*found: (forward_iterator_tag)
27 SqpIterator\.h:\d+:.*IPSIS_S06.*found: (value_type)
26 ArrayData\.h:\d+:.*IPSIS_S06.*found: (value_type)
28 SqpIterator\.h:\d+:.*IPSIS_S06.*found: (T)
27 ArrayData\.h:\d+:.*IPSIS_S06.*found: (IteratorValue)
29 SqpIterator\.h:\d+:.*IPSIS_S06.*found: (difference_type)
28 ArrayData\.h:\d+:.*IPSIS_S06.*found: (difference_type)
30 SqpIterator\.h:\d+:.*IPSIS_S06.*found: (ptrdiff_t)
29 ArrayData\.h:\d+:.*IPSIS_S06.*found: (ptrdiff_t)
31 SqpIterator\.h:\d+:.*IPSIS_S06.*found: (pointer)
30 ArrayData\.h:\d+:.*IPSIS_S06.*found: (pointer)
32 SqpIterator\.h:\d+:.*IPSIS_S06.*found: (reference)
31 ArrayData\.h:\d+:.*IPSIS_S06.*found: (reference)
33 SqpIterator\.h:\d+:.*IPSIS_S06.*found: (value_type)
32 ArrayData\.h:\d+:.*IPSIS_S06.*found: (value_type)
33 DataSeriesIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (forward_iterator_tag)
34 DataSeriesIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (DataSeriesIteratorValue)
35 DataSeriesIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (ptrdiff_t)
36 DataSeriesIterator\.h:\d+:.*IPSIS_S04_VARIABLE.*found: (value_type)
37 DataSeriesIterator\.h:\d+:.*IPSIS_S05.*
38 DataSeriesIterator\.h:\d+:.*IPSIS_S06.*found: (iterator_category)
39 DataSeriesIterator\.h:\d+:.*IPSIS_S06.*found: (forward_iterator_tag)
40 DataSeriesIterator\.h:\d+:.*IPSIS_S06.*found: (value_type)
41 DataSeriesIterator\.h:\d+:.*IPSIS_S06.*found: (DataSeriesIteratorValue)
42 DataSeriesIterator\.h:\d+:.*IPSIS_S06.*found: (difference_type)
43 DataSeriesIterator\.h:\d+:.*IPSIS_S06.*found: (ptrdiff_t)
44 DataSeriesIterator\.h:\d+:.*IPSIS_S06.*found: (pointer)
45 DataSeriesIterator\.h:\d+:.*IPSIS_S06.*found: (reference)
46 DataSeriesIterator\.h:\d+:.*IPSIS_S06.*found: (value_type)
47
34
48 # Ignore false positive relative to an alias
35 # Ignore false positive relative to an alias
49 DataSourceItemAction\.h:\d+:.*IPSIS_S06.*found: (ExecuteFunction)
36 DataSourceItemAction\.h:\d+:.*IPSIS_S06.*found: (ExecuteFunction)
50
37
51 # Ignore false positive relative to unnamed namespace
38 # Ignore false positive relative to unnamed namespace
52 VariableController\.cpp:\d+:.*IPSIS_F13.*
39 VariableController\.cpp:\d+:.*IPSIS_F13.*
@@ -1,56 +1,55
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QWidget>
7 #include <QWidget>
8
8
9 #include <memory>
9 #include <memory>
10
10
11 #include <Common/spimpl.h>
11 #include <Common/spimpl.h>
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
14
14
15 namespace Ui {
15 namespace Ui {
16 class VisualizationZoneWidget;
16 class VisualizationZoneWidget;
17 } // Ui
17 } // Ui
18
18
19 class Variable;
19 class Variable;
20 class VisualizationGraphWidget;
20 class VisualizationGraphWidget;
21
21
22 class VisualizationZoneWidget : public QWidget, public IVisualizationWidget {
22 class VisualizationZoneWidget : public QWidget, public IVisualizationWidget {
23 Q_OBJECT
23 Q_OBJECT
24
24
25 public:
25 public:
26 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
26 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
27 virtual ~VisualizationZoneWidget();
27 virtual ~VisualizationZoneWidget();
28
28
29 /// Add a graph widget
29 /// Add a graph widget
30 void addGraph(VisualizationGraphWidget *graphWidget);
30 void addGraph(VisualizationGraphWidget *graphWidget);
31
31
32 /**
32 /**
33 * Creates a graph using a variable. The variable will be displayed in the new graph.
33 * Creates a graph using a variable. The variable will be displayed in the new graph.
34 * @param variable the variable for which to create the graph
34 * @param variable the variable for which to create the graph
35 * @return the pointer to the created graph
35 * @return the pointer to the created graph
36 */
36 */
37 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
37 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
38
38
39 // IVisualizationWidget interface
39 // IVisualizationWidget interface
40 void accept(IVisualizationWidgetVisitor *visitor) override;
40 void accept(IVisualizationWidgetVisitor *visitor) override;
41 bool canDrop(const Variable &variable) const override;
41 bool canDrop(const Variable &variable) const override;
42 bool contains(const Variable &variable) const override;
42 bool contains(const Variable &variable) const override;
43 QString name() const override;
43 QString name() const override;
44
44
45
46 private slots:
47 void onVariableAdded(std::shared_ptr<Variable> variable);
48
49 private:
45 private:
50 Ui::VisualizationZoneWidget *ui;
46 Ui::VisualizationZoneWidget *ui;
51
47
52 class VisualizationZoneWidgetPrivate;
48 class VisualizationZoneWidgetPrivate;
53 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
49 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
50
51 private slots:
52 void onVariableAdded(std::shared_ptr<Variable> variable);
54 };
53 };
55
54
56 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
55 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -1,100 +1,100
1 #include <DataSource/DataSourceWidget.h>
1 #include <DataSource/DataSourceWidget.h>
2
2
3 #include <ui_DataSourceWidget.h>
3 #include <ui_DataSourceWidget.h>
4
4
5 #include <DataSource/DataSourceItem.h>
5 #include <DataSource/DataSourceItem.h>
6 #include <DataSource/DataSourceTreeWidgetHelper.h>
6 #include <DataSource/DataSourceTreeWidgetHelper.h>
7 #include <DataSource/DataSourceTreeWidgetItem.h>
7 #include <DataSource/DataSourceTreeWidgetItem.h>
8
8
9 #include <QMenu>
9 #include <QMenu>
10
10
11 namespace {
11 namespace {
12
12
13 /// Number of columns displayed in the tree
13 /// Number of columns displayed in the tree
14 const auto TREE_NB_COLUMNS = 1;
14 const auto TREE_NB_COLUMNS = 1;
15
15
16 /// Header labels for the tree
16 /// Header labels for the tree
17 const auto TREE_HEADER_LABELS = QStringList{QObject::tr("Name")};
17 const auto TREE_HEADER_LABELS = QStringList{QObject::tr("Name")};
18
18
19 /**
19 /**
20 * Creates the item associated to a data source
20 * Creates the item associated to a data source
21 * @param dataSource the data source for which to create the item
21 * @param dataSource the data source for which to create the item
22 * @return the new item
22 * @return the new item
23 */
23 */
24 DataSourceTreeWidgetItem *createTreeWidgetItem(DataSourceItem *dataSource)
24 DataSourceTreeWidgetItem *createTreeWidgetItem(DataSourceItem *dataSource)
25 {
25 {
26 // Creates item for the data source
26 // Creates item for the data source
27 auto item = new DataSourceTreeWidgetItem{dataSource};
27 auto item = new DataSourceTreeWidgetItem{dataSource};
28
28
29 // Generates items for the children of the data source
29 // Generates items for the children of the data source
30 for (auto i = 0; i < dataSource->childCount(); ++i) {
30 for (auto i = 0; i < dataSource->childCount(); ++i) {
31 item->addChild(createTreeWidgetItem(dataSource->child(i)));
31 item->addChild(createTreeWidgetItem(dataSource->child(i)));
32 }
32 }
33
33
34 return item;
34 return item;
35 }
35 }
36
36
37 } // namespace
37 } // namespace
38
38
39 DataSourceWidget::DataSourceWidget(QWidget *parent) : QWidget{parent}, ui{new Ui::DataSourceWidget}
39 DataSourceWidget::DataSourceWidget(QWidget *parent) : QWidget{parent}, ui{new Ui::DataSourceWidget}
40 {
40 {
41 ui->setupUi(this);
41 ui->setupUi(this);
42
42
43 // Set tree properties
43 // Set tree properties
44 ui->treeWidget->setColumnCount(TREE_NB_COLUMNS);
44 ui->treeWidget->setColumnCount(TREE_NB_COLUMNS);
45 ui->treeWidget->setHeaderLabels(TREE_HEADER_LABELS);
45 ui->treeWidget->setHeaderLabels(TREE_HEADER_LABELS);
46 ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
46 ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
47
47
48 // Connection to show a menu when right clicking on the tree
48 // Connection to show a menu when right clicking on the tree
49 connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this,
49 connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this,
50 &DataSourceWidget::onTreeMenuRequested);
50 &DataSourceWidget::onTreeMenuRequested);
51
51
52 // Connection to filter tree
52 // Connection to filter tree
53 connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &DataSourceWidget::filterChanged);
53 connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &DataSourceWidget::filterChanged);
54 }
54 }
55
55
56 DataSourceWidget::~DataSourceWidget() noexcept
56 DataSourceWidget::~DataSourceWidget() noexcept
57 {
57 {
58 delete ui;
58 delete ui;
59 }
59 }
60
60
61 void DataSourceWidget::addDataSource(DataSourceItem *dataSource) noexcept
61 void DataSourceWidget::addDataSource(DataSourceItem *dataSource) noexcept
62 {
62 {
63 // Creates the item associated to the source and adds it to the tree widget. The tree widget
63 // Creates the item associated to the source and adds it to the tree widget. The tree widget
64 // takes the ownership of the item
64 // takes the ownership of the item
65 if (dataSource) {
65 if (dataSource) {
66 ui->treeWidget->addTopLevelItem(createTreeWidgetItem(dataSource));
66 ui->treeWidget->addTopLevelItem(createTreeWidgetItem(dataSource));
67 }
67 }
68 }
68 }
69
69
70 void DataSourceWidget::filterChanged(const QString &text) noexcept
70 void DataSourceWidget::filterChanged(const QString &text) noexcept
71 {
71 {
72 auto validateItem = [&text](const DataSourceTreeWidgetItem &item) {
72 auto validateItem = [&text](const DataSourceTreeWidgetItem &item) {
73 auto regExp = QRegExp{text, Qt::CaseInsensitive, QRegExp::Wildcard};
73 auto regExp = QRegExp{text, Qt::CaseInsensitive, QRegExp::Wildcard};
74
74
75 // An item is valid if any of its metadata validates the text filter
75 // An item is valid if any of its metadata validates the text filter
76 auto itemMetadata = item.data()->data();
76 auto itemMetadata = item.data()->data();
77 auto itemMetadataEnd = itemMetadata.cend();
77 auto itemMetadataEnd = itemMetadata.cend();
78 auto acceptFilter
78 auto acceptFilter
79 = [&regExp](const auto &variant) { return variant.toString().contains(regExp); };
79 = [&regExp](const auto &variant) { return variant.toString().contains(regExp); };
80
80
81 return std::find_if(itemMetadata.cbegin(), itemMetadataEnd, acceptFilter)
81 return std::find_if(itemMetadata.cbegin(), itemMetadataEnd, acceptFilter)
82 != itemMetadataEnd;
82 != itemMetadataEnd;
83 };
83 };
84
84
85 // Applies filter on tree widget
85 // Applies filter on tree widget
86 DataSourceTreeWidgetHelper::filter(*ui->treeWidget, validateItem);
86 DataSourceTreeWidgetHelper::filter(*ui->treeWidget, validateItem);
87 }
87 }
88
88
89 void DataSourceWidget::onTreeMenuRequested(const QPoint &pos) noexcept
89 void DataSourceWidget::onTreeMenuRequested(const QPoint &pos) noexcept
90 {
90 {
91 // Retrieves the selected item in the tree, and build the menu from its actions
91 // Retrieves the selected item in the tree, and build the menu from its actions
92 if (auto selectedItem = dynamic_cast<DataSourceTreeWidgetItem *>(ui->treeWidget->itemAt(pos))) {
92 if (auto selectedItem = dynamic_cast<DataSourceTreeWidgetItem *>(ui->treeWidget->itemAt(pos))) {
93 QMenu treeMenu{};
93 QMenu treeMenu{};
94 treeMenu.addActions(selectedItem->actions());
94 treeMenu.addActions(selectedItem->actions());
95
95
96 if (!treeMenu.isEmpty()) {
96 if (!treeMenu.isEmpty()) {
97 treeMenu.exec(mapToGlobal(pos));
97 treeMenu.exec(QCursor::pos());
98 }
98 }
99 }
99 }
100 }
100 }
@@ -1,45 +1,51
1 #include "Settings/SqpSettingsGeneralWidget.h"
1 #include "Settings/SqpSettingsGeneralWidget.h"
2
2
3 #include "Settings/SqpSettingsDefs.h"
3 #include "Settings/SqpSettingsDefs.h"
4
4
5 #include "ui_SqpSettingsGeneralWidget.h"
5 #include "ui_SqpSettingsGeneralWidget.h"
6
6
7 SqpSettingsGeneralWidget::SqpSettingsGeneralWidget(QWidget *parent)
7 SqpSettingsGeneralWidget::SqpSettingsGeneralWidget(QWidget *parent)
8 : QWidget{parent}, ui{new Ui::SqpSettingsGeneralWidget}
8 : QWidget{parent}, ui{new Ui::SqpSettingsGeneralWidget}
9 {
9 {
10 ui->setupUi(this);
10 ui->setupUi(this);
11
12 // Value limits
13 ui->toleranceInitSpinBox->setMinimum(0.);
14 ui->toleranceInitSpinBox->setMaximum(std::numeric_limits<double>::max());
15 ui->toleranceUpdateSpinBox->setMinimum(0.);
16 ui->toleranceUpdateSpinBox->setMaximum(std::numeric_limits<double>::max());
11 }
17 }
12
18
13 SqpSettingsGeneralWidget::~SqpSettingsGeneralWidget() noexcept
19 SqpSettingsGeneralWidget::~SqpSettingsGeneralWidget() noexcept
14 {
20 {
15 delete ui;
21 delete ui;
16 }
22 }
17
23
18 void SqpSettingsGeneralWidget::loadSettings()
24 void SqpSettingsGeneralWidget::loadSettings()
19 {
25 {
20 QSettings settings{};
26 QSettings settings{};
21
27
22 auto loadTolerance = [&settings](const QString &key, double defaultValue) {
28 auto loadTolerance = [&settings](const QString &key, double defaultValue) {
23 // Tolerance is converted to percent
29 // Tolerance is converted to percent
24 auto toleranceValue = settings.value(key, defaultValue).toDouble();
30 auto toleranceValue = settings.value(key, defaultValue).toDouble();
25 return toleranceValue * 100.;
31 return toleranceValue * 100.;
26 };
32 };
27
33
28 ui->toleranceInitSpinBox->setValue(
34 ui->toleranceInitSpinBox->setValue(
29 loadTolerance(GENERAL_TOLERANCE_AT_INIT_KEY, GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE));
35 loadTolerance(GENERAL_TOLERANCE_AT_INIT_KEY, GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE));
30 ui->toleranceUpdateSpinBox->setValue(
36 ui->toleranceUpdateSpinBox->setValue(
31 loadTolerance(GENERAL_TOLERANCE_AT_UPDATE_KEY, GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE));
37 loadTolerance(GENERAL_TOLERANCE_AT_UPDATE_KEY, GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE));
32 }
38 }
33
39
34 void SqpSettingsGeneralWidget::saveSettings() const
40 void SqpSettingsGeneralWidget::saveSettings() const
35 {
41 {
36 QSettings settings{};
42 QSettings settings{};
37
43
38 auto saveTolerance = [&settings](const QString &key, double value) {
44 auto saveTolerance = [&settings](const QString &key, double value) {
39 // Tolerance is converted from percent
45 // Tolerance is converted from percent
40 settings.setValue(key, value * 0.01);
46 settings.setValue(key, value * 0.01);
41 };
47 };
42
48
43 saveTolerance(GENERAL_TOLERANCE_AT_INIT_KEY, ui->toleranceInitSpinBox->value());
49 saveTolerance(GENERAL_TOLERANCE_AT_INIT_KEY, ui->toleranceInitSpinBox->value());
44 saveTolerance(GENERAL_TOLERANCE_AT_UPDATE_KEY, ui->toleranceUpdateSpinBox->value());
50 saveTolerance(GENERAL_TOLERANCE_AT_UPDATE_KEY, ui->toleranceUpdateSpinBox->value());
45 }
51 }
@@ -1,199 +1,199
1 #include <Variable/VariableController.h>
1 #include <Variable/VariableController.h>
2 #include <Variable/VariableInspectorWidget.h>
2 #include <Variable/VariableInspectorWidget.h>
3 #include <Variable/VariableMenuHeaderWidget.h>
3 #include <Variable/VariableMenuHeaderWidget.h>
4 #include <Variable/VariableModel.h>
4 #include <Variable/VariableModel.h>
5
5
6 #include <ui_VariableInspectorWidget.h>
6 #include <ui_VariableInspectorWidget.h>
7
7
8 #include <QMouseEvent>
8 #include <QMouseEvent>
9 #include <QSortFilterProxyModel>
9 #include <QSortFilterProxyModel>
10 #include <QStyledItemDelegate>
10 #include <QStyledItemDelegate>
11 #include <QWidgetAction>
11 #include <QWidgetAction>
12
12
13 #include <SqpApplication.h>
13 #include <SqpApplication.h>
14
14
15 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
15 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
16
16
17
17
18 class QProgressBarItemDelegate : public QStyledItemDelegate {
18 class QProgressBarItemDelegate : public QStyledItemDelegate {
19
19
20 public:
20 public:
21 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
21 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
22
22
23 void paint(QPainter *painter, const QStyleOptionViewItem &option,
23 void paint(QPainter *painter, const QStyleOptionViewItem &option,
24 const QModelIndex &index) const
24 const QModelIndex &index) const
25 {
25 {
26 auto data = index.data(Qt::DisplayRole);
26 auto data = index.data(Qt::DisplayRole);
27 auto progressData = index.data(VariableRoles::ProgressRole);
27 auto progressData = index.data(VariableRoles::ProgressRole);
28 if (data.isValid() && progressData.isValid()) {
28 if (data.isValid() && progressData.isValid()) {
29 auto name = data.value<QString>();
29 auto name = data.value<QString>();
30 auto progress = progressData.value<double>();
30 auto progress = progressData.value<double>();
31 if (progress > 0) {
31 if (progress > 0) {
32 auto cancelButtonWidth = 20;
32 auto cancelButtonWidth = 20;
33 auto progressBarOption = QStyleOptionProgressBar{};
33 auto progressBarOption = QStyleOptionProgressBar{};
34 auto progressRect = option.rect;
34 auto progressRect = option.rect;
35 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
35 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
36 progressBarOption.rect = progressRect;
36 progressBarOption.rect = progressRect;
37 progressBarOption.minimum = 0;
37 progressBarOption.minimum = 0;
38 progressBarOption.maximum = 100;
38 progressBarOption.maximum = 100;
39 progressBarOption.progress = progress;
39 progressBarOption.progress = progress;
40 progressBarOption.text
40 progressBarOption.text
41 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
41 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
42 progressBarOption.textVisible = true;
42 progressBarOption.textVisible = true;
43 progressBarOption.textAlignment = Qt::AlignCenter;
43 progressBarOption.textAlignment = Qt::AlignCenter;
44
44
45
45
46 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
46 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
47 painter);
47 painter);
48
48
49 // Cancel button
49 // Cancel button
50 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
50 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
51 option.rect.height());
51 option.rect.height());
52 auto buttonOption = QStyleOptionButton{};
52 auto buttonOption = QStyleOptionButton{};
53 buttonOption.rect = buttonRect;
53 buttonOption.rect = buttonRect;
54 buttonOption.text = "X";
54 buttonOption.text = "X";
55
55
56 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
56 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
57 }
57 }
58 else {
58 else {
59 QStyledItemDelegate::paint(painter, option, index);
59 QStyledItemDelegate::paint(painter, option, index);
60 }
60 }
61 }
61 }
62 else {
62 else {
63 QStyledItemDelegate::paint(painter, option, index);
63 QStyledItemDelegate::paint(painter, option, index);
64 }
64 }
65 }
65 }
66
66
67 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
67 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
68 const QModelIndex &index)
68 const QModelIndex &index)
69 {
69 {
70 if (event->type() == QEvent::MouseButtonRelease) {
70 if (event->type() == QEvent::MouseButtonRelease) {
71 auto data = index.data(Qt::DisplayRole);
71 auto data = index.data(Qt::DisplayRole);
72 auto progressData = index.data(VariableRoles::ProgressRole);
72 auto progressData = index.data(VariableRoles::ProgressRole);
73 if (data.isValid() && progressData.isValid()) {
73 if (data.isValid() && progressData.isValid()) {
74 auto cancelButtonWidth = 20;
74 auto cancelButtonWidth = 20;
75 auto progressRect = option.rect;
75 auto progressRect = option.rect;
76 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
76 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
77 // Cancel button
77 // Cancel button
78 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
78 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
79 option.rect.height());
79 option.rect.height());
80
80
81 auto e = (QMouseEvent *)event;
81 auto e = (QMouseEvent *)event;
82 auto clickX = e->x();
82 auto clickX = e->x();
83 auto clickY = e->y();
83 auto clickY = e->y();
84
84
85 auto x = buttonRect.left(); // the X coordinate
85 auto x = buttonRect.left(); // the X coordinate
86 auto y = buttonRect.top(); // the Y coordinate
86 auto y = buttonRect.top(); // the Y coordinate
87 auto w = buttonRect.width(); // button width
87 auto w = buttonRect.width(); // button width
88 auto h = buttonRect.height(); // button height
88 auto h = buttonRect.height(); // button height
89
89
90 if (clickX > x && clickX < x + w) {
90 if (clickX > x && clickX < x + w) {
91 if (clickY > y && clickY < y + h) {
91 if (clickY > y && clickY < y + h) {
92 auto variableModel = sqpApp->variableController().variableModel();
92 auto variableModel = sqpApp->variableController().variableModel();
93 variableModel->abortProgress(index);
93 variableModel->abortProgress(index);
94 }
94 }
95 }
95 }
96 else {
96 else {
97 QStyledItemDelegate::editorEvent(event, model, option, index);
97 QStyledItemDelegate::editorEvent(event, model, option, index);
98 }
98 }
99 }
99 }
100 else {
100 else {
101 QStyledItemDelegate::editorEvent(event, model, option, index);
101 QStyledItemDelegate::editorEvent(event, model, option, index);
102 }
102 }
103 }
103 }
104 else {
104 else {
105 QStyledItemDelegate::editorEvent(event, model, option, index);
105 QStyledItemDelegate::editorEvent(event, model, option, index);
106 }
106 }
107 }
107 }
108 };
108 };
109
109
110 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
110 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
111 : QWidget{parent},
111 : QWidget{parent},
112 ui{new Ui::VariableInspectorWidget},
112 ui{new Ui::VariableInspectorWidget},
113 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
113 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
114 {
114 {
115 ui->setupUi(this);
115 ui->setupUi(this);
116
116
117 // Sets model for table
117 // Sets model for table
118 // auto sortFilterModel = new QSortFilterProxyModel{this};
118 // auto sortFilterModel = new QSortFilterProxyModel{this};
119 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
119 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
120
120
121 auto variableModel = sqpApp->variableController().variableModel();
121 auto variableModel = sqpApp->variableController().variableModel();
122 ui->tableView->setModel(variableModel);
122 ui->tableView->setModel(variableModel);
123
123
124 // Adds extra signal/slot between view and model, so the view can be updated instantly when
124 // Adds extra signal/slot between view and model, so the view can be updated instantly when
125 // there is a change of data in the model
125 // there is a change of data in the model
126 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
126 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
127 SLOT(refresh()));
127 SLOT(refresh()));
128
128
129 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
129 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
130 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
130 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
131
131
132 // Fixes column sizes
132 // Fixes column sizes
133 auto model = ui->tableView->model();
133 auto model = ui->tableView->model();
134 const auto count = model->columnCount();
134 const auto count = model->columnCount();
135 for (auto i = 0; i < count; ++i) {
135 for (auto i = 0; i < count; ++i) {
136 ui->tableView->setColumnWidth(
136 ui->tableView->setColumnWidth(
137 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
137 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
138 }
138 }
139
139
140 // Sets selection options
140 // Sets selection options
141 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
141 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
142 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
142 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
143
143
144 // Connection to show a menu when right clicking on the tree
144 // Connection to show a menu when right clicking on the tree
145 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
145 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
146 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
146 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
147 &VariableInspectorWidget::onTableMenuRequested);
147 &VariableInspectorWidget::onTableMenuRequested);
148 }
148 }
149
149
150 VariableInspectorWidget::~VariableInspectorWidget()
150 VariableInspectorWidget::~VariableInspectorWidget()
151 {
151 {
152 delete ui;
152 delete ui;
153 }
153 }
154
154
155 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
155 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
156 {
156 {
157 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
157 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
158
158
159 // Gets the model to retrieve the underlying selected variables
159 // Gets the model to retrieve the underlying selected variables
160 auto model = sqpApp->variableController().variableModel();
160 auto model = sqpApp->variableController().variableModel();
161 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
161 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
162 for (const auto &selectedRow : qAsConst(selectedRows)) {
162 for (const auto &selectedRow : qAsConst(selectedRows)) {
163 if (auto selectedVariable = model->variable(selectedRow.row())) {
163 if (auto selectedVariable = model->variable(selectedRow.row())) {
164 selectedVariables.push_back(selectedVariable);
164 selectedVariables.push_back(selectedVariable);
165 }
165 }
166 }
166 }
167
167
168 QMenu tableMenu{};
168 QMenu tableMenu{};
169
169
170 // Emits a signal so that potential receivers can populate the menu before displaying it
170 // Emits a signal so that potential receivers can populate the menu before displaying it
171 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
171 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
172
172
173 // Adds menu-specific actions
173 // Adds menu-specific actions
174 if (!selectedVariables.isEmpty()) {
174 if (!selectedVariables.isEmpty()) {
175 // 'Delete' action
175 // 'Delete' action
176 auto deleteFun = [&selectedVariables]() {
176 auto deleteFun = [&selectedVariables]() {
177 sqpApp->variableController().deleteVariables(selectedVariables);
177 sqpApp->variableController().deleteVariables(selectedVariables);
178 };
178 };
179
179
180 tableMenu.addSeparator();
180 tableMenu.addSeparator();
181 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
181 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
182 }
182 }
183
183
184 if (!tableMenu.isEmpty()) {
184 if (!tableMenu.isEmpty()) {
185 // Generates menu header (inserted before first action)
185 // Generates menu header (inserted before first action)
186 auto firstAction = tableMenu.actions().first();
186 auto firstAction = tableMenu.actions().first();
187 auto headerAction = new QWidgetAction{&tableMenu};
187 auto headerAction = new QWidgetAction{&tableMenu};
188 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
188 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
189 tableMenu.insertAction(firstAction, headerAction);
189 tableMenu.insertAction(firstAction, headerAction);
190
190
191 // Displays menu
191 // Displays menu
192 tableMenu.exec(mapToGlobal(pos));
192 tableMenu.exec(QCursor::pos());
193 }
193 }
194 }
194 }
195
195
196 void VariableInspectorWidget::refresh() noexcept
196 void VariableInspectorWidget::refresh() noexcept
197 {
197 {
198 ui->tableView->viewport()->update();
198 ui->tableView->viewport()->update();
199 }
199 }
@@ -1,313 +1,313
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationDefs.h"
3 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationGraphHelper.h"
4 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "ui_VisualizationGraphWidget.h"
6 #include "ui_VisualizationGraphWidget.h"
7
7
8 #include <Data/ArrayData.h>
8 #include <Data/ArrayData.h>
9 #include <Data/IDataSeries.h>
9 #include <Data/IDataSeries.h>
10 #include <Settings/SqpSettingsDefs.h>
10 #include <Settings/SqpSettingsDefs.h>
11 #include <SqpApplication.h>
11 #include <SqpApplication.h>
12 #include <Variable/Variable.h>
12 #include <Variable/Variable.h>
13 #include <Variable/VariableController.h>
13 #include <Variable/VariableController.h>
14
14
15 #include <unordered_map>
15 #include <unordered_map>
16
16
17 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
17 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
18
18
19 namespace {
19 namespace {
20
20
21 /// Key pressed to enable zoom on horizontal axis
21 /// Key pressed to enable zoom on horizontal axis
22 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
22 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
23
23
24 /// Key pressed to enable zoom on vertical axis
24 /// Key pressed to enable zoom on vertical axis
25 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
25 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
26
26
27 } // namespace
27 } // namespace
28
28
29 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
29 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
30
30
31 explicit VisualizationGraphWidgetPrivate()
31 explicit VisualizationGraphWidgetPrivate()
32 : m_DoAcquisition{true}, m_IsCalibration{false}, m_RenderingDelegate{nullptr}
32 : m_DoAcquisition{true}, m_IsCalibration{false}, m_RenderingDelegate{nullptr}
33 {
33 {
34 }
34 }
35
35
36 // 1 variable -> n qcpplot
36 // 1 variable -> n qcpplot
37 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
37 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
38 bool m_DoAcquisition;
38 bool m_DoAcquisition;
39 bool m_IsCalibration;
39 bool m_IsCalibration;
40 QCPItemTracer *m_TextTracer;
40 QCPItemTracer *m_TextTracer;
41 /// Delegate used to attach rendering features to the plot
41 /// Delegate used to attach rendering features to the plot
42 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
42 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
43 };
43 };
44
44
45 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
45 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
46 : QWidget{parent},
46 : QWidget{parent},
47 ui{new Ui::VisualizationGraphWidget},
47 ui{new Ui::VisualizationGraphWidget},
48 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
48 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>()}
49 {
49 {
50 ui->setupUi(this);
50 ui->setupUi(this);
51
51
52 // The delegate must be initialized after the ui as it uses the plot
52 // The delegate must be initialized after the ui as it uses the plot
53 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*ui->widget);
53 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*ui->widget);
54
54
55 ui->graphNameLabel->setText(name);
55 ui->graphNameLabel->setText(name);
56
56
57 // 'Close' options : widget is deleted when closed
57 // 'Close' options : widget is deleted when closed
58 setAttribute(Qt::WA_DeleteOnClose);
58 setAttribute(Qt::WA_DeleteOnClose);
59 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
59 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationGraphWidget::close);
60 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
60 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
61
61
62 // Set qcpplot properties :
62 // Set qcpplot properties :
63 // - Drag (on x-axis) and zoom are enabled
63 // - Drag (on x-axis) and zoom are enabled
64 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
64 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
65 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
65 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
66 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
66 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
67
67
68 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
68 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
69 connect(ui->widget, &QCustomPlot::mouseRelease, this,
69 connect(ui->widget, &QCustomPlot::mouseRelease, this,
70 &VisualizationGraphWidget::onMouseRelease);
70 &VisualizationGraphWidget::onMouseRelease);
71 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
71 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
72 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
72 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
73 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
73 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
74 &QCPAxis::rangeChanged),
74 &QCPAxis::rangeChanged),
75 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
75 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
76
76
77 // Activates menu when right clicking on the graph
77 // Activates menu when right clicking on the graph
78 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
78 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
79 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
79 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
80 &VisualizationGraphWidget::onGraphMenuRequested);
80 &VisualizationGraphWidget::onGraphMenuRequested);
81
81
82 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
82 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
83 &VariableController::onRequestDataLoading);
83 &VariableController::onRequestDataLoading);
84
84
85 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
85 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
86 &VisualizationGraphWidget::onUpdateVarDisplaying);
86 &VisualizationGraphWidget::onUpdateVarDisplaying);
87 }
87 }
88
88
89
89
90 VisualizationGraphWidget::~VisualizationGraphWidget()
90 VisualizationGraphWidget::~VisualizationGraphWidget()
91 {
91 {
92 delete ui;
92 delete ui;
93 }
93 }
94
94
95 void VisualizationGraphWidget::enableAcquisition(bool enable)
95 void VisualizationGraphWidget::enableAcquisition(bool enable)
96 {
96 {
97 impl->m_DoAcquisition = enable;
97 impl->m_DoAcquisition = enable;
98 }
98 }
99
99
100 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
100 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
101 {
101 {
102 // Uses delegate to create the qcpplot components according to the variable
102 // Uses delegate to create the qcpplot components according to the variable
103 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
103 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
104 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
104 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
105
105
106 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
106 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
107
107
108 auto varRange = variable->range();
108 auto varRange = variable->range();
109
109
110 this->enableAcquisition(false);
110 this->enableAcquisition(false);
111 this->setGraphRange(range);
111 this->setGraphRange(range);
112 this->enableAcquisition(true);
112 this->enableAcquisition(true);
113
113
114 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, varRange,
114 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, varRange,
115 false);
115 false);
116
116
117 emit variableAdded(variable);
117 emit variableAdded(variable);
118 }
118 }
119
119
120 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
120 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
121 {
121 {
122 // Each component associated to the variable :
122 // Each component associated to the variable :
123 // - is removed from qcpplot (which deletes it)
123 // - is removed from qcpplot (which deletes it)
124 // - is no longer referenced in the map
124 // - is no longer referenced in the map
125 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
125 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
126 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
126 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
127 auto &plottablesMap = variableIt->second;
127 auto &plottablesMap = variableIt->second;
128
128
129 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
129 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
130 plottableIt != plottableEnd;) {
130 plottableIt != plottableEnd;) {
131 ui->widget->removePlottable(plottableIt->second);
131 ui->widget->removePlottable(plottableIt->second);
132 plottableIt = plottablesMap.erase(plottableIt);
132 plottableIt = plottablesMap.erase(plottableIt);
133 }
133 }
134
134
135 impl->m_VariableToPlotMultiMap.erase(variableIt);
135 impl->m_VariableToPlotMultiMap.erase(variableIt);
136 }
136 }
137
137
138 // Updates graph
138 // Updates graph
139 ui->widget->replot();
139 ui->widget->replot();
140 }
140 }
141
141
142 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable, const SqpRange &range)
142 void VisualizationGraphWidget::setRange(std::shared_ptr<Variable> variable, const SqpRange &range)
143 {
143 {
144 // Note: in case of different axes that depends on variable, we could start with a code like
144 // Note: in case of different axes that depends on variable, we could start with a code like
145 // that:
145 // that:
146 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
146 // auto componentsIt = impl->m_VariableToPlotMultiMap.equal_range(variable);
147 // for (auto it = componentsIt.first; it != componentsIt.second;) {
147 // for (auto it = componentsIt.first; it != componentsIt.second;) {
148 // }
148 // }
149 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
149 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
150 ui->widget->replot();
150 ui->widget->replot();
151 }
151 }
152
152
153 void VisualizationGraphWidget::setYRange(const SqpRange &range)
153 void VisualizationGraphWidget::setYRange(const SqpRange &range)
154 {
154 {
155 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
155 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
156 }
156 }
157
157
158 SqpRange VisualizationGraphWidget::graphRange() const noexcept
158 SqpRange VisualizationGraphWidget::graphRange() const noexcept
159 {
159 {
160 auto graphRange = ui->widget->xAxis->range();
160 auto graphRange = ui->widget->xAxis->range();
161 return SqpRange{graphRange.lower, graphRange.upper};
161 return SqpRange{graphRange.lower, graphRange.upper};
162 }
162 }
163
163
164 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
164 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
165 {
165 {
166 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
166 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
167 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
167 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
168 ui->widget->replot();
168 ui->widget->replot();
169 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
169 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
170 }
170 }
171
171
172 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
172 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
173 {
173 {
174 if (visitor) {
174 if (visitor) {
175 visitor->visit(this);
175 visitor->visit(this);
176 }
176 }
177 else {
177 else {
178 qCCritical(LOG_VisualizationGraphWidget())
178 qCCritical(LOG_VisualizationGraphWidget())
179 << tr("Can't visit widget : the visitor is null");
179 << tr("Can't visit widget : the visitor is null");
180 }
180 }
181 }
181 }
182
182
183 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
183 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
184 {
184 {
185 /// @todo : for the moment, a graph can always accomodate a variable
185 /// @todo : for the moment, a graph can always accomodate a variable
186 Q_UNUSED(variable);
186 Q_UNUSED(variable);
187 return true;
187 return true;
188 }
188 }
189
189
190 bool VisualizationGraphWidget::contains(const Variable &variable) const
190 bool VisualizationGraphWidget::contains(const Variable &variable) const
191 {
191 {
192 // Finds the variable among the keys of the map
192 // Finds the variable among the keys of the map
193 auto variablePtr = &variable;
193 auto variablePtr = &variable;
194 auto findVariable
194 auto findVariable
195 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
195 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
196
196
197 auto end = impl->m_VariableToPlotMultiMap.cend();
197 auto end = impl->m_VariableToPlotMultiMap.cend();
198 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
198 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
199 return it != end;
199 return it != end;
200 }
200 }
201
201
202 QString VisualizationGraphWidget::name() const
202 QString VisualizationGraphWidget::name() const
203 {
203 {
204 return ui->graphNameLabel->text();
204 return ui->graphNameLabel->text();
205 }
205 }
206
206
207 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
207 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
208 {
208 {
209 QMenu graphMenu{};
209 QMenu graphMenu{};
210
210
211 // Iterates on variables (unique keys)
211 // Iterates on variables (unique keys)
212 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
212 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
213 end = impl->m_VariableToPlotMultiMap.cend();
213 end = impl->m_VariableToPlotMultiMap.cend();
214 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
214 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
215 // 'Remove variable' action
215 // 'Remove variable' action
216 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
216 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
217 [ this, var = it->first ]() { removeVariable(var); });
217 [ this, var = it->first ]() { removeVariable(var); });
218 }
218 }
219
219
220 if (!graphMenu.isEmpty()) {
220 if (!graphMenu.isEmpty()) {
221 graphMenu.exec(mapToGlobal(pos));
221 graphMenu.exec(QCursor::pos());
222 }
222 }
223 }
223 }
224
224
225 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
225 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
226 {
226 {
227 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
227 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
228 << QThread::currentThread()->objectName() << "DoAcqui"
228 << QThread::currentThread()->objectName() << "DoAcqui"
229 << impl->m_DoAcquisition;
229 << impl->m_DoAcquisition;
230
230
231 auto graphRange = SqpRange{t1.lower, t1.upper};
231 auto graphRange = SqpRange{t1.lower, t1.upper};
232 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
232 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
233
233
234 if (impl->m_DoAcquisition) {
234 if (impl->m_DoAcquisition) {
235 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
235 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
236
236
237 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
237 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
238 end = impl->m_VariableToPlotMultiMap.end();
238 end = impl->m_VariableToPlotMultiMap.end();
239 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
239 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
240 variableUnderGraphVector.push_back(it->first);
240 variableUnderGraphVector.push_back(it->first);
241 }
241 }
242 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange, oldGraphRange,
242 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange, oldGraphRange,
243 !impl->m_IsCalibration);
243 !impl->m_IsCalibration);
244
244
245 if (!impl->m_IsCalibration) {
245 if (!impl->m_IsCalibration) {
246 qCDebug(LOG_VisualizationGraphWidget())
246 qCDebug(LOG_VisualizationGraphWidget())
247 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
247 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
248 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
248 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
249 emit synchronize(graphRange, oldGraphRange);
249 emit synchronize(graphRange, oldGraphRange);
250 }
250 }
251 }
251 }
252 }
252 }
253
253
254 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
254 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
255 {
255 {
256 // Handles plot rendering when mouse is moving
256 // Handles plot rendering when mouse is moving
257 impl->m_RenderingDelegate->onMouseMove(event);
257 impl->m_RenderingDelegate->onMouseMove(event);
258 }
258 }
259
259
260 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
260 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
261 {
261 {
262 auto zoomOrientations = QFlags<Qt::Orientation>{};
262 auto zoomOrientations = QFlags<Qt::Orientation>{};
263
263
264 // Lambda that enables a zoom orientation if the key modifier related to this orientation
264 // Lambda that enables a zoom orientation if the key modifier related to this orientation
265 // has
265 // has
266 // been pressed
266 // been pressed
267 auto enableOrientation
267 auto enableOrientation
268 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
268 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
269 auto orientationEnabled = event->modifiers().testFlag(modifier);
269 auto orientationEnabled = event->modifiers().testFlag(modifier);
270 zoomOrientations.setFlag(orientation, orientationEnabled);
270 zoomOrientations.setFlag(orientation, orientationEnabled);
271 };
271 };
272 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
272 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
273 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
273 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
274
274
275 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
275 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
276 }
276 }
277
277
278 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
278 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
279 {
279 {
280 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
280 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
281 }
281 }
282
282
283 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
283 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
284 {
284 {
285 impl->m_IsCalibration = false;
285 impl->m_IsCalibration = false;
286 }
286 }
287
287
288 void VisualizationGraphWidget::onDataCacheVariableUpdated()
288 void VisualizationGraphWidget::onDataCacheVariableUpdated()
289 {
289 {
290 auto graphRange = ui->widget->xAxis->range();
290 auto graphRange = ui->widget->xAxis->range();
291 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
291 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
292
292
293 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
293 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
294 auto variable = variableEntry.first;
294 auto variable = variableEntry.first;
295 qCDebug(LOG_VisualizationGraphWidget())
295 qCDebug(LOG_VisualizationGraphWidget())
296 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
296 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
297 qCDebug(LOG_VisualizationGraphWidget())
297 qCDebug(LOG_VisualizationGraphWidget())
298 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
298 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
299 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
299 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
300 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
300 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
301 variable->range());
301 variable->range());
302 }
302 }
303 }
303 }
304 }
304 }
305
305
306 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
306 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
307 const SqpRange &range)
307 const SqpRange &range)
308 {
308 {
309 auto it = impl->m_VariableToPlotMultiMap.find(variable);
309 auto it = impl->m_VariableToPlotMultiMap.find(variable);
310 if (it != impl->m_VariableToPlotMultiMap.end()) {
310 if (it != impl->m_VariableToPlotMultiMap.end()) {
311 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
311 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
312 }
312 }
313 }
313 }
@@ -1,86 +1,74
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>SqpSettingsGeneralWidget</class>
3 <class>SqpSettingsGeneralWidget</class>
4 <widget class="QWidget" name="SqpSettingsGeneralWidget">
4 <widget class="QWidget" name="SqpSettingsGeneralWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>343</width>
9 <width>343</width>
10 <height>300</height>
10 <height>300</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QGridLayout" name="gridLayout">
16 <layout class="QGridLayout" name="gridLayout">
17 <item row="0" column="0">
17 <item row="0" column="0">
18 <widget class="QLabel" name="toleranceInitLabel">
18 <widget class="QLabel" name="toleranceInitLabel">
19 <property name="text">
19 <property name="text">
20 <string>Tolerance on first acquisition:</string>
20 <string>Tolerance on first acquisition:</string>
21 </property>
21 </property>
22 </widget>
22 </widget>
23 </item>
23 </item>
24 <item row="0" column="1">
24 <item row="0" column="1">
25 <widget class="QDoubleSpinBox" name="toleranceInitSpinBox">
25 <widget class="QDoubleSpinBox" name="toleranceInitSpinBox">
26 <property name="sizePolicy">
26 <property name="sizePolicy">
27 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
27 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
28 <horstretch>0</horstretch>
28 <horstretch>0</horstretch>
29 <verstretch>0</verstretch>
29 <verstretch>0</verstretch>
30 </sizepolicy>
30 </sizepolicy>
31 </property>
31 </property>
32 <property name="suffix">
32 <property name="suffix">
33 <string> %</string>
33 <string> %</string>
34 </property>
34 </property>
35 <property name="minimum">
36 <double>0.000000000000000</double>
37 </property>
38 <property name="maximum">
39 <double>500.000000000000000</double>
40 </property>
41 </widget>
35 </widget>
42 </item>
36 </item>
43 <item row="1" column="0">
37 <item row="1" column="0">
44 <widget class="QLabel" name="toleranceUpdateLabel">
38 <widget class="QLabel" name="toleranceUpdateLabel">
45 <property name="text">
39 <property name="text">
46 <string>Tolerance when updating acquisition:</string>
40 <string>Tolerance when updating acquisition:</string>
47 </property>
41 </property>
48 </widget>
42 </widget>
49 </item>
43 </item>
50 <item row="1" column="1">
44 <item row="1" column="1">
51 <widget class="QDoubleSpinBox" name="toleranceUpdateSpinBox">
45 <widget class="QDoubleSpinBox" name="toleranceUpdateSpinBox">
52 <property name="sizePolicy">
46 <property name="sizePolicy">
53 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
47 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
54 <horstretch>0</horstretch>
48 <horstretch>0</horstretch>
55 <verstretch>0</verstretch>
49 <verstretch>0</verstretch>
56 </sizepolicy>
50 </sizepolicy>
57 </property>
51 </property>
58 <property name="suffix">
52 <property name="suffix">
59 <string> %</string>
53 <string> %</string>
60 </property>
54 </property>
61 <property name="minimum">
62 <double>0.000000000000000</double>
63 </property>
64 <property name="maximum">
65 <double>500.000000000000000</double>
66 </property>
67 </widget>
55 </widget>
68 </item>
56 </item>
69 <item row="2" column="0">
57 <item row="2" column="0">
70 <spacer name="verticalSpacer">
58 <spacer name="verticalSpacer">
71 <property name="orientation">
59 <property name="orientation">
72 <enum>Qt::Vertical</enum>
60 <enum>Qt::Vertical</enum>
73 </property>
61 </property>
74 <property name="sizeHint" stdset="0">
62 <property name="sizeHint" stdset="0">
75 <size>
63 <size>
76 <width>20</width>
64 <width>20</width>
77 <height>40</height>
65 <height>40</height>
78 </size>
66 </size>
79 </property>
67 </property>
80 </spacer>
68 </spacer>
81 </item>
69 </item>
82 </layout>
70 </layout>
83 </widget>
71 </widget>
84 <resources/>
72 <resources/>
85 <connections/>
73 <connections/>
86 </ui>
74 </ui>
General Comments 0
You need to be logged in to leave comments. Login now