// ATSPartialsFrameProxyModel class definition // // ATS proxy model for the partials data associated to 1 given frame // (Row = Partial index, Column = property id) // // QATSH Copyright 2009 Jean-Philippe MEURET #include #include #include "ATSModelItems.h" #include "ATSPartialsProxyModel.h" #include "ATSPartialsFrameProxyModel.h" // Constructors / Destructor =============================================== ATSPartialsFrameProxyModel::ATSPartialsFrameProxyModel(QObject *parent) : ATSFrameProxyModel(parent) { } ATSPartialsFrameProxyModel::~ATSPartialsFrameProxyModel() { } // Get number of partials ================================================== int ATSPartialsFrameProxyModel::nbPartials() const { return static_cast(sourceModel())->nbPartials(); } // Proxy <-> Main model index conversions ================================== QModelIndex ATSPartialsFrameProxyModel::mapFromSource(const QModelIndex& miSource) const { // Is this really ever called ? if (miSource.isValid()) { const ATSModelItem *pmiSourceItem = static_cast(miSource.internalPointer()); if (pmiSourceItem && pmiSourceItem->type() == ATSPartialItem::ePartial) { const ATSPartialItem *pmiPartItem = static_cast(pmiSourceItem); // Here, we select the first column=property ... what else anyway ? return createIndex(pmiPartItem->partialIndex(), 0); } } return QModelIndex(); } // Implementation for source model = partials model QModelIndex ATSPartialsFrameProxyModel::mapToSource(const QModelIndex& miProxy) const { if (miProxy.isValid()) { // std::cout << "ATSPartialsFrameProxyModel::mapToSource : currFrameIdx = " // << _nCurrFrameIndex << ", miProxy = " // << miProxy.row() << ',' << miProxy.column() // << ':' << (miProxy.internalPointer() ? static_cast(miProxy.internalPointer())->type() : -1) // << std::endl; const ATSPartialsProxyModel* pSourceModel = static_cast(sourceModel()); QModelIndex miSource = pSourceModel->index(_nCurrFrameIndex, miProxy.column(), pSourceModel->index(0, miProxy.row(), QModelIndex())); // std::cout << "ATSPartialsFrameProxyModel::mapToSource : miSource = " // << miSource.row() << ',' << miSource.column() // << ':' << (miSource.internalPointer() ? static_cast(miSource.internalPointer())->type() : -1) // << std::endl; return pSourceModel->index(_nCurrFrameIndex, miProxy.column(), pSourceModel->index(0, miProxy.row(), QModelIndex())); } return QModelIndex(); } // Proxy <-> Main model selection conversions ============================== QItemSelection ATSPartialsFrameProxyModel::mapSelectionFromSource(const QItemSelection& isSource) const { // Specialized implementation, as we only consider whole partial selection here // (i.e. We consider all partial properties selected as soon as the partial is selected). // Question: Shouldn't this trick moved to the model manager ? QItemSelection isProxy; foreach (QModelIndex miSource, isSource.indexes()) { const ATSModelItem *pmiSourceItem = static_cast(miSource.internalPointer()); if (pmiSourceItem && pmiSourceItem->type() == ATSPartialItem::ePartial) { const ATSPartialItem *pmiPartItem = static_cast(pmiSourceItem); const QModelIndex miProxyFirst = createIndex(pmiPartItem->partialIndex(), 0); const QModelIndex miProxyLast = createIndex(pmiPartItem->partialIndex(), pmiPartItem->nbProperties() - 1); isProxy.select(miProxyFirst, miProxyLast); // std::cout << "ATSPartialsFrameProxyModel::mapSelectionToSource : miSource :" // << miSource.row() << ',' << miSource.column() // << ':' << static_cast(miSource.internalPointer())->type() // << std::endl; } } return isProxy; } QItemSelection ATSPartialsFrameProxyModel::mapSelectionToSource(const QItemSelection& isProxy) const { // Specialized implementation, as we only consider whole partial selection here // (i.e. We consider a partial is selected as soon as 1 property for 1 frame of it is). // Question: Shouldn't this trick moved to the model manager ? const ATSPartialsProxyModel* pSourceModel = static_cast(sourceModel()); QItemSelection isSource; foreach (QModelIndex miProxy, isProxy.indexes()) { const QModelIndex miSource = pSourceModel->index(0, miProxy.row(), QModelIndex()); if (!isSource.contains(miSource)) isSource.select(miSource, miSource); // std::cout << "ATSPartialsFrameProxyModel::mapSelectionToSource : miSource :" // << miSource.row() << ',' << miSource.column() // << ':' << static_cast(miSource.internalPointer())->type() // << std::endl; } return isSource; } // QAbstractItemModel implementation ======================================= QModelIndex ATSPartialsFrameProxyModel::index(int row, int column, const QModelIndex &miParent) const { if (!miParent.isValid()) // Only the root item is supported. { return createIndex(row, column); // And (row, column) is sufficient as an identifier. } return QModelIndex(); } QVariant ATSPartialsFrameProxyModel::data(const QModelIndex &miIndex, int role) const { // Note: Here, we specialize standard QAbstractModelItem::data(...) implementation // only to be able to format each column in a different and customized way. QVariant qvValue; // Get data to display and format it smartly but differently for each column if (role == Qt::DisplayRole) { const double dValue = sourceModel()->data(mapToSource(miIndex), role).toDouble(); switch ((ATSPartialItem::EPropertyId)miIndex.column()) { case ATSPartialItem::ePropFrequency: qvValue = QString::number(dValue, 'f', 2); break; case ATSPartialItem::ePropAmplitude: qvValue = QString::number(dValue, 'f', 6); break; case ATSPartialItem::ePropPhase: qvValue = QString::number(dValue, 'f', 3); break; case ATSPartialItem::ePropSMR: qvValue = QString::number(dValue, 'f', 1); break; // As columnCount() returns ePropNumber - 1, should never happen. case ATSPartialItem::ePropTime: break; // N/A. case ATSPartialItem::ePropNumber: break; } } // Always align right (we only have numerical values). else if (role == Qt::TextAlignmentRole) qvValue = Qt::AlignRight; return qvValue; } int ATSPartialsFrameProxyModel::columnCount(const QModelIndex &miParent) const { int nCount = 0; if (!miParent.isValid()) // Only the root item is supported. { nCount = ATSPartialItem::nbProperties() - 1; // We don't display the "time" column. } // std::cout << "ATSPartialsFrameProxyModel::columnCount(" // << miParent.row() << ',' << miParent.column() // << ':' << miParent.internalPointer() << ") = " << nCount << std::endl; return nCount; } int ATSPartialsFrameProxyModel::rowCount(const QModelIndex &miParent) const { int nCount = 0; if (!miParent.isValid()) // Only the root item is supported. { nCount = nbPartials(); } // std::cout << "ATSPartialsFrameProxyModel::rowCount(" // << miParent.row() << ',' << miParent.column() // << ':' << miParent.internalPointer() << ") = " << nCount << std::endl; return nCount; } QVariant ATSPartialsFrameProxyModel::headerData(int section, Qt::Orientation orientation, int role) const { switch (orientation) { case Qt::Horizontal: if (role == Qt::DisplayRole) return ATSPartialItem::propertyName((ATSPartialItem::EPropertyId)section); else if (role == Qt::ToolTipRole) return ATSPartialItem::propertyToolTip((ATSPartialItem::EPropertyId)section); case Qt::Vertical: if (role == Qt::DisplayRole) return section+1; } return QVariant(); } QModelIndex ATSPartialsFrameProxyModel::parent(const QModelIndex &miChild) const { return QModelIndex(); // No parent here (flat model). }