301 lines
10 KiB
C++
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();
|
||
|
}
|
||
|
|