akonadi
entitymimetypefiltermodel.cpp
00001 /* 00002 Copyright (c) 2007 Bruno Virlet <bruno.virlet@gmail.com> 00003 Copyright (c) 2009 Stephen Kelly <steveire@gmail.com> 00004 00005 00006 This library is free software; you can redistribute it and/or modify it 00007 under the terms of the GNU Library General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or (at your 00009 option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, but WITHOUT 00012 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00014 License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to the 00018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00019 02110-1301, USA. 00020 */ 00021 00022 #include "entitymimetypefiltermodel.h" 00023 00024 #include "entitytreemodel.h" 00025 #include "mimetypechecker.h" 00026 00027 #include <kdebug.h> 00028 #include <kmimetype.h> 00029 00030 #include <QtCore/QString> 00031 #include <QtCore/QStringList> 00032 00033 using namespace Akonadi; 00034 00035 namespace Akonadi { 00039 class EntityMimeTypeFilterModelPrivate 00040 { 00041 public: 00042 EntityMimeTypeFilterModelPrivate( EntityMimeTypeFilterModel *parent ) 00043 : q_ptr( parent ), 00044 m_headerGroup( EntityTreeModel::EntityTreeHeaders ) 00045 { 00046 } 00047 00048 Q_DECLARE_PUBLIC(EntityMimeTypeFilterModel) 00049 EntityMimeTypeFilterModel *q_ptr; 00050 00051 QStringList includedMimeTypes; 00052 QStringList excludedMimeTypes; 00053 00054 QPersistentModelIndex m_rootIndex; 00055 00056 EntityTreeModel::HeaderGroup m_headerGroup; 00057 }; 00058 00059 } 00060 00061 EntityMimeTypeFilterModel::EntityMimeTypeFilterModel( QObject *parent ) 00062 : QSortFilterProxyModel( parent ), 00063 d_ptr( new EntityMimeTypeFilterModelPrivate( this ) ) 00064 { 00065 } 00066 00067 EntityMimeTypeFilterModel::~EntityMimeTypeFilterModel() 00068 { 00069 delete d_ptr; 00070 } 00071 00072 void EntityMimeTypeFilterModel::addMimeTypeInclusionFilters(const QStringList &typeList) 00073 { 00074 Q_D(EntityMimeTypeFilterModel); 00075 d->includedMimeTypes << typeList; 00076 invalidateFilter(); 00077 } 00078 00079 void EntityMimeTypeFilterModel::addMimeTypeExclusionFilters(const QStringList &typeList) 00080 { 00081 Q_D(EntityMimeTypeFilterModel); 00082 d->excludedMimeTypes << typeList; 00083 invalidateFilter(); 00084 } 00085 00086 void EntityMimeTypeFilterModel::addMimeTypeInclusionFilter(const QString &type) 00087 { 00088 Q_D(EntityMimeTypeFilterModel); 00089 d->includedMimeTypes << type; 00090 invalidateFilter(); 00091 } 00092 00093 void EntityMimeTypeFilterModel::addMimeTypeExclusionFilter(const QString &type) 00094 { 00095 Q_D(EntityMimeTypeFilterModel); 00096 d->excludedMimeTypes << type; 00097 invalidateFilter(); 00098 } 00099 00100 bool EntityMimeTypeFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent) const 00101 { 00102 Q_D(const EntityMimeTypeFilterModel); 00103 00104 const QModelIndex idx = sourceModel()->index(sourceRow, 0, sourceParent); 00105 00106 const QString rowMimetype = idx.data( EntityTreeModel::MimeTypeRole ).toString(); 00107 00108 const Akonadi::Item item = idx.data( EntityTreeModel::ItemRole ).value<Akonadi::Item>(); 00109 00110 if ( item.isValid() && !item.hasPayload() ) { 00111 kDebug() << "Item " << item.id() << " doesn't have payload"; 00112 return false; 00113 } 00114 00115 if ( d->excludedMimeTypes.contains( rowMimetype ) ) 00116 return false; 00117 if ( d->includedMimeTypes.isEmpty() || d->includedMimeTypes.contains( rowMimetype ) ) 00118 return true; 00119 00120 return false; 00121 } 00122 00123 QStringList EntityMimeTypeFilterModel::mimeTypeInclusionFilters() const 00124 { 00125 Q_D(const EntityMimeTypeFilterModel); 00126 return d->includedMimeTypes; 00127 } 00128 00129 QStringList EntityMimeTypeFilterModel::mimeTypeExclusionFilters() const 00130 { 00131 Q_D(const EntityMimeTypeFilterModel); 00132 return d->excludedMimeTypes; 00133 } 00134 00135 void EntityMimeTypeFilterModel::clearFilters() 00136 { 00137 Q_D(EntityMimeTypeFilterModel); 00138 d->includedMimeTypes.clear(); 00139 d->excludedMimeTypes.clear(); 00140 invalidateFilter(); 00141 } 00142 00143 void EntityMimeTypeFilterModel::setHeaderGroup(EntityTreeModel::HeaderGroup headerGroup) 00144 { 00145 Q_D(EntityMimeTypeFilterModel); 00146 d->m_headerGroup = headerGroup; 00147 } 00148 00149 QVariant EntityMimeTypeFilterModel::headerData(int section, Qt::Orientation orientation, int role ) const 00150 { 00151 if (!sourceModel()) 00152 return QVariant(); 00153 00154 Q_D(const EntityMimeTypeFilterModel); 00155 role += (EntityTreeModel::TerminalUserRole * d->m_headerGroup); 00156 return sourceModel()->headerData(section, orientation, role); 00157 } 00158 00159 QModelIndexList EntityMimeTypeFilterModel::match( const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags ) const 00160 { 00161 if ( !sourceModel() ) 00162 return QModelIndexList(); 00163 00164 if ( EntityTreeModel::AmazingCompletionRole != role ) { 00165 if ( role < Qt::UserRole ) 00166 return QSortFilterProxyModel::match( start, role, value, hits, flags ); 00167 00168 QModelIndexList list; 00169 QModelIndex proxyIndex; 00170 foreach ( const QModelIndex &idx, sourceModel()->match( mapToSource( start ), role, value, hits, flags ) ) { 00171 proxyIndex = mapFromSource(idx); 00172 if (proxyIndex.isValid()) 00173 list << proxyIndex; 00174 } 00175 00176 return list; 00177 } 00178 // We match everything in the source model because sorting will change what we should show. 00179 const int allHits = -1; 00180 00181 QModelIndexList proxyList; 00182 QMap<int, QModelIndex> proxyMap; 00183 const QModelIndexList sourceList = sourceModel()->match( mapToSource( start ), role, value, allHits, flags ); 00184 QModelIndexList::const_iterator it; 00185 const QModelIndexList::const_iterator begin = sourceList.constBegin(); 00186 const QModelIndexList::const_iterator end = sourceList.constEnd(); 00187 QModelIndex proxyIndex; 00188 for ( it = begin; it != end; ++it ) { 00189 proxyIndex = mapFromSource( *it ); 00190 00191 // Any filtered indexes will be invalid when mapped. 00192 if ( !proxyIndex.isValid() ) 00193 continue; 00194 00195 // Inserting in a QMap gives us sorting by key for free. 00196 proxyMap.insert( proxyIndex.row(), proxyIndex ); 00197 } 00198 00199 if ( hits == -1 ) 00200 return proxyMap.values(); 00201 00202 return proxyMap.values().mid( 0, hits ); 00203 } 00204 00205 int EntityMimeTypeFilterModel::columnCount(const QModelIndex &parent) const 00206 { 00207 Q_D(const EntityMimeTypeFilterModel); 00208 00209 if (!sourceModel()) 00210 return 0; 00211 00212 const QVariant value = sourceModel()->data(mapToSource(parent), EntityTreeModel::ColumnCountRole + (EntityTreeModel::TerminalUserRole * d->m_headerGroup)); 00213 if ( !value.isValid() ) 00214 return 0; 00215 00216 return value.toInt(); 00217 } 00218 00219 bool EntityMimeTypeFilterModel::hasChildren(const QModelIndex &parent) const 00220 { 00221 if (!sourceModel()) 00222 return false; 00223 00224 // QSortFilterProxyModel implementation is buggy in that it emits rowsAboutToBeInserted etc 00225 // only after the source model has emitted rowsInserted, instead of emitting it when the 00226 // source model emits rowsAboutToBeInserted. That means that the source and the proxy are out 00227 // of sync around the time of insertions, so we can't use the optimization below. 00228 return rowCount(parent) > 0; 00229 #if 0 00230 00231 if ( !parent.isValid() ) 00232 return sourceModel()->hasChildren(parent); 00233 00234 Q_D(const EntityMimeTypeFilterModel); 00235 if ( EntityTreeModel::ItemListHeaders == d->m_headerGroup) 00236 return false; 00237 00238 if ( EntityTreeModel::CollectionTreeHeaders == d->m_headerGroup ) 00239 { 00240 QModelIndex childIndex = parent.child( 0, 0 ); 00241 while ( childIndex.isValid() ) 00242 { 00243 Collection col = childIndex.data( EntityTreeModel::CollectionRole ).value<Collection>(); 00244 if (col.isValid()) 00245 return true; 00246 childIndex = childIndex.sibling( childIndex.row() + 1, childIndex.column() ); 00247 } 00248 } 00249 return false; 00250 #endif 00251 } 00252 00253 bool EntityMimeTypeFilterModel::canFetchMore( const QModelIndex &parent ) const 00254 { 00255 Q_D(const EntityMimeTypeFilterModel); 00256 if ( EntityTreeModel::CollectionTreeHeaders == d->m_headerGroup ) 00257 return false; 00258 return QSortFilterProxyModel::canFetchMore(parent); 00259 } 00260 00261 #include "entitymimetypefiltermodel.moc" 00262