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 setDynamicSortFilter(true);
32 }
33
34 void setShowHidden(bool showHidden)
35 {
36 if (mShowHidden != showHidden) {
37 mShowHidden = showHidden;
38 invalidateFilter();
39 }
40 }
41
42 bool showHidden() const
43 {
44 return mShowHidden;
45 }
46
47protected:
48 bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
49 {
50 const auto source_index = sourceModel()->index(source_row, 0, source_parent);
51 const auto col = source_index.data(EntityTreeModel::CollectionRole).value<Collection>();
52 if (mShowHidden) {
53 return true;
54 }
55
57 }
58
59private:
60 bool mShowHidden = false;
61};
62
63} // namespace
64
65/**
66 * @internal
67 */
68class Akonadi::SubscriptionModelPrivate
69{
70public:
71 explicit SubscriptionModelPrivate(Monitor *monitor)
72 : etm(monitor)
73 {
74 etm.setShowSystemEntities(true); // show hidden collections
77
78 proxy.setSourceModel(&etm);
79 }
80
81 Collection::List changedSubscriptions(bool subscribed) const
82 {
83 return Views::range(subscriptions.constKeyValueBegin(), subscriptions.constKeyValueEnd()) | Views::filter([subscribed](const auto &val) {
84 return val.second == subscribed;
85 })
86 | Views::transform([](const auto &val) {
87 return Collection{val.first};
88 })
89 | Actions::toQVector;
90 }
91
92 bool isSubscribable(const Collection &col)
93 {
94 if (CollectionUtils::isStructural(col) || col.isVirtual() || CollectionUtils::isUnifiedMailbox(col)) {
95 return false;
96 }
98 return false;
99 }
100 if (col.contentMimeTypes().isEmpty()) {
101 return false;
102 }
103 return true;
104 }
105
106public:
107 EntityTreeModel etm;
108 FilterProxyModel proxy;
109 QHash<Collection::Id, bool> subscriptions;
110};
111
112SubscriptionModel::SubscriptionModel(Monitor *monitor, QObject *parent)
113 : QIdentityProxyModel(parent)
114 , d(new SubscriptionModelPrivate(monitor))
115{
117
118 connect(&d->etm, &EntityTreeModel::collectionTreeFetched, this, &SubscriptionModel::modelLoaded);
119}
120
121SubscriptionModel::~SubscriptionModel() = default;
122
123void SubscriptionModel::setSourceModel(QAbstractItemModel * /*sourceModel*/)
124{
125 // no-op
126}
127
128QVariant SubscriptionModel::data(const QModelIndex &index, int role) const
129{
130 switch (role) {
131 case Qt::CheckStateRole: {
132 const auto col = index.data(EntityTreeModel::CollectionRole).value<Collection>();
133 if (!d->isSubscribable(col)) {
134 return QVariant();
135 }
136 // Check if we have "override" for the subscription state stored
137 const auto it = d->subscriptions.constFind(col.id());
138 if (it != d->subscriptions.cend()) {
139 return (*it) ? Qt::Checked : Qt::Unchecked;
140 } else {
141 // Fallback to the current state of the collection
142 return col.enabled() ? Qt::Checked : Qt::Unchecked;
143 }
144 }
145 case SubscriptionChangedRole: {
146 const auto col = index.data(EntityTreeModel::CollectionIdRole).toLongLong();
147 return d->subscriptions.contains(col);
148 }
149 case Qt::FontRole: {
150 const auto col = index.data(EntityTreeModel::CollectionIdRole).toLongLong();
151 auto font = QIdentityProxyModel::data(index, role).value<QFont>();
152 font.setBold(d->subscriptions.contains(col));
153 return font;
154 }
155 }
156
157 return QIdentityProxyModel::data(index, role);
158}
159
160Qt::ItemFlags SubscriptionModel::flags(const QModelIndex &index) const
161{
163 const auto col = index.data(EntityTreeModel::CollectionRole).value<Collection>();
164 if (d->isSubscribable(col)) {
165 return flags | Qt::ItemIsUserCheckable;
166 }
167 return flags;
168}
169
170bool SubscriptionModel::setData(const QModelIndex &index, const QVariant &value, int role)
171{
172 if (role == Qt::CheckStateRole) {
173 const auto col = index.data(EntityTreeModel::CollectionRole).value<Collection>();
174 if (!d->isSubscribable(col)) {
175 return true; // No change
176 }
177 if (col.enabled() == (value == Qt::Checked)) { // No change compared to the underlying model
178 d->subscriptions.remove(col.id());
179 } else {
180 d->subscriptions[col.id()] = (value == Qt::Checked);
181 }
182 Q_EMIT dataChanged(index, index);
183 return true;
184 }
185 return QIdentityProxyModel::setData(index, value, role);
186}
187
188Akonadi::Collection::List SubscriptionModel::subscribed() const
189{
190 return d->changedSubscriptions(true);
191}
192
193Akonadi::Collection::List SubscriptionModel::unsubscribed() const
194{
195 return d->changedSubscriptions(false);
196}
197
198void SubscriptionModel::setShowHiddenCollections(bool showHidden)
199{
200 d->proxy.setShowHidden(showHidden);
201}
202
203bool SubscriptionModel::showHiddenCollections() const
204{
205 return d->proxy.showHidden();
206}
207
208#include "subscriptionmodel.moc"
209
210#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:72
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 Tue Mar 26 2024 11:13:38 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.