Mercurial > hg > svcore
comparison data/model/ModelDataTableModel.cpp @ 416:a00902d5f0ab
* basics of data editing in data table view
author | Chris Cannam |
---|---|
date | Mon, 09 Jun 2008 16:01:50 +0000 |
parents | 0b274e1aaf10 |
children | 12b7bf0c3915 |
comparison
equal
deleted
inserted
replaced
415:e37e44681720 | 416:a00902d5f0ab |
---|---|
33 } | 33 } |
34 | 34 |
35 QVariant | 35 QVariant |
36 ModelDataTableModel::data(const QModelIndex &index, int role) const | 36 ModelDataTableModel::data(const QModelIndex &index, int role) const |
37 { | 37 { |
38 if (role != Qt::DisplayRole) { | 38 if (role != Qt::DisplayRole && role != Qt::EditRole) { |
39 return QVariant(); | 39 return QVariant(); |
40 } | 40 } |
41 | 41 |
42 bool withUnit = (role == Qt::DisplayRole); | |
43 | |
42 if (!index.isValid()) return QVariant(); | 44 if (!index.isValid()) return QVariant(); |
43 | 45 |
44 int row = index.row(), col = index.column(); | 46 int row = index.row(), col = index.column(); |
45 | 47 |
46 if (row < 0 || row >= m_rows.size()) return QVariant(); | 48 if (row < 0 || row >= m_rows.size()) return QVariant(); |
47 | 49 |
48 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { | 50 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { |
49 return dataSparse<SparseOneDimensionalModel::Point>(row, col); | 51 return dataSparse<SparseOneDimensionalModel::Point>(row, col, withUnit); |
50 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { | 52 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { |
51 return dataSparse<SparseTimeValueModel::Point>(row, col); | 53 return dataSparse<SparseTimeValueModel::Point>(row, col, withUnit); |
52 } | 54 } |
53 | 55 |
54 return QVariant(); | 56 return QVariant(); |
55 } | 57 } |
56 | 58 |
57 template <typename PointType> | 59 template <typename PointType> |
58 QVariant | 60 QVariant |
59 ModelDataTableModel::dataSparse(int row, int col) const | 61 ModelDataTableModel::dataSparse(int row, int col, bool withUnit) const |
60 { | 62 { |
61 size_t frame = m_rows[row]; | 63 size_t frame = m_rows[row]; |
62 | 64 |
63 // This is just garbage. This would be a reasonable enough way to | 65 // This is just garbage. This would be a reasonable enough way to |
64 // handle this in a dynamically typed language but it's hopeless | 66 // handle this in a dynamically typed language but it's hopeless |
87 if (indexAtFrame > 0) { --indexAtFrame; continue; } | 89 if (indexAtFrame > 0) { --indexAtFrame; continue; } |
88 | 90 |
89 switch (col) { | 91 switch (col) { |
90 | 92 |
91 case 0: | 93 case 0: |
94 { | |
95 RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate()); | |
96 std::cerr << "Returning time " << rt << std::endl; | |
97 return QVariant(rt.toText().c_str()); | |
98 } | |
99 | |
100 case 1: | |
92 std::cerr << "Returning frame " << frame << std::endl; | 101 std::cerr << "Returning frame " << frame << std::endl; |
93 return QVariant(frame); //!!! RealTime | 102 return QVariant(frame); //!!! RealTime |
94 | 103 |
95 case 1: | 104 case 2: |
96 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { | 105 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { |
97 const SparseOneDimensionalModel::Point *cp = | 106 const SparseOneDimensionalModel::Point *cp = |
98 reinterpret_cast<const SparseOneDimensionalModel::Point *>(point); | 107 reinterpret_cast<const SparseOneDimensionalModel::Point *>(point); |
99 std::cerr << "Returning label \"" << cp->label.toStdString() << "\"" << std::endl; | 108 std::cerr << "Returning label \"" << cp->label.toStdString() << "\"" << std::endl; |
100 return QVariant(cp->label); | 109 return QVariant(cp->label); |
101 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { | 110 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { |
102 const SparseTimeValueModel::Point *cp = | 111 const SparseTimeValueModel::Point *cp = |
103 reinterpret_cast<const SparseTimeValueModel::Point *>(point); | 112 reinterpret_cast<const SparseTimeValueModel::Point *>(point); |
104 std::cerr << "Returning value " << cp->value << std::endl; | 113 std::cerr << "Returning value " << cp->value << std::endl; |
105 return cp->value; | 114 if (withUnit) { |
115 return QVariant(QString("%1 %2").arg(cp->value) | |
116 .arg(dynamic_cast<const SparseTimeValueModel *>(m_model)->getScaleUnits())); | |
117 } else { | |
118 return cp->value; | |
119 } | |
106 } else return QVariant(); | 120 } else return QVariant(); |
107 | 121 |
108 case 2: | 122 case 3: |
109 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { | 123 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { |
110 return QVariant(); | 124 return QVariant(); |
111 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { | 125 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { |
112 return reinterpret_cast<const SparseTimeValueModel::Point *>(point)->label; | 126 return reinterpret_cast<const SparseTimeValueModel::Point *>(point)->label; |
113 } else return QVariant(); | 127 } else return QVariant(); |
118 } | 132 } |
119 | 133 |
120 bool | 134 bool |
121 ModelDataTableModel::setData(const QModelIndex &index, const QVariant &value, int role) | 135 ModelDataTableModel::setData(const QModelIndex &index, const QVariant &value, int role) |
122 { | 136 { |
137 if (role != Qt::EditRole) { | |
138 std::cerr << "setData: ignoring role " << role << std::endl; | |
139 return false; | |
140 } | |
141 | |
142 //!!! see comment about disgustuality of this whole process, in | |
143 //dataSparse above | |
144 | |
145 if (!index.isValid()) return false; | |
146 | |
147 int row = index.row(), col = index.column(); | |
148 | |
149 if (row < 0 || row >= m_rows.size()) return false; | |
150 | |
151 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { | |
152 return setDataSparse<SparseOneDimensionalModel::Point>(row, col, value); | |
153 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { | |
154 return setDataSparse<SparseTimeValueModel::Point>(row, col, value); | |
155 } | |
156 | |
157 return false; | |
158 } | |
159 | |
160 template <typename PointType> | |
161 bool | |
162 ModelDataTableModel::setDataSparse(int row, int col, QVariant value) | |
163 { | |
164 size_t frame = m_rows[row]; | |
165 | |
166 typedef SparseModel<PointType> ModelType; | |
167 typedef std::multiset<PointType, typename PointType::OrderComparator> | |
168 PointListType; | |
169 typedef typename ModelType::EditCommand EditCommandType; | |
170 | |
171 ModelType *sm = dynamic_cast<const ModelType *>(m_model); | |
172 const PointListType &points = sm->getPoints(frame); | |
173 | |
174 // it is possible to have more than one point at the same frame | |
175 | |
176 int indexAtFrame = 0; | |
177 int ri = row; | |
178 while (ri > 0 && m_rows[ri-1] == m_rows[row]) { --ri; ++indexAtFrame; } | |
179 | |
180 for (typename PointListType::const_iterator i = points.begin(); | |
181 i != points.end(); ++i) { | |
182 | |
183 const PointType *point = &(*i); | |
184 if (point->frame < frame) continue; | |
185 if (point->frame > frame) return false; | |
186 if (indexAtFrame > 0) { --indexAtFrame; continue; } | |
187 | |
188 switch (col) { | |
189 | |
190 case 0: | |
191 { | |
192 /* | |
193 RealTime rt = RealTime::frame2RealTime(frame, m_model->getSampleRate()); | |
194 std::cerr << "Returning time " << rt << std::endl; | |
195 return QVariant(rt.toText().c_str()); | |
196 */ | |
197 } | |
198 | |
199 case 1: | |
200 { | |
201 EditCommandType *command = | |
202 new EditCommandType(sm, tr("Edit point time")); | |
203 PointType newPoint(*point); | |
204 newPoint.frame = value.toInt(); //!!! check validity | |
205 command->deletePoint(*point); | |
206 command->addPoint(newPoint); | |
207 command = command->finish(); | |
208 if (command) emit executeCommand(command); | |
209 return true; | |
210 } | |
211 // std::cerr << "Returning frame " << frame << std::endl; | |
212 // return QVariant(frame); //!!! RealTime | |
213 | |
214 case 2: | |
215 break; | |
216 | |
217 case 3: | |
218 break; | |
219 } | |
220 } | |
221 | |
123 return false; | 222 return false; |
124 } | 223 } |
125 | 224 |
126 Qt::ItemFlags | 225 Qt::ItemFlags |
127 ModelDataTableModel::flags(const QModelIndex &index) const | 226 ModelDataTableModel::flags(const QModelIndex &index) const |
128 { | 227 { |
129 return Qt::ItemFlags(); | 228 Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable | |
229 Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsSelectable; | |
230 return flags; | |
130 } | 231 } |
131 | 232 |
132 QVariant | 233 QVariant |
133 ModelDataTableModel::headerData(int section, Qt::Orientation orientation, int role) const | 234 ModelDataTableModel::headerData(int section, Qt::Orientation orientation, int role) const |
134 { | 235 { |
135 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { | 236 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { |
136 if (section == 0) return QVariant(tr("Frame")); | 237 if (section == 0) return QVariant(tr("Time")); |
137 else if (section == 1) { | 238 if (section == 1) return QVariant(tr("Frame")); |
239 else if (section == 2) { | |
138 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { | 240 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { |
139 return QVariant(tr("Label")); | 241 return QVariant(tr("Label")); |
140 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { | 242 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { |
141 return QVariant(tr("Value")); | 243 return QVariant(tr("Value")); |
142 } | 244 } |
143 } else if (section == 2) { | 245 } else if (section == 3) { |
144 if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { | 246 if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { |
145 return QVariant(tr("Label")); | 247 return QVariant(tr("Label")); |
146 } | 248 } |
147 } | 249 } |
148 } | 250 } |
173 { | 275 { |
174 if (parent.isValid()) return 0; | 276 if (parent.isValid()) return 0; |
175 if (!canHandleModelType(m_model)) return 0; | 277 if (!canHandleModelType(m_model)) return 0; |
176 | 278 |
177 if (dynamic_cast<SparseOneDimensionalModel *>(m_model)) { | 279 if (dynamic_cast<SparseOneDimensionalModel *>(m_model)) { |
178 return 2; | 280 return 3; |
179 } else if (dynamic_cast<SparseTimeValueModel *>(m_model)) { | 281 } else if (dynamic_cast<SparseTimeValueModel *>(m_model)) { |
180 return 3; | 282 return 4; |
181 } | 283 } |
182 | 284 |
183 return 1; | 285 return 2; |
286 } | |
287 | |
288 QModelIndex | |
289 ModelDataTableModel::getModelIndexForFrame(size_t frame) const | |
290 { | |
291 std::vector<size_t>::const_iterator i = | |
292 std::lower_bound(m_rows.begin(), m_rows.end(), frame); | |
293 size_t dist = std::distance(m_rows.begin(), i); | |
294 return createIndex(dist, 0, 0); | |
184 } | 295 } |
185 | 296 |
186 void | 297 void |
187 ModelDataTableModel::modelChanged() | 298 ModelDataTableModel::modelChanged() |
188 { | 299 { |
189 rebuildRowVector(); | 300 rebuildRowVector(); |
190 emit layoutChanged(); | 301 emit layoutChanged(); |
191 } | 302 } |
192 | 303 |
193 void | 304 void |
194 ModelDataTableModel::modelChanged(size_t, size_t) | 305 ModelDataTableModel::modelChanged(size_t f0, size_t f1) |
195 {} | 306 { |
307 std::cerr << "ModelDataTableModel::modelChanged(" << f0 << "," << f1 << ")" << std::endl; | |
308 //!!! highly inefficient | |
309 rebuildRowVector(); | |
310 emit layoutChanged(); | |
311 } | |
196 | 312 |
197 void | 313 void |
198 ModelDataTableModel::rebuildRowVector() | 314 ModelDataTableModel::rebuildRowVector() |
199 { | 315 { |
200 if (!canHandleModelType(m_model)) return; | 316 if (!canHandleModelType(m_model)) return; |