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

Nepomuk-Core

  • KTp
  • Models
contacts-filter-model.cpp
Go to the documentation of this file.
1 /*
2  * Provide some filters on the account model
3  *
4  * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk>
5  * Copyright (C) 2011 Martin Klapetek <martin dot klapetek at gmail dot com>
6  * Copyright (C) 2012 Daniele E. Domenichelli <daniele.domenichelli@gmail.com>
7  * Copyright (C) 2012 Dominik Cermak <d.cermak@arcor.de>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23 
24 #include "contacts-filter-model.h"
25 
26 #include "types.h"
27 
28 #include <presence.h>
29 
30 #include <KDebug>
31 
32 
33 class KTp::ContactsFilterModel::Private
34 {
35 public:
36  Private(ContactsFilterModel *parent)
37  : q(parent),
38  presenceTypeFilterFlags(DoNotFilterByPresence),
39  capabilityFilterFlags(DoNotFilterByCapability),
40  subscriptionStateFilterFlags(DoNotFilterBySubscription),
41  globalFilterMatchFlags(Qt::MatchContains),
42  displayNameFilterMatchFlags(Qt::MatchContains),
43  nicknameFilterMatchFlags(Qt::MatchContains),
44  aliasFilterMatchFlags(Qt::MatchContains),
45  groupsFilterMatchFlags(Qt::MatchContains),
46  idFilterMatchFlags(Qt::MatchContains)
47  {
48  }
49 
50  ContactsFilterModel *q;
51 
52  PresenceTypeFilterFlags presenceTypeFilterFlags;
53  CapabilityFilterFlags capabilityFilterFlags;
54  SubscriptionStateFilterFlags subscriptionStateFilterFlags;
55 
56  QString globalFilterString;
57  Qt::MatchFlags globalFilterMatchFlags;
58 
59  QString displayNameFilterString;
60  QString nicknameFilterString;
61  QString aliasFilterString;
62  QString groupsFilterString;
63  QString idFilterString;
64  QStringList tubesFilterStrings;
65  Qt::MatchFlags displayNameFilterMatchFlags;
66  Qt::MatchFlags nicknameFilterMatchFlags;
67  Qt::MatchFlags aliasFilterMatchFlags;
68  Qt::MatchFlags groupsFilterMatchFlags;
69  Qt::MatchFlags idFilterMatchFlags;
70  Tp::AccountPtr accountFilter;
71 
72  bool filterAcceptsAccount(const QModelIndex &index) const;
73  bool filterAcceptsContact(const QModelIndex &index) const;
74  bool filterAcceptsGroup(const QModelIndex &index);
75 
76  void countContacts(const QModelIndex &sourceParent);
77  void sourceModelChanged(const QModelIndex &sourceIndex);
78 
79  QHash<QString, int> m_onlineContactsCounts;
80  QHash<QString, int> m_totalContactsCounts;
81 };
82 
83 using namespace KTp;
84 
85 bool ContactsFilterModel::Private::filterAcceptsAccount(const QModelIndex &index) const
86 {
87  // Check capability
88  if (capabilityFilterFlags != DoNotFilterByCapability) {
89  if ((capabilityFilterFlags & FilterByTextChatCapability)
90  && !index.data(KTp::ContactCanTextChatRole).toBool()) {
91  return false;
92  }
93  if ((capabilityFilterFlags & FilterByAudioCallCapability)
94  && !index.data(KTp::ContactCanAudioCallRole).toBool()) {
95  return false;
96  }
97  if ((capabilityFilterFlags & FilterByVideoCallCapability)
98  && !index.data(KTp::ContactCanVideoCallRole).toBool()) {
99  return false;
100  }
101  if ((capabilityFilterFlags & FilterByFileTransferCapability)
102  && !index.data(KTp::ContactCanFileTransferRole).toBool()) {
103  return false;
104  }
105  if (capabilityFilterFlags & FilterByTubes) {
106  Q_FOREACH(const QString &tube, index.data(KTp::ContactTubesRole).toStringList()) {
107  if (tubesFilterStrings.contains(tube)) {
108  return true;
109  }
110  }
111  return false;
112  }
113  }
114 
115  return true;
116 }
117 
118 bool ContactsFilterModel::Private::filterAcceptsContact(const QModelIndex &index) const
119 {
120  // Presence type, capability and subscription state are always checked
121  // Then if global filter is set we can return true if a result is found for
122  // any of the strings, otherwise we check all of them
123 
124  Q_ASSERT(index.isValid());
125  if (!index.isValid()) {
126  return false;
127  }
128 
129  // Check presence type
130  if (presenceTypeFilterFlags != DoNotFilterByPresence) {
131  switch (static_cast<Tp::ConnectionPresenceType>(index.data(KTp::ContactPresenceTypeRole).toUInt())) {
132  case Tp::ConnectionPresenceTypeUnset:
133  if (presenceTypeFilterFlags & HidePresenceTypeUnset) {
134  return false;
135  }
136  break;
137  case Tp::ConnectionPresenceTypeOffline:
138  if (presenceTypeFilterFlags & HidePresenceTypeOffline) {
139  return false;
140  }
141  break;
142  case Tp::ConnectionPresenceTypeAvailable:
143  if (presenceTypeFilterFlags & HidePresenceTypeAvailable) {
144  return false;
145  }
146  break;
147  case Tp::ConnectionPresenceTypeAway:
148  if (presenceTypeFilterFlags & HidePresenceTypeAway) {
149  return false;
150  }
151  break;
152  case Tp::ConnectionPresenceTypeExtendedAway:
153  if (presenceTypeFilterFlags & HidePresenceTypeExtendedAway) {
154  return false;
155  }
156  break;
157  case Tp::ConnectionPresenceTypeHidden:
158  if (presenceTypeFilterFlags & HidePresenceTypeHidden) {
159  return false;
160  }
161  break;
162  case Tp::ConnectionPresenceTypeBusy:
163  if (presenceTypeFilterFlags & HidePresenceTypeBusy) {
164  return false;
165  }
166  break;
167  case Tp::ConnectionPresenceTypeUnknown:
168  if (presenceTypeFilterFlags & HidePresenceTypeUnknown) {
169  return false;
170  }
171  break;
172  case Tp::ConnectionPresenceTypeError:
173  if (presenceTypeFilterFlags & HidePresenceTypeError) {
174  return false;
175  }
176  break;
177  default:
178  //This should never happen
179  Q_ASSERT(false);
180  return false;
181  }
182  }
183 
184 
185  // Check capability
186  if (capabilityFilterFlags != DoNotFilterByCapability) {
187  if ((capabilityFilterFlags & FilterByTextChatCapability)
188  && !index.data(KTp::ContactCanTextChatRole).toBool()) {
189  return false;
190  }
191  if ((capabilityFilterFlags & FilterByAudioCallCapability)
192  && !index.data(KTp::ContactCanAudioCallRole).toBool()) {
193  return false;
194  }
195  if ((capabilityFilterFlags & FilterByVideoCallCapability)
196  && !index.data(KTp::ContactCanVideoCallRole).toBool()) {
197  return false;
198  }
199  if ((capabilityFilterFlags & FilterByFileTransferCapability)
200  && !index.data(KTp::ContactCanFileTransferRole).toBool()) {
201  return false;
202  }
203  if (capabilityFilterFlags & FilterByTubes) {
204  if (!tubesFilterStrings.isEmpty()) {
205  bool tubeFound = false;
206  Q_FOREACH(const QString &tube, index.data(KTp::ContactTubesRole).toStringList()) {
207  if (tubesFilterStrings.contains(tube)) {
208  tubeFound = true;
209  }
210  }
211  if (!tubeFound) {
212  return false;
213  }
214  }
215  }
216  }
217 
218 
219  // Check subscription state
220  if (subscriptionStateFilterFlags != DoNotFilterBySubscription) {
221  switch (index.data(KTp::ContactSubscriptionStateRole).toUInt()) {
222  case Tp::Contact::PresenceStateNo:
223  if (subscriptionStateFilterFlags & HideSubscriptionStateNo) {
224  return false;
225  }
226  break;
227  case Tp::Contact::PresenceStateAsk:
228  if (subscriptionStateFilterFlags & HideSubscriptionStateAsk) {
229  return false;
230  }
231  break;
232  case Tp::Contact::PresenceStateYes:
233  if (subscriptionStateFilterFlags & HideSubscriptionStateYes) {
234  return false;
235  }
236  break;
237  default:
238  //This should never happen
239  Q_ASSERT(false);
240  return false;
241  }
242 
243  switch (index.data(KTp::ContactPublishStateRole).toUInt()) {
244  case Tp::Contact::PresenceStateNo:
245  if (subscriptionStateFilterFlags & HidePublishStateNo) {
246  return false;
247  }
248  break;
249  case Tp::Contact::PresenceStateAsk:
250  if (subscriptionStateFilterFlags & HidePublishStateAsk) {
251  return false;
252  }
253  break;
254  case Tp::Contact::PresenceStateYes:
255  if (subscriptionStateFilterFlags & HidePublishStateYes) {
256  return false;
257  }
258  break;
259  default:
260  //This should never happen
261  Q_ASSERT(false);
262  return false;
263  }
264 
265  if (index.data(KTp::ContactIsBlockedRole).toBool()) {
266  if (subscriptionStateFilterFlags & HideBlocked) {
267  return false;
268  }
269  } else {
270  if (subscriptionStateFilterFlags & HideNonBlocked) {
271  return false;
272  }
273  }
274  }
275 
276  if (!globalFilterString.isEmpty()) {
277  // Check global filter (search on all the roles)
278 
279  // Check display name
280  if (!q->match(index, Qt::DisplayRole, globalFilterString, 1, globalFilterMatchFlags).isEmpty()) {
281  return true;
282  }
283 
284  // check groups
285  // TODO Check if exact match on a single group works
286  if (!q->match(index, KTp::ContactGroupsRole, globalFilterString, 1, globalFilterMatchFlags).isEmpty()) {
287  return true;
288  }
289 
290  // Check id
291  if (!q->match(index, KTp::IdRole, globalFilterString, 1, globalFilterMatchFlags).isEmpty()) {
292  return true;
293  }
294 
295  return false;
296  } else {
297  // Check on single filters
298  // Check display name
299  if (!displayNameFilterString.isEmpty()) {
300  if (q->match(index, Qt::DisplayRole, displayNameFilterString, 1, displayNameFilterMatchFlags).isEmpty()) {
301  return false;
302  }
303  }
304  // check groups
305  // TODO Check if exact match on a single group works
306  if (!groupsFilterString.isEmpty()) {
307  if (q->match(index, KTp::ContactGroupsRole, groupsFilterString, 1, groupsFilterMatchFlags).isEmpty()) {
308  return false;
309  }
310  }
311 
312  // Check id
313  if (!idFilterString.isEmpty()) {
314  if (q->match(index, KTp::IdRole, idFilterString, 1, idFilterMatchFlags).isEmpty()) {
315  return false;
316  }
317  }
318  }
319 
320  //check account
321  if (accountFilter) {
322  if(index.data(KTp::AccountRole).value<Tp::AccountPtr>() != accountFilter) {
323  return false;
324  }
325  }
326 
327  return true;
328 }
329 
330 bool ContactsFilterModel::Private::filterAcceptsGroup(const QModelIndex &index)
331 {
332  QString groupName = index.data(KTp::IdRole).toString();
333 
334  if (presenceTypeFilterFlags != DoNotFilterByPresence) {
335  // If there is no cached value, create one
336  if (!m_onlineContactsCounts.contains(groupName)) {
337  countContacts(index);
338  }
339 
340  // Don't accept groups with no online contacts
341  if (m_onlineContactsCounts.value(groupName) == 0) {
342 // return false;
343  }
344  }
345  else {
346  // If there is no cached value, create one
347  if (!m_totalContactsCounts.contains(groupName)) {
348  countContacts(index);
349  }
350 
351  // Don't accept groups with no total contacts
352  if (m_totalContactsCounts.value(groupName) == 0) {
353 // return false;
354  }
355  }
356  return true;
357 }
358 
359 void ContactsFilterModel::Private::countContacts(const QModelIndex &sourceParent)
360 {
361  QString key = sourceParent.data(KTp::IdRole).toString();
362 
363  // Count the online contacts
364  int tmpCounter = 0;
365 
366  for (int i = 0; i < q->sourceModel()->rowCount(sourceParent); ++i) {
367  QModelIndex child = q->sourceModel()->index(i, 0, sourceParent);
368 
369  // We want all online contacts that are accepted by the filter
370  if (q->filterAcceptsRow(child.row(), sourceParent)
371  && child.data(KTp::ContactPresenceTypeRole).toUInt() != Tp::ConnectionPresenceTypeOffline
372  && child.data(KTp::ContactPresenceTypeRole).toUInt() != Tp::ConnectionPresenceTypeUnknown) {
373  tmpCounter++;
374  }
375  }
376 
377  m_onlineContactsCounts.insert(key, tmpCounter);
378 
379  // Now count the total contacts accepted by the filter (but ignore presence filter).
380  // Save the presenceTypeFilterFlags to reapply them later, because we need to disable
381  // presence filtering to get the right numbers
382  PresenceTypeFilterFlags saved = q->presenceTypeFilterFlags();
383  presenceTypeFilterFlags = ContactsFilterModel::DoNotFilterByPresence;
384 
385  tmpCounter = 0;
386  for (int i = 0; i < q->sourceModel()->rowCount(sourceParent); ++i) {
387  QModelIndex child = q->sourceModel()->index(i, 0, sourceParent);
388  if (q->filterAcceptsRow(child.row(), sourceParent)) {
389  tmpCounter++;
390  }
391  }
392 
393  // Restore the saved presenceTypeFilterFlags
394  presenceTypeFilterFlags = saved;
395 
396  m_totalContactsCounts.insert(key, tmpCounter);
397 }
398 
399 void ContactsFilterModel::Private::sourceModelChanged(const QModelIndex &sourceIndex)
400 {
401  QModelIndex groupSourceIndex;
402  if (sourceIndex.data(KTp::RowTypeRole).toUInt() == KTp::ContactRowType) {
403  groupSourceIndex = sourceIndex.parent();
404  } else {
405  groupSourceIndex = sourceIndex;
406  }
407 
408  countContacts(groupSourceIndex);
409 
410  const QModelIndex mappedIndex = q->mapFromSource(sourceIndex);
411  Q_EMIT q->dataChanged(mappedIndex, mappedIndex);
412 }
413 
414 
415 ContactsFilterModel::ContactsFilterModel(QObject *parent)
416  : QSortFilterProxyModel(parent),
417  d(new Private(this))
418 {
419  sort(0); //sort always
420  setDynamicSortFilter(true);
421 }
422 
423 ContactsFilterModel::~ContactsFilterModel()
424 {
425  delete d;
426 }
427 
428 QVariant ContactsFilterModel::data(const QModelIndex &index, int role) const
429 {
430  if (!index.isValid()) {
431  return QVariant();
432  }
433 
434  QModelIndex sourceIndex = mapToSource(index);
435  if (!sourceIndex.isValid()) {
436  return QVariant();
437  }
438 
439  if (role == KTp::HeaderOnlineUsersRole) {
440  const QString &key = sourceIndex.data(KTp::IdRole).toString();
441  if (!d->m_onlineContactsCounts.contains(key)) {
442  d->countContacts(sourceIndex);
443  }
444  return d->m_onlineContactsCounts.value(key);
445  } else if (role == KTp::HeaderTotalUsersRole) {
446  const QString &key = sourceIndex.data(KTp::IdRole).toString();
447  if (!d->m_totalContactsCounts.contains(key)) {
448  d->countContacts(sourceIndex);
449  }
450  return d->m_totalContactsCounts.value(key);
451  }
452 
453  // In all other cases just delegate it to the source model
454  return sourceModel()->data(sourceIndex, role);
455 }
456 
457 void ContactsFilterModel::setSourceModel(QAbstractItemModel *sourceModel)
458 {
459  // Disconnect the previous source model
460  if (this->sourceModel()) {
461  disconnect(this->sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
462  this, SLOT(sourceModelChanged(QModelIndex)));
463  disconnect(this->sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
464  this, SLOT(sourceModelChanged(QModelIndex)));
465  disconnect(this->sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
466  this, SLOT(sourceModelChanged(QModelIndex)));
467  disconnect(this->sourceModel(), SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
468  this, SLOT(sourceModelChanged(QModelIndex)));
469  }
470 
471  // Clear all cached values as they aren't valid anymore because the source model changed.
472  d->m_onlineContactsCounts.clear();
473  d->m_totalContactsCounts.clear();
474  QSortFilterProxyModel::setSourceModel(sourceModel);
475 
476  // Connect the new source model
477  connect(this->sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
478  this, SLOT(sourceModelChanged(QModelIndex)));
479  connect(this->sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
480  this, SLOT(sourceModelChanged(QModelIndex)));
481  connect(this->sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)),
482  this, SLOT(sourceModelChanged(QModelIndex)));
483  connect(this->sourceModel(), SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
484  this, SLOT(sourceModelChanged(QModelIndex)));
485 }
486 
487 void ContactsFilterModel::invalidateFilter()
488 {
489  // Clear all cached values as they aren't valid anymore because the filter changed.
490  d->m_onlineContactsCounts.clear();
491  d->m_totalContactsCounts.clear();
492  QSortFilterProxyModel::invalidateFilter();
493 }
494 
495 ContactsFilterModel::PresenceTypeFilterFlags ContactsFilterModel::presenceTypeFilterFlags() const
496 {
497  return d->presenceTypeFilterFlags;
498 }
499 
500 void ContactsFilterModel::clearPresenceTypeFilterFlags()
501 {
502  setPresenceTypeFilterFlags(DoNotFilterByPresence);
503 }
504 
505 void ContactsFilterModel::setPresenceTypeFilterFlags(ContactsFilterModel::PresenceTypeFilterFlags presenceTypeFilterFlags)
506 {
507  if (d->presenceTypeFilterFlags != presenceTypeFilterFlags) {
508  d->presenceTypeFilterFlags = presenceTypeFilterFlags;
509  invalidateFilter();
510  Q_EMIT presenceTypeFilterFlagsChanged(presenceTypeFilterFlags);
511  }
512 }
513 
514 ContactsFilterModel::CapabilityFilterFlags ContactsFilterModel::capabilityFilterFlags() const
515 {
516  return d->capabilityFilterFlags;
517 }
518 
519 void ContactsFilterModel::clearCapabilityFilterFlags()
520 {
521  setCapabilityFilterFlags(DoNotFilterByCapability);
522 }
523 
524 void ContactsFilterModel::setCapabilityFilterFlags(ContactsFilterModel::CapabilityFilterFlags capabilityFilterFlags)
525 {
526  if (d->capabilityFilterFlags != capabilityFilterFlags) {
527  d->capabilityFilterFlags = capabilityFilterFlags;
528  invalidateFilter();
529  Q_EMIT capabilityFilterFlagsChanged(capabilityFilterFlags);
530  }
531 }
532 
533 ContactsFilterModel::SubscriptionStateFilterFlags ContactsFilterModel::subscriptionStateFilterFlags() const
534 {
535  return d->subscriptionStateFilterFlags;
536 }
537 
538 void ContactsFilterModel::clearSubscriptionStateFilterFlags()
539 {
540  setSubscriptionStateFilterFlags(DoNotFilterBySubscription);
541 }
542 
543 void ContactsFilterModel::setSubscriptionStateFilterFlags(ContactsFilterModel::SubscriptionStateFilterFlags subscriptionStateFilterFlags)
544 {
545  if (d->subscriptionStateFilterFlags != subscriptionStateFilterFlags) {
546  d->subscriptionStateFilterFlags = subscriptionStateFilterFlags;
547  invalidateFilter();
548  Q_EMIT subscriptionStateFilterFlagsChanged(subscriptionStateFilterFlags);
549  }
550 }
551 
552 QString ContactsFilterModel::globalFilterString() const
553 {
554  return d->globalFilterString;
555 }
556 
557 void ContactsFilterModel::clearGlobalFilterString()
558 {
559  setGlobalFilterString(QString());
560 }
561 
562 void ContactsFilterModel::setGlobalFilterString(const QString &globalFilterString)
563 {
564  if (d->globalFilterString != globalFilterString) {
565  d->globalFilterString = globalFilterString;
566  invalidateFilter();
567  Q_EMIT globalFilterStringChanged(globalFilterString);
568  }
569 }
570 
571 Qt::MatchFlags ContactsFilterModel::globalFilterMatchFlags() const
572 {
573  return d->globalFilterMatchFlags;
574 }
575 
576 void ContactsFilterModel::resetGlobalFilterMatchFlags()
577 {
578  setGlobalFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
579 }
580 
581 void ContactsFilterModel::setGlobalFilterMatchFlags(Qt::MatchFlags globalFilterMatchFlags)
582 {
583  if (d->globalFilterMatchFlags != globalFilterMatchFlags) {
584  d->globalFilterMatchFlags = globalFilterMatchFlags;
585  invalidateFilter();
586  Q_EMIT globalFilterMatchFlagsChanged(globalFilterMatchFlags);
587  }
588 }
589 
590 QString ContactsFilterModel::displayNameFilterString() const
591 {
592  return d->displayNameFilterString;
593 }
594 
595 void ContactsFilterModel::clearDisplayNameFilterString()
596 {
597  setDisplayNameFilterString(QString());
598 }
599 
600 void ContactsFilterModel::setDisplayNameFilterString(const QString &displayNameFilterString)
601 {
602  if (d->displayNameFilterString != displayNameFilterString) {
603  d->displayNameFilterString = displayNameFilterString;
604  invalidateFilter();
605  Q_EMIT displayNameFilterStringChanged(displayNameFilterString);
606  }
607 }
608 
609 Qt::MatchFlags ContactsFilterModel::displayNameFilterMatchFlags() const
610 {
611  return d->displayNameFilterMatchFlags;
612 }
613 
614 void ContactsFilterModel::resetDisplayNameFilterMatchFlags()
615 {
616  setDisplayNameFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
617 }
618 
619 void ContactsFilterModel::setDisplayNameFilterMatchFlags(Qt::MatchFlags displayNameFilterMatchFlags)
620 {
621  if (d->displayNameFilterMatchFlags != displayNameFilterMatchFlags) {
622  d->displayNameFilterMatchFlags = displayNameFilterMatchFlags;
623  invalidateFilter();
624  Q_EMIT displayNameFilterMatchFlagsChanged(displayNameFilterMatchFlags);
625  }
626 }
627 
628 QString ContactsFilterModel::nicknameFilterString() const
629 {
630  return d->nicknameFilterString;
631 }
632 
633 void ContactsFilterModel::clearNicknameFilterString()
634 {
635  setNicknameFilterString(QString());
636 }
637 
638 void ContactsFilterModel::setNicknameFilterString(const QString &nicknameFilterString)
639 {
640  if (d->nicknameFilterString != nicknameFilterString) {
641  d->nicknameFilterString = nicknameFilterString;
642  invalidateFilter();
643  Q_EMIT nicknameFilterStringChanged(nicknameFilterString);
644  }
645 }
646 
647 Qt::MatchFlags ContactsFilterModel::nicknameFilterMatchFlags() const
648 {
649  return d->nicknameFilterMatchFlags;
650 }
651 
652 void ContactsFilterModel::resetNicknameFilterMatchFlags()
653 {
654  setNicknameFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
655 }
656 
657 void ContactsFilterModel::setNicknameFilterMatchFlags(Qt::MatchFlags nicknameFilterMatchFlags)
658 {
659  if (d->nicknameFilterMatchFlags != nicknameFilterMatchFlags) {
660  d->nicknameFilterMatchFlags = nicknameFilterMatchFlags;
661  invalidateFilter();
662  Q_EMIT nicknameFilterMatchFlagsChanged(nicknameFilterMatchFlags);
663  }
664 }
665 
666 QString ContactsFilterModel::aliasFilterString() const
667 {
668  return d->aliasFilterString;
669 }
670 
671 void ContactsFilterModel::clearAliasFilterString()
672 {
673  setAliasFilterString(QString());
674 }
675 
676 void ContactsFilterModel::setAliasFilterString(const QString &aliasFilterString)
677 {
678  if (d->aliasFilterString != aliasFilterString) {
679  d->aliasFilterString = aliasFilterString;
680  invalidateFilter();
681  Q_EMIT aliasFilterStringChanged(aliasFilterString);
682  }
683 }
684 
685 Qt::MatchFlags ContactsFilterModel::aliasFilterMatchFlags() const
686 {
687  return d->aliasFilterMatchFlags;
688 }
689 
690 void ContactsFilterModel::resetAliasFilterMatchFlags()
691 {
692  setAliasFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
693 }
694 
695 void ContactsFilterModel::setAliasFilterMatchFlags(Qt::MatchFlags aliasFilterMatchFlags)
696 {
697  if (d->aliasFilterMatchFlags != aliasFilterMatchFlags) {
698  d->aliasFilterMatchFlags = aliasFilterMatchFlags;
699  invalidateFilter();
700  Q_EMIT aliasFilterMatchFlagsChanged(aliasFilterMatchFlags);
701  }
702 }
703 
704 QString ContactsFilterModel::groupsFilterString() const
705 {
706  return d->groupsFilterString;
707 }
708 
709 void ContactsFilterModel::clearGroupsFilterString()
710 {
711  setGroupsFilterString(QString());
712 }
713 
714 void ContactsFilterModel::setGroupsFilterString(const QString &groupsFilterString)
715 {
716  if (d->groupsFilterString != groupsFilterString) {
717  d->groupsFilterString = groupsFilterString;
718  invalidateFilter();
719  Q_EMIT groupsFilterStringChanged(groupsFilterString);
720  }
721 }
722 
723 Qt::MatchFlags ContactsFilterModel::groupsFilterMatchFlags() const
724 {
725  return d->groupsFilterMatchFlags;
726 }
727 
728 void ContactsFilterModel::resetGroupsFilterMatchFlags()
729 {
730  setGroupsFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
731 }
732 
733 void ContactsFilterModel::setGroupsFilterMatchFlags(Qt::MatchFlags groupsFilterMatchFlags)
734 {
735  if (d->groupsFilterMatchFlags != groupsFilterMatchFlags) {
736  d->groupsFilterMatchFlags = groupsFilterMatchFlags;
737  invalidateFilter();
738  Q_EMIT groupsFilterMatchFlagsChanged(groupsFilterMatchFlags);
739  }
740 }
741 
742 QString ContactsFilterModel::idFilterString() const
743 {
744  return d->idFilterString;
745 }
746 
747 void ContactsFilterModel::clearIdFilterString()
748 {
749  setIdFilterString(QString());
750 }
751 
752 void ContactsFilterModel::setIdFilterString(const QString &idFilterString)
753 {
754  if (d->idFilterString != idFilterString) {
755  d->idFilterString = idFilterString;
756  invalidateFilter();
757  Q_EMIT idFilterStringChanged(idFilterString);
758  }
759 }
760 
761 Qt::MatchFlags ContactsFilterModel::idFilterMatchFlags() const
762 {
763  return d->idFilterMatchFlags;
764 }
765 
766 
767 Tp::AccountPtr ContactsFilterModel::accountFilter() const
768 {
769  return d->accountFilter;
770 }
771 
772 void ContactsFilterModel::setAccountFilter(const Tp::AccountPtr &accountFilter)
773 {
774  if (d->accountFilter != accountFilter) {
775  d->accountFilter = accountFilter;
776  invalidateFilter();
777  Q_EMIT accountFilterChanged(accountFilter);
778  }
779 }
780 
781 void ContactsFilterModel::clearAccountFilter()
782 {
783  setAccountFilter(Tp::AccountPtr());
784 }
785 
786 void ContactsFilterModel::resetIdFilterMatchFlags()
787 {
788  setIdFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
789 }
790 
791 void ContactsFilterModel::setIdFilterMatchFlags(Qt::MatchFlags idFilterMatchFlags)
792 {
793  if (d->idFilterMatchFlags != idFilterMatchFlags) {
794  d->idFilterMatchFlags = idFilterMatchFlags;
795  invalidateFilter();
796  Q_EMIT idFilterMatchFlagsChanged(idFilterMatchFlags);
797  }
798 }
799 
800 QStringList ContactsFilterModel::tubesFilterStrings() const
801 {
802  return d->tubesFilterStrings;
803 }
804 
805 void ContactsFilterModel::clearTubesFilterStrings()
806 {
807  setTubesFilterStrings(QStringList());
808 }
809 
810 void ContactsFilterModel::setTubesFilterStrings(const QStringList &tubesFilterStrings)
811 {
812  if (d->tubesFilterStrings != tubesFilterStrings) {
813  d->tubesFilterStrings = tubesFilterStrings;
814  invalidateFilter();
815  Q_EMIT tubesFilterStringsChanged(tubesFilterStrings);
816  }
817 }
818 
819 bool ContactsFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
820 {
821  QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
822 
823  int type = index.data(KTp::RowTypeRole).toInt();
824  if (type == KTp::ContactRowType) {
825  return d->filterAcceptsContact(index);
826  }
827  else if (type == KTp::AccountRowType) {
828  return d->filterAcceptsAccount(index);
829  }
830  else if (type == KTp::GroupRowType) {
831  return d->filterAcceptsGroup(index);
832  }
833  else {
834  kDebug() << "Unknown type found in Account Filter";
835  return true;
836  }
837 }
838 
839 bool ContactsFilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
840 {
841 
842  QString leftDisplayedName = sourceModel()->data(left).toString();
843  QString rightDisplayedName = sourceModel()->data(right).toString();
844 
845  switch (sortRole()) {
846  case KTp::ContactPresenceTypeRole:
847  {
848  Tp::ConnectionPresenceType leftPresence = (Tp::ConnectionPresenceType)left.data(KTp::ContactPresenceTypeRole).toUInt();
849  Tp::ConnectionPresenceType rightPresence = (Tp::ConnectionPresenceType)right.data(KTp::ContactPresenceTypeRole).toUInt();
850 
851  if (leftPresence == rightPresence) {
852  //presences are the same, compare client types
853 
854  bool leftPhone = left.data(KTp::ContactClientTypesRole).toStringList().contains(QLatin1String("phone"));
855  bool rightPhone = right.data(KTp::ContactClientTypesRole).toStringList().contains(QLatin1String("phone"));
856 
857  if (leftPhone && ! rightPhone) {
858  return false;
859  }
860  else if (rightPhone && !leftPhone) {
861  return true;
862  }
863 
864  return QString::localeAwareCompare(leftDisplayedName, rightDisplayedName) < 0;
865  } else {
866  if (leftPresence == Tp::ConnectionPresenceTypeAvailable) {
867  return true;
868  }
869  if (leftPresence == Tp::ConnectionPresenceTypeUnset ||
870  leftPresence == Tp::ConnectionPresenceTypeOffline ||
871  leftPresence == Tp::ConnectionPresenceTypeUnknown ||
872  leftPresence == Tp::ConnectionPresenceTypeError) {
873  return false;
874  }
875 
876  return KTp::Presence::sortPriority(leftPresence) < KTp::Presence::sortPriority(rightPresence);
877  }
878  }
879  case Qt::DisplayRole:
880  default:
881  return QString::localeAwareCompare(leftDisplayedName, rightDisplayedName) < 0;
882  }
883 }
884 
885 
886 QModelIndexList ContactsFilterModel::match(const QModelIndex &start, int role,
887  const QVariant &value, int hits,
888  Qt::MatchFlags flags) const
889 {
890  if (!start.isValid()) {
891  return QModelIndexList();
892  }
893 
894  QModelIndexList result;
895  uint matchType = flags & 0x0F;
896  Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
897  bool recurse = flags & Qt::MatchRecursive;
898  bool allHits = (hits == -1);
899  QString text; // only convert to a string if it is needed
900  QVariant v = start.data(role);
901  // QVariant based matching
902  if (matchType == Qt::MatchExactly) {
903  if (value == v)
904  result.append(start);
905  } else { // QString based matching
906  if (text.isEmpty()) // lazy conversion
907  text = value.toString();
908  QString t = v.toString();
909  switch (matchType) {
910  case Qt::MatchRegExp:
911  if (QRegExp(text, cs).exactMatch(t))
912  result.append(start);
913  break;
914  case Qt::MatchWildcard:
915  if (QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t))
916  result.append(start);
917  break;
918  case Qt::MatchStartsWith:
919  if (t.startsWith(text, cs))
920  result.append(start);
921  break;
922  case Qt::MatchEndsWith:
923  if (t.endsWith(text, cs))
924  result.append(start);
925  break;
926  case Qt::MatchFixedString:
927  if (t.compare(text, cs) == 0)
928  result.append(start);
929  break;
930  case Qt::MatchContains:
931  default:
932  if (t.contains(text, cs))
933  result.append(start);
934  }
935  }
936  if (recurse && hasChildren(start)) { // search the hierarchy
937  result += match(index(0, start.column(), start), role,
938  (text.isEmpty() ? value : text),
939  (allHits ? -1 : hits - result.count()), flags);
940  }
941  return result;
942 }
943 
944 void ContactsFilterModel::setSortRoleString(const QString &role)
945 {
946  Q_ASSERT(!roleNames().keys(role.toUtf8()).isEmpty());
947  setSortRole(roleNames().key(role.toUtf8()));
948 }
949 
950 QString ContactsFilterModel::sortRoleString() const
951 {
952  Q_ASSERT(roleNames().contains(sortRole()));
953  return QString::fromUtf8(roleNames().value(sortRole()));
954 }
955 
956 #include "contacts-filter-model.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Fri Mar 22 2013 10:58:52 by doxygen 1.8.1.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

ktp-common-internals API Reference

Skip menu "ktp-common-internals API Reference"
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