33 class KTp::ContactsFilterModel::Private
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)
52 PresenceTypeFilterFlags presenceTypeFilterFlags;
53 CapabilityFilterFlags capabilityFilterFlags;
54 SubscriptionStateFilterFlags subscriptionStateFilterFlags;
56 QString globalFilterString;
57 Qt::MatchFlags globalFilterMatchFlags;
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;
72 bool filterAcceptsAccount(
const QModelIndex &index)
const;
73 bool filterAcceptsContact(
const QModelIndex &index)
const;
74 bool filterAcceptsGroup(
const QModelIndex &index);
76 void countContacts(
const QModelIndex &sourceParent);
77 void sourceModelChanged(
const QModelIndex &sourceIndex);
79 QHash<QString, int> m_onlineContactsCounts;
80 QHash<QString, int> m_totalContactsCounts;
85 bool ContactsFilterModel::Private::filterAcceptsAccount(
const QModelIndex &index)
const
88 if (capabilityFilterFlags != DoNotFilterByCapability) {
89 if ((capabilityFilterFlags & FilterByTextChatCapability)
93 if ((capabilityFilterFlags & FilterByAudioCallCapability)
97 if ((capabilityFilterFlags & FilterByVideoCallCapability)
101 if ((capabilityFilterFlags & FilterByFileTransferCapability)
105 if (capabilityFilterFlags & FilterByTubes) {
107 if (tubesFilterStrings.contains(tube)) {
118 bool ContactsFilterModel::Private::filterAcceptsContact(
const QModelIndex &index)
const
124 Q_ASSERT(index.isValid());
125 if (!index.isValid()) {
130 if (presenceTypeFilterFlags != DoNotFilterByPresence) {
132 case Tp::ConnectionPresenceTypeUnset:
133 if (presenceTypeFilterFlags & HidePresenceTypeUnset) {
137 case Tp::ConnectionPresenceTypeOffline:
138 if (presenceTypeFilterFlags & HidePresenceTypeOffline) {
142 case Tp::ConnectionPresenceTypeAvailable:
143 if (presenceTypeFilterFlags & HidePresenceTypeAvailable) {
147 case Tp::ConnectionPresenceTypeAway:
148 if (presenceTypeFilterFlags & HidePresenceTypeAway) {
152 case Tp::ConnectionPresenceTypeExtendedAway:
153 if (presenceTypeFilterFlags & HidePresenceTypeExtendedAway) {
157 case Tp::ConnectionPresenceTypeHidden:
158 if (presenceTypeFilterFlags & HidePresenceTypeHidden) {
162 case Tp::ConnectionPresenceTypeBusy:
163 if (presenceTypeFilterFlags & HidePresenceTypeBusy) {
167 case Tp::ConnectionPresenceTypeUnknown:
168 if (presenceTypeFilterFlags & HidePresenceTypeUnknown) {
172 case Tp::ConnectionPresenceTypeError:
173 if (presenceTypeFilterFlags & HidePresenceTypeError) {
186 if (capabilityFilterFlags != DoNotFilterByCapability) {
187 if ((capabilityFilterFlags & FilterByTextChatCapability)
191 if ((capabilityFilterFlags & FilterByAudioCallCapability)
195 if ((capabilityFilterFlags & FilterByVideoCallCapability)
199 if ((capabilityFilterFlags & FilterByFileTransferCapability)
203 if (capabilityFilterFlags & FilterByTubes) {
204 if (!tubesFilterStrings.isEmpty()) {
205 bool tubeFound =
false;
207 if (tubesFilterStrings.contains(tube)) {
220 if (subscriptionStateFilterFlags != DoNotFilterBySubscription) {
222 case Tp::Contact::PresenceStateNo:
223 if (subscriptionStateFilterFlags & HideSubscriptionStateNo) {
227 case Tp::Contact::PresenceStateAsk:
228 if (subscriptionStateFilterFlags & HideSubscriptionStateAsk) {
232 case Tp::Contact::PresenceStateYes:
233 if (subscriptionStateFilterFlags & HideSubscriptionStateYes) {
244 case Tp::Contact::PresenceStateNo:
245 if (subscriptionStateFilterFlags & HidePublishStateNo) {
249 case Tp::Contact::PresenceStateAsk:
250 if (subscriptionStateFilterFlags & HidePublishStateAsk) {
254 case Tp::Contact::PresenceStateYes:
255 if (subscriptionStateFilterFlags & HidePublishStateYes) {
266 if (subscriptionStateFilterFlags & HideBlocked) {
270 if (subscriptionStateFilterFlags & HideNonBlocked) {
276 if (!globalFilterString.isEmpty()) {
280 if (!q->match(index, Qt::DisplayRole, globalFilterString, 1, globalFilterMatchFlags).isEmpty()) {
291 if (!q->match(index,
KTp::IdRole, globalFilterString, 1, globalFilterMatchFlags).isEmpty()) {
299 if (!displayNameFilterString.isEmpty()) {
300 if (q->match(index, Qt::DisplayRole, displayNameFilterString, 1, displayNameFilterMatchFlags).isEmpty()) {
306 if (!groupsFilterString.isEmpty()) {
313 if (!idFilterString.isEmpty()) {
314 if (q->match(index,
KTp::IdRole, idFilterString, 1, idFilterMatchFlags).isEmpty()) {
330 bool ContactsFilterModel::Private::filterAcceptsGroup(
const QModelIndex &index)
332 QString groupName = index.data(
KTp::IdRole).toString();
334 if (presenceTypeFilterFlags != DoNotFilterByPresence) {
336 if (!m_onlineContactsCounts.contains(groupName)) {
337 countContacts(index);
341 if (m_onlineContactsCounts.value(groupName) == 0) {
347 if (!m_totalContactsCounts.contains(groupName)) {
348 countContacts(index);
352 if (m_totalContactsCounts.value(groupName) == 0) {
359 void ContactsFilterModel::Private::countContacts(
const QModelIndex &sourceParent)
361 QString key = sourceParent.data(
KTp::IdRole).toString();
366 for (
int i = 0; i < q->sourceModel()->rowCount(sourceParent); ++i) {
367 QModelIndex child = q->sourceModel()->index(i, 0, sourceParent);
370 if (q->filterAcceptsRow(child.row(), sourceParent)
377 m_onlineContactsCounts.insert(key, tmpCounter);
382 PresenceTypeFilterFlags saved = q->presenceTypeFilterFlags();
383 presenceTypeFilterFlags = ContactsFilterModel::DoNotFilterByPresence;
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)) {
394 presenceTypeFilterFlags = saved;
396 m_totalContactsCounts.insert(key, tmpCounter);
399 void ContactsFilterModel::Private::sourceModelChanged(
const QModelIndex &sourceIndex)
401 QModelIndex groupSourceIndex;
403 groupSourceIndex = sourceIndex.parent();
405 groupSourceIndex = sourceIndex;
408 countContacts(groupSourceIndex);
410 const QModelIndex mappedIndex = q->mapFromSource(sourceIndex);
411 Q_EMIT q->dataChanged(mappedIndex, mappedIndex);
415 ContactsFilterModel::ContactsFilterModel(
QObject *parent)
420 setDynamicSortFilter(
true);
423 ContactsFilterModel::~ContactsFilterModel()
428 QVariant ContactsFilterModel::data(
const QModelIndex &index,
int role)
const
430 if (!index.isValid()) {
434 QModelIndex sourceIndex = mapToSource(index);
435 if (!sourceIndex.isValid()) {
440 const QString &key = sourceIndex.data(
KTp::IdRole).toString();
441 if (!d->m_onlineContactsCounts.contains(key)) {
442 d->countContacts(sourceIndex);
444 return d->m_onlineContactsCounts.value(key);
446 const QString &key = sourceIndex.data(
KTp::IdRole).toString();
447 if (!d->m_totalContactsCounts.contains(key)) {
448 d->countContacts(sourceIndex);
450 return d->m_totalContactsCounts.value(key);
454 return sourceModel()->data(sourceIndex, role);
457 void ContactsFilterModel::setSourceModel(QAbstractItemModel *sourceModel)
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)));
472 d->m_onlineContactsCounts.clear();
473 d->m_totalContactsCounts.clear();
474 QSortFilterProxyModel::setSourceModel(sourceModel);
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)));
487 void ContactsFilterModel::invalidateFilter()
490 d->m_onlineContactsCounts.clear();
491 d->m_totalContactsCounts.clear();
492 QSortFilterProxyModel::invalidateFilter();
495 ContactsFilterModel::PresenceTypeFilterFlags ContactsFilterModel::presenceTypeFilterFlags()
const
497 return d->presenceTypeFilterFlags;
500 void ContactsFilterModel::clearPresenceTypeFilterFlags()
502 setPresenceTypeFilterFlags(DoNotFilterByPresence);
505 void ContactsFilterModel::setPresenceTypeFilterFlags(ContactsFilterModel::PresenceTypeFilterFlags presenceTypeFilterFlags)
507 if (d->presenceTypeFilterFlags != presenceTypeFilterFlags) {
508 d->presenceTypeFilterFlags = presenceTypeFilterFlags;
510 Q_EMIT presenceTypeFilterFlagsChanged(presenceTypeFilterFlags);
514 ContactsFilterModel::CapabilityFilterFlags ContactsFilterModel::capabilityFilterFlags()
const
516 return d->capabilityFilterFlags;
519 void ContactsFilterModel::clearCapabilityFilterFlags()
521 setCapabilityFilterFlags(DoNotFilterByCapability);
524 void ContactsFilterModel::setCapabilityFilterFlags(ContactsFilterModel::CapabilityFilterFlags capabilityFilterFlags)
526 if (d->capabilityFilterFlags != capabilityFilterFlags) {
527 d->capabilityFilterFlags = capabilityFilterFlags;
529 Q_EMIT capabilityFilterFlagsChanged(capabilityFilterFlags);
533 ContactsFilterModel::SubscriptionStateFilterFlags ContactsFilterModel::subscriptionStateFilterFlags()
const
535 return d->subscriptionStateFilterFlags;
538 void ContactsFilterModel::clearSubscriptionStateFilterFlags()
540 setSubscriptionStateFilterFlags(DoNotFilterBySubscription);
543 void ContactsFilterModel::setSubscriptionStateFilterFlags(ContactsFilterModel::SubscriptionStateFilterFlags subscriptionStateFilterFlags)
545 if (d->subscriptionStateFilterFlags != subscriptionStateFilterFlags) {
546 d->subscriptionStateFilterFlags = subscriptionStateFilterFlags;
548 Q_EMIT subscriptionStateFilterFlagsChanged(subscriptionStateFilterFlags);
552 QString ContactsFilterModel::globalFilterString()
const
554 return d->globalFilterString;
557 void ContactsFilterModel::clearGlobalFilterString()
559 setGlobalFilterString(QString());
562 void ContactsFilterModel::setGlobalFilterString(
const QString &globalFilterString)
564 if (d->globalFilterString != globalFilterString) {
565 d->globalFilterString = globalFilterString;
567 Q_EMIT globalFilterStringChanged(globalFilterString);
571 Qt::MatchFlags ContactsFilterModel::globalFilterMatchFlags()
const
573 return d->globalFilterMatchFlags;
576 void ContactsFilterModel::resetGlobalFilterMatchFlags()
578 setGlobalFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
581 void ContactsFilterModel::setGlobalFilterMatchFlags(Qt::MatchFlags globalFilterMatchFlags)
583 if (d->globalFilterMatchFlags != globalFilterMatchFlags) {
584 d->globalFilterMatchFlags = globalFilterMatchFlags;
586 Q_EMIT globalFilterMatchFlagsChanged(globalFilterMatchFlags);
590 QString ContactsFilterModel::displayNameFilterString()
const
592 return d->displayNameFilterString;
595 void ContactsFilterModel::clearDisplayNameFilterString()
597 setDisplayNameFilterString(QString());
600 void ContactsFilterModel::setDisplayNameFilterString(
const QString &displayNameFilterString)
602 if (d->displayNameFilterString != displayNameFilterString) {
603 d->displayNameFilterString = displayNameFilterString;
605 Q_EMIT displayNameFilterStringChanged(displayNameFilterString);
609 Qt::MatchFlags ContactsFilterModel::displayNameFilterMatchFlags()
const
611 return d->displayNameFilterMatchFlags;
614 void ContactsFilterModel::resetDisplayNameFilterMatchFlags()
616 setDisplayNameFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
619 void ContactsFilterModel::setDisplayNameFilterMatchFlags(Qt::MatchFlags displayNameFilterMatchFlags)
621 if (d->displayNameFilterMatchFlags != displayNameFilterMatchFlags) {
622 d->displayNameFilterMatchFlags = displayNameFilterMatchFlags;
624 Q_EMIT displayNameFilterMatchFlagsChanged(displayNameFilterMatchFlags);
628 QString ContactsFilterModel::nicknameFilterString()
const
630 return d->nicknameFilterString;
633 void ContactsFilterModel::clearNicknameFilterString()
635 setNicknameFilterString(QString());
638 void ContactsFilterModel::setNicknameFilterString(
const QString &nicknameFilterString)
640 if (d->nicknameFilterString != nicknameFilterString) {
641 d->nicknameFilterString = nicknameFilterString;
643 Q_EMIT nicknameFilterStringChanged(nicknameFilterString);
647 Qt::MatchFlags ContactsFilterModel::nicknameFilterMatchFlags()
const
649 return d->nicknameFilterMatchFlags;
652 void ContactsFilterModel::resetNicknameFilterMatchFlags()
654 setNicknameFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
657 void ContactsFilterModel::setNicknameFilterMatchFlags(Qt::MatchFlags nicknameFilterMatchFlags)
659 if (d->nicknameFilterMatchFlags != nicknameFilterMatchFlags) {
660 d->nicknameFilterMatchFlags = nicknameFilterMatchFlags;
662 Q_EMIT nicknameFilterMatchFlagsChanged(nicknameFilterMatchFlags);
666 QString ContactsFilterModel::aliasFilterString()
const
668 return d->aliasFilterString;
671 void ContactsFilterModel::clearAliasFilterString()
673 setAliasFilterString(QString());
676 void ContactsFilterModel::setAliasFilterString(
const QString &aliasFilterString)
678 if (d->aliasFilterString != aliasFilterString) {
679 d->aliasFilterString = aliasFilterString;
681 Q_EMIT aliasFilterStringChanged(aliasFilterString);
685 Qt::MatchFlags ContactsFilterModel::aliasFilterMatchFlags()
const
687 return d->aliasFilterMatchFlags;
690 void ContactsFilterModel::resetAliasFilterMatchFlags()
692 setAliasFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
695 void ContactsFilterModel::setAliasFilterMatchFlags(Qt::MatchFlags aliasFilterMatchFlags)
697 if (d->aliasFilterMatchFlags != aliasFilterMatchFlags) {
698 d->aliasFilterMatchFlags = aliasFilterMatchFlags;
700 Q_EMIT aliasFilterMatchFlagsChanged(aliasFilterMatchFlags);
704 QString ContactsFilterModel::groupsFilterString()
const
706 return d->groupsFilterString;
709 void ContactsFilterModel::clearGroupsFilterString()
711 setGroupsFilterString(QString());
714 void ContactsFilterModel::setGroupsFilterString(
const QString &groupsFilterString)
716 if (d->groupsFilterString != groupsFilterString) {
717 d->groupsFilterString = groupsFilterString;
719 Q_EMIT groupsFilterStringChanged(groupsFilterString);
723 Qt::MatchFlags ContactsFilterModel::groupsFilterMatchFlags()
const
725 return d->groupsFilterMatchFlags;
728 void ContactsFilterModel::resetGroupsFilterMatchFlags()
730 setGroupsFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
733 void ContactsFilterModel::setGroupsFilterMatchFlags(Qt::MatchFlags groupsFilterMatchFlags)
735 if (d->groupsFilterMatchFlags != groupsFilterMatchFlags) {
736 d->groupsFilterMatchFlags = groupsFilterMatchFlags;
738 Q_EMIT groupsFilterMatchFlagsChanged(groupsFilterMatchFlags);
742 QString ContactsFilterModel::idFilterString()
const
744 return d->idFilterString;
747 void ContactsFilterModel::clearIdFilterString()
749 setIdFilterString(QString());
752 void ContactsFilterModel::setIdFilterString(
const QString &idFilterString)
754 if (d->idFilterString != idFilterString) {
755 d->idFilterString = idFilterString;
757 Q_EMIT idFilterStringChanged(idFilterString);
761 Qt::MatchFlags ContactsFilterModel::idFilterMatchFlags()
const
763 return d->idFilterMatchFlags;
767 Tp::AccountPtr ContactsFilterModel::accountFilter()
const
769 return d->accountFilter;
772 void ContactsFilterModel::setAccountFilter(
const Tp::AccountPtr &accountFilter)
774 if (d->accountFilter != accountFilter) {
775 d->accountFilter = accountFilter;
777 Q_EMIT accountFilterChanged(accountFilter);
781 void ContactsFilterModel::clearAccountFilter()
783 setAccountFilter(Tp::AccountPtr());
786 void ContactsFilterModel::resetIdFilterMatchFlags()
788 setIdFilterMatchFlags(Qt::MatchStartsWith | Qt::MatchWrap);
791 void ContactsFilterModel::setIdFilterMatchFlags(Qt::MatchFlags idFilterMatchFlags)
793 if (d->idFilterMatchFlags != idFilterMatchFlags) {
794 d->idFilterMatchFlags = idFilterMatchFlags;
796 Q_EMIT idFilterMatchFlagsChanged(idFilterMatchFlags);
800 QStringList ContactsFilterModel::tubesFilterStrings()
const
802 return d->tubesFilterStrings;
805 void ContactsFilterModel::clearTubesFilterStrings()
807 setTubesFilterStrings(QStringList());
810 void ContactsFilterModel::setTubesFilterStrings(
const QStringList &tubesFilterStrings)
812 if (d->tubesFilterStrings != tubesFilterStrings) {
813 d->tubesFilterStrings = tubesFilterStrings;
815 Q_EMIT tubesFilterStringsChanged(tubesFilterStrings);
821 QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
825 return d->filterAcceptsContact(index);
828 return d->filterAcceptsAccount(index);
831 return d->filterAcceptsGroup(index);
834 kDebug() <<
"Unknown type found in Account Filter";
842 QString leftDisplayedName = sourceModel()->data(left).toString();
843 QString rightDisplayedName = sourceModel()->data(right).toString();
845 switch (sortRole()) {
851 if (leftPresence == rightPresence) {
857 if (leftPhone && ! rightPhone) {
860 else if (rightPhone && !leftPhone) {
864 return QString::localeAwareCompare(leftDisplayedName, rightDisplayedName) < 0;
866 if (leftPresence == Tp::ConnectionPresenceTypeAvailable) {
869 if (leftPresence == Tp::ConnectionPresenceTypeUnset ||
870 leftPresence == Tp::ConnectionPresenceTypeOffline ||
871 leftPresence == Tp::ConnectionPresenceTypeUnknown ||
872 leftPresence == Tp::ConnectionPresenceTypeError) {
879 case Qt::DisplayRole:
881 return QString::localeAwareCompare(leftDisplayedName, rightDisplayedName) < 0;
887 const QVariant &value,
int hits,
888 Qt::MatchFlags flags)
const
890 if (!start.isValid()) {
891 return QModelIndexList();
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);
900 QVariant v = start.data(role);
902 if (matchType == Qt::MatchExactly) {
904 result.append(start);
907 text = value.toString();
908 QString t = v.toString();
910 case Qt::MatchRegExp:
911 if (QRegExp(text, cs).exactMatch(t))
912 result.append(start);
914 case Qt::MatchWildcard:
915 if (QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t))
916 result.append(start);
918 case Qt::MatchStartsWith:
919 if (t.startsWith(text, cs))
920 result.append(start);
922 case Qt::MatchEndsWith:
923 if (t.endsWith(text, cs))
924 result.append(start);
926 case Qt::MatchFixedString:
927 if (t.compare(text, cs) == 0)
928 result.append(start);
930 case Qt::MatchContains:
932 if (t.contains(text, cs))
933 result.append(start);
936 if (recurse && hasChildren(start)) {
937 result +=
match(index(0, start.column(), start), role,
938 (text.isEmpty() ? value : text),
939 (allHits ? -1 : hits - result.count()), flags);
944 void ContactsFilterModel::setSortRoleString(
const QString &role)
946 Q_ASSERT(!roleNames().keys(role.toUtf8()).isEmpty());
947 setSortRole(roleNames().key(role.toUtf8()));
950 QString ContactsFilterModel::sortRoleString()
const
952 Q_ASSERT(roleNames().contains(sortRole()));
953 return QString::fromUtf8(roleNames().value(sortRole()));
956 #include "contacts-filter-model.moc"