File indexing completed on 2024-05-12 04:20:32

0001 /*
0002  * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
0003  *
0004  * This file is part of the KD Chart library.
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "KChartDatasetProxyModel.h"
0010 
0011 #include "KChartMath_p.h"
0012 
0013 #include <QtDebug>
0014 
0015 
0016 using namespace KChart;
0017 
0018 DatasetProxyModel::DatasetProxyModel(QObject* parent)
0019     : QSortFilterProxyModel( parent )
0020 {
0021 }
0022 
0023 QModelIndex DatasetProxyModel::buddy( const QModelIndex& index ) const
0024 {
0025     return index;
0026 }
0027 
0028 Qt::ItemFlags DatasetProxyModel::flags( const QModelIndex& index ) const
0029 {
0030     return sourceModel()->flags( mapToSource( index ) );
0031 }
0032 
0033 void DatasetProxyModel::setDatasetRowDescriptionVector(
0034     const DatasetDescriptionVector& configuration )
0035 {
0036     Q_ASSERT_X( sourceModel(), "DatasetProxyModel::setDatasetRowDescriptionVector",
0037                 "A source model must be set before the selection can be configured." );
0038     initializeDatasetDecriptors( configuration, sourceModel()->rowCount(mRootIndex),
0039                                  mRowSrcToProxyMap,  mRowProxyToSrcMap );
0040     invalidate(); // clear emits layoutChanged()
0041 }
0042 
0043 void DatasetProxyModel::setDatasetColumnDescriptionVector(
0044     const DatasetDescriptionVector& configuration )
0045 {
0046     Q_ASSERT_X( sourceModel(), "DatasetProxyModel::setDatasetColumnDescriptionVector",
0047                 "A source model must be set before the selection can be configured." );
0048     initializeDatasetDecriptors( configuration, sourceModel()->columnCount(mRootIndex),
0049                                  mColSrcToProxyMap, mColProxyToSrcMap );
0050     invalidate(); // clear emits layoutChanged()
0051 }
0052 
0053 void DatasetProxyModel::setDatasetDescriptionVectors(
0054     const DatasetDescriptionVector& rowConfig,
0055     const DatasetDescriptionVector& columnConfig )
0056 {
0057     setDatasetRowDescriptionVector( rowConfig );
0058     setDatasetColumnDescriptionVector( columnConfig );
0059 }
0060 
0061 QModelIndex DatasetProxyModel::index( int row, int column,
0062                                       const QModelIndex &parent ) const
0063 {
0064     return mapFromSource( sourceModel()->index( mapProxyRowToSource(row),
0065                                                 mapProxyColumnToSource(column),
0066                                                 parent ) );
0067 }
0068 
0069 QModelIndex DatasetProxyModel::parent( const QModelIndex& child ) const
0070 {
0071 //    return mapFromSource( sourceModel()->parent( child ) );
0072     return mapFromSource( sourceModel()->parent( mapToSource( child ) ) );
0073 }
0074 
0075 QModelIndex DatasetProxyModel::mapFromSource( const QModelIndex & sourceIndex ) const
0076 {
0077     Q_ASSERT_X( sourceModel(), "DatasetProxyModel::mapFromSource", "A source "
0078                 "model must be set before the selection can be configured." );
0079 
0080     if ( !sourceIndex.isValid() ) return sourceIndex;
0081 
0082     if ( mRowSrcToProxyMap.isEmpty() && mColSrcToProxyMap.isEmpty() )
0083     {
0084         return createIndex( sourceIndex.row(), sourceIndex.column(),
0085                             sourceIndex.internalPointer() );
0086     } else {
0087         int row = mapSourceRowToProxy( sourceIndex.row() );
0088         int column = mapSourceColumnToProxy( sourceIndex.column() );
0089         return createIndex( row, column, sourceIndex.internalPointer() );
0090     }
0091 }
0092 
0093 QModelIndex DatasetProxyModel::mapToSource( const QModelIndex& proxyIndex ) const
0094 {
0095     Q_ASSERT_X( sourceModel(), "DatasetProxyModel::mapToSource", "A source "
0096                 "model must be set before the selection can be configured." );
0097 
0098     if ( !proxyIndex.isValid() ) return proxyIndex;
0099     if ( mRowSrcToProxyMap.isEmpty() && mColSrcToProxyMap.isEmpty() )
0100     {
0101         return sourceModel()->index( proxyIndex.row(),  proxyIndex.column(), mRootIndex );
0102     } else {
0103         int row = mapProxyRowToSource( proxyIndex.row() );
0104         int column = mapProxyColumnToSource( proxyIndex.column() );
0105         return sourceModel()->index( row, column, mRootIndex );
0106     }
0107 }
0108 
0109 bool DatasetProxyModel::filterAcceptsRow( int sourceRow,
0110                                           const QModelIndex & ) const
0111 {
0112     if ( mRowSrcToProxyMap.isEmpty() )
0113     {   // no row mapping set, all rows are passed down:
0114         return true;
0115     } else {
0116         Q_ASSERT( sourceModel() );
0117         Q_ASSERT( mRowSrcToProxyMap.size() == sourceModel()->rowCount(mRootIndex) );
0118         if ( mRowSrcToProxyMap[sourceRow] == -1 )
0119         {   // this row is explicitly not accepted:
0120             return false;
0121         } else {
0122             Q_ASSERT( mRowSrcToProxyMap[sourceRow] >= 0
0123                       && mRowSrcToProxyMap[sourceRow] < mRowSrcToProxyMap.size() );
0124             return true;
0125         }
0126     }
0127 }
0128 
0129 bool DatasetProxyModel::filterAcceptsColumn( int sourceColumn,
0130                                              const QModelIndex & ) const
0131 {
0132     if ( mColSrcToProxyMap.isEmpty() )
0133     {   // no column mapping set up yet, all columns are passed down:
0134         return true;
0135     } else {
0136         Q_ASSERT( sourceModel() );
0137         Q_ASSERT( mColSrcToProxyMap.size() == sourceModel()->columnCount(mRootIndex) );
0138         if ( mColSrcToProxyMap[sourceColumn] == -1 )
0139         {   // this column is explicitly not accepted:
0140             return false;
0141         } else {
0142             Q_ASSERT( mColSrcToProxyMap[sourceColumn] >= 0
0143                       && mColSrcToProxyMap[sourceColumn] < mColSrcToProxyMap.size() );
0144             return true;
0145         }
0146     }
0147 }
0148 
0149 int DatasetProxyModel::mapProxyRowToSource( const int& proxyRow ) const
0150 {
0151     if ( mRowProxyToSrcMap.isEmpty() )
0152     {   // if no row mapping is set, we pass down the row:
0153         return proxyRow;
0154     } else {
0155         Q_ASSERT( proxyRow >= 0 && proxyRow < mRowProxyToSrcMap.size() );
0156         return mRowProxyToSrcMap[ proxyRow ];
0157     }
0158 }
0159 
0160 int DatasetProxyModel::mapProxyColumnToSource( const int& proxyColumn ) const
0161 {
0162     if ( mColProxyToSrcMap.isEmpty() )
0163     {   // if no column mapping is set, we pass down the column:
0164         return proxyColumn;
0165     } else {
0166         Q_ASSERT( proxyColumn >= 0 && proxyColumn < mColProxyToSrcMap.size() );
0167         return mColProxyToSrcMap[ proxyColumn ];
0168     }
0169 }
0170 
0171 int DatasetProxyModel::mapSourceRowToProxy( const int& sourceRow ) const
0172 {
0173     if ( mRowSrcToProxyMap.isEmpty() )
0174     {
0175         return sourceRow;
0176     } else {
0177         Q_ASSERT( sourceRow >= 0 && sourceRow < mRowSrcToProxyMap.size() );
0178         return mRowSrcToProxyMap[sourceRow];
0179     }
0180 }
0181 
0182 int DatasetProxyModel::mapSourceColumnToProxy( const int& sourceColumn ) const
0183 {
0184     if ( mColSrcToProxyMap.isEmpty() )
0185     {
0186         return sourceColumn;
0187     } else {
0188         Q_ASSERT( sourceColumn >= 0 && sourceColumn < mColSrcToProxyMap.size() );
0189         return mColSrcToProxyMap.at( sourceColumn ) ;
0190     }
0191 }
0192 
0193 void DatasetProxyModel::resetDatasetDescriptions()
0194 {
0195     mRowSrcToProxyMap.clear();
0196     mRowProxyToSrcMap.clear();
0197     mColSrcToProxyMap.clear();
0198     mColProxyToSrcMap.clear();
0199     invalidate();
0200 }
0201 
0202 QVariant DatasetProxyModel::data(const QModelIndex &index, int role) const
0203 {
0204    return sourceModel()->data( mapToSource( index ), role );
0205 }
0206 
0207 bool DatasetProxyModel::setData( const QModelIndex& index, const QVariant& value, int role )
0208 {
0209     return sourceModel()->setData( mapToSource( index ), value, role );
0210 }
0211 
0212 QVariant DatasetProxyModel::headerData( int section, Qt::Orientation orientation, int role ) const
0213 {
0214     if ( orientation == Qt::Horizontal )
0215     {
0216         if ( mapProxyColumnToSource ( section ) == -1 )
0217         {
0218             return QVariant();
0219         } else {
0220             return sourceModel()->headerData( mapProxyColumnToSource( section ), orientation,  role );
0221         }
0222     } else {
0223         if ( mapProxyRowToSource ( section ) == -1 )
0224         {
0225             return QVariant();
0226         } else {
0227             return sourceModel()->headerData( mapProxyRowToSource ( section ), orientation, role );
0228         }
0229     }
0230 }
0231 
0232 void DatasetProxyModel::initializeDatasetDecriptors(
0233     const DatasetDescriptionVector& inConfiguration,
0234     const int sourceCount,
0235     DatasetDescriptionVector& outSourceToProxyMap,
0236     DatasetDescriptionVector& outProxyToSourceMap )
0237 {
0238     // in the current mapping implementation, the proxy-to-source map is
0239     // identical to the configuration vector:
0240     outProxyToSourceMap = inConfiguration;
0241     outSourceToProxyMap.fill( -1,  sourceCount );
0242 
0243     for ( int index = 0; index < inConfiguration.size(); ++index ) {
0244         // make sure the values in inConfiguration point to columns in the
0245         // source model:
0246 
0247         if ( inConfiguration[index] == -1 ) {
0248             continue;
0249         }
0250 
0251         Q_ASSERT_X( inConfiguration[ index ] >= 0 && inConfiguration[ index ] < sourceCount,
0252                     "DatasetProxyModel::initializeDatasetDecriptors",
0253                     "column index outside of source model" );
0254         Q_ASSERT_X( outSourceToProxyMap[ inConfiguration[ index ] ] == -1 ,
0255                     "DatasetProxyModel::initializeDatasetDecriptors",
0256                     "no duplicates allowed in mapping configuration, mapping has to be reversible" );
0257 
0258         outSourceToProxyMap[ inConfiguration[ index ] ] = index;
0259     }
0260 }
0261 
0262 void DatasetProxyModel::setSourceModel(QAbstractItemModel *m)
0263 {
0264     if ( sourceModel() ) {
0265         disconnect( sourceModel(),  SIGNAL(layoutChanged()),
0266                     this, SLOT(resetDatasetDescriptions()) );
0267     }
0268     QSortFilterProxyModel::setSourceModel( m );
0269     mRootIndex = QModelIndex();
0270     if ( m ) {
0271         connect( m,  SIGNAL(layoutChanged()),
0272                  this, SLOT(resetDatasetDescriptions()) );
0273         connect( m, SIGNAL(layoutChanged()), this, SIGNAL(layoutChanged()) );
0274     }
0275     resetDatasetDescriptions();
0276 }
0277 
0278 void DatasetProxyModel::setSourceRootIndex(const QModelIndex& rootIdx)
0279 {
0280     mRootIndex = rootIdx;
0281     resetDatasetDescriptions();
0282 }
0283