@@ -26,8 +26,21 struct SqpRange { | |||
|
26 | 26 | { |
|
27 | 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 | 44 | inline QDebug operator<<(QDebug d, SqpRange obj) |
|
32 | 45 | { |
|
33 | 46 | auto tendDateTimeStart = DateUtils::dateTime(obj.m_TStart); |
@@ -3,6 +3,7 | |||
|
3 | 3 | |
|
4 | 4 | #include "CoreGlobal.h" |
|
5 | 5 | |
|
6 | #include <Data/DataSeriesIterator.h> | |
|
6 | 7 | #include <Data/SqpRange.h> |
|
7 | 8 | |
|
8 | 9 | #include <QLoggingCategory> |
@@ -33,6 +34,14 public: | |||
|
33 | 34 | SqpRange cacheRange() const noexcept; |
|
34 | 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 | 45 | /// @return the data of the variable, nullptr if there is no data |
|
37 | 46 | std::shared_ptr<IDataSeries> dataSeries() const noexcept; |
|
38 | 47 |
@@ -12,7 +12,11 Q_LOGGING_CATEGORY(LOG_Variable, "Variable") | |||
|
12 | 12 | struct Variable::VariablePrivate { |
|
13 | 13 | explicit VariablePrivate(const QString &name, const SqpRange &dateTime, |
|
14 | 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 | 24 | void lockWrite() { m_Lock.lockForWrite(); } |
|
21 | 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 | 46 | QString m_Name; |
|
24 | 47 | |
|
25 | 48 | SqpRange m_Range; |
|
26 | 49 | SqpRange m_CacheRange; |
|
27 | 50 | QVariantHash m_Metadata; |
|
28 | 51 | std::shared_ptr<IDataSeries> m_DataSeries; |
|
52 | SqpRange m_RealRange; | |
|
29 | 53 | |
|
30 | 54 | QReadWriteLock m_Lock; |
|
31 | 55 | }; |
@@ -55,6 +79,7 void Variable::setRange(const SqpRange &range) noexcept | |||
|
55 | 79 | { |
|
56 | 80 | impl->lockWrite(); |
|
57 | 81 | impl->m_Range = range; |
|
82 | impl->updateRealRange(); | |
|
58 | 83 | impl->unlock(); |
|
59 | 84 | } |
|
60 | 85 | |
@@ -73,6 +98,11 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept | |||
|
73 | 98 | impl->unlock(); |
|
74 | 99 | } |
|
75 | 100 | |
|
101 | SqpRange Variable::realRange() const noexcept | |
|
102 | { | |
|
103 | return impl->m_RealRange; | |
|
104 | } | |
|
105 | ||
|
76 | 106 | void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept |
|
77 | 107 | { |
|
78 | 108 | qCDebug(LOG_Variable()) << "TORM Variable::setDataSeries" |
@@ -83,6 +113,7 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept | |||
|
83 | 113 | } |
|
84 | 114 | impl->lockWrite(); |
|
85 | 115 | impl->m_DataSeries = dataSeries->clone(); |
|
116 | impl->updateRealRange(); | |
|
86 | 117 | impl->unlock(); |
|
87 | 118 | } |
|
88 | 119 |
@@ -153,35 +153,21 QVariant VariableModel::data(const QModelIndex &index, int role) const | |||
|
153 | 153 | |
|
154 | 154 | if (role == Qt::DisplayRole) { |
|
155 | 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 | 156 | switch (index.column()) { |
|
175 | 157 | case NAME_COLUMN: |
|
176 | 158 | return variable->name(); |
|
177 | case TSTART_COLUMN: | |
|
178 | // Shows the min value of the data series above the range tstart | |
|
179 | return dateTimeVariant([min = variable->range().m_TStart]( | |
|
180 | const auto &dataSeries) { return dataSeries.minXAxisData(min); }); | |
|
181 | case TEND_COLUMN: | |
|
182 | // Shows the max value of the data series under the range tend | |
|
183 | return dateTimeVariant([max = variable->range().m_TEnd]( | |
|
184 | const auto &dataSeries) { return dataSeries.maxXAxisData(max); }); | |
|
159 | case TSTART_COLUMN: { | |
|
160 | auto range = variable->realRange(); | |
|
161 | return range != INVALID_RANGE | |
|
162 | ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT) | |
|
163 | : QVariant{}; | |
|
164 | } | |
|
165 | case TEND_COLUMN: { | |
|
166 | auto range = variable->realRange(); | |
|
167 | return range != INVALID_RANGE | |
|
168 | ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT) | |
|
169 | : QVariant{}; | |
|
170 | } | |
|
185 | 171 | case UNIT_COLUMN: |
|
186 | 172 | return variable->metadata().value(QStringLiteral("units")); |
|
187 | 173 | case MISSION_COLUMN: |
General Comments 0
You need to be logged in to leave comments.
Login now