annotate widgets/LayerTree.cpp @ 312:6de6f78b13a1

* Make it possible to drop audio files, layer files, session files and images onto SV panes. Need to do a bit more work on where we expect the dropped file to go, particularly in the case of audio files -- at the moment they're always opened in new panes, but it may be better to by default replace whatever is in the target pane.
author Chris Cannam
date Wed, 10 Oct 2007 15:18:02 +0000
parents 226cb289bdf4
children 4a542ba875c2
rev   line source
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