##// END OF EJS Templates
Adds column to display nb points in variable widget
Alexandre Leroux -
r719:3f7959a8e9dd
parent child
Show More
@@ -1,290 +1,294
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 #include <Common/StringUtils.h>
5 #include <Common/StringUtils.h>
6
6
7 #include <Data/IDataSeries.h>
7 #include <Data/IDataSeries.h>
8
8
9 #include <QSize>
9 #include <QSize>
10 #include <unordered_map>
10 #include <unordered_map>
11
11
12 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
12 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
13
13
14 namespace {
14 namespace {
15
15
16 // Column indexes
16 // Column indexes
17 const auto NAME_COLUMN = 0;
17 const auto NAME_COLUMN = 0;
18 const auto TSTART_COLUMN = 1;
18 const auto TSTART_COLUMN = 1;
19 const auto TEND_COLUMN = 2;
19 const auto TEND_COLUMN = 2;
20 const auto UNIT_COLUMN = 3;
20 const auto NBPOINTS_COLUMN = 3;
21 const auto MISSION_COLUMN = 4;
21 const auto UNIT_COLUMN = 4;
22 const auto PLUGIN_COLUMN = 5;
22 const auto MISSION_COLUMN = 5;
23 const auto NB_COLUMNS = 6;
23 const auto PLUGIN_COLUMN = 6;
24 const auto NB_COLUMNS = 7;
24
25
25 // Column properties
26 // Column properties
26 const auto DEFAULT_HEIGHT = 25;
27 const auto DEFAULT_HEIGHT = 25;
27 const auto DEFAULT_WIDTH = 100;
28 const auto DEFAULT_WIDTH = 100;
28
29
29 struct ColumnProperties {
30 struct ColumnProperties {
30 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
31 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
31 int height = DEFAULT_HEIGHT)
32 int height = DEFAULT_HEIGHT)
32 : m_Name{name}, m_Width{width}, m_Height{height}
33 : m_Name{name}, m_Width{width}, m_Height{height}
33 {
34 {
34 }
35 }
35
36
36 QString m_Name;
37 QString m_Name;
37 int m_Width;
38 int m_Width;
38 int m_Height;
39 int m_Height;
39 };
40 };
40
41
41 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
42 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
42 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
43 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
43 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {UNIT_COLUMN, {QObject::tr("Unit")}},
44 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
44 {MISSION_COLUMN, {QObject::tr("Mission")}}, {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
45 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
46 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
45
47
46 /// Format for datetimes
48 /// Format for datetimes
47 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
49 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
48
50
49 QString uniqueName(const QString &defaultName,
51 QString uniqueName(const QString &defaultName,
50 const std::vector<std::shared_ptr<Variable> > &variables)
52 const std::vector<std::shared_ptr<Variable> > &variables)
51 {
53 {
52 auto forbiddenNames = std::vector<QString>(variables.size());
54 auto forbiddenNames = std::vector<QString>(variables.size());
53 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
55 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
54 [](const auto &variable) { return variable->name(); });
56 [](const auto &variable) { return variable->name(); });
55 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
57 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
56 Q_ASSERT(!uniqueName.isEmpty());
58 Q_ASSERT(!uniqueName.isEmpty());
57
59
58 return uniqueName;
60 return uniqueName;
59 }
61 }
60
62
61 } // namespace
63 } // namespace
62
64
63 struct VariableModel::VariableModelPrivate {
65 struct VariableModel::VariableModelPrivate {
64 /// Variables created in SciQlop
66 /// Variables created in SciQlop
65 std::vector<std::shared_ptr<Variable> > m_Variables;
67 std::vector<std::shared_ptr<Variable> > m_Variables;
66 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
68 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
67
69
68 /// Return the row index of the variable. -1 if it's not found
70 /// Return the row index of the variable. -1 if it's not found
69 int indexOfVariable(Variable *variable) const noexcept;
71 int indexOfVariable(Variable *variable) const noexcept;
70 };
72 };
71
73
72 VariableModel::VariableModel(QObject *parent)
74 VariableModel::VariableModel(QObject *parent)
73 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
75 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
74 {
76 {
75 }
77 }
76
78
77 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
79 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
78 {
80 {
79 auto insertIndex = rowCount();
81 auto insertIndex = rowCount();
80 beginInsertRows({}, insertIndex, insertIndex);
82 beginInsertRows({}, insertIndex, insertIndex);
81
83
82 // Generates unique name for the variable
84 // Generates unique name for the variable
83 variable->setName(uniqueName(variable->name(), impl->m_Variables));
85 variable->setName(uniqueName(variable->name(), impl->m_Variables));
84
86
85 impl->m_Variables.push_back(variable);
87 impl->m_Variables.push_back(variable);
86 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
88 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
87
89
88 endInsertRows();
90 endInsertRows();
89 }
91 }
90
92
91 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
93 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
92 {
94 {
93 auto end = impl->m_Variables.cend();
95 auto end = impl->m_Variables.cend();
94 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
96 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
95 }
97 }
96
98
97 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
99 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
98 const SqpRange &dateTime,
100 const SqpRange &dateTime,
99 const QVariantHash &metadata) noexcept
101 const QVariantHash &metadata) noexcept
100 {
102 {
101 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
103 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
102 addVariable(variable);
104 addVariable(variable);
103
105
104 return variable;
106 return variable;
105 }
107 }
106
108
107 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
109 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
108 {
110 {
109 if (!variable) {
111 if (!variable) {
110 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
112 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
111 return;
113 return;
112 }
114 }
113
115
114 // Finds variable in the model
116 // Finds variable in the model
115 auto begin = impl->m_Variables.cbegin();
117 auto begin = impl->m_Variables.cbegin();
116 auto end = impl->m_Variables.cend();
118 auto end = impl->m_Variables.cend();
117 auto it = std::find(begin, end, variable);
119 auto it = std::find(begin, end, variable);
118 if (it != end) {
120 if (it != end) {
119 auto removeIndex = std::distance(begin, it);
121 auto removeIndex = std::distance(begin, it);
120
122
121 // Deletes variable
123 // Deletes variable
122 beginRemoveRows({}, removeIndex, removeIndex);
124 beginRemoveRows({}, removeIndex, removeIndex);
123 impl->m_Variables.erase(it);
125 impl->m_Variables.erase(it);
124 endRemoveRows();
126 endRemoveRows();
125 }
127 }
126 else {
128 else {
127 qCritical(LOG_VariableModel())
129 qCritical(LOG_VariableModel())
128 << tr("Can't delete variable %1 from the model: the variable is not in the model")
130 << tr("Can't delete variable %1 from the model: the variable is not in the model")
129 .arg(variable->name());
131 .arg(variable->name());
130 }
132 }
131
133
132 // Removes variable from progress map
134 // Removes variable from progress map
133 impl->m_VariableToProgress.erase(variable);
135 impl->m_VariableToProgress.erase(variable);
134 }
136 }
135
137
136
138
137 std::shared_ptr<Variable> VariableModel::variable(int index) const
139 std::shared_ptr<Variable> VariableModel::variable(int index) const
138 {
140 {
139 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
141 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
140 }
142 }
141
143
142 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
144 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
143 {
145 {
144 return impl->m_Variables;
146 return impl->m_Variables;
145 }
147 }
146
148
147 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
149 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
148 {
150 {
149 if (progress > 0.0) {
151 if (progress > 0.0) {
150 impl->m_VariableToProgress[variable] = progress;
152 impl->m_VariableToProgress[variable] = progress;
151 }
153 }
152 else {
154 else {
153 impl->m_VariableToProgress.erase(variable);
155 impl->m_VariableToProgress.erase(variable);
154 }
156 }
155 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
157 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
156
158
157 emit dataChanged(modelIndex, modelIndex);
159 emit dataChanged(modelIndex, modelIndex);
158 }
160 }
159
161
160 int VariableModel::columnCount(const QModelIndex &parent) const
162 int VariableModel::columnCount(const QModelIndex &parent) const
161 {
163 {
162 Q_UNUSED(parent);
164 Q_UNUSED(parent);
163
165
164 return NB_COLUMNS;
166 return NB_COLUMNS;
165 }
167 }
166
168
167 int VariableModel::rowCount(const QModelIndex &parent) const
169 int VariableModel::rowCount(const QModelIndex &parent) const
168 {
170 {
169 Q_UNUSED(parent);
171 Q_UNUSED(parent);
170
172
171 return impl->m_Variables.size();
173 return impl->m_Variables.size();
172 }
174 }
173
175
174 QVariant VariableModel::data(const QModelIndex &index, int role) const
176 QVariant VariableModel::data(const QModelIndex &index, int role) const
175 {
177 {
176 if (!index.isValid()) {
178 if (!index.isValid()) {
177 return QVariant{};
179 return QVariant{};
178 }
180 }
179
181
180 if (index.row() < 0 || index.row() >= rowCount()) {
182 if (index.row() < 0 || index.row() >= rowCount()) {
181 return QVariant{};
183 return QVariant{};
182 }
184 }
183
185
184 if (role == Qt::DisplayRole) {
186 if (role == Qt::DisplayRole) {
185 if (auto variable = impl->m_Variables.at(index.row()).get()) {
187 if (auto variable = impl->m_Variables.at(index.row()).get()) {
186 switch (index.column()) {
188 switch (index.column()) {
187 case NAME_COLUMN:
189 case NAME_COLUMN:
188 return variable->name();
190 return variable->name();
189 case TSTART_COLUMN: {
191 case TSTART_COLUMN: {
190 auto range = variable->realRange();
192 auto range = variable->realRange();
191 return range != INVALID_RANGE
193 return range != INVALID_RANGE
192 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
194 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
193 : QVariant{};
195 : QVariant{};
194 }
196 }
195 case TEND_COLUMN: {
197 case TEND_COLUMN: {
196 auto range = variable->realRange();
198 auto range = variable->realRange();
197 return range != INVALID_RANGE
199 return range != INVALID_RANGE
198 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
200 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
199 : QVariant{};
201 : QVariant{};
200 }
202 }
203 case NBPOINTS_COLUMN:
204 return variable->nbPoints();
201 case UNIT_COLUMN:
205 case UNIT_COLUMN:
202 return variable->metadata().value(QStringLiteral("units"));
206 return variable->metadata().value(QStringLiteral("units"));
203 case MISSION_COLUMN:
207 case MISSION_COLUMN:
204 return variable->metadata().value(QStringLiteral("mission"));
208 return variable->metadata().value(QStringLiteral("mission"));
205 case PLUGIN_COLUMN:
209 case PLUGIN_COLUMN:
206 return variable->metadata().value(QStringLiteral("plugin"));
210 return variable->metadata().value(QStringLiteral("plugin"));
207 default:
211 default:
208 // No action
212 // No action
209 break;
213 break;
210 }
214 }
211
215
212 qWarning(LOG_VariableModel())
216 qWarning(LOG_VariableModel())
213 << tr("Can't get data (unknown column %1)").arg(index.column());
217 << tr("Can't get data (unknown column %1)").arg(index.column());
214 }
218 }
215 else {
219 else {
216 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
220 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
217 }
221 }
218 }
222 }
219 else if (role == VariableRoles::ProgressRole) {
223 else if (role == VariableRoles::ProgressRole) {
220 if (auto variable = impl->m_Variables.at(index.row())) {
224 if (auto variable = impl->m_Variables.at(index.row())) {
221
225
222 auto it = impl->m_VariableToProgress.find(variable);
226 auto it = impl->m_VariableToProgress.find(variable);
223 if (it != impl->m_VariableToProgress.cend()) {
227 if (it != impl->m_VariableToProgress.cend()) {
224 return it->second;
228 return it->second;
225 }
229 }
226 }
230 }
227 }
231 }
228
232
229 return QVariant{};
233 return QVariant{};
230 }
234 }
231
235
232 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
236 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
233 {
237 {
234 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
238 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
235 return QVariant{};
239 return QVariant{};
236 }
240 }
237
241
238 if (orientation == Qt::Horizontal) {
242 if (orientation == Qt::Horizontal) {
239 auto propertiesIt = COLUMN_PROPERTIES.find(section);
243 auto propertiesIt = COLUMN_PROPERTIES.find(section);
240 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
244 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
241 // Role is either DisplayRole or SizeHintRole
245 // Role is either DisplayRole or SizeHintRole
242 return (role == Qt::DisplayRole)
246 return (role == Qt::DisplayRole)
243 ? QVariant{propertiesIt->m_Name}
247 ? QVariant{propertiesIt->m_Name}
244 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
248 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
245 }
249 }
246 else {
250 else {
247 qWarning(LOG_VariableModel())
251 qWarning(LOG_VariableModel())
248 << tr("Can't get header data (unknown column %1)").arg(section);
252 << tr("Can't get header data (unknown column %1)").arg(section);
249 }
253 }
250 }
254 }
251
255
252 return QVariant{};
256 return QVariant{};
253 }
257 }
254
258
255 void VariableModel::abortProgress(const QModelIndex &index)
259 void VariableModel::abortProgress(const QModelIndex &index)
256 {
260 {
257 if (auto variable = impl->m_Variables.at(index.row())) {
261 if (auto variable = impl->m_Variables.at(index.row())) {
258 emit abortProgessRequested(variable);
262 emit abortProgessRequested(variable);
259 }
263 }
260 }
264 }
261
265
262 void VariableModel::onVariableUpdated() noexcept
266 void VariableModel::onVariableUpdated() noexcept
263 {
267 {
264 // Finds variable that has been updated in the model
268 // Finds variable that has been updated in the model
265 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
269 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
266 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
270 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
267
271
268 if (updatedVariableIndex > -1) {
272 if (updatedVariableIndex > -1) {
269 emit dataChanged(createIndex(updatedVariableIndex, 0),
273 emit dataChanged(createIndex(updatedVariableIndex, 0),
270 createIndex(updatedVariableIndex, columnCount() - 1));
274 createIndex(updatedVariableIndex, columnCount() - 1));
271 }
275 }
272 }
276 }
273 }
277 }
274
278
275 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
279 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
276 {
280 {
277 auto begin = std::cbegin(m_Variables);
281 auto begin = std::cbegin(m_Variables);
278 auto end = std::cend(m_Variables);
282 auto end = std::cend(m_Variables);
279 auto it
283 auto it
280 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
284 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
281
285
282 if (it != end) {
286 if (it != end) {
283 // Gets the index of the variable in the model: we assume here that views have the same
287 // Gets the index of the variable in the model: we assume here that views have the same
284 // order as the model
288 // order as the model
285 return std::distance(begin, it);
289 return std::distance(begin, it);
286 }
290 }
287 else {
291 else {
288 return -1;
292 return -1;
289 }
293 }
290 }
294 }
General Comments 0
You need to be logged in to leave comments. Login now