Akonadi

subscriptionmodel.cpp
1/*
2 SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "collectionutils.h"
8#include "entityhiddenattribute.h"
9#include "entitytreemodel.h"
10#include "specialcollectionattribute.h"
11#include "subscriptionmodel_p.h"
12
13#include "shared/akranges.h"
14#include <qnamespace.h>
15
16#include <QFont>
17#include <QSortFilterProxyModel>
18
19using namespace Akonadi;
20using namespace AkRanges;
21
22namespace
23{
24class FilterProxyModel : public QSortFilterProxyModel
25{
26 Q_OBJECT
27
28public:
29 FilterProxyModel()
30 {
31 }
32
33 void setShowHidden(bool showHidden)
34 {
35 if (mShowHidden != showHidden) {
36 mShowHidden = showHidden;
37 invalidateFilter();
38 }
39 }
40
41 bool showHidden() const
42 {
43 return mShowHidden;
44 }
45
46protected:
47 bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
48 {
49 const auto source_index = sourceModel()->index(source_row, 0, source_parent);
50 const auto col = source_index.data(EntityTreeModel::CollectionRole).value<Collection>();
51 if (mShowHidden) {
52 return true;
53 }
54
56 }
57
58private:
59 bool mShowHidden = false;
60};
61
62} // namespace
63
64/**
65 * @internal
66 */
67class Akonadi::SubscriptionModelPrivate
68{
69public:
70 explicit SubscriptionModelPrivate(Monitor *monitor)
71 : etm(monitor)
72 {
73 etm.setShowSystemEntities(true); // show hidden collections
76
77 proxy.setSourceModel(&etm);
78 }
79
80 Collection::List changedSubscriptions(bool subscribed) const
81 {
82 return Views::range(subscriptions.constKeyValueBegin(), subscriptions.constKeyValueEnd()) | Views::filter([subscribed](const auto &val) {
83 return val.second == subscribed;
84 })
85 | Views::transform([](const auto &val) {
86 return Collection{val.first};
87 })
88 | Actions::toQVector;
89 }
90
91 bool isSubscribable(const Collection &col)
92 {
93 if (CollectionUtils::isStructural(col) || col.isVirtual() || CollectionUtils::isUnifiedMailbox(col)) {
94 return false;
95 }
97 return false;
98 }
99 if (col.contentMimeTypes().isEmpty()) {
100 return false;
101 }
102 return true;
103 }
104
105public:
106 EntityTreeModel etm;
107 FilterProxyModel proxy;
108 QHash<Collection::Id, bool> subscriptions;
109};
110
111SubscriptionModel::SubscriptionModel(Monitor *monitor, QObject *parent)
112 : QIdentityProxyModel(parent)
113 , d(new SubscriptionModelPrivate(monitor))
114{
116
117 connect(&d->etm, &EntityTreeModel::collectionTreeFetched, this, &SubscriptionModel::modelLoaded);
118}
119
120SubscriptionModel::~SubscriptionModel() = default;
121
122void SubscriptionModel::setSourceModel(QAbstractItemModel * /*sourceModel*/)
123{
124 // no-op
125}
126
127QVariant SubscriptionModel::data(const QModelIndex &index, int role) const
128{
129 switch (role) {
130 case Qt::CheckStateRole: {
131 const auto col = index.data(EntityTreeModel::CollectionRole).value<Collection>();
132 if (!d->isSubscribable(col)) {
133 return QVariant();
134 }
135 // Check if we have "override" for the subscription state stored
136 const auto it = d->subscriptions.constFind(col.id());
137 if (it != d->subscriptions.cend()) {
138 return (*it) ? Qt::Checked : Qt::Unchecked;
139 } else {
140 // Fallback to the current state of the collection
141 return col.enabled() ? Qt::Checked : Qt::Unchecked;
142 }
143 }
144 case SubscriptionChangedRole: {
145 const auto col = index.data(EntityTreeModel::CollectionIdRole).toLongLong();
146 return d->subscriptions.contains(col);
147 }
148 case Qt::FontRole: {
149 const auto col = index.data(EntityTreeModel::CollectionIdRole).toLongLong();
150 auto font = QIdentityProxyModel::data(index, role).value<QFont>();
151 font.setBold(d->subscriptions.contains(col));
152 return font;
153 }
154 }
155
156 return QIdentityProxyModel::data(index, role);
157}
158
159Qt::ItemFlags SubscriptionModel::flags(const QModelIndex &index) const
160{
161 const Qt::ItemFlags flags = QIdentityProxyModel::flags(index);
162 const auto col = index.data(EntityTreeModel::CollectionRole).value<Collection>();
163 if (d->isSubscribable(col)) {
164 return flags | Qt::ItemIsUserCheckable;
165 }
166 return flags;
167}
168
169bool SubscriptionModel::setData(const QModelIndex &index, const QVariant &value, int role)
170{
171 if (role == Qt::CheckStateRole) {
172 const auto col = index.data(EntityTreeModel::CollectionRole).value<Collection>();
173 if (!d->isSubscribable(col)) {
174 return true; // No change
175 }
176 if (col.enabled() == (value == Qt::Checked)) { // No change compared to the underlying model
177 d->subscriptions.remove(col.id());
178 } else {
179 d->subscriptions[col.id()] = (value == Qt::Checked);
180 }
181 Q_EMIT dataChanged(index, index);
182 return true;
183 }
184 return QIdentityProxyModel::setData(index, value, role);
185}
186
187Akonadi::Collection::List SubscriptionModel::subscribed() const
188{
189 return d->changedSubscriptions(true);
190}
191
192Akonadi::Collection::List SubscriptionModel::unsubscribed() const
193{
194 return d->changedSubscriptions(false);
195}
196
197void SubscriptionModel::setShowHiddenCollections(bool showHidden)
198{
199 d->proxy.setShowHidden(showHidden);
200}
201
202bool SubscriptionModel::showHiddenCollections() const
203{
204 return d->proxy.showHidden();
205}
206
207#include "subscriptionmodel.moc"
208
209#include "moc_subscriptionmodel_p.cpp"
Represents a collection of PIM items.
Definition collection.h:62
bool hasAttribute(const QByteArray &name) const
Returns true if the collection has an attribute of the given type name, false otherwise.
An Attribute that marks that an entity should be hidden in the UI.
A model for collections and items together.
void setShowSystemEntities(bool show)
Some Entities are hidden in the model, but exist for internal purposes, for example,...
@ NoItemPopulation
Do not include items in the model.
void collectionTreeFetched(const Akonadi::Collection::List &collections)
Signal emitted when the collection tree has been fetched for the first time.
void setCollectionFetchStrategy(CollectionFetchStrategy strategy)
Sets the collection fetch strategy of the model.
@ FetchCollectionsRecursive
Fetches collections in the root collection recursively. This is the default.
void setItemPopulationStrategy(ItemPopulationStrategy strategy)
Sets the item population strategy of the model.
@ CollectionRole
The collection.
@ CollectionIdRole
The collection id.
Monitors an item or collection for changes.
Definition monitor.h:71
An Attribute that stores the special collection type of a collection.
Helper integration between Akonadi and Qt.
virtual QVariant data(const QModelIndex &index, int role) const const=0
virtual Qt::ItemFlags flags(const QModelIndex &index) const const
virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
void setBold(bool enable)
const_key_value_iterator constKeyValueBegin() const const
const_key_value_iterator constKeyValueEnd() const const
virtual void setSourceModel(QAbstractItemModel *newSourceModel) override
bool isEmpty() const const
QVariant data(int role) const const
CheckStateRole
typedef ItemFlags
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
qlonglong toLongLong(bool *ok) const const
T value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:08:29 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.