akonadi
contactsfilterproxymodel.cpp
00001 /* 00002 This file is part of Akonadi Contact. 00003 00004 Copyright (c) 2009 Tobias Koenig <tokoe@kde.org> 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 "contactsfilterproxymodel.h" 00023 00024 #include "contactstreemodel.h" 00025 00026 #include <akonadi/entitytreemodel.h> 00027 #include <kabc/addressee.h> 00028 #include <kabc/contactgroup.h> 00029 00030 static bool contactMatchesFilter( const KABC::Addressee &contact, const QString &filterString ); 00031 static bool contactGroupMatchesFilter( const KABC::ContactGroup &group, const QString &filterString ); 00032 00033 using namespace Akonadi; 00034 00035 class ContactsFilterProxyModel::Private 00036 { 00037 public: 00038 QString mFilter; 00039 }; 00040 00041 ContactsFilterProxyModel::ContactsFilterProxyModel( QObject *parent ) 00042 : QSortFilterProxyModel( parent ), d( new Private ) 00043 { 00044 // contact names should be sorted correctly 00045 setSortLocaleAware( true ); 00046 setDynamicSortFilter( true ); 00047 } 00048 00049 ContactsFilterProxyModel::~ContactsFilterProxyModel() 00050 { 00051 delete d; 00052 } 00053 00054 void ContactsFilterProxyModel::setFilterString( const QString &filter ) 00055 { 00056 d->mFilter = filter; 00057 invalidateFilter(); 00058 } 00059 00060 bool ContactsFilterProxyModel::filterAcceptsRow( int row, const QModelIndex &parent ) const 00061 { 00062 if ( d->mFilter.isEmpty() ) 00063 return true; 00064 00065 const QModelIndex index = sourceModel()->index( row, 0, parent ); 00066 00067 const Akonadi::Item item = index.data( Akonadi::EntityTreeModel::ItemRole ).value<Akonadi::Item>(); 00068 00069 if ( item.hasPayload<KABC::Addressee>() ) { 00070 const KABC::Addressee contact = item.payload<KABC::Addressee>(); 00071 return contactMatchesFilter( contact, d->mFilter ); 00072 } else if ( item.hasPayload<KABC::ContactGroup>() ) { 00073 const KABC::ContactGroup group = item.payload<KABC::ContactGroup>(); 00074 return contactGroupMatchesFilter( group, d->mFilter ); 00075 } 00076 00077 return true; 00078 } 00079 00080 bool ContactsFilterProxyModel::lessThan( const QModelIndex &leftIndex, const QModelIndex &rightIndex ) const 00081 { 00082 const QDate leftDate = leftIndex.data( ContactsTreeModel::DateRole ).toDate(); 00083 const QDate rightDate = rightIndex.data( ContactsTreeModel::DateRole ).toDate(); 00084 00085 if ( leftDate.isValid() && rightDate.isValid() ) { 00086 if ( leftDate.month() < rightDate.month() ) 00087 return true; 00088 else if ( leftDate.month() == rightDate.month() ) 00089 return (leftDate.day() < rightDate.day()); 00090 else 00091 return false; 00092 } 00093 00094 return QSortFilterProxyModel::lessThan( leftIndex, rightIndex ); 00095 } 00096 00097 static bool addressMatchesFilter( const KABC::Address &address, const QString &filterString ) 00098 { 00099 if ( address.street().contains( filterString, Qt::CaseInsensitive ) ) 00100 return true; 00101 00102 if ( address.locality().contains( filterString, Qt::CaseInsensitive ) ) 00103 return true; 00104 00105 if ( address.region().contains( filterString, Qt::CaseInsensitive ) ) 00106 return true; 00107 00108 if ( address.postalCode().contains( filterString, Qt::CaseInsensitive ) ) 00109 return true; 00110 00111 if ( address.country().contains( filterString, Qt::CaseInsensitive ) ) 00112 return true; 00113 00114 if ( address.label().contains( filterString, Qt::CaseInsensitive ) ) 00115 return true; 00116 00117 if ( address.postOfficeBox().contains( filterString, Qt::CaseInsensitive ) ) 00118 return true; 00119 00120 return false; 00121 } 00122 00123 static bool contactMatchesFilter( const KABC::Addressee &contact, const QString &filterString ) 00124 { 00125 if ( contact.assembledName().contains( filterString, Qt::CaseInsensitive ) ) 00126 return true; 00127 00128 if ( contact.formattedName().contains( filterString, Qt::CaseInsensitive ) ) 00129 return true; 00130 00131 if ( contact.nickName().contains( filterString, Qt::CaseInsensitive ) ) 00132 return true; 00133 00134 if ( contact.birthday().toString().contains( filterString, Qt::CaseInsensitive ) ) 00135 return true; 00136 00137 const KABC::Address::List addresses = contact.addresses(); 00138 int count = addresses.count(); 00139 for ( int i = 0; i < count; ++i ) { 00140 if ( addressMatchesFilter( addresses.at( i ), filterString ) ) 00141 return true; 00142 } 00143 00144 const KABC::PhoneNumber::List phoneNumbers = contact.phoneNumbers(); 00145 count = phoneNumbers.count(); 00146 for ( int i = 0; i < count; ++i ) { 00147 if ( phoneNumbers.at( i ).number().contains( filterString, Qt::CaseInsensitive ) ) 00148 return true; 00149 } 00150 00151 const QStringList emails = contact.emails(); 00152 count = emails.count(); 00153 for ( int i = 0; i < count; ++i ) { 00154 if ( emails.at( i ).contains( filterString, Qt::CaseInsensitive ) ) 00155 return true; 00156 } 00157 00158 const QStringList categories = contact.categories(); 00159 count = categories.count(); 00160 for ( int i = 0; i < count; ++i ) { 00161 if ( categories.at( i ).contains( filterString, Qt::CaseInsensitive ) ) 00162 return true; 00163 } 00164 00165 if ( contact.mailer().contains( filterString, Qt::CaseInsensitive ) ) 00166 return true; 00167 00168 if ( contact.title().contains( filterString, Qt::CaseInsensitive ) ) 00169 return true; 00170 00171 if ( contact.role().contains( filterString, Qt::CaseInsensitive ) ) 00172 return true; 00173 00174 if ( contact.organization().contains( filterString, Qt::CaseInsensitive ) ) 00175 return true; 00176 00177 if ( contact.department().contains( filterString, Qt::CaseInsensitive ) ) 00178 return true; 00179 00180 if ( contact.note().contains( filterString, Qt::CaseInsensitive ) ) 00181 return true; 00182 00183 if ( contact.url().url().contains( filterString, Qt::CaseInsensitive ) ) 00184 return true; 00185 00186 const QStringList customs = contact.customs(); 00187 count = customs.count(); 00188 for ( int i = 0; i < count; ++i ) { 00189 if ( customs.at( i ).contains( filterString, Qt::CaseInsensitive ) ) 00190 return true; 00191 } 00192 00193 return false; 00194 } 00195 00196 bool contactGroupMatchesFilter( const KABC::ContactGroup &group, const QString &filterString ) 00197 { 00198 if ( group.name().contains( filterString, Qt::CaseInsensitive ) ) 00199 return true; 00200 00201 const int count = group.dataCount(); 00202 for ( int i = 0; i < count; ++i ) { 00203 if ( group.data( i ).name().contains( filterString, Qt::CaseInsensitive ) ) 00204 return true; 00205 if ( group.data( i ).email().contains( filterString, Qt::CaseInsensitive ) ) 00206 return true; 00207 } 00208 00209 return false; 00210 } 00211 00212 #include "contactsfilterproxymodel.moc"