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 const QModelIndex idx = sourceModel()->index(sourceRow, 0, sourceParent); 00104 00105 const Akonadi::Item item = idx.data( EntityTreeModel::ItemRole ).value<Akonadi::Item>(); 00106 00107 if ( item.isValid() && !item.hasPayload() ) { 00108 kDebug() << "Item " << item.id() << " doesn't have payload"; 00109 return false; 00110 } 00111 00112 const QString rowMimetype = idx.data( EntityTreeModel::MimeTypeRole ).toString(); 00113 00114 if ( d->excludedMimeTypes.contains( rowMimetype ) ) 00115 return false; 00116 if ( d->includedMimeTypes.isEmpty() || d->includedMimeTypes.contains( rowMimetype ) ) 00117 return true; 00118 00119 return false; 00120 } 00121 00122 QStringList EntityMimeTypeFilterModel::mimeTypeInclusionFilters() const 00123 { 00124 Q_D(const EntityMimeTypeFilterModel); 00125 return d->includedMimeTypes; 00126 } 00127 00128 QStringList EntityMimeTypeFilterModel::mimeTypeExclusionFilters() const 00129 { 00130 Q_D(const EntityMimeTypeFilterModel); 00131 return d->excludedMimeTypes; 00132 } 00133 00134 void EntityMimeTypeFilterModel::clearFilters() 00135 { 00136 Q_D(EntityMimeTypeFilterModel); 00137 d->includedMimeTypes.clear(); 00138 d->excludedMimeTypes.clear(); 00139 invalidateFilter(); 00140 } 00141 00142 void EntityMimeTypeFilterModel::setHeaderGroup(EntityTreeModel::HeaderGroup headerGroup) 00143 { 00144 Q_D(EntityMimeTypeFilterModel); 00145 d->m_headerGroup = headerGroup; 00146 } 00147 00148 QVariant EntityMimeTypeFilterModel::headerData(int section, Qt::Orientation orientation, int role ) const 00149 { 00150 if (!sourceModel()) 00151 return QVariant(); 00152 00153 Q_D(const EntityMimeTypeFilterModel); 00154 role += (EntityTreeModel::TerminalUserRole * d->m_headerGroup); 00155 return sourceModel()->headerData(section, orientation, role); 00156 } 00157 00158 QModelIndexList EntityMimeTypeFilterModel::match( const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags ) const 00159 { 00160 if ( !sourceModel() ) 00161 return QModelIndexList(); 00162 00163 if ( EntityTreeModel::AmazingCompletionRole != role ) { 00164 if ( role < Qt::UserRole ) 00165 return QSortFilterProxyModel::match( start, role, value, hits, flags ); 00166 00167 QModelIndexList list; 00168 QModelIndex proxyIndex; 00169 foreach ( const QModelIndex &idx, sourceModel()->match( mapToSource( start ), role, value, hits, flags ) ) { 00170 proxyIndex = mapFromSource(idx); 00171 if (proxyIndex.isValid()) 00172 list << proxyIndex; 00173 } 00174 00175 return list; 00176 } 00177 // We match everything in the source model because sorting will change what we should show. 00178 const int allHits = -1; 00179 00180 QModelIndexList proxyList; 00181 QMap<int, QModelIndex> proxyMap; 00182 const QModelIndexList sourceList = sourceModel()->match( mapToSource( start ), role, value, allHits, flags ); 00183 QModelIndexList::const_iterator it; 00184 const QModelIndexList::const_iterator begin = sourceList.constBegin(); 00185 const QModelIndexList::const_iterator end = sourceList.constEnd(); 00186 QModelIndex proxyIndex; 00187 for ( it = begin; it != end; ++it ) { 00188 proxyIndex = mapFromSource( *it ); 00189 00190 // Any filtered indexes will be invalid when mapped. 00191 if ( !proxyIndex.isValid() ) 00192 continue; 00193 00194 // Inserting in a QMap gives us sorting by key for free. 00195 proxyMap.insert( proxyIndex.row(), proxyIndex ); 00196 } 00197 00198 if ( hits == -1 ) 00199 return proxyMap.values(); 00200 00201 return proxyMap.values().mid( 0, hits ); 00202 } 00203 00204 int EntityMimeTypeFilterModel::columnCount(const QModelIndex &parent) const 00205 { 00206 Q_D(const EntityMimeTypeFilterModel); 00207 00208 if (!sourceModel()) 00209 return 0; 00210 00211 const QVariant value = sourceModel()->data(mapToSource(parent), EntityTreeModel::ColumnCountRole + (EntityTreeModel::TerminalUserRole * d->m_headerGroup)); 00212 if ( !value.isValid() ) 00213 return 0; 00214 00215 return value.toInt(); 00216 } 00217 00218 bool EntityMimeTypeFilterModel::hasChildren(const QModelIndex &parent) const 00219 { 00220 if (!sourceModel()) 00221 return false; 00222 00223 // QSortFilterProxyModel implementation is buggy in that it emits rowsAboutToBeInserted etc 00224 // only after the source model has emitted rowsInserted, instead of emitting it when the 00225 // source model emits rowsAboutToBeInserted. That means that the source and the proxy are out 00226 // of sync around the time of insertions, so we can't use the optimization below. 00227 return rowCount(parent) > 0; 00228 #if 0 00229 00230 if ( !parent.isValid() ) 00231 return sourceModel()->hasChildren(parent); 00232 00233 Q_D(const EntityMimeTypeFilterModel); 00234 if ( EntityTreeModel::ItemListHeaders == d->m_headerGroup) 00235 return false; 00236 00237 if ( EntityTreeModel::CollectionTreeHeaders == d->m_headerGroup ) 00238 { 00239 QModelIndex childIndex = parent.child( 0, 0 ); 00240 while ( childIndex.isValid() ) 00241 { 00242 Collection col = childIndex.data( EntityTreeModel::CollectionRole ).value<Collection>(); 00243 if (col.isValid()) 00244 return true; 00245 childIndex = childIndex.sibling( childIndex.row() + 1, childIndex.column() ); 00246 } 00247 } 00248 return false; 00249 #endif 00250 } 00251 00252 bool EntityMimeTypeFilterModel::canFetchMore( const QModelIndex &parent ) const 00253 { 00254 Q_D(const EntityMimeTypeFilterModel); 00255 if ( EntityTreeModel::CollectionTreeHeaders == d->m_headerGroup ) 00256 return false; 00257 return QSortFilterProxyModel::canFetchMore(parent); 00258 } 00259 00260 #include "entitymimetypefiltermodel.moc" 00261