File indexing completed on 2024-05-19 05:14:36
0001 /* 0002 SPDX-FileCopyrightText: 2014 Jonathan Marten <jjm@keelhaul.me.uk> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "categoryfilterproxymodel.h" 0008 0009 #include "kaddressbook_debug.h" 0010 0011 #include <Akonadi/EntityTreeModel> 0012 #include <Akonadi/Item> 0013 0014 #include <KContacts/Addressee> 0015 #include <KContacts/ContactGroup> 0016 0017 #include "categoryselectwidget.h" 0018 0019 using namespace Akonadi; 0020 0021 class CategoryFilterProxyModelPrivate : public QObject 0022 { 0023 Q_OBJECT 0024 Q_DECLARE_PUBLIC(CategoryFilterProxyModel) 0025 0026 public: 0027 explicit CategoryFilterProxyModelPrivate(CategoryFilterProxyModel *parent); 0028 0029 QList<Tag> filterTagList; 0030 bool filterEnabled = false; 0031 0032 bool containsId(Akonadi::Tag::Id id) const 0033 { 0034 for (const Tag &tag : filterTagList) { 0035 if (tag.id() == id) { 0036 return true; // a category matches filter 0037 } 0038 } 0039 return false; 0040 } 0041 bool containsName(const QString &cat) const 0042 { 0043 for (const Tag &tag : filterTagList) { 0044 if (tag.name() == cat) { 0045 return true; // a category matches filter 0046 } 0047 } 0048 return false; 0049 } 0050 0051 private: 0052 CategoryFilterProxyModel *const q_ptr; 0053 }; 0054 0055 CategoryFilterProxyModelPrivate::CategoryFilterProxyModelPrivate(CategoryFilterProxyModel *parent) 0056 : QObject() 0057 , q_ptr(parent) 0058 { 0059 } 0060 0061 CategoryFilterProxyModel::CategoryFilterProxyModel(QObject *parent) 0062 : QSortFilterProxyModel(parent) 0063 , d_ptr(new CategoryFilterProxyModelPrivate(this)) 0064 { 0065 setDynamicSortFilter(true); 0066 } 0067 0068 CategoryFilterProxyModel::~CategoryFilterProxyModel() = default; 0069 0070 bool CategoryFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const 0071 { 0072 Q_D(const CategoryFilterProxyModel); 0073 0074 const QModelIndex index = sourceModel()->index(row, 0, parent); 0075 const auto item = index.data(EntityTreeModel::ItemRole).value<Akonadi::Item>(); 0076 0077 if (!d->filterEnabled) { 0078 return true; // filter not enabled 0079 } 0080 if (d->filterTagList.isEmpty()) { 0081 return false; // nothing accepted 0082 } 0083 // all accepted 0084 if (d->filterTagList.at(0).id() == CategorySelectWidget::FilterAll) { 0085 return true; 0086 } 0087 0088 if (item.hasPayload<KContacts::Addressee>()) { 0089 const auto contact = item.payload<KContacts::Addressee>(); 0090 0091 const QStringList categories = contact.categories(); 0092 0093 int validCategories = 0; 0094 int count = categories.count(); 0095 for (int i = 0; i < count; ++i) { 0096 const QString cat = categories.at(i); 0097 if (cat.startsWith(QLatin1StringView("akonadi:"))) { 0098 const int idx = cat.indexOf(QLatin1StringView("?tag=")); 0099 if (idx >= 0) { 0100 ++validCategories; 0101 Tag::Id id = QStringView(cat).mid(idx + 5).toInt(); 0102 if (d->containsId(id)) { 0103 return true; // a category matches filter 0104 } 0105 } 0106 } else { 0107 ++validCategories; 0108 if (d->containsName(cat)) { 0109 return true; // a category matches filter 0110 } 0111 } 0112 } 0113 0114 if (validCategories > 0) { 0115 return false; // categorised but no match 0116 } else { 0117 return d->containsId(CategorySelectWidget::FilterUntagged); 0118 } 0119 } else if (item.hasPayload<KContacts::ContactGroup>()) { // a contact group item 0120 return d->containsId(CategorySelectWidget::FilterGroups); 0121 } 0122 0123 return true; // not a recognised item 0124 } 0125 0126 void CategoryFilterProxyModel::setFilterCategories(const QList<Akonadi::Tag> &tagList) 0127 { 0128 Q_D(CategoryFilterProxyModel); 0129 0130 if (tagList != d->filterTagList) { 0131 d->filterTagList = tagList; 0132 invalidateFilter(); 0133 } 0134 } 0135 0136 void CategoryFilterProxyModel::setFilterEnabled(bool enable) 0137 { 0138 Q_D(CategoryFilterProxyModel); 0139 0140 if (enable != d->filterEnabled) { 0141 d->filterEnabled = enable; 0142 invalidateFilter(); 0143 } 0144 } 0145 0146 #include "categoryfilterproxymodel.moc" 0147 0148 #include "moc_categoryfilterproxymodel.cpp"