##// END OF EJS Templates
Fixed untimely update of the range to be displayed in the variable widget
Alexandre Leroux -
r611:aff19a50babf
parent child
Show More
@@ -1,43 +1,56
1 1 #ifndef SCIQLOP_SQPRANGE_H
2 2 #define SCIQLOP_SQPRANGE_H
3 3
4 4 #include <QObject>
5 5
6 6 #include <QDebug>
7 7
8 8 #include <Common/DateUtils.h>
9 9 #include <Common/MetaTypes.h>
10 10
11 11 /**
12 12 * @brief The SqpRange struct holds the information of time parameters
13 13 */
14 14 struct SqpRange {
15 15 /// Start time (UTC)
16 16 double m_TStart;
17 17 /// End time (UTC)
18 18 double m_TEnd;
19 19
20 20 bool contains(const SqpRange &dateTime) const noexcept
21 21 {
22 22 return (m_TStart <= dateTime.m_TStart && m_TEnd >= dateTime.m_TEnd);
23 23 }
24 24
25 25 bool intersect(const SqpRange &dateTime) const noexcept
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);
34 47 auto tendDateTimeEnd = DateUtils::dateTime(obj.m_TEnd);
35 48
36 49 d << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd;
37 50 return d;
38 51 }
39 52
40 53 // Required for using shared_ptr in signals/slots
41 54 SCIQLOP_REGISTER_META_TYPE(SQPRANGE_REGISTRY, SqpRange)
42 55
43 56 #endif // SCIQLOP_SQPRANGE_H
@@ -1,66 +1,75
1 1 #ifndef SCIQLOP_VARIABLE_H
2 2 #define SCIQLOP_VARIABLE_H
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>
9 10 #include <QObject>
10 11
11 12 #include <Common/MetaTypes.h>
12 13 #include <Common/spimpl.h>
13 14
14 15 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
15 16
16 17 class IDataSeries;
17 18 class QString;
18 19
19 20 /**
20 21 * @brief The Variable class represents a variable in SciQlop.
21 22 */
22 23 class SCIQLOP_CORE_EXPORT Variable : public QObject {
23 24
24 25 Q_OBJECT
25 26
26 27 public:
27 28 explicit Variable(const QString &name, const SqpRange &dateTime,
28 29 const QVariantHash &metadata = {});
29 30
30 31 QString name() const noexcept;
31 32 SqpRange range() const noexcept;
32 33 void setRange(const SqpRange &range) noexcept;
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
39 48 QVariantHash metadata() const noexcept;
40 49
41 50 bool contains(const SqpRange &range) const noexcept;
42 51 bool intersect(const SqpRange &range) const noexcept;
43 52 bool isInside(const SqpRange &range) const noexcept;
44 53
45 54 bool cacheContains(const SqpRange &range) const noexcept;
46 55 bool cacheIntersect(const SqpRange &range) const noexcept;
47 56 bool cacheIsInside(const SqpRange &range) const noexcept;
48 57
49 58 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
50 59 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
51 60 void setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
52 61 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
53 62
54 63 signals:
55 64 void updated();
56 65
57 66 private:
58 67 class VariablePrivate;
59 68 spimpl::unique_impl_ptr<VariablePrivate> impl;
60 69 };
61 70
62 71 // Required for using shared_ptr in signals/slots
63 72 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
64 73 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
65 74
66 75 #endif // SCIQLOP_VARIABLE_H
@@ -1,248 +1,279
1 1 #include "Variable/Variable.h"
2 2
3 3 #include <Data/IDataSeries.h>
4 4 #include <Data/SqpRange.h>
5 5
6 6 #include <QMutex>
7 7 #include <QReadWriteLock>
8 8 #include <QThread>
9 9
10 10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
11 11
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
19 23 void lockRead() { m_Lock.lockForRead(); }
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 };
32 56
33 57 Variable::Variable(const QString &name, const SqpRange &dateTime, const QVariantHash &metadata)
34 58 : impl{spimpl::make_unique_impl<VariablePrivate>(name, dateTime, metadata)}
35 59 {
36 60 }
37 61
38 62 QString Variable::name() const noexcept
39 63 {
40 64 impl->lockRead();
41 65 auto name = impl->m_Name;
42 66 impl->unlock();
43 67 return name;
44 68 }
45 69
46 70 SqpRange Variable::range() const noexcept
47 71 {
48 72 impl->lockRead();
49 73 auto range = impl->m_Range;
50 74 impl->unlock();
51 75 return range;
52 76 }
53 77
54 78 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
61 86 SqpRange Variable::cacheRange() const noexcept
62 87 {
63 88 impl->lockRead();
64 89 auto cacheRange = impl->m_CacheRange;
65 90 impl->unlock();
66 91 return cacheRange;
67 92 }
68 93
69 94 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
70 95 {
71 96 impl->lockWrite();
72 97 impl->m_CacheRange = cacheRange;
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"
79 109 << QThread::currentThread()->objectName();
80 110 if (!dataSeries) {
81 111 /// @todo ALX : log
82 112 return;
83 113 }
84 114 impl->lockWrite();
85 115 impl->m_DataSeries = dataSeries->clone();
116 impl->updateRealRange();
86 117 impl->unlock();
87 118 }
88 119
89 120 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
90 121 {
91 122 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
92 123 << QThread::currentThread()->objectName();
93 124 if (!dataSeries) {
94 125 /// @todo ALX : log
95 126 return;
96 127 }
97 128
98 129 // Add or merge the data
99 130 // Inits the data series of the variable
100 131 impl->lockWrite();
101 132 if (!impl->m_DataSeries) {
102 133 impl->m_DataSeries = dataSeries->clone();
103 134 }
104 135 else {
105 136 impl->m_DataSeries->merge(dataSeries.get());
106 137 }
107 138 impl->unlock();
108 139
109 140 // sub the data
110 141 auto subData = this->dataSeries()->subDataSeries(this->cacheRange());
111 142 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries sub" << subData->range();
112 143 this->setDataSeries(subData);
113 144 qCDebug(LOG_Variable()) << "TORM: Variable::mergeDataSeries set" << this->dataSeries()->range();
114 145 }
115 146
116 147 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
117 148 {
118 149 impl->lockRead();
119 150 auto dataSeries = impl->m_DataSeries;
120 151 impl->unlock();
121 152
122 153 return dataSeries;
123 154 }
124 155
125 156 QVariantHash Variable::metadata() const noexcept
126 157 {
127 158 impl->lockRead();
128 159 auto metadata = impl->m_Metadata;
129 160 impl->unlock();
130 161 return metadata;
131 162 }
132 163
133 164 bool Variable::contains(const SqpRange &range) const noexcept
134 165 {
135 166 impl->lockRead();
136 167 auto res = impl->m_Range.contains(range);
137 168 impl->unlock();
138 169 return res;
139 170 }
140 171
141 172 bool Variable::intersect(const SqpRange &range) const noexcept
142 173 {
143 174
144 175 impl->lockRead();
145 176 auto res = impl->m_Range.intersect(range);
146 177 impl->unlock();
147 178 return res;
148 179 }
149 180
150 181 bool Variable::isInside(const SqpRange &range) const noexcept
151 182 {
152 183 impl->lockRead();
153 184 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
154 185 impl->unlock();
155 186 return res;
156 187 }
157 188
158 189 bool Variable::cacheContains(const SqpRange &range) const noexcept
159 190 {
160 191 impl->lockRead();
161 192 auto res = impl->m_CacheRange.contains(range);
162 193 impl->unlock();
163 194 return res;
164 195 }
165 196
166 197 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
167 198 {
168 199 impl->lockRead();
169 200 auto res = impl->m_CacheRange.intersect(range);
170 201 impl->unlock();
171 202 return res;
172 203 }
173 204
174 205 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
175 206 {
176 207 impl->lockRead();
177 208 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
178 209 impl->unlock();
179 210 return res;
180 211 }
181 212
182 213
183 214 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
184 215 {
185 216 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
186 217
187 218 auto notInCache = QVector<SqpRange>{};
188 219
189 220 if (!this->cacheContains(range)) {
190 221 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
191 222 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
192 223 notInCache << range;
193 224 }
194 225 else if (range.m_TStart < impl->m_CacheRange.m_TStart
195 226 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
196 227 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
197 228 }
198 229 else if (range.m_TStart < impl->m_CacheRange.m_TStart
199 230 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
200 231 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
201 232 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
202 233 }
203 234 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
204 235 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
205 236 }
206 237 else {
207 238 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
208 239 << QThread::currentThread();
209 240 }
210 241 }
211 242
212 243 return notInCache;
213 244 }
214 245
215 246 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
216 247 {
217 248 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
218 249
219 250 auto inCache = QVector<SqpRange>{};
220 251
221 252
222 253 if (this->intersect(range)) {
223 254 if (range.m_TStart <= impl->m_CacheRange.m_TStart
224 255 && range.m_TEnd >= impl->m_CacheRange.m_TStart
225 256 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
226 257 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
227 258 }
228 259
229 260 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
230 261 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
231 262 inCache << range;
232 263 }
233 264 else if (range.m_TStart > impl->m_CacheRange.m_TStart
234 265 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
235 266 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
236 267 }
237 268 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
238 269 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
239 270 inCache << impl->m_CacheRange;
240 271 }
241 272 else {
242 273 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
243 274 << QThread::currentThread();
244 275 }
245 276 }
246 277
247 278 return inCache;
248 279 }
@@ -1,274 +1,260
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableModel.h>
3 3
4 4 #include <Common/DateUtils.h>
5 5
6 6 #include <Data/IDataSeries.h>
7 7
8 8 #include <QSize>
9 9 #include <unordered_map>
10 10
11 11 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
12 12
13 13 namespace {
14 14
15 15 // Column indexes
16 16 const auto NAME_COLUMN = 0;
17 17 const auto TSTART_COLUMN = 1;
18 18 const auto TEND_COLUMN = 2;
19 19 const auto UNIT_COLUMN = 3;
20 20 const auto MISSION_COLUMN = 4;
21 21 const auto PLUGIN_COLUMN = 5;
22 22 const auto NB_COLUMNS = 6;
23 23
24 24 // Column properties
25 25 const auto DEFAULT_HEIGHT = 25;
26 26 const auto DEFAULT_WIDTH = 100;
27 27
28 28 struct ColumnProperties {
29 29 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
30 30 int height = DEFAULT_HEIGHT)
31 31 : m_Name{name}, m_Width{width}, m_Height{height}
32 32 {
33 33 }
34 34
35 35 QString m_Name;
36 36 int m_Width;
37 37 int m_Height;
38 38 };
39 39
40 40 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
41 41 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
42 42 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {UNIT_COLUMN, {QObject::tr("Unit")}},
43 43 {MISSION_COLUMN, {QObject::tr("Mission")}}, {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
44 44
45 45 /// Format for datetimes
46 46 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
47 47
48 48
49 49 } // namespace
50 50
51 51 struct VariableModel::VariableModelPrivate {
52 52 /// Variables created in SciQlop
53 53 std::vector<std::shared_ptr<Variable> > m_Variables;
54 54 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
55 55
56 56 /// Return the row index of the variable. -1 if it's not found
57 57 int indexOfVariable(Variable *variable) const noexcept;
58 58 };
59 59
60 60 VariableModel::VariableModel(QObject *parent)
61 61 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
62 62 {
63 63 }
64 64
65 65 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
66 66 const SqpRange &dateTime,
67 67 const QVariantHash &metadata) noexcept
68 68 {
69 69 auto insertIndex = rowCount();
70 70 beginInsertRows({}, insertIndex, insertIndex);
71 71
72 72 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
73 73
74 74 impl->m_Variables.push_back(variable);
75 75 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
76 76
77 77 endInsertRows();
78 78
79 79 return variable;
80 80 }
81 81
82 82 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
83 83 {
84 84 if (!variable) {
85 85 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
86 86 return;
87 87 }
88 88
89 89 // Finds variable in the model
90 90 auto begin = impl->m_Variables.cbegin();
91 91 auto end = impl->m_Variables.cend();
92 92 auto it = std::find(begin, end, variable);
93 93 if (it != end) {
94 94 auto removeIndex = std::distance(begin, it);
95 95
96 96 // Deletes variable
97 97 beginRemoveRows({}, removeIndex, removeIndex);
98 98 impl->m_Variables.erase(it);
99 99 endRemoveRows();
100 100 }
101 101 else {
102 102 qCritical(LOG_VariableModel())
103 103 << tr("Can't delete variable %1 from the model: the variable is not in the model")
104 104 .arg(variable->name());
105 105 }
106 106
107 107 // Removes variable from progress map
108 108 impl->m_VariableToProgress.erase(variable);
109 109 }
110 110
111 111
112 112 std::shared_ptr<Variable> VariableModel::variable(int index) const
113 113 {
114 114 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
115 115 }
116 116
117 117 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
118 118 {
119 119 if (progress > 0.0) {
120 120 impl->m_VariableToProgress[variable] = progress;
121 121 }
122 122 else {
123 123 impl->m_VariableToProgress.erase(variable);
124 124 }
125 125 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
126 126
127 127 emit dataChanged(modelIndex, modelIndex);
128 128 }
129 129
130 130 int VariableModel::columnCount(const QModelIndex &parent) const
131 131 {
132 132 Q_UNUSED(parent);
133 133
134 134 return NB_COLUMNS;
135 135 }
136 136
137 137 int VariableModel::rowCount(const QModelIndex &parent) const
138 138 {
139 139 Q_UNUSED(parent);
140 140
141 141 return impl->m_Variables.size();
142 142 }
143 143
144 144 QVariant VariableModel::data(const QModelIndex &index, int role) const
145 145 {
146 146 if (!index.isValid()) {
147 147 return QVariant{};
148 148 }
149 149
150 150 if (index.row() < 0 || index.row() >= rowCount()) {
151 151 return QVariant{};
152 152 }
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:
188 174 return variable->metadata().value(QStringLiteral("mission"));
189 175 case PLUGIN_COLUMN:
190 176 return variable->metadata().value(QStringLiteral("plugin"));
191 177 default:
192 178 // No action
193 179 break;
194 180 }
195 181
196 182 qWarning(LOG_VariableModel())
197 183 << tr("Can't get data (unknown column %1)").arg(index.column());
198 184 }
199 185 else {
200 186 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
201 187 }
202 188 }
203 189 else if (role == VariableRoles::ProgressRole) {
204 190 if (auto variable = impl->m_Variables.at(index.row())) {
205 191
206 192 auto it = impl->m_VariableToProgress.find(variable);
207 193 if (it != impl->m_VariableToProgress.cend()) {
208 194 return it->second;
209 195 }
210 196 }
211 197 }
212 198
213 199 return QVariant{};
214 200 }
215 201
216 202 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
217 203 {
218 204 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
219 205 return QVariant{};
220 206 }
221 207
222 208 if (orientation == Qt::Horizontal) {
223 209 auto propertiesIt = COLUMN_PROPERTIES.find(section);
224 210 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
225 211 // Role is either DisplayRole or SizeHintRole
226 212 return (role == Qt::DisplayRole)
227 213 ? QVariant{propertiesIt->m_Name}
228 214 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
229 215 }
230 216 else {
231 217 qWarning(LOG_VariableModel())
232 218 << tr("Can't get header data (unknown column %1)").arg(section);
233 219 }
234 220 }
235 221
236 222 return QVariant{};
237 223 }
238 224
239 225 void VariableModel::abortProgress(const QModelIndex &index)
240 226 {
241 227 if (auto variable = impl->m_Variables.at(index.row())) {
242 228 emit abortProgessRequested(variable);
243 229 }
244 230 }
245 231
246 232 void VariableModel::onVariableUpdated() noexcept
247 233 {
248 234 // Finds variable that has been updated in the model
249 235 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
250 236 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
251 237
252 238 if (updatedVariableIndex > -1) {
253 239 emit dataChanged(createIndex(updatedVariableIndex, 0),
254 240 createIndex(updatedVariableIndex, columnCount() - 1));
255 241 }
256 242 }
257 243 }
258 244
259 245 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
260 246 {
261 247 auto begin = std::cbegin(m_Variables);
262 248 auto end = std::cend(m_Variables);
263 249 auto it
264 250 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
265 251
266 252 if (it != end) {
267 253 // Gets the index of the variable in the model: we assume here that views have the same
268 254 // order as the model
269 255 return std::distance(begin, it);
270 256 }
271 257 else {
272 258 return -1;
273 259 }
274 260 }
General Comments 0
You need to be logged in to leave comments. Login now