##// END OF EJS Templates
Shows min/max x-axis data in Variable widget (3)...
Alexandre Leroux -
r601:fe5ae51adf07
parent child
Show More
@@ -1,258 +1,271
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
156 /// Lambda function that builds the variant to return for a time value
157 auto dateTimeVariant = [](double secs) {
157 /// @param getValueFun function used to get for a data series the iterator on the entry
158 auto dateTime = DateUtils::dateTime(secs);
158 /// that contains the time value to display
159 return dateTime.toString(DATETIME_FORMAT);
159 auto dateTimeVariant = [variable](const auto &getValueFun) {
160 if (auto dataSeries = variable->dataSeries()) {
161 auto it = getValueFun(*dataSeries);
162 return (it != dataSeries->cend())
163 ? DateUtils::dateTime(it->x()).toString(DATETIME_FORMAT)
164 : QVariant{};
165 }
166 else {
167 return QVariant{};
168 }
160 };
169 };
161
170
162 switch (index.column()) {
171 switch (index.column()) {
163 case NAME_COLUMN:
172 case NAME_COLUMN:
164 return variable->name();
173 return variable->name();
165 case TSTART_COLUMN:
174 case TSTART_COLUMN:
166 return dateTimeVariant(variable->range().m_TStart);
175 // Shows the min value of the data series above the range tstart
176 return dateTimeVariant([min = variable->range().m_TStart](
177 const auto &dataSeries) { return dataSeries.minData(min); });
167 case TEND_COLUMN:
178 case TEND_COLUMN:
168 return dateTimeVariant(variable->range().m_TEnd);
179 // Shows the max value of the data series under the range tend
180 return dateTimeVariant([max = variable->range().m_TEnd](
181 const auto &dataSeries) { return dataSeries.maxData(max); });
169 case UNIT_COLUMN:
182 case UNIT_COLUMN:
170 return variable->metadata().value(QStringLiteral("units"));
183 return variable->metadata().value(QStringLiteral("units"));
171 case MISSION_COLUMN:
184 case MISSION_COLUMN:
172 return variable->metadata().value(QStringLiteral("mission"));
185 return variable->metadata().value(QStringLiteral("mission"));
173 case PLUGIN_COLUMN:
186 case PLUGIN_COLUMN:
174 return variable->metadata().value(QStringLiteral("plugin"));
187 return variable->metadata().value(QStringLiteral("plugin"));
175 default:
188 default:
176 // No action
189 // No action
177 break;
190 break;
178 }
191 }
179
192
180 qWarning(LOG_VariableModel())
193 qWarning(LOG_VariableModel())
181 << tr("Can't get data (unknown column %1)").arg(index.column());
194 << tr("Can't get data (unknown column %1)").arg(index.column());
182 }
195 }
183 else {
196 else {
184 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
197 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
185 }
198 }
186 }
199 }
187 else if (role == VariableRoles::ProgressRole) {
200 else if (role == VariableRoles::ProgressRole) {
188 if (auto variable = impl->m_Variables.at(index.row())) {
201 if (auto variable = impl->m_Variables.at(index.row())) {
189
202
190 auto it = impl->m_VariableToProgress.find(variable);
203 auto it = impl->m_VariableToProgress.find(variable);
191 if (it != impl->m_VariableToProgress.cend()) {
204 if (it != impl->m_VariableToProgress.cend()) {
192 return it->second;
205 return it->second;
193 }
206 }
194 }
207 }
195 }
208 }
196
209
197 return QVariant{};
210 return QVariant{};
198 }
211 }
199
212
200 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
213 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
201 {
214 {
202 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
215 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
203 return QVariant{};
216 return QVariant{};
204 }
217 }
205
218
206 if (orientation == Qt::Horizontal) {
219 if (orientation == Qt::Horizontal) {
207 auto propertiesIt = COLUMN_PROPERTIES.find(section);
220 auto propertiesIt = COLUMN_PROPERTIES.find(section);
208 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
221 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
209 // Role is either DisplayRole or SizeHintRole
222 // Role is either DisplayRole or SizeHintRole
210 return (role == Qt::DisplayRole)
223 return (role == Qt::DisplayRole)
211 ? QVariant{propertiesIt->m_Name}
224 ? QVariant{propertiesIt->m_Name}
212 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
225 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
213 }
226 }
214 else {
227 else {
215 qWarning(LOG_VariableModel())
228 qWarning(LOG_VariableModel())
216 << tr("Can't get header data (unknown column %1)").arg(section);
229 << tr("Can't get header data (unknown column %1)").arg(section);
217 }
230 }
218 }
231 }
219
232
220 return QVariant{};
233 return QVariant{};
221 }
234 }
222
235
223 void VariableModel::abortProgress(const QModelIndex &index)
236 void VariableModel::abortProgress(const QModelIndex &index)
224 {
237 {
225 if (auto variable = impl->m_Variables.at(index.row())) {
238 if (auto variable = impl->m_Variables.at(index.row())) {
226 emit abortProgessRequested(variable);
239 emit abortProgessRequested(variable);
227 }
240 }
228 }
241 }
229
242
230 void VariableModel::onVariableUpdated() noexcept
243 void VariableModel::onVariableUpdated() noexcept
231 {
244 {
232 // Finds variable that has been updated in the model
245 // Finds variable that has been updated in the model
233 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
246 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
234 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
247 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
235
248
236 if (updatedVariableIndex > -1) {
249 if (updatedVariableIndex > -1) {
237 emit dataChanged(createIndex(updatedVariableIndex, 0),
250 emit dataChanged(createIndex(updatedVariableIndex, 0),
238 createIndex(updatedVariableIndex, columnCount() - 1));
251 createIndex(updatedVariableIndex, columnCount() - 1));
239 }
252 }
240 }
253 }
241 }
254 }
242
255
243 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
256 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
244 {
257 {
245 auto begin = std::cbegin(m_Variables);
258 auto begin = std::cbegin(m_Variables);
246 auto end = std::cend(m_Variables);
259 auto end = std::cend(m_Variables);
247 auto it
260 auto it
248 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
261 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
249
262
250 if (it != end) {
263 if (it != end) {
251 // Gets the index of the variable in the model: we assume here that views have the same
264 // Gets the index of the variable in the model: we assume here that views have the same
252 // order as the model
265 // order as the model
253 return std::distance(begin, it);
266 return std::distance(begin, it);
254 }
267 }
255 else {
268 else {
256 return -1;
269 return -1;
257 }
270 }
258 }
271 }
General Comments 0
You need to be logged in to leave comments. Login now