KDChartDatasetProxyModel.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB.  All rights reserved.
00003 **
00004 ** This file is part of the KD Chart library.
00005 **
00006 ** Licensees holding valid commercial KD Chart licenses may use this file in
00007 ** accordance with the KD Chart Commercial License Agreement provided with
00008 ** the Software.
00009 **
00010 **
00011 ** This file may be distributed and/or modified under the terms of the
00012 ** GNU General Public License version 2 and version 3 as published by the
00013 ** Free Software Foundation and appearing in the file LICENSE.GPL included.
00014 **
00015 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017 **
00018 ** Contact info@kdab.com if any conditions of this licensing are not
00019 ** clear to you.
00020 **
00021 **********************************************************************/
00022 
00023 #include "KDChartDatasetProxyModel.h"
00024 
00025 #include <QtDebug>
00026 
00027 #include <KDABLibFakes>
00028 
00029 
00030 using namespace KDChart;
00031 
00032 DatasetProxyModel::DatasetProxyModel (QObject* parent)
00033     : QSortFilterProxyModel ( parent )
00034 {
00035 }
00036 
00037 QModelIndex DatasetProxyModel::buddy( const QModelIndex& index ) const
00038 {
00039     return index;
00040 }
00041 
00042 Qt::ItemFlags DatasetProxyModel::flags( const QModelIndex& index ) const
00043 {
00044     return sourceModel()->flags( mapToSource( index ) );
00045 }
00046 
00047 void DatasetProxyModel::setDatasetRowDescriptionVector (
00048     const DatasetDescriptionVector& configuration )
00049 {
00050     Q_ASSERT_X ( sourceModel(), "DatasetProxyModel::setDatasetRowDescriptionVector",
00051                  "A source model must be set before the selection can be configured." );
00052     initializeDatasetDecriptors ( configuration, sourceModel()->rowCount(mRootIndex),
00053                                   mRowSrcToProxyMap,  mRowProxyToSrcMap );
00054     clear(); // clear emits layoutChanged()
00055 }
00056 
00057 void DatasetProxyModel::setDatasetColumnDescriptionVector (
00058     const DatasetDescriptionVector& configuration )
00059 {
00060     Q_ASSERT_X ( sourceModel(), "DatasetProxyModel::setDatasetColumnDescriptionVector",
00061                  "A source model must be set before the selection can be configured." );
00062     initializeDatasetDecriptors ( configuration, sourceModel()->columnCount(mRootIndex),
00063                                   mColSrcToProxyMap, mColProxyToSrcMap );
00064     clear(); // clear emits layoutChanged()
00065 }
00066 
00067 void DatasetProxyModel::setDatasetDescriptionVectors (
00068     const DatasetDescriptionVector& rowConfig,
00069     const DatasetDescriptionVector& columnConfig )
00070 {
00071     setDatasetRowDescriptionVector( rowConfig );
00072     setDatasetColumnDescriptionVector ( columnConfig );
00073 }
00074 
00075 QModelIndex DatasetProxyModel::index( int row, int column, 
00076                                       const QModelIndex &parent ) const
00077 {
00078     return mapFromSource( sourceModel()->index( mapProxyRowToSource(row),
00079                                                 mapProxyColumnToSource(column),
00080                                                 parent ) );
00081 }
00082 
00083 QModelIndex DatasetProxyModel::parent( const QModelIndex& child ) const
00084 {
00085 //    return mapFromSource( sourceModel()->parent( child ) );
00086     return mapFromSource( sourceModel()->parent( mapToSource( child ) ) );
00087 }
00088 
00089 QModelIndex DatasetProxyModel::mapFromSource ( const QModelIndex & sourceIndex ) const
00090 {
00091     Q_ASSERT_X ( sourceModel(), "DatasetProxyModel::mapFromSource", "A source "
00092                  "model must be set before the selection can be configured." );
00093 
00094     if ( !sourceIndex.isValid() ) return sourceIndex;
00095 
00096     if ( mRowSrcToProxyMap.isEmpty() && mColSrcToProxyMap.isEmpty() )
00097     {
00098         return createIndex ( sourceIndex.row(), sourceIndex.column(),
00099                              sourceIndex.internalPointer() );
00100     } else {
00101         int row = mapSourceRowToProxy ( sourceIndex.row() );
00102         int column = mapSourceColumnToProxy ( sourceIndex.column() );
00103         return createIndex ( row, column, sourceIndex.internalPointer() );
00104     }
00105 }
00106 
00107 QModelIndex DatasetProxyModel::mapToSource ( const QModelIndex& proxyIndex ) const
00108 {
00109     Q_ASSERT_X ( sourceModel(), "DatasetProxyModel::mapToSource", "A source "
00110                  "model must be set before the selection can be configured." );
00111 
00112     if ( !proxyIndex.isValid() ) return proxyIndex;
00113     if ( mRowSrcToProxyMap.isEmpty() && mColSrcToProxyMap.isEmpty() )
00114     {
00115         return sourceModel()->index( proxyIndex.row(),  proxyIndex.column(), mRootIndex );
00116     } else {
00117         int row = mapProxyRowToSource ( proxyIndex.row() );
00118         int column = mapProxyColumnToSource ( proxyIndex.column() );
00119         return sourceModel()->index( row, column, mRootIndex );
00120     }
00121 }
00122 
00123 bool DatasetProxyModel::filterAcceptsRow ( int sourceRow,
00124                                            const QModelIndex & ) const
00125 {
00126     if ( mRowSrcToProxyMap.isEmpty() )
00127     {   // no row mapping set, all rows are passed down:
00128         return true;
00129     } else {
00130         Q_ASSERT ( sourceModel() );
00131         Q_ASSERT ( mRowSrcToProxyMap.size() == sourceModel()->rowCount(mRootIndex) );
00132         if ( mRowSrcToProxyMap[sourceRow] == -1 )
00133         {   // this row is explicitly not accepted:
00134             return false;
00135         } else {
00136             Q_ASSERT ( mRowSrcToProxyMap[sourceRow] >= 0
00137                        && mRowSrcToProxyMap[sourceRow] < mRowSrcToProxyMap.size() );
00138             return true;
00139         }
00140     }
00141 }
00142 
00143 bool DatasetProxyModel::filterAcceptsColumn ( int sourceColumn,
00144                                               const QModelIndex & ) const
00145 {
00146     if ( mColSrcToProxyMap.isEmpty() )
00147     {   // no column mapping set up yet, all columns are passed down:
00148         return true;
00149     } else {
00150         Q_ASSERT ( sourceModel() );
00151         Q_ASSERT ( mColSrcToProxyMap.size() == sourceModel()->columnCount(mRootIndex) );
00152         if ( mColSrcToProxyMap[sourceColumn] == -1 )
00153         {   // this column is explicitly not accepted:
00154             return false;
00155         } else {
00156             Q_ASSERT ( mColSrcToProxyMap[sourceColumn] >= 0
00157                        && mColSrcToProxyMap[sourceColumn] < mColSrcToProxyMap.size() );
00158             return true;
00159         }
00160     }
00161 }
00162 
00163 int DatasetProxyModel::mapProxyRowToSource ( const int& proxyRow ) const
00164 {
00165     if ( mRowProxyToSrcMap.isEmpty() )
00166     {   // if no row mapping is set, we pass down the row:
00167         return proxyRow;
00168     } else {
00169         Q_ASSERT ( proxyRow >= 0 && proxyRow < mRowProxyToSrcMap.size() );
00170         return mRowProxyToSrcMap[ proxyRow ];
00171     }
00172 }
00173 
00174 int DatasetProxyModel::mapProxyColumnToSource ( const int& proxyColumn ) const
00175 {
00176     if ( mColProxyToSrcMap.isEmpty()  )
00177     {   // if no column mapping is set, we pass down the column:
00178         return proxyColumn;
00179     } else {
00180         Q_ASSERT ( proxyColumn >= 0 && proxyColumn < mColProxyToSrcMap.size() );
00181         return mColProxyToSrcMap[ proxyColumn ];
00182     }
00183 }
00184 
00185 int DatasetProxyModel::mapSourceRowToProxy ( const int& sourceRow ) const
00186 {
00187     if ( mRowSrcToProxyMap.isEmpty() )
00188     {
00189         return sourceRow;
00190     } else {
00191         Q_ASSERT ( sourceRow >= 0 && sourceRow < mRowSrcToProxyMap.size() );
00192         return mRowSrcToProxyMap[sourceRow];
00193     }
00194 }
00195 
00196 int DatasetProxyModel::mapSourceColumnToProxy ( const int& sourceColumn ) const
00197 {
00198     if ( mColSrcToProxyMap.isEmpty() )
00199     {
00200         return sourceColumn;
00201     } else {
00202         Q_ASSERT ( sourceColumn >= 0 && sourceColumn < mColSrcToProxyMap.size() );
00203         return mColSrcToProxyMap.at( sourceColumn ) ;
00204     }
00205 }
00206 
00207 void DatasetProxyModel::resetDatasetDescriptions()
00208 {
00209     mRowSrcToProxyMap.clear();
00210     mRowProxyToSrcMap.clear();
00211     mColSrcToProxyMap.clear();
00212     mColProxyToSrcMap.clear();
00213     clear();
00214 }
00215 
00216 QVariant DatasetProxyModel::data(const QModelIndex &index, int role) const
00217 {
00218    return sourceModel()->data( mapToSource ( index ), role );
00219 }
00220 
00221 bool DatasetProxyModel::setData( const QModelIndex& index, const QVariant& value, int role )
00222 {
00223     return sourceModel()->setData( mapToSource( index ), value, role );
00224 }
00225 
00226 QVariant DatasetProxyModel::headerData ( int section, Qt::Orientation orientation, int role ) const
00227 {
00228     if ( orientation == Qt::Horizontal )
00229     {
00230         if ( mapProxyColumnToSource ( section ) == -1 )
00231         {
00232             return QVariant();
00233         } else {
00234             return sourceModel()->headerData ( mapProxyColumnToSource ( section ),
00235                                                        orientation,  role );
00236         }
00237     } else {
00238         if ( mapProxyRowToSource ( section ) == -1 )
00239         {
00240             return QVariant();
00241         } else {
00242             return sourceModel()->headerData ( mapProxyRowToSource ( section ),
00243                                                        orientation, role );
00244         }
00245     }
00246 }
00247 
00248 void DatasetProxyModel::initializeDatasetDecriptors (
00249     const DatasetDescriptionVector& inConfiguration,
00250     const int sourceCount,
00251     DatasetDescriptionVector& outSourceToProxyMap,
00252     DatasetDescriptionVector& outProxyToSourceMap )
00253 {
00254         // in the current mapping implementation, the proxy-to-source map is
00255     // identical to the configuration vector:
00256     outProxyToSourceMap = inConfiguration;
00257     outSourceToProxyMap.fill ( -1,  sourceCount );
00258         
00259     for ( int index = 0; index < inConfiguration.size(); ++index )
00260     {   
00261                 // make sure the values in inConfiguration point to columns in the
00262         // source model:
00263                 
00264                 if (inConfiguration[index] == -1)
00265                         continue;
00266 
00267         Q_ASSERT_X ( inConfiguration[index] >= 0
00268                    && inConfiguration[index] < sourceCount,
00269                      "DatasetProxyModel::initializeDatasetDecriptors",
00270                      "column index outside of source model" );
00271         Q_ASSERT_X ( outSourceToProxyMap[inConfiguration[index]] == -1 ,
00272                      "DatasetProxyModel::initializeDatasetDecriptors",
00273                      "no duplicates allowed in mapping configuration, mapping has to be revertible" );
00274                 
00275         outSourceToProxyMap[inConfiguration[index]] = index;
00276                 
00277     }
00278 }
00279 
00280 void DatasetProxyModel::setSourceModel (QAbstractItemModel *m)
00281 {
00282     if ( sourceModel() ) {
00283         disconnect ( sourceModel(),  SIGNAL ( layoutChanged() ),
00284                      this, SLOT( resetDatasetDescriptions() ) );
00285     }
00286     QSortFilterProxyModel::setSourceModel ( m );
00287     mRootIndex = QModelIndex();
00288     if ( m ) {
00289         connect ( m,  SIGNAL ( layoutChanged() ),
00290                   this, SLOT( resetDatasetDescriptions() ) );
00291     }
00292     resetDatasetDescriptions();
00293 }
00294 
00295 void DatasetProxyModel::setSourceRootIndex(const QModelIndex& rootIdx)
00296 {
00297     mRootIndex = rootIdx;
00298     resetDatasetDescriptions();
00299 }
00300