Mercurial > hg > svcore
comparison data/model/ModelDataTableModel.cpp @ 413:0b274e1aaf10
* Start adding a spreadsheet-style editor window for model data
author | Chris Cannam |
---|---|
date | Fri, 06 Jun 2008 15:26:27 +0000 |
parents | |
children | a00902d5f0ab |
comparison
equal
deleted
inserted
replaced
412:5e4238d08caa | 413:0b274e1aaf10 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2008 QMUL. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #include "ModelDataTableModel.h" | |
17 | |
18 #include "SparseTimeValueModel.h" | |
19 #include "SparseOneDimensionalModel.h" | |
20 #include "SparseModel.h" | |
21 | |
22 ModelDataTableModel::ModelDataTableModel(Model *m) : | |
23 m_model(m) | |
24 { | |
25 connect(m, SIGNAL(modelChanged()), this, SLOT(modelChanged())); | |
26 connect(m, SIGNAL(modelChanged(size_t, size_t)), | |
27 this, SLOT(modelChanged(size_t, size_t))); | |
28 rebuildRowVector(); | |
29 } | |
30 | |
31 ModelDataTableModel::~ModelDataTableModel() | |
32 { | |
33 } | |
34 | |
35 QVariant | |
36 ModelDataTableModel::data(const QModelIndex &index, int role) const | |
37 { | |
38 if (role != Qt::DisplayRole) { | |
39 return QVariant(); | |
40 } | |
41 | |
42 if (!index.isValid()) return QVariant(); | |
43 | |
44 int row = index.row(), col = index.column(); | |
45 | |
46 if (row < 0 || row >= m_rows.size()) return QVariant(); | |
47 | |
48 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { | |
49 return dataSparse<SparseOneDimensionalModel::Point>(row, col); | |
50 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { | |
51 return dataSparse<SparseTimeValueModel::Point>(row, col); | |
52 } | |
53 | |
54 return QVariant(); | |
55 } | |
56 | |
57 template <typename PointType> | |
58 QVariant | |
59 ModelDataTableModel::dataSparse(int row, int col) const | |
60 { | |
61 size_t frame = m_rows[row]; | |
62 | |
63 // This is just garbage. This would be a reasonable enough way to | |
64 // handle this in a dynamically typed language but it's hopeless | |
65 // in C++. The design is simply wrong. We need virtual helper | |
66 // methods in the model itself. | |
67 | |
68 typedef SparseModel<PointType> ModelType; | |
69 typedef std::multiset<PointType, typename PointType::OrderComparator> | |
70 PointListType; | |
71 | |
72 const ModelType *sm = dynamic_cast<const ModelType *>(m_model); | |
73 const PointListType &points = sm->getPoints(frame); | |
74 | |
75 // it is possible to have more than one point at the same frame | |
76 | |
77 int indexAtFrame = 0; | |
78 int ri = row; | |
79 while (ri > 0 && m_rows[ri-1] == m_rows[row]) { --ri; ++indexAtFrame; } | |
80 | |
81 for (typename PointListType::const_iterator i = points.begin(); | |
82 i != points.end(); ++i) { | |
83 | |
84 const PointType *point = &(*i); | |
85 if (point->frame < frame) continue; | |
86 if (point->frame > frame) return QVariant(); | |
87 if (indexAtFrame > 0) { --indexAtFrame; continue; } | |
88 | |
89 switch (col) { | |
90 | |
91 case 0: | |
92 std::cerr << "Returning frame " << frame << std::endl; | |
93 return QVariant(frame); //!!! RealTime | |
94 | |
95 case 1: | |
96 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { | |
97 const SparseOneDimensionalModel::Point *cp = | |
98 reinterpret_cast<const SparseOneDimensionalModel::Point *>(point); | |
99 std::cerr << "Returning label \"" << cp->label.toStdString() << "\"" << std::endl; | |
100 return QVariant(cp->label); | |
101 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { | |
102 const SparseTimeValueModel::Point *cp = | |
103 reinterpret_cast<const SparseTimeValueModel::Point *>(point); | |
104 std::cerr << "Returning value " << cp->value << std::endl; | |
105 return cp->value; | |
106 } else return QVariant(); | |
107 | |
108 case 2: | |
109 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { | |
110 return QVariant(); | |
111 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { | |
112 return reinterpret_cast<const SparseTimeValueModel::Point *>(point)->label; | |
113 } else return QVariant(); | |
114 } | |
115 } | |
116 | |
117 return QVariant(); | |
118 } | |
119 | |
120 bool | |
121 ModelDataTableModel::setData(const QModelIndex &index, const QVariant &value, int role) | |
122 { | |
123 return false; | |
124 } | |
125 | |
126 Qt::ItemFlags | |
127 ModelDataTableModel::flags(const QModelIndex &index) const | |
128 { | |
129 return Qt::ItemFlags(); | |
130 } | |
131 | |
132 QVariant | |
133 ModelDataTableModel::headerData(int section, Qt::Orientation orientation, int role) const | |
134 { | |
135 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { | |
136 if (section == 0) return QVariant(tr("Frame")); | |
137 else if (section == 1) { | |
138 if (dynamic_cast<const SparseOneDimensionalModel *>(m_model)) { | |
139 return QVariant(tr("Label")); | |
140 } else if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { | |
141 return QVariant(tr("Value")); | |
142 } | |
143 } else if (section == 2) { | |
144 if (dynamic_cast<const SparseTimeValueModel *>(m_model)) { | |
145 return QVariant(tr("Label")); | |
146 } | |
147 } | |
148 } | |
149 return QVariant(); | |
150 } | |
151 | |
152 QModelIndex | |
153 ModelDataTableModel::index(int row, int column, const QModelIndex &parent) const | |
154 { | |
155 return createIndex(row, column, 0); | |
156 } | |
157 | |
158 QModelIndex | |
159 ModelDataTableModel::parent(const QModelIndex &index) const | |
160 { | |
161 return QModelIndex(); | |
162 } | |
163 | |
164 int | |
165 ModelDataTableModel::rowCount(const QModelIndex &parent) const | |
166 { | |
167 if (parent.isValid()) return 0; | |
168 return m_rows.size(); | |
169 } | |
170 | |
171 int | |
172 ModelDataTableModel::columnCount(const QModelIndex &parent) const | |
173 { | |
174 if (parent.isValid()) return 0; | |
175 if (!canHandleModelType(m_model)) return 0; | |
176 | |
177 if (dynamic_cast<SparseOneDimensionalModel *>(m_model)) { | |
178 return 2; | |
179 } else if (dynamic_cast<SparseTimeValueModel *>(m_model)) { | |
180 return 3; | |
181 } | |
182 | |
183 return 1; | |
184 } | |
185 | |
186 void | |
187 ModelDataTableModel::modelChanged() | |
188 { | |
189 rebuildRowVector(); | |
190 emit layoutChanged(); | |
191 } | |
192 | |
193 void | |
194 ModelDataTableModel::modelChanged(size_t, size_t) | |
195 {} | |
196 | |
197 void | |
198 ModelDataTableModel::rebuildRowVector() | |
199 { | |
200 if (!canHandleModelType(m_model)) return; | |
201 | |
202 m_rows.clear(); | |
203 | |
204 if (dynamic_cast<SparseOneDimensionalModel *>(m_model)) { | |
205 rebuildRowVectorSparse<SparseOneDimensionalModel::Point>(); | |
206 } else if (dynamic_cast<SparseTimeValueModel *>(m_model)) { | |
207 rebuildRowVectorSparse<SparseTimeValueModel::Point>(); | |
208 } | |
209 } | |
210 | |
211 template <typename PointType> | |
212 void | |
213 ModelDataTableModel::rebuildRowVectorSparse() | |
214 { | |
215 // gah | |
216 | |
217 typedef SparseModel<PointType> ModelType; | |
218 typedef std::multiset<PointType, typename PointType::OrderComparator> | |
219 PointListType; | |
220 | |
221 ModelType *sm = dynamic_cast<ModelType *>(m_model); | |
222 const PointListType &points = sm->getPoints(); | |
223 | |
224 for (typename PointListType::const_iterator i = points.begin(); | |
225 i != points.end(); ++i) { | |
226 m_rows.push_back(i->frame); | |
227 } | |
228 } | |
229 | |
230 bool | |
231 ModelDataTableModel::canHandleModelType(Model *m) | |
232 { | |
233 if (dynamic_cast<SparseOneDimensionalModel *>(m)) return true; | |
234 if (dynamic_cast<SparseTimeValueModel *>(m)) return true; | |
235 return false; | |
236 } | |
237 | |
238 |