soundeditor/qatsh/ATSModel.cpp

367 lines
10 KiB
C++
Raw Normal View History

// ATSModel class implementation
//
// The ATS document "model" (in the Qt 4 meaning)
//
// QATSH Copyright 2009 Jean-Philippe MEURET <jpmeuret@free.fr>
#include <iostream>
#include <QModelIndex>
#include "ATSModel.h"
#include "ATSModelItems.h"
#include "ATSSound.h"
// Constructors / Destructor ===============================================
ATSModel::ATSModel(QObject *parent)
: QAbstractItemModel(parent), _pATSSound(0), _pmiRootItem(0)
{
}
ATSModel::~ATSModel()
{
if (_pmiRootItem)
{
delete _pmiRootItem;
_pmiRootItem = 0;
}
if (_pATSSound)
delete _pATSSound;
}
// ATS sound accessors ======================================================
void ATSModel::setSound(ATSSound* pSound)
{
if (_pATSSound)
delete _pATSSound;
_pATSSound = pSound;
if (_pATSSound)
{
reInitialize();
_pATSSound->dump("Analysed ", std::cout);
}
}
ATSSound* ATSModel::sound()
{
return _pATSSound;
}
// Item model (re-)initialization =======================================
void ATSModel::reInitialize(EReInitType eReInitType) // Don't call before load() or setSound()
{
//std::cout << "ATSModel::reInitialize(" << eReInitType << ")" << std::endl;
switch (eReInitType)
{
case eEverything:
beginResetModel();
if (_pmiRootItem)
delete _pmiRootItem;
_pmiRootItem = new ATSRootItem(_pATSSound);
// Warn attached views and proxy models that the whole model has changed.
endResetModel();
break;
case ePartialsListOnly:
// Rebuild partials list.
_pmiRootItem->resetPartials();
// Warn attached views/proxy models of the changes.
const QModelIndex qmiPartials = index(1, 0, QModelIndex());
emit dataChanged(qmiPartials, qmiPartials);
const QModelIndex qmiProps = index(0, 0, QModelIndex());
emit dataChanged(index(0, ATSFilePropertiesItem::eSoundPropNbPartials, qmiProps),
index(0, ATSFilePropertiesItem::eSoundPropMaxPartialFrequency, qmiProps));
break;
}
}
// Model load from .ats file =============================================
bool ATSModel::load(const QString& qsATSFileName)
{
if (_pATSSound)
delete _pATSSound;
_pATSSound = new ATSSound();
const bool bLoaded = _pATSSound->load(qsATSFileName.toStdString().c_str());
if (bLoaded)
{
reInitialize();
_pATSSound->dump("Loaded ", std::cout);
}
return bLoaded;
}
// Model store to .ats file ================================================
bool ATSModel::store(const QString& qsATSFileName) const
{
_pATSSound->dump("Storing ", std::cout);
return _pATSSound->store(qsATSFileName.toStdString().c_str());
}
// Direct accessors to the root item =======================================
ATSRootItem* ATSModel::rootItem()
{
return _pmiRootItem;
}
// QAbstractItemModel implementation =======================================
Qt::ItemFlags ATSModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QModelIndex ATSModel::index(int row, int column, const QModelIndex &miParent) const
{
// If parent is the root item
if (!miParent.isValid())
{
switch (row) // Column ignored (should always be 0 according to columnCount()).
{
// Row 0 = Sound Properties
case 0:
return createIndex(0, 0, _pmiRootItem->fileProperties());
// Row 1 = Partials
case 1:
return createIndex(1, 0, _pmiRootItem->partials());
// Row 2 = Residual (Noise) bands
case 2:
return createIndex(2, 0, _pmiRootItem->residualBands());
// Nothing else.
default:
return QModelIndex();
}
}
// If parent is not the root item
const ATSModelItem *pmiParent =
static_cast<const ATSModelItem*>(miParent.internalPointer());
if (pmiParent)
{
switch (pmiParent->type())
{
case ATSModelItem::eFileProperties: // Row ignored, Column = property id
if (column >= 0 && column < ATSFilePropertiesItem::eSoundPropNumber)
return createIndex(0, column, miParent.internalPointer());
else
return QModelIndex();
case ATSModelItem::ePartials: // Row ignored, Column = partial index
if (column >= 0 && column < _pmiRootItem->partials()->count())
return createIndex(0, column, _pmiRootItem->partials()->partial(column));
else
return QModelIndex();
case ATSModelItem::eResidualBands:// Row ignored, Column = residual band index
if (column >= 0 && column < _pmiRootItem->residualBands()->count())
return createIndex(0, column, _pmiRootItem->residualBands()->residualBand(column));
else
return QModelIndex();
case ATSModelItem::ePartial: // Row = frame index, Column = property id
{
const ATSPartialItem *pmiPart =
static_cast<const ATSPartialItem*>(pmiParent);
if (row >= 0 && row < pmiPart->nbFrames()
&& column >= 0 && column < ATSPartialItem::nbProperties())
return createIndex(row, column, miParent.internalPointer());
else
return QModelIndex();
}
case ATSModelItem::eResidualBand: // Row = frame index, Column = property id
{
const ATSResidualBandItem *pmiResid =
static_cast<const ATSResidualBandItem*>(pmiParent);
if (row >= 0 && row < pmiResid->nbFrames()
&& column >= 0 && column < ATSResidualBandItem::nbProperties())
return createIndex(row, column, miParent.internalPointer());
else
return QModelIndex();
}
default:
return QModelIndex();
}
}
return QModelIndex();
}
QVariant ATSModel::data(const QModelIndex &miIndex, int role) const
{
if (!miIndex.isValid())
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
const ATSModelItem *pmiItem = static_cast<const ATSModelItem*>(miIndex.internalPointer());
if (pmiItem)
{
switch (pmiItem->type())
{
case ATSModelItem::eFileProperties: // Row ignored, Column = property id
{
const ATSFilePropertiesItem *pmiPropsItem =
static_cast<const ATSFilePropertiesItem*>(pmiItem);
return pmiPropsItem->property((ATSFilePropertiesItem::ESoundPropertyId)miIndex.column());
}
case ATSModelItem::ePartial: // Row = frame, Column = property id
{
const ATSPartialItem *pmiPartItem =
static_cast<const ATSPartialItem*>(pmiItem);
return pmiPartItem->property(miIndex.row(),
(ATSPartialItem::EPropertyId)miIndex.column());
}
case ATSModelItem::eResidualBand: // Row = 2 => Column = Frame index (frame energy)
{
const ATSResidualBandItem *pmiResidItem =
static_cast<const ATSResidualBandItem*>(pmiItem);
return pmiResidItem->property(miIndex.row(),
(ATSResidualBandItem::EPropertyId)miIndex.column());
}
default:
return QVariant();
}
}
return QVariant();
}
int ATSModel::columnCount(const QModelIndex &miParent) const
{
// If parent is the root item
if (!miParent.isValid())
return 1;
// If parent is not the root item
const ATSModelItem *pmiParent = static_cast<const ATSModelItem*>(miParent.internalPointer());
if (pmiParent)
{
switch (pmiParent->type())
{
case ATSModelItem::eFileProperties: // Column = property id
return ATSFilePropertiesItem::eSoundPropNumber;
case ATSModelItem::ePartials: // Column = partial index
{
const ATSPartialsItem *pmiParts =
static_cast<const ATSPartialsItem*>(pmiParent);
return pmiParts->count();
}
case ATSModelItem::eResidualBands: // Column = residual band index
{
const ATSResidualBandsItem *pmiResids =
static_cast<const ATSResidualBandsItem*>(pmiParent);
return pmiResids->count();
}
case ATSModelItem::ePartial: // Column = property id
return ATSPartialItem::nbProperties();
case ATSModelItem::eResidualBand: // Column = property id
return ATSResidualBandItem::nbProperties();
default:
return 0;
}
}
return 0;
}
int ATSModel::rowCount(const QModelIndex &miParent) const
{
// If parent is the root item
if (!miParent.isValid())
{
return 2 + (_pmiRootItem->residualBands()->count() > 0 ? 1 : 0);
}
// If parent is not the root item
const ATSModelItem *pmiParent = static_cast<const ATSModelItem*>(miParent.internalPointer());
if (pmiParent)
{
switch (pmiParent->type())
{
case ATSModelItem::eFileProperties: // Only 1 row (list of properties)
return 1;
case ATSModelItem::ePartials: // Only 1 row (list of partials)
return 1;
case ATSModelItem::eResidualBands: // Only 1 row (list of residual bands)
return 1;
case ATSModelItem::ePartial: // Row = frame index (matrix: frame, property)
{
const ATSPartialItem *pmiPart =
static_cast<const ATSPartialItem*>(pmiParent);
return pmiPart->nbFrames();
}
case ATSModelItem::eResidualBand: // Row = frame index (matrix: frame, property)
{
const ATSResidualBandItem *pmiResid =
static_cast<const ATSResidualBandItem*>(pmiParent);
return pmiResid->nbFrames();
}
default:
return 0;
}
}
return 0;
}
QModelIndex ATSModel::parent(const QModelIndex &miChild) const
{
// Note: MUST be implemented at least for QItemSelection::indexes() (undocumented).
if (miChild.isValid() && miChild.internalPointer())
{
const ATSModelItem *pmiChild =
static_cast<const ATSModelItem*>(miChild.internalPointer());
switch (pmiChild->type())
{
case ATSModelItem::ePartial:
return createIndex(1, 0, _pmiRootItem->partials());
case ATSModelItem::eResidualBand:
return createIndex(2, 0, _pmiRootItem->residualBands());
default:
return QModelIndex();
}
}
return QModelIndex();
}