Chris@43
|
1
|
Chris@58
|
2 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@43
|
3
|
Chris@43
|
4 /*
|
Chris@59
|
5 Sonic Visualiser
|
Chris@59
|
6 An audio file viewer and annotation editor.
|
Chris@59
|
7 Centre for Digital Music, Queen Mary, University of London.
|
Chris@59
|
8 This file copyright 2006 Chris Cannam.
|
Chris@43
|
9
|
Chris@59
|
10 This program is free software; you can redistribute it and/or
|
Chris@59
|
11 modify it under the terms of the GNU General Public License as
|
Chris@59
|
12 published by the Free Software Foundation; either version 2 of the
|
Chris@59
|
13 License, or (at your option) any later version. See the file
|
Chris@59
|
14 COPYING included with this distribution for more information.
|
Chris@43
|
15 */
|
Chris@43
|
16
|
Chris@43
|
17 #include "LayerTree.h"
|
Chris@128
|
18 #include "view/PaneStack.h"
|
Chris@43
|
19
|
Chris@298
|
20 #include "base/PlayParameters.h"
|
Chris@128
|
21 #include "view/Pane.h"
|
Chris@128
|
22 #include "layer/Layer.h"
|
Chris@128
|
23 #include "data/model/Model.h"
|
Chris@43
|
24
|
Chris@280
|
25 #include <QIcon>
|
Chris@43
|
26 #include <iostream>
|
Chris@43
|
27
|
Chris@43
|
28
|
Chris@43
|
29 LayerTreeModel::LayerTreeModel(PaneStack *stack, QObject *parent) :
|
Chris@43
|
30 QAbstractItemModel(parent),
|
Chris@43
|
31 m_stack(stack)
|
Chris@43
|
32 {
|
Chris@271
|
33 connect(stack, SIGNAL(paneAdded()), this, SIGNAL(layoutChanged()));
|
Chris@271
|
34 connect(stack, SIGNAL(paneDeleted()), this, SIGNAL(layoutChanged()));
|
Chris@298
|
35
|
Chris@298
|
36 for (int i = 0; i < stack->getPaneCount(); ++i) {
|
Chris@298
|
37 Pane *pane = stack->getPane(i);
|
Chris@298
|
38 if (!pane) continue;
|
Chris@298
|
39 connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)),
|
Chris@298
|
40 this, SLOT(propertyContainerAdded(PropertyContainer *)));
|
Chris@298
|
41 connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
|
Chris@298
|
42 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
|
Chris@298
|
43 connect(pane, SIGNAL(propertyContainerSelected(PropertyContainer *)),
|
Chris@298
|
44 this, SLOT(propertyContainerSelected(PropertyContainer *)));
|
Chris@298
|
45 connect(pane, SIGNAL(propertyContainerPropertyChanged(PropertyContainer *)),
|
Chris@298
|
46 this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
|
Chris@298
|
47 connect(pane, SIGNAL(propertyContainerNameChanged(PropertyContainer *)),
|
Chris@298
|
48 this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
|
Chris@298
|
49 for (int j = 0; j < pane->getLayerCount(); ++j) {
|
Chris@298
|
50 Layer *layer = pane->getLayer(j);
|
Chris@298
|
51 if (!layer) continue;
|
Chris@298
|
52 PlayParameters *params = layer->getPlayParameters();
|
Chris@298
|
53 if (!params) continue;
|
Chris@298
|
54 connect(params, SIGNAL(playAudibleChanged(bool)),
|
Chris@298
|
55 this, SLOT(playParametersAudibilityChanged(bool)));
|
Chris@298
|
56 }
|
Chris@298
|
57 }
|
Chris@43
|
58 }
|
Chris@43
|
59
|
Chris@43
|
60 LayerTreeModel::~LayerTreeModel()
|
Chris@43
|
61 {
|
Chris@43
|
62 }
|
Chris@43
|
63
|
Chris@298
|
64 void
|
Chris@298
|
65 LayerTreeModel::propertyContainerAdded(PropertyContainer *)
|
Chris@298
|
66 {
|
Chris@298
|
67 emit layoutChanged();
|
Chris@298
|
68 }
|
Chris@298
|
69
|
Chris@298
|
70 void
|
Chris@298
|
71 LayerTreeModel::propertyContainerRemoved(PropertyContainer *)
|
Chris@298
|
72 {
|
Chris@298
|
73 emit layoutChanged();
|
Chris@298
|
74 }
|
Chris@298
|
75
|
Chris@298
|
76 void
|
Chris@298
|
77 LayerTreeModel::propertyContainerSelected(PropertyContainer *)
|
Chris@298
|
78 {
|
Chris@298
|
79 emit layoutChanged();
|
Chris@298
|
80 }
|
Chris@298
|
81
|
Chris@298
|
82 void
|
Chris@298
|
83 LayerTreeModel::propertyContainerPropertyChanged(PropertyContainer *pc)
|
Chris@298
|
84 {
|
Chris@298
|
85 for (int i = 0; i < m_stack->getPaneCount(); ++i) {
|
Chris@298
|
86 Pane *pane = m_stack->getPane(i);
|
Chris@298
|
87 if (!pane) continue;
|
Chris@298
|
88 for (int j = 0; j < pane->getLayerCount(); ++j) {
|
Chris@298
|
89 if (pane->getLayer(j) == pc) {
|
Chris@298
|
90 emit dataChanged(createIndex(pane->getLayerCount() - j - 1,
|
Chris@298
|
91 0, pane),
|
Chris@298
|
92 createIndex(pane->getLayerCount() - j - 1,
|
Chris@298
|
93 3, pane));
|
Chris@298
|
94 }
|
Chris@298
|
95 }
|
Chris@298
|
96 }
|
Chris@298
|
97 }
|
Chris@298
|
98
|
Chris@298
|
99 void
|
Chris@298
|
100 LayerTreeModel::playParametersAudibilityChanged(bool a)
|
Chris@298
|
101 {
|
Chris@298
|
102 PlayParameters *params = dynamic_cast<PlayParameters *>(sender());
|
Chris@298
|
103 if (!params) return;
|
Chris@298
|
104
|
Chris@298
|
105 std::cerr << "LayerTreeModel::playParametersAudibilityChanged("
|
Chris@298
|
106 << params << "," << a << ")" << std::endl;
|
Chris@298
|
107
|
Chris@298
|
108 for (int i = 0; i < m_stack->getPaneCount(); ++i) {
|
Chris@298
|
109 Pane *pane = m_stack->getPane(i);
|
Chris@298
|
110 if (!pane) continue;
|
Chris@298
|
111 for (int j = 0; j < pane->getLayerCount(); ++j) {
|
Chris@298
|
112 Layer *layer = pane->getLayer(j);
|
Chris@298
|
113 if (!layer) continue;
|
Chris@298
|
114 if (layer->getPlayParameters() == params) {
|
Chris@298
|
115 std::cerr << "LayerTreeModel::playParametersAudibilityChanged("
|
Chris@298
|
116 << params << "," << a << "): row " << pane->getLayerCount() - j - 1 << ", col " << 2 << std::endl;
|
Chris@298
|
117
|
Chris@298
|
118 emit dataChanged(createIndex(pane->getLayerCount() - j - 1,
|
Chris@298
|
119 2, pane),
|
Chris@298
|
120 createIndex(pane->getLayerCount() - j - 1,
|
Chris@298
|
121 2, pane));
|
Chris@298
|
122 }
|
Chris@298
|
123 }
|
Chris@298
|
124 }
|
Chris@298
|
125 }
|
Chris@298
|
126
|
Chris@43
|
127 QVariant
|
Chris@43
|
128 LayerTreeModel::data(const QModelIndex &index, int role) const
|
Chris@43
|
129 {
|
Chris@43
|
130 if (!index.isValid()) return QVariant();
|
Chris@56
|
131
|
Chris@43
|
132 QObject *obj = static_cast<QObject *>(index.internalPointer());
|
Chris@277
|
133 int row = index.row(), col = index.column();
|
Chris@277
|
134
|
Chris@277
|
135 Pane *pane = dynamic_cast<Pane *>(obj);
|
Chris@277
|
136 if (!pane) {
|
Chris@277
|
137 if (col == 0 && row < m_stack->getPaneCount()) {
|
Chris@277
|
138 switch (role) {
|
Chris@277
|
139 case Qt::DisplayRole:
|
Chris@277
|
140 return QVariant(QString("Pane %1").arg(row + 1));
|
Chris@277
|
141 case Qt::DecorationRole:
|
Chris@277
|
142 return QVariant(QIcon(QString(":/icons/pane.png")));
|
Chris@277
|
143 default: break;
|
Chris@277
|
144 }
|
Chris@277
|
145 }
|
Chris@43
|
146 }
|
Chris@43
|
147
|
Chris@277
|
148 if (pane && pane->getLayerCount() > row) {
|
Chris@298
|
149 Layer *layer = pane->getLayer(pane->getLayerCount() - row - 1);
|
Chris@277
|
150 if (layer) {
|
Chris@277
|
151 if (col == 0) {
|
Chris@277
|
152 switch (role) {
|
Chris@277
|
153 case Qt::DisplayRole:
|
Chris@277
|
154 return QVariant(layer->objectName());
|
Chris@277
|
155 case Qt::DecorationRole:
|
Chris@277
|
156 return QVariant
|
Chris@277
|
157 (QIcon(QString(":/icons/%1.png")
|
Chris@277
|
158 .arg(layer->getPropertyContainerIconName())));
|
Chris@277
|
159 default: break;
|
Chris@277
|
160 }
|
Chris@277
|
161 } else if (col == 1) {
|
Chris@298
|
162 if (role == Qt::CheckStateRole) {
|
Chris@298
|
163 return QVariant(layer->isLayerDormant(pane) ?
|
Chris@298
|
164 Qt::Unchecked : Qt::Checked);
|
Chris@298
|
165 } else if (role == Qt::TextAlignmentRole) {
|
Chris@298
|
166 return QVariant(Qt::AlignHCenter);
|
Chris@298
|
167 }
|
Chris@298
|
168 } else if (col == 2) {
|
Chris@298
|
169 if (role == Qt::CheckStateRole) {
|
Chris@298
|
170 PlayParameters *params = layer->getPlayParameters();
|
Chris@298
|
171 if (params) return QVariant(params->isPlayMuted() ?
|
Chris@298
|
172 Qt::Unchecked : Qt::Checked);
|
Chris@298
|
173 else return QVariant();
|
Chris@298
|
174 } else if (role == Qt::TextAlignmentRole) {
|
Chris@298
|
175 return QVariant(Qt::AlignHCenter);
|
Chris@298
|
176 }
|
Chris@298
|
177 } else if (col == 3) {
|
Chris@277
|
178 Model *model = layer->getModel();
|
Chris@277
|
179 if (model && role == Qt::DisplayRole) {
|
Chris@277
|
180 return QVariant(model->objectName());
|
Chris@277
|
181 }
|
Chris@277
|
182 }
|
Chris@277
|
183 }
|
Chris@43
|
184 }
|
Chris@43
|
185
|
Chris@43
|
186 return QVariant();
|
Chris@43
|
187 }
|
Chris@43
|
188
|
Chris@298
|
189 bool
|
Chris@298
|
190 LayerTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
Chris@298
|
191 {
|
Chris@298
|
192 if (!index.isValid()) return false;
|
Chris@298
|
193
|
Chris@298
|
194 QObject *obj = static_cast<QObject *>(index.internalPointer());
|
Chris@298
|
195 int row = index.row(), col = index.column();
|
Chris@298
|
196
|
Chris@298
|
197 Pane *pane = dynamic_cast<Pane *>(obj);
|
Chris@298
|
198 if (!pane || pane->getLayerCount() <= row) return false;
|
Chris@298
|
199
|
Chris@298
|
200 Layer *layer = pane->getLayer(pane->getLayerCount() - row - 1);
|
Chris@298
|
201 if (!layer) return false;
|
Chris@298
|
202
|
Chris@298
|
203 if (col == 1) {
|
Chris@298
|
204 if (role == Qt::CheckStateRole) {
|
Chris@298
|
205 layer->showLayer(pane, value.toInt() == Qt::Checked);
|
Chris@298
|
206 emit dataChanged(index, index);
|
Chris@298
|
207 return true;
|
Chris@298
|
208 }
|
Chris@298
|
209 } else if (col == 2) {
|
Chris@298
|
210 if (role == Qt::CheckStateRole) {
|
Chris@298
|
211 PlayParameters *params = layer->getPlayParameters();
|
Chris@298
|
212 if (params) {
|
Chris@298
|
213 params->setPlayMuted(value.toInt() == Qt::Unchecked);
|
Chris@298
|
214 emit dataChanged(index, index);
|
Chris@298
|
215 return true;
|
Chris@298
|
216 }
|
Chris@298
|
217 }
|
Chris@298
|
218 }
|
Chris@298
|
219
|
Chris@298
|
220 return false;
|
Chris@298
|
221 }
|
Chris@298
|
222
|
Chris@43
|
223 Qt::ItemFlags
|
Chris@43
|
224 LayerTreeModel::flags(const QModelIndex &index) const
|
Chris@43
|
225 {
|
Chris@298
|
226 Qt::ItemFlags flags = Qt::ItemIsEnabled;
|
Chris@298
|
227 if (!index.isValid()) return flags;
|
Chris@298
|
228
|
Chris@298
|
229 if (index.column() == 1 || index.column() == 2) {
|
Chris@298
|
230 flags |= Qt::ItemIsUserCheckable;
|
Chris@298
|
231 } else if (index.column() == 0) {
|
Chris@298
|
232 flags |= Qt::ItemIsSelectable;
|
Chris@298
|
233 }
|
Chris@298
|
234
|
Chris@298
|
235 return flags;
|
Chris@43
|
236 }
|
Chris@43
|
237
|
Chris@43
|
238 QVariant
|
Chris@56
|
239 LayerTreeModel::headerData(int section,
|
Chris@43
|
240 Qt::Orientation orientation,
|
Chris@43
|
241 int role) const
|
Chris@43
|
242 {
|
Chris@56
|
243 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
Chris@56
|
244 if (section == 0) return QVariant(tr("Layer"));
|
Chris@298
|
245 else if (section == 1) return QVariant(tr("Shown"));
|
Chris@298
|
246 else if (section == 2) return QVariant(tr("Played"));
|
Chris@298
|
247 else if (section == 3) return QVariant(tr("Model"));
|
Chris@56
|
248 }
|
Chris@56
|
249
|
Chris@56
|
250 return QVariant();
|
Chris@43
|
251 }
|
Chris@43
|
252
|
Chris@43
|
253 QModelIndex
|
Chris@43
|
254 LayerTreeModel::index(int row, int column, const QModelIndex &parent) const
|
Chris@43
|
255 {
|
Chris@277
|
256 // cell for a pane contains row, column, pane stack
|
Chris@277
|
257 // -> its parent is the invalid cell
|
Chris@277
|
258
|
Chris@277
|
259 // cell for a layer contains row, column, pane
|
Chris@277
|
260 // -> its parent is row, column, pane stack (which identify the pane)
|
Chris@43
|
261
|
Chris@43
|
262 if (!parent.isValid()) {
|
Chris@277
|
263 if (row >= m_stack->getPaneCount() || column > 0) return QModelIndex();
|
Chris@43
|
264 return createIndex(row, column, m_stack);
|
Chris@43
|
265 }
|
Chris@43
|
266
|
Chris@43
|
267 QObject *obj = static_cast<QObject *>(parent.internalPointer());
|
Chris@277
|
268
|
Chris@277
|
269 if (obj == m_stack) {
|
Chris@277
|
270 Pane *pane = m_stack->getPane(parent.row());
|
Chris@277
|
271 if (!pane || parent.column() > 0) return QModelIndex();
|
Chris@277
|
272 return createIndex(row, column, pane);
|
Chris@43
|
273 }
|
Chris@43
|
274
|
Chris@43
|
275 return QModelIndex();
|
Chris@43
|
276 }
|
Chris@43
|
277
|
Chris@43
|
278 QModelIndex
|
Chris@43
|
279 LayerTreeModel::parent(const QModelIndex &index) const
|
Chris@43
|
280 {
|
Chris@43
|
281 QObject *obj = static_cast<QObject *>(index.internalPointer());
|
Chris@43
|
282
|
Chris@43
|
283 Pane *pane = dynamic_cast<Pane *>(obj);
|
Chris@43
|
284 if (pane) {
|
Chris@277
|
285 int index = m_stack->getPaneIndex(pane);
|
Chris@277
|
286 if (index >= 0) return createIndex(index, 0, m_stack);
|
Chris@43
|
287 }
|
Chris@43
|
288
|
Chris@43
|
289 return QModelIndex();
|
Chris@43
|
290 }
|
Chris@43
|
291
|
Chris@43
|
292 int
|
Chris@43
|
293 LayerTreeModel::rowCount(const QModelIndex &parent) const
|
Chris@43
|
294 {
|
Chris@277
|
295 if (!parent.isValid()) return m_stack->getPaneCount();
|
Chris@43
|
296
|
Chris@43
|
297 QObject *obj = static_cast<QObject *>(parent.internalPointer());
|
Chris@43
|
298
|
Chris@277
|
299 if (obj == m_stack) {
|
Chris@277
|
300 Pane *pane = m_stack->getPane(parent.row());
|
Chris@277
|
301 if (!pane || parent.column() > 0) return 0;
|
Chris@277
|
302 return pane->getLayerCount();
|
Chris@43
|
303 }
|
Chris@43
|
304
|
Chris@43
|
305 return 0;
|
Chris@43
|
306 }
|
Chris@43
|
307
|
Chris@43
|
308 int
|
Chris@43
|
309 LayerTreeModel::columnCount(const QModelIndex &parent) const
|
Chris@43
|
310 {
|
Chris@298
|
311 if (!parent.isValid()) return 4;
|
Chris@43
|
312
|
Chris@43
|
313 QObject *obj = static_cast<QObject *>(parent.internalPointer());
|
Chris@298
|
314 if (obj == m_stack) return 4; // row for a layer
|
Chris@56
|
315
|
Chris@43
|
316 return 1;
|
Chris@43
|
317 }
|
Chris@43
|
318
|