soundeditor/qatsh/ATSPartialsFrameProxyModel.cpp

239 lines
7.8 KiB
C++

// 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 <jpmeuret@free.fr>
#include <iostream>
#include <QtGui/QItemSelection>
#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<ATSPartialsProxyModel*>(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<const ATSModelItem*>(miSource.internalPointer());
if (pmiSourceItem && pmiSourceItem->type() == ATSPartialItem::ePartial)
{
const ATSPartialItem *pmiPartItem =
static_cast<const ATSPartialItem*>(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<const ATSModelItem*>(miProxy.internalPointer())->type() : -1)
// << std::endl;
const ATSPartialsProxyModel* pSourceModel =
static_cast<const ATSPartialsProxyModel*>(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<const ATSModelItem*>(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<const ATSModelItem*>(miSource.internalPointer());
if (pmiSourceItem && pmiSourceItem->type() == ATSPartialItem::ePartial)
{
const ATSPartialItem *pmiPartItem =
static_cast<const ATSPartialItem*>(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<const ATSModelItem*>(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<ATSPartialsProxyModel*>(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<const ATSModelItem*>(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).
}