@@ -26,8 +26,21 struct SqpRange { | |||||
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); |
@@ -3,6 +3,7 | |||||
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> | |
@@ -33,6 +34,14 public: | |||||
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 |
@@ -12,7 +12,11 Q_LOGGING_CATEGORY(LOG_Variable, "Variable") | |||||
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 | |||
@@ -20,12 +24,32 struct Variable::VariablePrivate { | |||||
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 | }; | |
@@ -55,6 +79,7 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 | |||
@@ -73,6 +98,11 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept | |||||
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" | |
@@ -83,6 +113,7 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept | |||||
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 |
@@ -153,35 +153,21 QVariant VariableModel::data(const QModelIndex &index, int role) const | |||||
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: |
General Comments 0
You need to be logged in to leave comments.
Login now