282 lines
8.9 KiB
C++
282 lines
8.9 KiB
C++
// ATSPartialsProxyModel class definition
|
|
//
|
|
// ATS proxy model for the partials data of the ATS model :
|
|
// - at the root level, a list of ATSPartialItem (1 row, nPartials columns)
|
|
// - for a given ATSPartialItem, Row = Frame, Column = property id)
|
|
//
|
|
// QATSH Copyright 2009 Jean-Philippe MEURET <jpmeuret@free.fr>
|
|
|
|
#include <iostream>
|
|
|
|
#include <QtGui/QItemSelection>
|
|
|
|
#include "TypesAndConstants.h"
|
|
#include "ATSModel.h"
|
|
#include "ATSModelItems.h"
|
|
#include "ATSPartialsProxyModel.h"
|
|
|
|
|
|
// Constructors / Destructor ===============================================
|
|
ATSPartialsProxyModel::ATSPartialsProxyModel(QObject *parent)
|
|
: ATSDataProxyModel(parent)
|
|
{
|
|
}
|
|
|
|
ATSPartialsProxyModel::~ATSPartialsProxyModel()
|
|
{
|
|
}
|
|
|
|
// Proxy <-> Main model index conversions ==================================
|
|
QModelIndex ATSPartialsProxyModel::mapFromSource(const QModelIndex& miSource) const
|
|
{
|
|
if (miSource.isValid())
|
|
{
|
|
const ATSModelItem *pmiSourceItem =
|
|
static_cast<const ATSModelItem*>(miSource.internalPointer());
|
|
switch (pmiSourceItem->type())
|
|
{
|
|
case ATSModelItem::ePartials: // Row ignored, Column = partial index
|
|
return createIndex(miSource.row(), miSource.column());
|
|
|
|
case ATSModelItem::ePartial: // Row = frame index, Column = property id
|
|
return miSource;
|
|
|
|
default:
|
|
return QModelIndex();
|
|
}
|
|
}
|
|
|
|
return QModelIndex();
|
|
}
|
|
|
|
QModelIndex ATSPartialsProxyModel::mapToSource(const QModelIndex& miProxy) const
|
|
{
|
|
if (miProxy.isValid())
|
|
{
|
|
// If proxy parent is the root item => PartialsItem
|
|
if (!miProxy.internalPointer())
|
|
{
|
|
ATSPartialsItem* pPartsItem =
|
|
static_cast<ATSModel*>(sourceModel())->rootItem()->partials();
|
|
if (miProxy.row() == 0
|
|
&& miProxy.column() >= 0 && miProxy.column() < pPartsItem->count())
|
|
return createIndex(0, miProxy.column(), pPartsItem->partial(miProxy.column()));
|
|
else
|
|
return QModelIndex();
|
|
}
|
|
|
|
// If proxy parent is not the root item => PartialItem
|
|
else
|
|
{
|
|
const ATSPartialItem *pmiPartItem =
|
|
static_cast<const ATSPartialItem*>(miProxy.internalPointer());
|
|
if (pmiPartItem && pmiPartItem->type() == ATSModelItem::ePartial)
|
|
return miProxy;
|
|
}
|
|
}
|
|
|
|
return QModelIndex();
|
|
}
|
|
|
|
// Proxy <-> Main model selection conversions ==============================
|
|
QItemSelection ATSPartialsProxyModel::mapSelectionFromSource(const QItemSelection& isSource) const
|
|
{
|
|
QItemSelection isProxy;
|
|
foreach (QModelIndex miSource, isSource.indexes())
|
|
{
|
|
const ATSModelItem *pmiSourceItem =
|
|
static_cast<const ATSModelItem*>(miSource.internalPointer());
|
|
if (pmiSourceItem)
|
|
{
|
|
// std::cout << "ATSPartialsProxyModel::mapSelectionFromSource : src :"
|
|
// << miSource.row() << ',' << miSource.column()
|
|
// << ':' << pmiSourceItem->type() << std::endl;
|
|
switch (pmiSourceItem->type())
|
|
{
|
|
case ATSModelItem::ePartial:
|
|
{
|
|
// Note: Here we recreate the index to be sure it belongs to this model.
|
|
const QModelIndex miProxy =
|
|
createIndex(miSource.row(), miSource.column(), miSource.internalPointer());
|
|
if (!isProxy.contains(miProxy))
|
|
isProxy.select(miProxy, miProxy);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return isProxy;
|
|
}
|
|
|
|
// QAbstractItemModel implementation =======================================
|
|
QModelIndex ATSPartialsProxyModel::index(int row, int column, const QModelIndex &miParent) const
|
|
{
|
|
// If parent is the root item, column = partial index.
|
|
if (!miParent.isValid())
|
|
{
|
|
ATSPartialsItem* pPartsItem =
|
|
static_cast<ATSModel*>(sourceModel())->rootItem()->partials();
|
|
if (row == 0 && column >= 0 && column < pPartsItem->count())
|
|
return createIndex(0, column, pPartsItem->partial(column));
|
|
else
|
|
return QModelIndex();
|
|
}
|
|
|
|
// If parent is not the root item, row = frame index, column = partial frame property id.
|
|
const ATSModelItem *pmiParentItem =
|
|
static_cast<const ATSModelItem*>(miParent.internalPointer());
|
|
|
|
if (pmiParentItem && pmiParentItem->type() == ATSModelItem::ePartial)
|
|
{
|
|
// Row = frame index, Column = property id
|
|
const ATSPartialItem *pmiPartItem =
|
|
static_cast<const ATSPartialItem*>(miParent.internalPointer());
|
|
if (row >= 0 && row < pmiPartItem->nbFrames()
|
|
&& column >= 0 && column < ATSPartialItem::nbProperties())
|
|
return createIndex(row, column, miParent.internalPointer());
|
|
else
|
|
return QModelIndex();
|
|
}
|
|
|
|
return QModelIndex();
|
|
}
|
|
|
|
int ATSPartialsProxyModel::columnCount(const QModelIndex &miParent) const
|
|
{
|
|
if (!miParent.isValid())
|
|
{
|
|
ATSModel* pSourceModel = static_cast<ATSModel*>(sourceModel());
|
|
return pSourceModel->rootItem()->partials()->count();
|
|
}
|
|
|
|
// If parent is not the root item
|
|
const ATSModelItem *pmiParent = static_cast<const ATSModelItem*>(miParent.internalPointer());
|
|
if (pmiParent && pmiParent->type() == ATSModelItem::ePartial)
|
|
// Column = property id
|
|
return ATSPartialItem::nbProperties();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int ATSPartialsProxyModel::rowCount(const QModelIndex &miParent) const
|
|
{
|
|
if (!miParent.isValid())
|
|
{
|
|
return 1; // Column = Partials, 1 row => the partials list
|
|
}
|
|
|
|
// If parent is not the root item
|
|
const ATSModelItem *pmiParent = static_cast<const ATSModelItem*>(miParent.internalPointer());
|
|
if (pmiParent && pmiParent->type() == ATSModelItem::ePartial)
|
|
{
|
|
const ATSPartialItem *pmiPart = static_cast<const ATSPartialItem*>(pmiParent);
|
|
return pmiPart->nbFrames();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
QModelIndex ATSPartialsProxyModel::parent(const QModelIndex &miChild) const
|
|
{
|
|
return QModelIndex(); // 2 level model => always the same parent
|
|
}
|
|
|
|
// Get number of partials ==================================================
|
|
int ATSPartialsProxyModel::nbPartials() const
|
|
{
|
|
return static_cast<ATSModel*>(sourceModel())->rootItem()->partials()->count();
|
|
}
|
|
|
|
// Add/remove partials in the model =======================================
|
|
void ATSPartialsProxyModel::addPartial(const QModelIndex& qmiToCopy)
|
|
{
|
|
// Translate model index to ATSSound partial index (ignore non ePartial type index)
|
|
int nCopyIndex = -1; // Invalid index.
|
|
if (qmiToCopy.isValid()&& qmiToCopy.internalPointer()
|
|
&& static_cast<const ATSModelItem*>(qmiToCopy.internalPointer())->type()
|
|
== ATSModelItem::ePartial)
|
|
nCopyIndex = qmiToCopy.column();
|
|
|
|
// Add the partial.
|
|
ATSModel* pSourceModel = static_cast<ATSModel*>(sourceModel());
|
|
pSourceModel->sound()->addPartial(nCopyIndex);
|
|
|
|
// Re-initialize the dedictated part of the source model.
|
|
pSourceModel->reInitialize(ATSModel::ePartialsListOnly);
|
|
|
|
// Warn everyone that the model heavily changed.
|
|
reset();
|
|
}
|
|
|
|
void ATSPartialsProxyModel::removePartials(const QModelIndexList& qlmiToRemove)
|
|
{
|
|
// Convert this model indexes to ATSSound indexes (ignore non-ePartial type indexes).
|
|
int* aToRemoveIndexes = new int[qlmiToRemove.size()];
|
|
int nPartsToRemove = 0;
|
|
for (int nToRemoveIndex = 0; nToRemoveIndex < qlmiToRemove.size(); nToRemoveIndex++)
|
|
{
|
|
const QModelIndex qmiToRemove = qlmiToRemove.at(nToRemoveIndex);
|
|
if (qmiToRemove.isValid() && qmiToRemove.internalPointer()
|
|
&& static_cast<const ATSModelItem*>(qmiToRemove.internalPointer())->type()
|
|
== ATSModelItem::ePartial)
|
|
{
|
|
aToRemoveIndexes[nToRemoveIndex] = qmiToRemove.column();
|
|
nPartsToRemove++;
|
|
}
|
|
}
|
|
|
|
// Remove the selected partials.
|
|
ATSModel* pSourceModel = static_cast<ATSModel*>(sourceModel());
|
|
pSourceModel->sound()->removePartials(aToRemoveIndexes, nPartsToRemove);
|
|
|
|
// Delete now useless ATSSound indexes.
|
|
delete[] aToRemoveIndexes;
|
|
|
|
// Re-initialize the dedictated part of the source model.
|
|
pSourceModel->reInitialize(ATSModel::ePartialsListOnly);
|
|
|
|
// Warn everyone that the model heavily changed.
|
|
reset();
|
|
}
|
|
|
|
std::string ATSPartialsProxyModel::modifyPartials(const QModelIndexList& qlmiToModify,
|
|
const QString& qsFormula,
|
|
TypesAndConstants::EPartialMagnitude eMagnitude)
|
|
{
|
|
// Convert this model indexes to ATSSound indexes (ignore non-ePartial type indexes).
|
|
int* aToModifyIndexes = new int[qlmiToModify.size()];
|
|
int nPartsToModify = 0;
|
|
for (int nToModifyIndex = 0; nToModifyIndex < qlmiToModify.size(); nToModifyIndex++)
|
|
{
|
|
const QModelIndex qmiToModify = qlmiToModify.at(nToModifyIndex);
|
|
if (qmiToModify.isValid() && qmiToModify.internalPointer()
|
|
&& static_cast<const ATSModelItem*>(qmiToModify.internalPointer())->type()
|
|
== ATSModelItem::ePartial)
|
|
{
|
|
aToModifyIndexes[nToModifyIndex] = qmiToModify.column();
|
|
nPartsToModify++;
|
|
}
|
|
}
|
|
|
|
// Modify the selected partials.
|
|
ATSModel* pSourceModel = static_cast<ATSModel*>(sourceModel());
|
|
std::string strParsedFormula =
|
|
pSourceModel->sound()->modifyPartials(aToModifyIndexes, nPartsToModify,
|
|
qsFormula.toStdString(), eMagnitude);
|
|
|
|
// Delete now useless ATSSound indexes.
|
|
delete[] aToModifyIndexes;
|
|
|
|
// Re-initialize the dedicated part of the source model.
|
|
pSourceModel->reInitialize(ATSModel::ePartialsListOnly);
|
|
|
|
// Warn everyone that the model heavily changed.
|
|
reset();
|
|
|
|
return strParsedFormula;
|
|
}
|