// 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 #include #include #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(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(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(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(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(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(miParent.internalPointer()); if (pmiParentItem && pmiParentItem->type() == ATSModelItem::ePartial) { // Row = frame index, Column = property id const ATSPartialItem *pmiPartItem = static_cast(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(sourceModel()); return pSourceModel->rootItem()->partials()->count(); } // If parent is not the root item const ATSModelItem *pmiParent = static_cast(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(miParent.internalPointer()); if (pmiParent && pmiParent->type() == ATSModelItem::ePartial) { const ATSPartialItem *pmiPart = static_cast(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(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(qmiToCopy.internalPointer())->type() == ATSModelItem::ePartial) nCopyIndex = qmiToCopy.column(); // Add the partial. ATSModel* pSourceModel = static_cast(sourceModel()); pSourceModel->sound()->addPartial(nCopyIndex); // Re-initialize the dedicated part of the source model. pSourceModel->reInitialize(ATSModel::ePartialsListOnly); // Warn everyone that the model heavily changed. beginResetModel(); endResetModel(); } 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(qmiToRemove.internalPointer())->type() == ATSModelItem::ePartial) { aToRemoveIndexes[nToRemoveIndex] = qmiToRemove.column(); nPartsToRemove++; } } // Remove the selected partials. ATSModel* pSourceModel = static_cast(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. beginResetModel(); endResetModel(); } 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(qmiToModify.internalPointer())->type() == ATSModelItem::ePartial) { aToModifyIndexes[nToModifyIndex] = qmiToModify.column(); nPartsToModify++; } } // Modify the selected partials. ATSModel* pSourceModel = static_cast(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. beginResetModel(); endResetModel(); return strParsedFormula; }