KissCount/lib/libkdchart/src/KDChartDatasetProxyModel.cpp

301 lines
10 KiB
C++

/****************************************************************************
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#include "KDChartDatasetProxyModel.h"
#include <QtDebug>
#include <KDABLibFakes>
using namespace KDChart;
DatasetProxyModel::DatasetProxyModel (QObject* parent)
: QSortFilterProxyModel ( parent )
{
}
QModelIndex DatasetProxyModel::buddy( const QModelIndex& index ) const
{
return index;
}
Qt::ItemFlags DatasetProxyModel::flags( const QModelIndex& index ) const
{
return sourceModel()->flags( mapToSource( index ) );
}
void DatasetProxyModel::setDatasetRowDescriptionVector (
const DatasetDescriptionVector& configuration )
{
Q_ASSERT_X ( sourceModel(), "DatasetProxyModel::setDatasetRowDescriptionVector",
"A source model must be set before the selection can be configured." );
initializeDatasetDecriptors ( configuration, sourceModel()->rowCount(mRootIndex),
mRowSrcToProxyMap, mRowProxyToSrcMap );
clear(); // clear emits layoutChanged()
}
void DatasetProxyModel::setDatasetColumnDescriptionVector (
const DatasetDescriptionVector& configuration )
{
Q_ASSERT_X ( sourceModel(), "DatasetProxyModel::setDatasetColumnDescriptionVector",
"A source model must be set before the selection can be configured." );
initializeDatasetDecriptors ( configuration, sourceModel()->columnCount(mRootIndex),
mColSrcToProxyMap, mColProxyToSrcMap );
clear(); // clear emits layoutChanged()
}
void DatasetProxyModel::setDatasetDescriptionVectors (
const DatasetDescriptionVector& rowConfig,
const DatasetDescriptionVector& columnConfig )
{
setDatasetRowDescriptionVector( rowConfig );
setDatasetColumnDescriptionVector ( columnConfig );
}
QModelIndex DatasetProxyModel::index( int row, int column,
const QModelIndex &parent ) const
{
return mapFromSource( sourceModel()->index( mapProxyRowToSource(row),
mapProxyColumnToSource(column),
parent ) );
}
QModelIndex DatasetProxyModel::parent( const QModelIndex& child ) const
{
// return mapFromSource( sourceModel()->parent( child ) );
return mapFromSource( sourceModel()->parent( mapToSource( child ) ) );
}
QModelIndex DatasetProxyModel::mapFromSource ( const QModelIndex & sourceIndex ) const
{
Q_ASSERT_X ( sourceModel(), "DatasetProxyModel::mapFromSource", "A source "
"model must be set before the selection can be configured." );
if ( !sourceIndex.isValid() ) return sourceIndex;
if ( mRowSrcToProxyMap.isEmpty() && mColSrcToProxyMap.isEmpty() )
{
return createIndex ( sourceIndex.row(), sourceIndex.column(),
sourceIndex.internalPointer() );
} else {
int row = mapSourceRowToProxy ( sourceIndex.row() );
int column = mapSourceColumnToProxy ( sourceIndex.column() );
return createIndex ( row, column, sourceIndex.internalPointer() );
}
}
QModelIndex DatasetProxyModel::mapToSource ( const QModelIndex& proxyIndex ) const
{
Q_ASSERT_X ( sourceModel(), "DatasetProxyModel::mapToSource", "A source "
"model must be set before the selection can be configured." );
if ( !proxyIndex.isValid() ) return proxyIndex;
if ( mRowSrcToProxyMap.isEmpty() && mColSrcToProxyMap.isEmpty() )
{
return sourceModel()->index( proxyIndex.row(), proxyIndex.column(), mRootIndex );
} else {
int row = mapProxyRowToSource ( proxyIndex.row() );
int column = mapProxyColumnToSource ( proxyIndex.column() );
return sourceModel()->index( row, column, mRootIndex );
}
}
bool DatasetProxyModel::filterAcceptsRow ( int sourceRow,
const QModelIndex & ) const
{
if ( mRowSrcToProxyMap.isEmpty() )
{ // no row mapping set, all rows are passed down:
return true;
} else {
Q_ASSERT ( sourceModel() );
Q_ASSERT ( mRowSrcToProxyMap.size() == sourceModel()->rowCount(mRootIndex) );
if ( mRowSrcToProxyMap[sourceRow] == -1 )
{ // this row is explicitly not accepted:
return false;
} else {
Q_ASSERT ( mRowSrcToProxyMap[sourceRow] >= 0
&& mRowSrcToProxyMap[sourceRow] < mRowSrcToProxyMap.size() );
return true;
}
}
}
bool DatasetProxyModel::filterAcceptsColumn ( int sourceColumn,
const QModelIndex & ) const
{
if ( mColSrcToProxyMap.isEmpty() )
{ // no column mapping set up yet, all columns are passed down:
return true;
} else {
Q_ASSERT ( sourceModel() );
Q_ASSERT ( mColSrcToProxyMap.size() == sourceModel()->columnCount(mRootIndex) );
if ( mColSrcToProxyMap[sourceColumn] == -1 )
{ // this column is explicitly not accepted:
return false;
} else {
Q_ASSERT ( mColSrcToProxyMap[sourceColumn] >= 0
&& mColSrcToProxyMap[sourceColumn] < mColSrcToProxyMap.size() );
return true;
}
}
}
int DatasetProxyModel::mapProxyRowToSource ( const int& proxyRow ) const
{
if ( mRowProxyToSrcMap.isEmpty() )
{ // if no row mapping is set, we pass down the row:
return proxyRow;
} else {
Q_ASSERT ( proxyRow >= 0 && proxyRow < mRowProxyToSrcMap.size() );
return mRowProxyToSrcMap[ proxyRow ];
}
}
int DatasetProxyModel::mapProxyColumnToSource ( const int& proxyColumn ) const
{
if ( mColProxyToSrcMap.isEmpty() )
{ // if no column mapping is set, we pass down the column:
return proxyColumn;
} else {
Q_ASSERT ( proxyColumn >= 0 && proxyColumn < mColProxyToSrcMap.size() );
return mColProxyToSrcMap[ proxyColumn ];
}
}
int DatasetProxyModel::mapSourceRowToProxy ( const int& sourceRow ) const
{
if ( mRowSrcToProxyMap.isEmpty() )
{
return sourceRow;
} else {
Q_ASSERT ( sourceRow >= 0 && sourceRow < mRowSrcToProxyMap.size() );
return mRowSrcToProxyMap[sourceRow];
}
}
int DatasetProxyModel::mapSourceColumnToProxy ( const int& sourceColumn ) const
{
if ( mColSrcToProxyMap.isEmpty() )
{
return sourceColumn;
} else {
Q_ASSERT ( sourceColumn >= 0 && sourceColumn < mColSrcToProxyMap.size() );
return mColSrcToProxyMap.at( sourceColumn ) ;
}
}
void DatasetProxyModel::resetDatasetDescriptions()
{
mRowSrcToProxyMap.clear();
mRowProxyToSrcMap.clear();
mColSrcToProxyMap.clear();
mColProxyToSrcMap.clear();
clear();
}
QVariant DatasetProxyModel::data(const QModelIndex &index, int role) const
{
return sourceModel()->data( mapToSource ( index ), role );
}
bool DatasetProxyModel::setData( const QModelIndex& index, const QVariant& value, int role )
{
return sourceModel()->setData( mapToSource( index ), value, role );
}
QVariant DatasetProxyModel::headerData ( int section, Qt::Orientation orientation, int role ) const
{
if ( orientation == Qt::Horizontal )
{
if ( mapProxyColumnToSource ( section ) == -1 )
{
return QVariant();
} else {
return sourceModel()->headerData ( mapProxyColumnToSource ( section ),
orientation, role );
}
} else {
if ( mapProxyRowToSource ( section ) == -1 )
{
return QVariant();
} else {
return sourceModel()->headerData ( mapProxyRowToSource ( section ),
orientation, role );
}
}
}
void DatasetProxyModel::initializeDatasetDecriptors (
const DatasetDescriptionVector& inConfiguration,
const int sourceCount,
DatasetDescriptionVector& outSourceToProxyMap,
DatasetDescriptionVector& outProxyToSourceMap )
{
// in the current mapping implementation, the proxy-to-source map is
// identical to the configuration vector:
outProxyToSourceMap = inConfiguration;
outSourceToProxyMap.fill ( -1, sourceCount );
for ( int index = 0; index < inConfiguration.size(); ++index )
{
// make sure the values in inConfiguration point to columns in the
// source model:
if (inConfiguration[index] == -1)
continue;
Q_ASSERT_X ( inConfiguration[index] >= 0
&& inConfiguration[index] < sourceCount,
"DatasetProxyModel::initializeDatasetDecriptors",
"column index outside of source model" );
Q_ASSERT_X ( outSourceToProxyMap[inConfiguration[index]] == -1 ,
"DatasetProxyModel::initializeDatasetDecriptors",
"no duplicates allowed in mapping configuration, mapping has to be revertible" );
outSourceToProxyMap[inConfiguration[index]] = index;
}
}
void DatasetProxyModel::setSourceModel (QAbstractItemModel *m)
{
if ( sourceModel() ) {
disconnect ( sourceModel(), SIGNAL ( layoutChanged() ),
this, SLOT( resetDatasetDescriptions() ) );
}
QSortFilterProxyModel::setSourceModel ( m );
mRootIndex = QModelIndex();
if ( m ) {
connect ( m, SIGNAL ( layoutChanged() ),
this, SLOT( resetDatasetDescriptions() ) );
}
resetDatasetDescriptions();
}
void DatasetProxyModel::setSourceRootIndex(const QModelIndex& rootIdx)
{
mRootIndex = rootIdx;
resetDatasetDescriptions();
}