akonadi/contact
leafextensionproxymodel.cpp
00001 /* 00002 This file is part of Akonadi Contact. 00003 00004 Copyright (c) 2010 KDAB 00005 Author: Tobias Koenig <tokoe@kde.org> 00006 00007 This library is free software; you can redistribute it and/or modify it 00008 under the terms of the GNU Library General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or (at your 00010 option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, but WITHOUT 00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00015 License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to the 00019 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00020 02110-1301, USA. 00021 */ 00022 00023 #include "leafextensionproxymodel_p.h" 00024 00025 #include <QtCore/QSet> 00026 00027 using namespace Akonadi; 00028 00029 class LeafExtensionProxyModel::Private 00030 { 00031 public: 00032 Private( LeafExtensionProxyModel *qq ) 00033 : q( qq ), mUniqueKeyCounter( 0 ) 00034 { 00035 } 00036 00037 void sourceRowsInserted( const QModelIndex&, int, int ); 00038 void sourceRowsRemoved( const QModelIndex&, int, int ); 00039 00040 LeafExtensionProxyModel *q; 00041 QMap<qint64, QModelIndex> mParentIndexes; 00042 QSet<QModelIndex> mOwnIndexes; 00043 qint64 mUniqueKeyCounter; 00044 }; 00045 00046 void LeafExtensionProxyModel::Private::sourceRowsInserted( const QModelIndex &parentIndex, int start, int end ) 00047 { 00048 // iterate over all of our stored parent indexes 00049 QMutableMapIterator<qint64, QModelIndex> it( mParentIndexes ); 00050 while ( it.hasNext() ) { 00051 it.next(); 00052 if ( it.value().parent() == parentIndex ) { 00053 if ( it.value().row() >= start ) { 00054 const QModelIndex newIndex = q->QSortFilterProxyModel::index( it.value().row() + (end-start) + 1, it.value().column(), parentIndex ); 00055 it.setValue( newIndex ); 00056 } 00057 } 00058 } 00059 } 00060 00061 void LeafExtensionProxyModel::Private::sourceRowsRemoved( const QModelIndex &parentIndex, int start, int end ) 00062 { 00063 // iterate over all of our stored parent indexes 00064 QMutableMapIterator<qint64, QModelIndex> it( mParentIndexes ); 00065 while ( it.hasNext() ) { 00066 it.next(); 00067 if ( it.value().parent() == parentIndex ) { 00068 if ( it.value().row() >= start && it.value().row() <= end ) { 00069 it.remove(); 00070 } else if ( it.value().row() > end ) { 00071 const QModelIndex newIndex = q->index( it.value().row() - (end-start) - 1, it.value().column(), parentIndex ); 00072 it.setValue( newIndex ); 00073 } 00074 } 00075 } 00076 } 00077 00078 LeafExtensionProxyModel::LeafExtensionProxyModel( QObject *parent ) 00079 : QSortFilterProxyModel( parent ), d( new Private( this ) ) 00080 { 00081 } 00082 00083 LeafExtensionProxyModel::~LeafExtensionProxyModel() 00084 { 00085 delete d; 00086 } 00087 00088 QModelIndex LeafExtensionProxyModel::index( int row, int column, const QModelIndex &parent ) const 00089 { 00090 if ( row < 0 || column < 0 ) 00091 return QModelIndex(); 00092 00093 if ( parent.isValid() ) { 00094 const QModelIndex sourceParent = mapToSource( parent ); 00095 const QModelIndex sourceIndex = sourceModel()->index( row, column, sourceParent ); 00096 if ( !sourceIndex.isValid() ) { 00097 00098 qint64 key = -1; 00099 QMapIterator<qint64, QModelIndex> it( d->mParentIndexes ); 00100 while ( it.hasNext() ) { 00101 it.next(); 00102 if ( it.value() == parent ) { 00103 key = it.key(); 00104 break; 00105 } 00106 } 00107 00108 if ( key == -1 ) { 00109 key = ++(d->mUniqueKeyCounter); 00110 d->mParentIndexes.insert( key, parent ); 00111 } 00112 00113 const QModelIndex index = createIndex( row, column, static_cast<quint32>( key ) ); 00114 d->mOwnIndexes.insert( index ); 00115 00116 return index; 00117 } 00118 } 00119 00120 return QSortFilterProxyModel::index( row, column, parent ); 00121 } 00122 00123 QModelIndex LeafExtensionProxyModel::parent( const QModelIndex &index ) const 00124 { 00125 if ( d->mOwnIndexes.contains( index ) ) 00126 return d->mParentIndexes.value( index.internalId() ); 00127 00128 return QSortFilterProxyModel::parent( index ); 00129 } 00130 00131 int LeafExtensionProxyModel::rowCount( const QModelIndex &index ) const 00132 { 00133 if ( d->mOwnIndexes.contains( index ) ) 00134 return 0; 00135 00136 const QModelIndex sourceIndex = mapToSource( index ); 00137 if ( sourceModel()->rowCount( sourceIndex ) == 0 ) 00138 return leafRowCount( index ); 00139 00140 return QSortFilterProxyModel::rowCount( index ); 00141 } 00142 00143 int LeafExtensionProxyModel::columnCount( const QModelIndex &index ) const 00144 { 00145 if ( d->mOwnIndexes.contains( index ) ) 00146 return 1; 00147 00148 return QSortFilterProxyModel::columnCount( index ); 00149 } 00150 00151 QVariant LeafExtensionProxyModel::data( const QModelIndex &index, int role ) const 00152 { 00153 if ( d->mOwnIndexes.contains( index ) ) 00154 return leafData( index.parent(), index.row(), index.column(), role ); 00155 00156 return QSortFilterProxyModel::data( index, role ); 00157 } 00158 00159 Qt::ItemFlags LeafExtensionProxyModel::flags( const QModelIndex &index ) const 00160 { 00161 if ( d->mOwnIndexes.contains( index ) ) 00162 return Qt::ItemIsEnabled|Qt::ItemIsSelectable; 00163 00164 return QSortFilterProxyModel::flags( index ); 00165 } 00166 00167 bool LeafExtensionProxyModel::setData( const QModelIndex &index, const QVariant &data, int role ) 00168 { 00169 if ( d->mOwnIndexes.contains( index ) ) 00170 return false; 00171 00172 return QSortFilterProxyModel::setData( index, data, role ); 00173 } 00174 00175 bool LeafExtensionProxyModel::hasChildren( const QModelIndex &parent ) const 00176 { 00177 if ( d->mOwnIndexes.contains( parent ) ) 00178 return false; // extensible in the future? 00179 00180 const QModelIndex sourceParent = mapToSource( parent ); 00181 if ( sourceModel() && sourceModel()->rowCount( sourceParent ) == 0 ) 00182 return (leafRowCount( parent ) != 0); 00183 00184 return QSortFilterProxyModel::hasChildren( parent ); 00185 } 00186 00187 QModelIndex LeafExtensionProxyModel::buddy( const QModelIndex &index ) const 00188 { 00189 if ( d->mOwnIndexes.contains( index ) ) 00190 return index; 00191 00192 return QSortFilterProxyModel::buddy( index ); 00193 } 00194 00195 void LeafExtensionProxyModel::fetchMore( const QModelIndex &index ) 00196 { 00197 if ( d->mOwnIndexes.contains( index ) ) 00198 return; 00199 00200 QSortFilterProxyModel::fetchMore( index ); 00201 } 00202 00203 void LeafExtensionProxyModel::setSourceModel( QAbstractItemModel *_sourceModel ) 00204 { 00205 if ( _sourceModel == sourceModel() ) 00206 return; 00207 00208 beginResetModel(); 00209 00210 disconnect( this, SIGNAL( rowsInserted( const QModelIndex&, int, int ) ), 00211 this, SLOT( sourceRowsInserted( const QModelIndex&, int, int ) ) ); 00212 disconnect( this, SIGNAL( rowsRemoved( const QModelIndex&, int, int ) ), 00213 this, SLOT( sourceRowsRemoved( const QModelIndex&, int, int ) ) ); 00214 00215 QSortFilterProxyModel::setSourceModel( _sourceModel ); 00216 00217 connect( this, SIGNAL( rowsInserted( const QModelIndex&, int, int ) ), 00218 this, SLOT( sourceRowsInserted( const QModelIndex&, int, int ) ) ); 00219 connect( this, SIGNAL( rowsRemoved( const QModelIndex&, int, int ) ), 00220 this, SLOT( sourceRowsRemoved( const QModelIndex&, int, int ) ) ); 00221 00222 endResetModel(); 00223 } 00224 00225 #include "leafextensionproxymodel_p.moc"