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