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