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