##// END OF EJS Templates
Fixed untimely update of the range to be displayed in the variable widget
Alexandre Leroux -
r654:aff19a50babf
parent child
Show More
@@ -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