LayerTree.cpp
Go to the documentation of this file.
1 
2 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
3 
4 /*
5  Sonic Visualiser
6  An audio file viewer and annotation editor.
7  Centre for Digital Music, Queen Mary, University of London.
8  This file copyright 2006 Chris Cannam.
9 
10  This program is free software; you can redistribute it and/or
11  modify it under the terms of the GNU General Public License as
12  published by the Free Software Foundation; either version 2 of the
13  License, or (at your option) any later version. See the file
14  COPYING included with this distribution for more information.
15 */
16 
17 #include "LayerTree.h"
18 #include "view/PaneStack.h"
19 
20 #include "base/PlayParameters.h"
21 #include "view/Pane.h"
22 #include "layer/Layer.h"
23 #include "data/model/Model.h"
24 #include "data/model/WaveFileModel.h"
25 
26 #include <QIcon>
27 #include <iostream>
28 
29 
31  QObject *parent) :
32  QAbstractItemModel(parent),
33  m_stack(stack),
34  m_waveModelsOnly(waveModelsOnly)
35 {
36  if (m_waveModelsOnly) {
37  m_modelTypeColumn = -1;
41  m_columnCount = 3;
42  } else {
47  m_columnCount = 4;
48  }
49 
50  connect(stack, SIGNAL(paneAdded()), this, SLOT(paneAdded()));
51  connect(stack, SIGNAL(paneDeleted()), this, SLOT(paneDeleted()));
52 
53  for (int i = 0; i < stack->getPaneCount(); ++i) {
54  Pane *pane = stack->getPane(i);
55  if (!pane) continue;
56  connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)),
57  this, SLOT(propertyContainerAdded(PropertyContainer *)));
58  connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
59  this, SLOT(propertyContainerRemoved(PropertyContainer *)));
60  connect(pane, SIGNAL(propertyContainerSelected(PropertyContainer *)),
61  this, SLOT(propertyContainerSelected(PropertyContainer *)));
62  connect(pane, SIGNAL(propertyContainerPropertyChanged(PropertyContainer *)),
63  this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
64  connect(pane, SIGNAL(propertyContainerNameChanged(PropertyContainer *)),
65  this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
66  connect(pane, SIGNAL(layerModelChanged()),
67  this, SLOT(paneLayerModelChanged()));
68  }
69 
71 }
72 
74 {
75 }
76 
77 void
79 {
80  std::set<ModelId> unfound = m_models;
81 
82  for (int i = 0; i < m_stack->getPaneCount(); ++i) {
83 
84  Pane *pane = m_stack->getPane(i);
85  if (!pane) continue;
86 
87  for (int j = 0; j < pane->getLayerCount(); ++j) {
88 
89  Layer *layer = pane->getLayer(j);
90  if (!layer) continue;
91 
92  ModelId modelId = layer->getModel();
93  if (modelId.isNone()) continue;
94 
95  if (m_waveModelsOnly) {
96  if (!ModelById::getAs<WaveFileModel>(modelId)) continue;
97  }
98 
99  if (m_models.find(modelId) == m_models.end()) {
100  m_models.insert(modelId);
101  } else {
102  unfound.erase(modelId);
103  }
104  }
105  }
106 
107  for (ModelId m: unfound) {
108  m_models.erase(m);
109  }
110 
111  SVDEBUG << "ModelMetadataModel::rebuildModelSet: " << m_models.size() << " models" << endl;
112 }
113 
114 void
116 {
117  rebuildModelSet();
118  emit layoutChanged();
119 }
120 
121 void
123 {
124  rebuildModelSet();
125  emit layoutChanged();
126 }
127 
128 void
130 {
131  rebuildModelSet();
132  emit layoutChanged();
133 }
134 
135 void
137 {
138  rebuildModelSet();
139  emit layoutChanged();
140 }
141 
142 void
144 {
145  rebuildModelSet();
146  emit layoutChanged();
147 }
148 
149 void
151 {
152 }
153 
154 void
156 {
157 }
158 
159 void
161 {
162 }
163 
164 QVariant
165 ModelMetadataModel::data(const QModelIndex &index, int role) const
166 {
167  if (!index.isValid()) return QVariant();
168 
169 // QObject *obj = static_cast<QObject *>(index.internalPointer());
170  int row = index.row(), col = index.column();
171 
173  std::set<ModelId>::iterator itr = m_models.begin();
174  for (int i = 0; i < row && itr != m_models.end(); ++i, ++itr);
175  if (itr == m_models.end()) return QVariant();
176 
177  auto model = ModelById::get(*itr);
178  if (!model) return QVariant();
179 
180  if (role != Qt::DisplayRole) {
181  if (m_waveModelsOnly && col == m_modelNameColumn &&
182  role == Qt::DecorationRole) {
183  // There is no meaningful icon for a model, in general --
184  // the icons we have represent layer types and it would be
185  // misleading to use them for models. However, if we're
186  // only showing wave models, we use the waveform icon just
187  // for decorative purposes.
188  return QVariant(QIcon(QString(":/icons/waveform.png")));
189  }
190  return QVariant();
191  }
192 
193  if (col == m_modelTypeColumn) {
194  return QVariant(model->getTypeName());
195  } else if (col == m_modelNameColumn) {
196  return QVariant(model->objectName());
197  } else if (col == m_modelMakerColumn) {
198  return QVariant(model->getMaker());
199  } else if (col == m_modelSourceColumn) {
200  return QVariant(model->getLocation());
201  }
202 
203  return QVariant();
204 }
205 
206 bool
207 ModelMetadataModel::setData(const QModelIndex &, const QVariant &, int )
208 {
209  return false;
210 }
211 
212 Qt::ItemFlags
213 ModelMetadataModel::flags(const QModelIndex &) const
214 {
215  Qt::ItemFlags flags = Qt::ItemIsEnabled;
216  return flags;
217 }
218 
219 QVariant
221  Qt::Orientation orientation,
222  int role) const
223 {
224  if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
225  if (section == m_modelTypeColumn) return QVariant(tr("Type"));
226  else if (section == m_modelNameColumn) return QVariant(tr("Name"));
227  else if (section == m_modelMakerColumn) return QVariant(tr("Maker"));
228  else if (section == m_modelSourceColumn) return QVariant(tr("Source"));
229  }
230 
231  return QVariant();
232 }
233 
234 QModelIndex
235 ModelMetadataModel::index(int row, int column, const QModelIndex &parent) const
236 {
237  if (!parent.isValid()) {
238  if (row >= (int)m_models.size()) return QModelIndex();
239  return createIndex(row, column, (void *)nullptr);
240  }
241 
242  return QModelIndex();
243 }
244 
245 QModelIndex
246 ModelMetadataModel::parent(const QModelIndex &) const
247 {
248  return QModelIndex();
249 }
250 
251 int
252 ModelMetadataModel::rowCount(const QModelIndex &parent) const
253 {
254  if (!parent.isValid()) return int(m_models.size());
255  return 0;
256 }
257 
258 int
259 ModelMetadataModel::columnCount(const QModelIndex &) const
260 {
261  return m_columnCount;
262 }
263 
264 
265 
267  QAbstractItemModel(parent),
268  m_stack(stack)
269 {
270  m_layerNameColumn = 0;
273  m_modelNameColumn = 3;
274  m_columnCount = 4;
275 
276  connect(stack, SIGNAL(paneAdded()), this, SLOT(paneAdded()));
277  connect(stack, SIGNAL(paneAboutToBeDeleted(Pane *)),
278  this, SLOT(paneAboutToBeDeleted(Pane *)));
279 
280  for (int i = 0; i < stack->getPaneCount(); ++i) {
281  Pane *pane = stack->getPane(i);
282  if (!pane) continue;
283  connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)),
284  this, SLOT(propertyContainerAdded(PropertyContainer *)));
285  connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
286  this, SLOT(propertyContainerRemoved(PropertyContainer *)));
287  connect(pane, SIGNAL(propertyContainerSelected(PropertyContainer *)),
288  this, SLOT(propertyContainerSelected(PropertyContainer *)));
289  connect(pane, SIGNAL(propertyContainerPropertyChanged(PropertyContainer *)),
290  this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
291  connect(pane, SIGNAL(propertyContainerNameChanged(PropertyContainer *)),
292  this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
293  connect(pane, SIGNAL(layerModelChanged()),
294  this, SLOT(paneLayerModelChanged()));
295 
296  for (int j = 0; j < pane->getLayerCount(); ++j) {
297  Layer *layer = pane->getLayer(j);
298  if (!layer) continue;
299  auto params = layer->getPlayParameters();
300  if (!params) continue;
301  connect(params.get(), SIGNAL(playAudibleChanged(bool)),
302  this, SLOT(playParametersAudibilityChanged(bool)));
303  }
304  }
305 }
306 
308 {
309 }
310 
311 void
313 {
314  emit layoutChanged();
315 }
316 
317 void
319 {
320  cerr << "paneDeleted: " << pane << endl;
321  m_deletedPanes.insert(pane);
322  emit layoutChanged();
323 }
324 
325 void
327 {
328  emit layoutChanged();
329 }
330 
331 void
333 {
334  emit layoutChanged();
335 }
336 
337 void
339 {
340  emit layoutChanged();
341 }
342 
343 void
345 {
346  emit layoutChanged();
347 }
348 
349 void
351 {
352  for (int i = 0; i < m_stack->getPaneCount(); ++i) {
353  Pane *pane = m_stack->getPane(i);
354  if (!pane) continue;
355  for (int j = 0; j < pane->getLayerCount(); ++j) {
356  if (pane->getLayer(j) == pc) {
357  emit dataChanged(createIndex(pane->getLayerCount() - j - 1,
358  m_layerNameColumn, pane),
359  createIndex(pane->getLayerCount() - j - 1,
360  m_modelNameColumn, pane));
361  }
362  }
363  }
364 }
365 
366 void
368 {
369  PlayParameters *params = dynamic_cast<PlayParameters *>(sender());
370  if (!params) return;
371 
372  SVDEBUG << "LayerTreeModel::playParametersAudibilityChanged("
373  << params << "," << a << ")" << endl;
374 
375  for (int i = 0; i < m_stack->getPaneCount(); ++i) {
376  Pane *pane = m_stack->getPane(i);
377  if (!pane) continue;
378  for (int j = 0; j < pane->getLayerCount(); ++j) {
379  Layer *layer = pane->getLayer(j);
380  if (!layer) continue;
381  if (layer->getPlayParameters().get() == params) { // ugh
382  SVDEBUG << "LayerTreeModel::playParametersAudibilityChanged("
383  << params << "," << a << "): row " << pane->getLayerCount() - j - 1 << ", col " << 2 << endl;
384 
385  emit dataChanged(createIndex(pane->getLayerCount() - j - 1,
386  m_layerPlayedColumn, pane),
387  createIndex(pane->getLayerCount() - j - 1,
388  m_layerPlayedColumn, pane));
389  }
390  }
391  }
392 }
393 
394 QVariant
395 LayerTreeModel::data(const QModelIndex &index, int role) const
396 {
397  if (!index.isValid()) return QVariant();
398 
399  QObject *obj = static_cast<QObject *>(index.internalPointer());
400  int row = index.row(), col = index.column();
401 
402  Pane *pane = dynamic_cast<Pane *>(obj);
403  if (!pane) {
404  if (col == 0 && row < m_stack->getPaneCount()) {
405  switch (role) {
406  case Qt::DisplayRole:
407  return QVariant(QString("Pane %1").arg(row + 1));
408  case Qt::DecorationRole:
409  return QVariant(QIcon(QString(":/icons/pane.png")));
410  default: break;
411  }
412  }
413  }
414 
415  if (pane && pane->getLayerCount() > row) {
416  Layer *layer = pane->getLayer(pane->getLayerCount() - row - 1);
417  if (layer) {
418  if (col == m_layerNameColumn) {
419  switch (role) {
420  case Qt::DisplayRole:
421  return QVariant(layer->objectName());
422  case Qt::DecorationRole:
423  return QVariant
424  (QIcon(QString(":/icons/%1.png")
425  .arg(layer->getPropertyContainerIconName())));
426  default: break;
427  }
428  } else if (col == m_layerVisibleColumn) {
429  if (role == Qt::CheckStateRole) {
430  return QVariant(layer->isLayerDormant(pane) ?
431  Qt::Unchecked : Qt::Checked);
432  } else if (role == Qt::TextAlignmentRole) {
433  return QVariant(Qt::AlignHCenter);
434  }
435  } else if (col == m_layerPlayedColumn) {
436  if (role == Qt::CheckStateRole) {
437  auto params = layer->getPlayParameters();
438  if (params) return QVariant(params->isPlayMuted() ?
439  Qt::Unchecked : Qt::Checked);
440  else return QVariant();
441  } else if (role == Qt::TextAlignmentRole) {
442  return QVariant(Qt::AlignHCenter);
443  }
444  } else if (col == m_modelNameColumn) {
445  auto model = ModelById::get(layer->getModel());
446  if (model && role == Qt::DisplayRole) {
447  return QVariant(model->objectName());
448  }
449  }
450  }
451  }
452 
453  return QVariant();
454 }
455 
456 bool
457 LayerTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
458 {
459  if (!index.isValid()) return false;
460 
461  QObject *obj = static_cast<QObject *>(index.internalPointer());
462  int row = index.row(), col = index.column();
463 
464  Pane *pane = dynamic_cast<Pane *>(obj);
465  if (!pane || pane->getLayerCount() <= row) return false;
466 
467  Layer *layer = pane->getLayer(pane->getLayerCount() - row - 1);
468  if (!layer) return false;
469 
470  if (col == m_layerVisibleColumn) {
471  if (role == Qt::CheckStateRole) {
472  layer->showLayer(pane, value.toInt() == Qt::Checked);
473  emit dataChanged(index, index);
474  return true;
475  }
476  } else if (col == m_layerPlayedColumn) {
477  if (role == Qt::CheckStateRole) {
478  auto params = layer->getPlayParameters();
479  if (params) {
480  params->setPlayMuted(value.toInt() == Qt::Unchecked);
481  emit dataChanged(index, index);
482  return true;
483  }
484  }
485  }
486 
487  return false;
488 }
489 
490 Qt::ItemFlags
491 LayerTreeModel::flags(const QModelIndex &index) const
492 {
493  Qt::ItemFlags flags = Qt::ItemIsEnabled;
494  if (!index.isValid()) return flags;
495 
496  if (index.column() == m_layerVisibleColumn ||
497  index.column() == m_layerPlayedColumn) {
498  flags |= Qt::ItemIsUserCheckable;
499  } else if (index.column() == 0) {
500  flags |= Qt::ItemIsSelectable;
501  }
502 
503  return flags;
504 }
505 
506 QVariant
508  Qt::Orientation orientation,
509  int role) const
510 {
511  if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
512  if (section == m_layerNameColumn) return QVariant(tr("Layer"));
513  else if (section == m_layerVisibleColumn) return QVariant(tr("Shown"));
514  else if (section == m_layerPlayedColumn) return QVariant(tr("Played"));
515  else if (section == m_modelNameColumn) return QVariant(tr("Model"));
516  }
517 
518  return QVariant();
519 }
520 
521 QModelIndex
522 LayerTreeModel::index(int row, int column, const QModelIndex &parent) const
523 {
524  // cell for a pane contains row, column, pane stack
525  // -> its parent is the invalid cell
526 
527  // cell for a layer contains row, column, pane
528  // -> its parent is row, column, pane stack (which identify the pane)
529 
530  if (!parent.isValid()) {
531  if (row >= m_stack->getPaneCount() || column > 0) return QModelIndex();
532  return createIndex(row, column, m_stack);
533  }
534 
535  QObject *obj = static_cast<QObject *>(parent.internalPointer());
536 
537  if (obj == m_stack) {
538  Pane *pane = m_stack->getPane(parent.row());
539  if (!pane || parent.column() > 0) return QModelIndex();
540  return createIndex(row, column, pane);
541  }
542 
543  return QModelIndex();
544 }
545 
546 QModelIndex
547 LayerTreeModel::parent(const QModelIndex &index) const
548 {
549  QObject *obj = static_cast<QObject *>(index.internalPointer());
550 
551  if (m_deletedPanes.find(obj) != m_deletedPanes.end()) {
552 // m_deletedPanes.erase(obj);
553  return QModelIndex();
554  }
555 
556  Pane *pane = dynamic_cast<Pane *>(obj);
557  if (pane) {
558  int index = m_stack->getPaneIndex(pane);
559  if (index >= 0) return createIndex(index, 0, m_stack);
560  }
561 
562  return QModelIndex();
563 }
564 
565 int
566 LayerTreeModel::rowCount(const QModelIndex &parent) const
567 {
568  if (!parent.isValid()) return m_stack->getPaneCount();
569 
570  QObject *obj = static_cast<QObject *>(parent.internalPointer());
571 
572  if (obj == m_stack) {
573  Pane *pane = m_stack->getPane(parent.row());
574  if (!pane || parent.column() > 0) return 0;
575  return pane->getLayerCount();
576  }
577 
578  return 0;
579 }
580 
581 int
582 LayerTreeModel::columnCount(const QModelIndex &parent) const
583 {
584  if (!parent.isValid()) return m_columnCount;
585 
586  QObject *obj = static_cast<QObject *>(parent.internalPointer());
587  if (obj == m_stack) return m_columnCount; // row for a layer
588 
589  return 1;
590 }
591 
Pane * getPane(int n)
Definition: PaneStack.cpp:335
void paneLayerModelChanged()
Definition: LayerTree.cpp:129
virtual bool isLayerDormant(const LayerGeometryProvider *v) const
Return whether the layer is dormant (i.e.
Definition: Layer.cpp:144
Definition: Pane.h:35
virtual ~ModelMetadataModel()
Definition: LayerTree.cpp:73
The base class for visual representations of the data found in a Model.
Definition: Layer.h:54
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: LayerTree.cpp:522
std::set< QObject * > m_deletedPanes
Definition: LayerTree.h:117
int m_layerPlayedColumn
Definition: LayerTree.h:120
QVariant data(const QModelIndex &index, int role) const override
Definition: LayerTree.cpp:165
void propertyContainerRemoved(PropertyContainer *)
Definition: LayerTree.cpp:332
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: LayerTree.cpp:213
virtual int getLayerCount() const
Return the number of layers, regardless of whether visible or dormant, i.e.
Definition: View.h:197
ModelMetadataModel(PaneStack *stack, bool waveModelsOnly, QObject *parent=0)
Definition: LayerTree.cpp:30
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: LayerTree.cpp:491
int getPaneCount() const
Definition: PaneStack.cpp:455
int m_modelNameColumn
Definition: LayerTree.h:121
QModelIndex parent(const QModelIndex &index) const override
Definition: LayerTree.cpp:246
PaneStack * m_stack
Definition: LayerTree.h:69
void propertyContainerRemoved(PropertyContainer *)
Definition: LayerTree.cpp:143
LayerTreeModel(PaneStack *stack, QObject *parent=0)
Definition: LayerTree.cpp:266
virtual ~LayerTreeModel()
Definition: LayerTree.cpp:307
void propertyContainerSelected(PropertyContainer *)
Definition: LayerTree.cpp:338
void propertyContainerPropertyChanged(PropertyContainer *)
Definition: LayerTree.cpp:155
void propertyContainerAdded(PropertyContainer *)
Definition: LayerTree.cpp:136
int getPaneIndex(Pane *pane)
Definition: PaneStack.cpp:345
std::shared_ptr< PlayParameters > getPlayParameters() override
Return the play parameters for this layer, if any.
Definition: Layer.cpp:129
void propertyContainerPropertyChanged(PropertyContainer *)
Definition: LayerTree.cpp:350
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition: LayerTree.cpp:235
PaneStack * m_stack
Definition: LayerTree.h:116
void propertyContainerAdded(PropertyContainer *)
Definition: LayerTree.cpp:326
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Definition: LayerTree.cpp:259
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Definition: LayerTree.cpp:566
void propertyContainerSelected(PropertyContainer *)
Definition: LayerTree.cpp:150
std::set< ModelId > m_models
Definition: LayerTree.h:77
virtual Layer * getLayer(int n)
Return the nth layer, counted in stacking order.
Definition: View.h:205
QModelIndex parent(const QModelIndex &index) const override
Definition: LayerTree.cpp:547
void playParametersAudibilityChanged(bool)
Definition: LayerTree.cpp:160
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Definition: LayerTree.cpp:507
void paneAdded()
Definition: LayerTree.cpp:312
void showLayer(LayerGeometryProvider *, bool show)
Change the visibility status (dormancy) of the layer in the given view.
Definition: Layer.cpp:153
void rebuildModelSet()
Definition: LayerTree.cpp:78
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Definition: LayerTree.cpp:220
void playParametersAudibilityChanged(bool)
Definition: LayerTree.cpp:367
virtual ModelId getModel() const =0
Return the ID of the model represented in this layer.
bool setData(const QModelIndex &index, const QVariant &value, int role) override
Definition: LayerTree.cpp:207
void paneAboutToBeDeleted(Pane *)
Definition: LayerTree.cpp:318
QString getPropertyContainerIconName() const override
Definition: Layer.cpp:80
int m_layerVisibleColumn
Definition: LayerTree.h:119
bool setData(const QModelIndex &index, const QVariant &value, int role) override
Definition: LayerTree.cpp:457
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Definition: LayerTree.cpp:252
void paneLayerModelChanged()
Definition: LayerTree.cpp:344
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Definition: LayerTree.cpp:582
int m_layerNameColumn
Definition: LayerTree.h:118
QVariant data(const QModelIndex &index, int role) const override
Definition: LayerTree.cpp:395