• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • sources
  • kde-4.14
  • kdepimlibs
  • akonadi
  • contact
contactsfilterproxymodel.cpp
1 /*
2  This file is part of Akonadi Contact.
3 
4  Copyright (c) 2009 Tobias Koenig <tokoe@kde.org>
5 
6  This library is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Library General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or (at your
9  option) any later version.
10 
11  This library is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14  License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to the
18  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  02110-1301, USA.
20 */
21 
22 #include "contactsfilterproxymodel.h"
23 
24 #include "contactstreemodel.h"
25 
26 #include <akonadi/entitytreemodel.h>
27 #include <kabc/addressee.h>
28 #include <kabc/contactgroup.h>
29 
30 static bool contactMatchesFilter( const KABC::Addressee &contact, const QString &filterString );
31 static bool contactGroupMatchesFilter( const KABC::ContactGroup &group, const QString &filterString );
32 
33 using namespace Akonadi;
34 
35 class ContactsFilterProxyModel::Private
36 {
37  public:
38  Private()
39  : flags( 0 ),
40  mExcludeVirtualCollections( false )
41  {
42  }
43  QString mFilter;
44  ContactsFilterProxyModel::FilterFlags flags;
45  bool mExcludeVirtualCollections;
46 };
47 
48 ContactsFilterProxyModel::ContactsFilterProxyModel( QObject *parent )
49  : QSortFilterProxyModel( parent ), d( new Private )
50 {
51  // contact names should be sorted correctly
52  setSortLocaleAware( true );
53  setDynamicSortFilter( true );
54 }
55 
56 ContactsFilterProxyModel::~ContactsFilterProxyModel()
57 {
58  delete d;
59 }
60 
61 void ContactsFilterProxyModel::setFilterString( const QString &filter )
62 {
63  d->mFilter = filter;
64  invalidateFilter();
65 }
66 
67 bool ContactsFilterProxyModel::filterAcceptsRow( int row, const QModelIndex &parent ) const
68 {
69  const QModelIndex index = sourceModel()->index( row, 0, parent );
70  if ( d->mExcludeVirtualCollections ) {
71  const Akonadi::Collection collection = index.data( Akonadi::EntityTreeModel::CollectionRole ).value<Akonadi::Collection>();
72  if ( collection.isValid() && collection.isVirtual() ) {
73  return false;
74  }
75  }
76 
77  if ( ( d->mFilter.isEmpty() ) && ( !( d->flags & ContactsFilterProxyModel::HasEmail ) ) ) {
78  return true;
79  }
80 
81  const Akonadi::Item item = index.data( Akonadi::EntityTreeModel::ItemRole ).value<Akonadi::Item>();
82 
83  if ( item.hasPayload<KABC::Addressee>() ) {
84  const KABC::Addressee contact = item.payload<KABC::Addressee>();
85  if ( d->flags & ContactsFilterProxyModel::HasEmail ) {
86  if ( contact.emails().isEmpty() ) {
87  return false;
88  }
89  }
90  if ( !d->mFilter.isEmpty() ) {
91  return contactMatchesFilter( contact, d->mFilter );
92  }
93  } else {
94  if ( !d->mFilter.isEmpty() ) {
95  if ( item.hasPayload<KABC::ContactGroup>() ) {
96  const KABC::ContactGroup group = item.payload<KABC::ContactGroup>();
97  return contactGroupMatchesFilter( group, d->mFilter );
98  }
99  }
100  }
101 
102  return true;
103 }
104 
105 bool ContactsFilterProxyModel::lessThan( const QModelIndex &leftIndex, const QModelIndex &rightIndex ) const
106 {
107  const QDate leftDate = leftIndex.data( ContactsTreeModel::DateRole ).toDate();
108  const QDate rightDate = rightIndex.data( ContactsTreeModel::DateRole ).toDate();
109  if ( leftDate.isValid() && rightDate.isValid() ) {
110  if ( leftDate.month() < rightDate.month() ) {
111  return true;
112  } else if ( leftDate.month() == rightDate.month() ) {
113  if ( leftDate.day() < rightDate.day() ) {
114  return true;
115  }
116  } else {
117  return false;
118  }
119  }
120 
121  return QSortFilterProxyModel::lessThan( leftIndex, rightIndex );
122 }
123 
124 void ContactsFilterProxyModel::setFilterFlags( ContactsFilterProxyModel::FilterFlags flags )
125 {
126  d->flags = flags;
127 }
128 
129 void ContactsFilterProxyModel::setExcludeVirtualCollections( bool exclude )
130 {
131  if ( exclude != d->mExcludeVirtualCollections ) {
132  d->mExcludeVirtualCollections = exclude;
133  invalidateFilter();
134  }
135 }
136 
137 Qt::ItemFlags ContactsFilterProxyModel::flags( const QModelIndex& index ) const
138 {
139  if ( !index.isValid() ) {
140  // Don't crash
141  return 0;
142  }
143  const Akonadi::Collection collection = index.data( Akonadi::EntityTreeModel::CollectionRole ).value<Akonadi::Collection>();
144  if ( collection.isValid() ) {
145  return QSortFilterProxyModel::flags( index ) & ~( Qt::ItemIsSelectable );
146  }
147  return QSortFilterProxyModel::flags( index );
148 }
149 
150 static bool addressMatchesFilter( const KABC::Address &address, const QString &filterString )
151 {
152  if ( address.street().contains( filterString, Qt::CaseInsensitive ) ) {
153  return true;
154  }
155 
156  if ( address.locality().contains( filterString, Qt::CaseInsensitive ) ) {
157  return true;
158  }
159 
160  if ( address.region().contains( filterString, Qt::CaseInsensitive ) ) {
161  return true;
162  }
163 
164  if ( address.postalCode().contains( filterString, Qt::CaseInsensitive ) ) {
165  return true;
166  }
167 
168  if ( address.country().contains( filterString, Qt::CaseInsensitive ) ) {
169  return true;
170  }
171 
172  if ( address.label().contains( filterString, Qt::CaseInsensitive ) ) {
173  return true;
174  }
175 
176  if ( address.postOfficeBox().contains( filterString, Qt::CaseInsensitive ) ) {
177  return true;
178  }
179 
180  return false;
181 }
182 
183 static bool contactMatchesFilter( const KABC::Addressee &contact, const QString &filterString )
184 {
185  if ( contact.assembledName().contains( filterString, Qt::CaseInsensitive ) ) {
186  return true;
187  }
188 
189  if ( contact.formattedName().contains( filterString, Qt::CaseInsensitive ) ) {
190  return true;
191  }
192 
193  if ( contact.nickName().contains( filterString, Qt::CaseInsensitive ) ) {
194  return true;
195  }
196 
197  if ( contact.birthday().toString().contains( filterString, Qt::CaseInsensitive ) ) {
198  return true;
199  }
200 
201  const KABC::Address::List addresses = contact.addresses();
202  int count = addresses.count();
203  for ( int i = 0; i < count; ++i ) {
204  if ( addressMatchesFilter( addresses.at( i ), filterString ) ) {
205  return true;
206  }
207  }
208 
209  const KABC::PhoneNumber::List phoneNumbers = contact.phoneNumbers();
210  count = phoneNumbers.count();
211  for ( int i = 0; i < count; ++i ) {
212  if ( phoneNumbers.at( i ).number().contains( filterString, Qt::CaseInsensitive ) ) {
213  return true;
214  }
215  }
216 
217  const QStringList emails = contact.emails();
218  count = emails.count();
219  for ( int i = 0; i < count; ++i ) {
220  if ( emails.at( i ).contains( filterString, Qt::CaseInsensitive ) ) {
221  return true;
222  }
223  }
224 
225  const QStringList categories = contact.categories();
226  count = categories.count();
227  for ( int i = 0; i < count; ++i ) {
228  if ( categories.at( i ).contains( filterString, Qt::CaseInsensitive ) ) {
229  return true;
230  }
231  }
232 
233  if ( contact.mailer().contains( filterString, Qt::CaseInsensitive ) ) {
234  return true;
235  }
236 
237  if ( contact.title().contains( filterString, Qt::CaseInsensitive ) ) {
238  return true;
239  }
240 
241  if ( contact.role().contains( filterString, Qt::CaseInsensitive ) ) {
242  return true;
243  }
244 
245  if ( contact.organization().contains( filterString, Qt::CaseInsensitive ) ) {
246  return true;
247  }
248 
249  if ( contact.department().contains( filterString, Qt::CaseInsensitive ) ) {
250  return true;
251  }
252 
253  if ( contact.note().contains( filterString, Qt::CaseInsensitive ) ) {
254  return true;
255  }
256 
257  if ( contact.url().url().contains( filterString, Qt::CaseInsensitive ) ) {
258  return true;
259  }
260 
261  const QStringList customs = contact.customs();
262  count = customs.count();
263  for ( int i = 0; i < count; ++i ) {
264  if ( customs.at( i ).contains( filterString, Qt::CaseInsensitive ) ) {
265  return true;
266  }
267  }
268 
269  return false;
270 }
271 
272 bool contactGroupMatchesFilter( const KABC::ContactGroup &group, const QString &filterString )
273 {
274  if ( group.name().contains( filterString, Qt::CaseInsensitive ) ) {
275  return true;
276  }
277 
278  const uint count = group.dataCount();
279  for ( uint i = 0; i < count; ++i ) {
280  if ( group.data( i ).name().contains( filterString, Qt::CaseInsensitive ) ) {
281  return true;
282  }
283  if ( group.data( i ).email().contains( filterString, Qt::CaseInsensitive ) ) {
284  return true;
285  }
286  }
287 
288  return false;
289 }
290 
QSortFilterProxyModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
Akonadi::ContactsFilterProxyModel::~ContactsFilterProxyModel
virtual ~ContactsFilterProxyModel()
Destroys the contacts filter proxy model.
Definition: contactsfilterproxymodel.cpp:56
QSortFilterProxyModel::lessThan
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const
Akonadi::ContactsFilterProxyModel::setFilterString
void setFilterString(const QString &filter)
Sets the filter that is used to filter for matching contacts and contact groups.
Definition: contactsfilterproxymodel.cpp:61
QModelIndex
QAbstractItemModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const =0
QSortFilterProxyModel::flags
virtual Qt::ItemFlags flags(const QModelIndex &index) const
Akonadi::ContactsFilterProxyModel::setFilterFlags
void setFilterFlags(ContactsFilterProxyModel::FilterFlags flags)
Sets the filter flags.
Definition: contactsfilterproxymodel.cpp:124
Akonadi::Collection
Represents a collection of PIM items.
Definition: collection.h:75
QList::at
const T & at(int i) const
QVariant::value
T value() const
QDate::month
int month() const
Akonadi::ContactsTreeModel::DateRole
The QDate object for the current index.
Definition: contactstreemodel.h:162
QModelIndex::isValid
bool isValid() const
QList::count
int count(const T &value) const
QObject
QDate::day
int day() const
QDate::isValid
bool isValid() const
QSortFilterProxyModel::invalidateFilter
void invalidateFilter()
QSortFilterProxyModel::setDynamicSortFilter
void setDynamicSortFilter(bool enable)
QDate
Akonadi::EntityTreeModel::CollectionRole
The collection.
Definition: entitytreemodel.h:336
QString
Akonadi::ContactsFilterProxyModel::setExcludeVirtualCollections
void setExcludeVirtualCollections(bool exclude)
Sets whether we want virtual collections to be filtered or not.
Definition: contactsfilterproxymodel.cpp:129
QStringList
QSortFilterProxyModel
QVariant::toDate
QDate toDate() const
QSortFilterProxyModel::filterAcceptsRow
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
QAbstractProxyModel::sourceModel
QAbstractItemModel * sourceModel() const
QModelIndex::data
QVariant data(int role) const
Akonadi::EntityTreeModel::ItemRole
The Item.
Definition: entitytreemodel.h:332
Akonadi::ContactsFilterProxyModel::ContactsFilterProxyModel
ContactsFilterProxyModel(QObject *parent=0)
Creates a new contacts filter proxy model.
Definition: contactsfilterproxymodel.cpp:48
QSortFilterProxyModel::setSortLocaleAware
void setSortLocaleAware(bool on)
Akonadi::Entity::isValid
bool isValid() const
Returns whether the entity is valid.
Definition: entity.cpp:97
Akonadi::Collection::isVirtual
bool isVirtual() const
Returns whether the collection is virtual, for example a search collection.
Definition: collection.cpp:261
Qt::ItemFlags
typedef ItemFlags
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:38:02 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal