Chris@43: 
Chris@58: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@43: 
Chris@43: /*
Chris@59:     Sonic Visualiser
Chris@59:     An audio file viewer and annotation editor.
Chris@59:     Centre for Digital Music, Queen Mary, University of London.
Chris@59:     This file copyright 2006 Chris Cannam.
Chris@43:     
Chris@59:     This program is free software; you can redistribute it and/or
Chris@59:     modify it under the terms of the GNU General Public License as
Chris@59:     published by the Free Software Foundation; either version 2 of the
Chris@59:     License, or (at your option) any later version.  See the file
Chris@59:     COPYING included with this distribution for more information.
Chris@43: */
Chris@43: 
Chris@43: #include "LayerTree.h"
Chris@128: #include "view/PaneStack.h"
Chris@43: 
Chris@298: #include "base/PlayParameters.h"
Chris@128: #include "view/Pane.h"
Chris@128: #include "layer/Layer.h"
Chris@128: #include "data/model/Model.h"
Chris@336: #include "data/model/WaveFileModel.h"
Chris@43: 
Chris@280: #include <QIcon>
Chris@43: #include <iostream>
Chris@43: 
Chris@43: 
Chris@392: ModelMetadataModel::ModelMetadataModel(PaneStack *stack, bool waveModelsOnly,
Chris@336:                                QObject *parent) :
Chris@43:     QAbstractItemModel(parent),
Chris@336:     m_stack(stack),
Chris@336:     m_waveModelsOnly(waveModelsOnly)
Chris@43: {
Chris@336:     if (m_waveModelsOnly) {
Chris@336:         m_modelTypeColumn = -1;
Chris@336:         m_modelNameColumn = 0;
Chris@336:         m_modelMakerColumn = 1;
Chris@336:         m_modelSourceColumn = 2;
Chris@336:         m_columnCount = 3;
Chris@336:     } else {
Chris@336:         m_modelTypeColumn = 0;
Chris@336:         m_modelNameColumn = 1;
Chris@336:         m_modelMakerColumn = 2;
Chris@336:         m_modelSourceColumn = 3;
Chris@336:         m_columnCount = 4;
Chris@336:     }
Chris@336: 
Chris@336:     connect(stack, SIGNAL(paneAdded()), this, SLOT(paneAdded()));
Chris@336:     connect(stack, SIGNAL(paneDeleted()), this, SLOT(paneDeleted()));
Chris@298: 
Chris@298:     for (int i = 0; i < stack->getPaneCount(); ++i) {
Chris@298:         Pane *pane = stack->getPane(i);
Chris@298:         if (!pane) continue;
Chris@298:         connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)),
Chris@298:                 this, SLOT(propertyContainerAdded(PropertyContainer *)));
Chris@298:         connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
Chris@298:                 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
Chris@298:         connect(pane, SIGNAL(propertyContainerSelected(PropertyContainer *)),
Chris@298:                 this, SLOT(propertyContainerSelected(PropertyContainer *)));
Chris@298:         connect(pane, SIGNAL(propertyContainerPropertyChanged(PropertyContainer *)),
Chris@298:                 this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
Chris@298:         connect(pane, SIGNAL(propertyContainerNameChanged(PropertyContainer *)),
Chris@298:                 this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
Chris@336:         connect(pane, SIGNAL(layerModelChanged()),
Chris@336:                 this, SLOT(paneLayerModelChanged()));
Chris@336:     }
Chris@336: 
Chris@336:     rebuildModelSet();
Chris@336: }
Chris@336: 
Chris@392: ModelMetadataModel::~ModelMetadataModel()
Chris@336: {
Chris@336: }
Chris@336: 
Chris@336: void
Chris@392: ModelMetadataModel::rebuildModelSet()
Chris@336: {
Chris@336:     std::set<Model *> unfound = m_models;
Chris@336: 
Chris@336:     for (int i = 0; i < m_stack->getPaneCount(); ++i) {
Chris@336: 
Chris@336:         Pane *pane = m_stack->getPane(i);
Chris@336:         if (!pane) continue;
Chris@336: 
Chris@336:         for (int j = 0; j < pane->getLayerCount(); ++j) {
Chris@336: 
Chris@336:             Layer *layer = pane->getLayer(j);
Chris@336:             if (!layer) continue;
Chris@336: 
Chris@336:             Model *model = layer->getModel();
Chris@336:             if (!model) continue;
Chris@336: 
Chris@336:             if (m_waveModelsOnly) {
Chris@336:                 if (!dynamic_cast<WaveFileModel *>(model)) continue;
Chris@336:             }
Chris@336: 
Chris@336:             if (m_models.find(model) == m_models.end()) {
Chris@336:                 connect(model, SIGNAL(aboutToBeDeleted()),
Chris@336:                         this, SLOT(rebuildModelSet()));
Chris@336:                 m_models.insert(model);
Chris@336:             } else {
Chris@336:                 unfound.erase(model);
Chris@336:             }
Chris@336:         }
Chris@336:     }
Chris@336: 
Chris@336:     for (std::set<Model *>::iterator i = unfound.begin();
Chris@336:          i != unfound.end(); ++i) {
Chris@336:         m_models.erase(*i);
Chris@336:     }
Chris@336: 
Chris@587:     SVDEBUG << "ModelMetadataModel::rebuildModelSet: " << m_models.size() << " models" << endl;
Chris@336: }
Chris@336: 
Chris@336: void
Chris@392: ModelMetadataModel::paneAdded()
Chris@336: {
Chris@336:     rebuildModelSet();
Chris@336:     emit layoutChanged();
Chris@336: }
Chris@336: 
Chris@336: void
Chris@392: ModelMetadataModel::paneDeleted()
Chris@336: {
Chris@336:     rebuildModelSet();
Chris@336:     emit layoutChanged();
Chris@336: }
Chris@336: 
Chris@336: void
Chris@392: ModelMetadataModel::paneLayerModelChanged()
Chris@336: {
Chris@336:     rebuildModelSet();
Chris@336:     emit layoutChanged();
Chris@336: }
Chris@336: 
Chris@336: void
Chris@392: ModelMetadataModel::propertyContainerAdded(PropertyContainer *)
Chris@336: {
Chris@336:     rebuildModelSet();
Chris@336:     emit layoutChanged();
Chris@336: }
Chris@336: 
Chris@336: void
Chris@392: ModelMetadataModel::propertyContainerRemoved(PropertyContainer *)
Chris@336: {
Chris@336:     rebuildModelSet();
Chris@336:     emit layoutChanged();
Chris@336: }
Chris@336: 
Chris@336: void
Chris@392: ModelMetadataModel::propertyContainerSelected(PropertyContainer *)
Chris@336: {
Chris@336: }
Chris@336: 
Chris@336: void
Chris@807: ModelMetadataModel::propertyContainerPropertyChanged(PropertyContainer *)
Chris@336: {
Chris@336: }
Chris@336: 
Chris@336: void
Chris@807: ModelMetadataModel::playParametersAudibilityChanged(bool )
Chris@336: {
Chris@336: }
Chris@336: 
Chris@336: QVariant
Chris@392: ModelMetadataModel::data(const QModelIndex &index, int role) const
Chris@336: {
Chris@336:     if (!index.isValid()) return QVariant();
Chris@336: 
Chris@807: //    QObject *obj = static_cast<QObject *>(index.internalPointer());
Chris@336:     int row = index.row(), col = index.column();
Chris@336: 
Chris@336:     //!!! not exactly the ideal use of a std::set
Chris@336:     std::set<Model *>::iterator itr = m_models.begin();
Chris@336:     for (int i = 0; i < row && itr != m_models.end(); ++i, ++itr);
Chris@336:     if (itr == m_models.end()) return QVariant();
Chris@336: 
Chris@336:     Model *model = *itr;
Chris@336: 
Chris@336:     if (role != Qt::DisplayRole) {
Chris@336:         if (m_waveModelsOnly && col == m_modelNameColumn &&
Chris@336:             role == Qt::DecorationRole) {
Chris@336:             // There is no meaningful icon for a model, in general --
Chris@336:             // the icons we have represent layer types and it would be
Chris@336:             // misleading to use them for models.  However, if we're
Chris@336:             // only showing wave models, we use the waveform icon just
Chris@336:             // for decorative purposes.
Chris@336:             return QVariant(QIcon(QString(":/icons/waveform.png")));
Chris@336:         }
Chris@336:         return QVariant();
Chris@336:     }
Chris@336:     
Chris@336:     if (col == m_modelTypeColumn) {
Chris@336:         return QVariant(model->getTypeName());
Chris@336:     } else if (col == m_modelNameColumn) {
Chris@336:         return QVariant(model->objectName());
Chris@336:     } else if (col == m_modelMakerColumn) {
Chris@336:         return QVariant(model->getMaker());
Chris@336:     } else if (col == m_modelSourceColumn) {
Chris@336:         return QVariant(model->getLocation());
Chris@336:     }        
Chris@336:     
Chris@336:     return QVariant();
Chris@336: }
Chris@336: 
Chris@336: bool
Chris@807: ModelMetadataModel::setData(const QModelIndex &, const QVariant &, int )
Chris@336: {
Chris@336:     return false;
Chris@336: }
Chris@336: 
Chris@336: Qt::ItemFlags
Chris@807: ModelMetadataModel::flags(const QModelIndex &) const
Chris@336: {
Chris@336:     Qt::ItemFlags flags = Qt::ItemIsEnabled;
Chris@336:     return flags;
Chris@336: }
Chris@336: 
Chris@336: QVariant
Chris@392: ModelMetadataModel::headerData(int section,
Chris@336: 			   Qt::Orientation orientation,
Chris@336: 			   int role) const
Chris@336: {
Chris@336:     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
Chris@336: 	if (section == m_modelTypeColumn) return QVariant(tr("Type"));
Chris@336: 	else if (section == m_modelNameColumn) return QVariant(tr("Name"));
Chris@336: 	else if (section == m_modelMakerColumn) return QVariant(tr("Maker"));
Chris@336: 	else if (section == m_modelSourceColumn) return QVariant(tr("Source"));
Chris@336:     }
Chris@336: 
Chris@336:     return QVariant();
Chris@336: }
Chris@336: 
Chris@336: QModelIndex
Chris@392: ModelMetadataModel::index(int row, int column, const QModelIndex &parent) const
Chris@336: {
Chris@336:     if (!parent.isValid()) {
Chris@807:         if (row >= (int)m_models.size()) return QModelIndex();
Chris@616: 	return createIndex(row, column, (void *)0);
Chris@336:     }
Chris@336: 
Chris@336:     return QModelIndex();
Chris@336: }
Chris@336: 
Chris@336: QModelIndex
Chris@807: ModelMetadataModel::parent(const QModelIndex &) const
Chris@336: {
Chris@336:     return QModelIndex();
Chris@336: }
Chris@336: 
Chris@336: int
Chris@392: ModelMetadataModel::rowCount(const QModelIndex &parent) const
Chris@336: {
Chris@908:     if (!parent.isValid()) return int(m_models.size());
Chris@336:     return 0;
Chris@336: }
Chris@336: 
Chris@336: int
Chris@807: ModelMetadataModel::columnCount(const QModelIndex &) const
Chris@336: {
Chris@336:     return m_columnCount;
Chris@336: }
Chris@336: 
Chris@336: 
Chris@336: 
Chris@336: LayerTreeModel::LayerTreeModel(PaneStack *stack, QObject *parent) :
Chris@336:     QAbstractItemModel(parent),
Chris@336:     m_stack(stack)
Chris@336: {
Chris@336:     m_layerNameColumn = 0;
Chris@336:     m_layerVisibleColumn = 1;
Chris@336:     m_layerPlayedColumn = 2;
Chris@336:     m_modelNameColumn = 3;
Chris@336:     m_columnCount = 4;
Chris@336: 
Chris@336:     connect(stack, SIGNAL(paneAdded()), this, SLOT(paneAdded()));
Chris@336:     connect(stack, SIGNAL(paneAboutToBeDeleted(Pane *)),
Chris@336:             this, SLOT(paneAboutToBeDeleted(Pane *)));
Chris@336: 
Chris@336:     for (int i = 0; i < stack->getPaneCount(); ++i) {
Chris@336:         Pane *pane = stack->getPane(i);
Chris@336:         if (!pane) continue;
Chris@336:         connect(pane, SIGNAL(propertyContainerAdded(PropertyContainer *)),
Chris@336:                 this, SLOT(propertyContainerAdded(PropertyContainer *)));
Chris@336:         connect(pane, SIGNAL(propertyContainerRemoved(PropertyContainer *)),
Chris@336:                 this, SLOT(propertyContainerRemoved(PropertyContainer *)));
Chris@336:         connect(pane, SIGNAL(propertyContainerSelected(PropertyContainer *)),
Chris@336:                 this, SLOT(propertyContainerSelected(PropertyContainer *)));
Chris@336:         connect(pane, SIGNAL(propertyContainerPropertyChanged(PropertyContainer *)),
Chris@336:                 this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
Chris@336:         connect(pane, SIGNAL(propertyContainerNameChanged(PropertyContainer *)),
Chris@336:                 this, SLOT(propertyContainerPropertyChanged(PropertyContainer *)));
Chris@336:         connect(pane, SIGNAL(layerModelChanged()),
Chris@336:                 this, SLOT(paneLayerModelChanged()));
Chris@336: 
Chris@298:         for (int j = 0; j < pane->getLayerCount(); ++j) {
Chris@298:             Layer *layer = pane->getLayer(j);
Chris@298:             if (!layer) continue;
Chris@298:             PlayParameters *params = layer->getPlayParameters();
Chris@298:             if (!params) continue;
Chris@298:             connect(params, SIGNAL(playAudibleChanged(bool)),
Chris@298:                     this, SLOT(playParametersAudibilityChanged(bool)));
Chris@298:         }
Chris@298:     }
Chris@43: }
Chris@43: 
Chris@43: LayerTreeModel::~LayerTreeModel()
Chris@43: {
Chris@43: }
Chris@43: 
Chris@298: void
Chris@336: LayerTreeModel::paneAdded()
Chris@336: {
Chris@336:     emit layoutChanged();
Chris@336: }
Chris@336: 
Chris@336: void
Chris@336: LayerTreeModel::paneAboutToBeDeleted(Pane *pane)
Chris@336: {
Chris@682:     cerr << "paneDeleted: " << pane << endl;
Chris@336:     m_deletedPanes.insert(pane);
Chris@336:     emit layoutChanged();
Chris@336: }
Chris@336: 
Chris@336: void
Chris@298: LayerTreeModel::propertyContainerAdded(PropertyContainer *)
Chris@298: {
Chris@298:     emit layoutChanged();
Chris@298: }
Chris@298: 
Chris@298: void
Chris@298: LayerTreeModel::propertyContainerRemoved(PropertyContainer *)
Chris@298: {
Chris@298:     emit layoutChanged();
Chris@298: }
Chris@298: 
Chris@298: void
Chris@298: LayerTreeModel::propertyContainerSelected(PropertyContainer *)
Chris@298: {
Chris@298:     emit layoutChanged();
Chris@298: }
Chris@298: 
Chris@298: void
Chris@336: LayerTreeModel::paneLayerModelChanged()
Chris@336: {
Chris@336:     emit layoutChanged();
Chris@336: }
Chris@336: 
Chris@336: void
Chris@298: LayerTreeModel::propertyContainerPropertyChanged(PropertyContainer *pc)
Chris@298: {
Chris@298:     for (int i = 0; i < m_stack->getPaneCount(); ++i) {
Chris@298:         Pane *pane = m_stack->getPane(i);
Chris@298:         if (!pane) continue;
Chris@298:         for (int j = 0; j < pane->getLayerCount(); ++j) {
Chris@298:             if (pane->getLayer(j) == pc) {
Chris@298:                 emit dataChanged(createIndex(pane->getLayerCount() - j - 1,
Chris@336:                                              m_layerNameColumn, pane),
Chris@298:                                  createIndex(pane->getLayerCount() - j - 1,
Chris@336:                                              m_modelNameColumn, pane));
Chris@298:             }
Chris@298:         }
Chris@298:     }
Chris@298: }
Chris@298: 
Chris@298: void
Chris@298: LayerTreeModel::playParametersAudibilityChanged(bool a)
Chris@298: {
Chris@298:     PlayParameters *params = dynamic_cast<PlayParameters *>(sender());
Chris@298:     if (!params) return;
Chris@298: 
Chris@587:     SVDEBUG << "LayerTreeModel::playParametersAudibilityChanged("
Chris@585:               << params << "," << a << ")" << endl;
Chris@298: 
Chris@298:     for (int i = 0; i < m_stack->getPaneCount(); ++i) {
Chris@298:         Pane *pane = m_stack->getPane(i);
Chris@298:         if (!pane) continue;
Chris@298:         for (int j = 0; j < pane->getLayerCount(); ++j) {
Chris@298:             Layer *layer = pane->getLayer(j);
Chris@298:             if (!layer) continue;
Chris@298:             if (layer->getPlayParameters() == params) {
Chris@587:                 SVDEBUG << "LayerTreeModel::playParametersAudibilityChanged("
Chris@585:                           << params << "," << a << "): row " << pane->getLayerCount() - j - 1 << ", col " << 2 << endl;
Chris@298: 
Chris@298:                 emit dataChanged(createIndex(pane->getLayerCount() - j - 1,
Chris@336:                                              m_layerPlayedColumn, pane),
Chris@298:                                  createIndex(pane->getLayerCount() - j - 1,
Chris@336:                                              m_layerPlayedColumn, pane));
Chris@298:             }
Chris@298:         }
Chris@298:     }
Chris@298: }
Chris@298: 
Chris@43: QVariant
Chris@43: LayerTreeModel::data(const QModelIndex &index, int role) const
Chris@43: {
Chris@43:     if (!index.isValid()) return QVariant();
Chris@56: 
Chris@43:     QObject *obj = static_cast<QObject *>(index.internalPointer());
Chris@277:     int row = index.row(), col = index.column();
Chris@277: 
Chris@277:     Pane *pane = dynamic_cast<Pane *>(obj);
Chris@277:     if (!pane) {
Chris@277:         if (col == 0 && row < m_stack->getPaneCount()) {
Chris@277:             switch (role) {
Chris@277:             case Qt::DisplayRole:
Chris@277:                 return QVariant(QString("Pane %1").arg(row + 1));
Chris@277:             case Qt::DecorationRole:
Chris@277:                 return QVariant(QIcon(QString(":/icons/pane.png")));
Chris@277:             default: break;
Chris@277:             }
Chris@277:         }
Chris@43:     }
Chris@43: 
Chris@277:     if (pane && pane->getLayerCount() > row) {
Chris@298:         Layer *layer = pane->getLayer(pane->getLayerCount() - row - 1);
Chris@277:         if (layer) {
Chris@336:             if (col == m_layerNameColumn) {
Chris@277:                 switch (role) {
Chris@277:                 case Qt::DisplayRole:
Chris@277:                     return QVariant(layer->objectName());
Chris@277:                 case Qt::DecorationRole:
Chris@277:                     return QVariant
Chris@277:                         (QIcon(QString(":/icons/%1.png")
Chris@277:                                .arg(layer->getPropertyContainerIconName())));
Chris@277:                 default: break;
Chris@277:                 }
Chris@336:             } else if (col == m_layerVisibleColumn) {
Chris@298:                 if (role == Qt::CheckStateRole) {
Chris@298:                     return QVariant(layer->isLayerDormant(pane) ?
Chris@298:                                     Qt::Unchecked : Qt::Checked);
Chris@298:                 } else if (role == Qt::TextAlignmentRole) {
Chris@298:                     return QVariant(Qt::AlignHCenter);
Chris@298:                 }
Chris@336:             } else if (col == m_layerPlayedColumn) {
Chris@298:                 if (role == Qt::CheckStateRole) {
Chris@298:                     PlayParameters *params = layer->getPlayParameters();
Chris@298:                     if (params) return QVariant(params->isPlayMuted() ?
Chris@298:                                                 Qt::Unchecked : Qt::Checked);
Chris@298:                     else return QVariant();
Chris@298:                 } else if (role == Qt::TextAlignmentRole) {
Chris@298:                     return QVariant(Qt::AlignHCenter);
Chris@298:                 }
Chris@336:             } else if (col == m_modelNameColumn) {
Chris@277:                 Model *model = layer->getModel();
Chris@277:                 if (model && role == Qt::DisplayRole) {
Chris@277:                     return QVariant(model->objectName());
Chris@277:                 }
Chris@277:             }
Chris@277:         }
Chris@43:     }
Chris@43: 
Chris@43:     return QVariant();
Chris@43: }
Chris@43: 
Chris@298: bool
Chris@298: LayerTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
Chris@298: {
Chris@298:     if (!index.isValid()) return false;
Chris@298: 
Chris@298:     QObject *obj = static_cast<QObject *>(index.internalPointer());
Chris@298:     int row = index.row(), col = index.column();
Chris@298: 
Chris@298:     Pane *pane = dynamic_cast<Pane *>(obj);
Chris@298:     if (!pane || pane->getLayerCount() <= row) return false;
Chris@298: 
Chris@298:     Layer *layer = pane->getLayer(pane->getLayerCount() - row - 1);
Chris@298:     if (!layer) return false;
Chris@298: 
Chris@336:     if (col == m_layerVisibleColumn) {
Chris@298:         if (role == Qt::CheckStateRole) {
Chris@298:             layer->showLayer(pane, value.toInt() == Qt::Checked);
Chris@298:             emit dataChanged(index, index);
Chris@298:             return true;
Chris@298:         }
Chris@336:     } else if (col == m_layerPlayedColumn) {
Chris@298:         if (role == Qt::CheckStateRole) {
Chris@298:             PlayParameters *params = layer->getPlayParameters();
Chris@298:             if (params) {
Chris@298:                 params->setPlayMuted(value.toInt() == Qt::Unchecked);
Chris@298:                 emit dataChanged(index, index);
Chris@298:                 return true;
Chris@298:             }
Chris@298:         }
Chris@298:     }
Chris@298: 
Chris@298:     return false;
Chris@298: }
Chris@298: 
Chris@43: Qt::ItemFlags
Chris@43: LayerTreeModel::flags(const QModelIndex &index) const
Chris@43: {
Chris@298:     Qt::ItemFlags flags = Qt::ItemIsEnabled;
Chris@298:     if (!index.isValid()) return flags;
Chris@298: 
Chris@336:     if (index.column() == m_layerVisibleColumn ||
Chris@336:         index.column() == m_layerPlayedColumn) {
Chris@298:         flags |= Qt::ItemIsUserCheckable;
Chris@298:     } else if (index.column() == 0) {
Chris@298:         flags |= Qt::ItemIsSelectable;
Chris@298:     }
Chris@298: 
Chris@298:     return flags;
Chris@43: }
Chris@43: 
Chris@43: QVariant
Chris@56: LayerTreeModel::headerData(int section,
Chris@43: 			   Qt::Orientation orientation,
Chris@43: 			   int role) const
Chris@43: {
Chris@56:     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
Chris@336: 	if (section == m_layerNameColumn) return QVariant(tr("Layer"));
Chris@336:         else if (section == m_layerVisibleColumn) return QVariant(tr("Shown"));
Chris@336:         else if (section == m_layerPlayedColumn) return QVariant(tr("Played"));
Chris@336: 	else if (section == m_modelNameColumn) return QVariant(tr("Model"));
Chris@56:     }
Chris@56: 
Chris@56:     return QVariant();
Chris@43: }
Chris@43: 
Chris@43: QModelIndex
Chris@43: LayerTreeModel::index(int row, int column, const QModelIndex &parent) const
Chris@43: {
Chris@277:     // cell for a pane contains row, column, pane stack
Chris@277:     // -> its parent is the invalid cell
Chris@277: 
Chris@277:     // cell for a layer contains row, column, pane
Chris@277:     // -> its parent is row, column, pane stack (which identify the pane)
Chris@43: 
Chris@43:     if (!parent.isValid()) {
Chris@277:         if (row >= m_stack->getPaneCount() || column > 0) return QModelIndex();
Chris@43: 	return createIndex(row, column, m_stack);
Chris@43:     }
Chris@43: 
Chris@43:     QObject *obj = static_cast<QObject *>(parent.internalPointer());
Chris@277: 
Chris@277:     if (obj == m_stack) {
Chris@277:         Pane *pane = m_stack->getPane(parent.row());
Chris@277:         if (!pane || parent.column() > 0) return QModelIndex();
Chris@277:         return createIndex(row, column, pane);
Chris@43:     }
Chris@43: 
Chris@43:     return QModelIndex();
Chris@43: }
Chris@43: 
Chris@43: QModelIndex
Chris@43: LayerTreeModel::parent(const QModelIndex &index) const
Chris@43: {
Chris@43:     QObject *obj = static_cast<QObject *>(index.internalPointer());
Chris@43: 
Chris@336:     if (m_deletedPanes.find(obj) != m_deletedPanes.end()) {
Chris@336: //        m_deletedPanes.erase(obj);
Chris@336:         return QModelIndex();
Chris@336:     }
Chris@336: 
Chris@43:     Pane *pane = dynamic_cast<Pane *>(obj);
Chris@43:     if (pane) {
Chris@277:         int index = m_stack->getPaneIndex(pane);
Chris@277:         if (index >= 0) return createIndex(index, 0, m_stack);
Chris@43:     }
Chris@43: 
Chris@43:     return QModelIndex();
Chris@43: }
Chris@43: 
Chris@43: int
Chris@43: LayerTreeModel::rowCount(const QModelIndex &parent) const
Chris@43: {
Chris@277:     if (!parent.isValid()) return m_stack->getPaneCount();
Chris@43: 
Chris@43:     QObject *obj = static_cast<QObject *>(parent.internalPointer());
Chris@43:     
Chris@277:     if (obj == m_stack) {
Chris@277:         Pane *pane = m_stack->getPane(parent.row());
Chris@277:         if (!pane || parent.column() > 0) return 0;
Chris@277:         return pane->getLayerCount();
Chris@43:     }
Chris@43: 
Chris@43:     return 0;
Chris@43: }
Chris@43: 
Chris@43: int
Chris@43: LayerTreeModel::columnCount(const QModelIndex &parent) const
Chris@43: {
Chris@336:     if (!parent.isValid()) return m_columnCount;
Chris@43: 
Chris@43:     QObject *obj = static_cast<QObject *>(parent.internalPointer());
Chris@336:     if (obj == m_stack) return m_columnCount; // row for a layer
Chris@56: 
Chris@43:     return 1;
Chris@43: }
Chris@43: