##// END OF EJS Templates
Corrects regression on variable destruction
Alexandre Leroux -
r421:a9d7c7f52b62
parent child
Show More
@@ -1,233 +1,236
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableModel.h>
2 #include <Variable/VariableModel.h>
3
3
4 #include <Data/IDataSeries.h>
4 #include <Data/IDataSeries.h>
5
5
6 #include <QDateTime>
6 #include <QDateTime>
7 #include <QSize>
7 #include <QSize>
8 #include <unordered_map>
8 #include <unordered_map>
9
9
10 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
10 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
11
11
12 namespace {
12 namespace {
13
13
14 // Column indexes
14 // Column indexes
15 const auto NAME_COLUMN = 0;
15 const auto NAME_COLUMN = 0;
16 const auto TSTART_COLUMN = 1;
16 const auto TSTART_COLUMN = 1;
17 const auto TEND_COLUMN = 2;
17 const auto TEND_COLUMN = 2;
18 const auto NB_COLUMNS = 3;
18 const auto NB_COLUMNS = 3;
19
19
20 // Column properties
20 // Column properties
21 const auto DEFAULT_HEIGHT = 25;
21 const auto DEFAULT_HEIGHT = 25;
22 const auto DEFAULT_WIDTH = 100;
22 const auto DEFAULT_WIDTH = 100;
23
23
24 struct ColumnProperties {
24 struct ColumnProperties {
25 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
25 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
26 int height = DEFAULT_HEIGHT)
26 int height = DEFAULT_HEIGHT)
27 : m_Name{name}, m_Width{width}, m_Height{height}
27 : m_Name{name}, m_Width{width}, m_Height{height}
28 {
28 {
29 }
29 }
30
30
31 QString m_Name;
31 QString m_Name;
32 int m_Width;
32 int m_Width;
33 int m_Height;
33 int m_Height;
34 };
34 };
35
35
36 const auto COLUMN_PROPERTIES
36 const auto COLUMN_PROPERTIES
37 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
37 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
38 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
38 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
39 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
39 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
40
40
41 /// Format for datetimes
41 /// Format for datetimes
42 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
42 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
43
43
44
44
45 } // namespace
45 } // namespace
46
46
47 struct VariableModel::VariableModelPrivate {
47 struct VariableModel::VariableModelPrivate {
48 /// Variables created in SciQlop
48 /// Variables created in SciQlop
49 std::vector<std::shared_ptr<Variable> > m_Variables;
49 std::vector<std::shared_ptr<Variable> > m_Variables;
50 std::unordered_map<Variable *, double> m_VariableToProgress;
50 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
51
51
52 /// Return the row index of the variable. -1 if it's not found
52 /// Return the row index of the variable. -1 if it's not found
53 int indexOfVariable(Variable *variable) const noexcept;
53 int indexOfVariable(Variable *variable) const noexcept;
54 };
54 };
55
55
56 VariableModel::VariableModel(QObject *parent)
56 VariableModel::VariableModel(QObject *parent)
57 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
57 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
58 {
58 {
59 }
59 }
60
60
61 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
61 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
62 const SqpDateTime &dateTime,
62 const SqpDateTime &dateTime,
63 const QVariantHash &metadata) noexcept
63 const QVariantHash &metadata) noexcept
64 {
64 {
65 auto insertIndex = rowCount();
65 auto insertIndex = rowCount();
66 beginInsertRows({}, insertIndex, insertIndex);
66 beginInsertRows({}, insertIndex, insertIndex);
67
67
68 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
68 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
69
69
70 impl->m_Variables.push_back(variable);
70 impl->m_Variables.push_back(variable);
71 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
71 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
72
72
73 endInsertRows();
73 endInsertRows();
74
74
75 return variable;
75 return variable;
76 }
76 }
77
77
78 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
78 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
79 {
79 {
80 if (!variable) {
80 if (!variable) {
81 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
81 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
82 return;
82 return;
83 }
83 }
84
84
85 // Finds variable in the model
85 // Finds variable in the model
86 auto begin = impl->m_Variables.cbegin();
86 auto begin = impl->m_Variables.cbegin();
87 auto end = impl->m_Variables.cend();
87 auto end = impl->m_Variables.cend();
88 auto it = std::find(begin, end, variable);
88 auto it = std::find(begin, end, variable);
89 if (it != end) {
89 if (it != end) {
90 auto removeIndex = std::distance(begin, it);
90 auto removeIndex = std::distance(begin, it);
91
91
92 // Deletes variable
92 // Deletes variable
93 beginRemoveRows({}, removeIndex, removeIndex);
93 beginRemoveRows({}, removeIndex, removeIndex);
94 impl->m_Variables.erase(it);
94 impl->m_Variables.erase(it);
95 endRemoveRows();
95 endRemoveRows();
96 }
96 }
97 else {
97 else {
98 qCritical(LOG_VariableModel())
98 qCritical(LOG_VariableModel())
99 << tr("Can't delete variable %1 from the model: the variable is not in the model")
99 << tr("Can't delete variable %1 from the model: the variable is not in the model")
100 .arg(variable->name());
100 .arg(variable->name());
101 }
101 }
102
103 // Removes variable from progress map
104 impl->m_VariableToProgress.erase(variable);
102 }
105 }
103
106
104
107
105 std::shared_ptr<Variable> VariableModel::variable(int index) const
108 std::shared_ptr<Variable> VariableModel::variable(int index) const
106 {
109 {
107 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
110 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
108 }
111 }
109
112
110 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
113 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
111 {
114 {
112 impl->m_VariableToProgress[variable.get()] = progress;
115 impl->m_VariableToProgress[variable] = progress;
113 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
116 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
114
117
115 emit dataChanged(modelIndex, modelIndex);
118 emit dataChanged(modelIndex, modelIndex);
116 }
119 }
117
120
118 int VariableModel::columnCount(const QModelIndex &parent) const
121 int VariableModel::columnCount(const QModelIndex &parent) const
119 {
122 {
120 Q_UNUSED(parent);
123 Q_UNUSED(parent);
121
124
122 return NB_COLUMNS;
125 return NB_COLUMNS;
123 }
126 }
124
127
125 int VariableModel::rowCount(const QModelIndex &parent) const
128 int VariableModel::rowCount(const QModelIndex &parent) const
126 {
129 {
127 Q_UNUSED(parent);
130 Q_UNUSED(parent);
128
131
129 return impl->m_Variables.size();
132 return impl->m_Variables.size();
130 }
133 }
131
134
132 QVariant VariableModel::data(const QModelIndex &index, int role) const
135 QVariant VariableModel::data(const QModelIndex &index, int role) const
133 {
136 {
134 if (!index.isValid()) {
137 if (!index.isValid()) {
135 return QVariant{};
138 return QVariant{};
136 }
139 }
137
140
138 if (index.row() < 0 || index.row() >= rowCount()) {
141 if (index.row() < 0 || index.row() >= rowCount()) {
139 return QVariant{};
142 return QVariant{};
140 }
143 }
141
144
142 if (role == Qt::DisplayRole) {
145 if (role == Qt::DisplayRole) {
143 if (auto variable = impl->m_Variables.at(index.row()).get()) {
146 if (auto variable = impl->m_Variables.at(index.row()).get()) {
144 /// Lambda function that builds the variant to return for a time value
147 /// Lambda function that builds the variant to return for a time value
145 auto dateTimeVariant = [](double time) {
148 auto dateTimeVariant = [](double time) {
146 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
149 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
147 return dateTime.toString(DATETIME_FORMAT);
150 return dateTime.toString(DATETIME_FORMAT);
148 };
151 };
149
152
150 switch (index.column()) {
153 switch (index.column()) {
151 case NAME_COLUMN:
154 case NAME_COLUMN:
152 return variable->name();
155 return variable->name();
153 case TSTART_COLUMN:
156 case TSTART_COLUMN:
154 return dateTimeVariant(variable->dateTime().m_TStart);
157 return dateTimeVariant(variable->dateTime().m_TStart);
155 case TEND_COLUMN:
158 case TEND_COLUMN:
156 return dateTimeVariant(variable->dateTime().m_TEnd);
159 return dateTimeVariant(variable->dateTime().m_TEnd);
157 default:
160 default:
158 // No action
161 // No action
159 break;
162 break;
160 }
163 }
161
164
162 qWarning(LOG_VariableModel())
165 qWarning(LOG_VariableModel())
163 << tr("Can't get data (unknown column %1)").arg(index.column());
166 << tr("Can't get data (unknown column %1)").arg(index.column());
164 }
167 }
165 else {
168 else {
166 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
169 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
167 }
170 }
168 }
171 }
169 else if (role == VariableRoles::ProgressRole) {
172 else if (role == VariableRoles::ProgressRole) {
170 if (auto variable = impl->m_Variables.at(index.row())) {
173 if (auto variable = impl->m_Variables.at(index.row())) {
171
174
172 auto it = impl->m_VariableToProgress.find(variable.get());
175 auto it = impl->m_VariableToProgress.find(variable);
173 if (it != impl->m_VariableToProgress.cend()) {
176 if (it != impl->m_VariableToProgress.cend()) {
174 return it->second;
177 return it->second;
175 }
178 }
176 }
179 }
177 }
180 }
178
181
179 return QVariant{};
182 return QVariant{};
180 }
183 }
181
184
182 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
185 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
183 {
186 {
184 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
187 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
185 return QVariant{};
188 return QVariant{};
186 }
189 }
187
190
188 if (orientation == Qt::Horizontal) {
191 if (orientation == Qt::Horizontal) {
189 auto propertiesIt = COLUMN_PROPERTIES.find(section);
192 auto propertiesIt = COLUMN_PROPERTIES.find(section);
190 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
193 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
191 // Role is either DisplayRole or SizeHintRole
194 // Role is either DisplayRole or SizeHintRole
192 return (role == Qt::DisplayRole)
195 return (role == Qt::DisplayRole)
193 ? QVariant{propertiesIt->m_Name}
196 ? QVariant{propertiesIt->m_Name}
194 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
197 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
195 }
198 }
196 else {
199 else {
197 qWarning(LOG_VariableModel())
200 qWarning(LOG_VariableModel())
198 << tr("Can't get header data (unknown column %1)").arg(section);
201 << tr("Can't get header data (unknown column %1)").arg(section);
199 }
202 }
200 }
203 }
201
204
202 return QVariant{};
205 return QVariant{};
203 }
206 }
204
207
205 void VariableModel::onVariableUpdated() noexcept
208 void VariableModel::onVariableUpdated() noexcept
206 {
209 {
207 // Finds variable that has been updated in the model
210 // Finds variable that has been updated in the model
208 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
211 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
209 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
212 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
210
213
211 if (updatedVariableIndex > -1) {
214 if (updatedVariableIndex > -1) {
212 emit dataChanged(createIndex(updatedVariableIndex, 0),
215 emit dataChanged(createIndex(updatedVariableIndex, 0),
213 createIndex(updatedVariableIndex, columnCount() - 1));
216 createIndex(updatedVariableIndex, columnCount() - 1));
214 }
217 }
215 }
218 }
216 }
219 }
217
220
218 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
221 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
219 {
222 {
220 auto begin = std::cbegin(m_Variables);
223 auto begin = std::cbegin(m_Variables);
221 auto end = std::cend(m_Variables);
224 auto end = std::cend(m_Variables);
222 auto it
225 auto it
223 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
226 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
224
227
225 if (it != end) {
228 if (it != end) {
226 // Gets the index of the variable in the model: we assume here that views have the same
229 // Gets the index of the variable in the model: we assume here that views have the same
227 // order as the model
230 // order as the model
228 return std::distance(begin, it);
231 return std::distance(begin, it);
229 }
232 }
230 else {
233 else {
231 return -1;
234 return -1;
232 }
235 }
233 }
236 }
General Comments 0
You need to be logged in to leave comments. Login now