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