Mailcommon

foldertreewidgetproxymodel.cpp
1/*
2 SPDX-FileCopyrightText: 2009-2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "foldertreewidgetproxymodel.h"
8#include "foldersettings.h"
9#include "kernel/mailkernel.h"
10#include "util/mailutil.h"
11
12#include <MessageCore/MessageCoreSettings>
13
14#include <Akonadi/AccountActivitiesAbstract>
15#include <Akonadi/AgentInstance>
16#include <Akonadi/AgentManager>
17#include <Akonadi/EntityTreeModel>
18#include <Akonadi/MimeTypeChecker>
19
20#include <Akonadi/CollectionQuotaAttribute>
21#include <KColorScheme>
22#include <KLocalizedString>
23
24#include <QIcon>
25#include <QPalette>
26
27using namespace MailCommon;
28class FolderTreeWidgetProxyModel::FolderTreeWidgetProxyModelPrivate
29{
30public:
31 FolderTreeWidgetProxyModelPrivate(FolderTreeWidgetProxyModel *qq)
32 : q(qq)
33 {
34 }
35
36 bool checkQuotaExcedded(const QModelIndex &index, qreal &percentage)
37 {
38 if (threshold >= 0.0) {
39 if (index.model()->hasChildren(index)) {
40 const int rowCount = index.model()->rowCount(index);
41 for (int row = 0; row < rowCount; row++) {
42 const QModelIndex firstIndex = q->mapToSource(index.model()->index(row, 0, index));
43
44 const auto collectionFirst = q->sourceModel()->data(firstIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
45 if (collectionFirst.isValid() && collectionFirst.hasAttribute<Akonadi::CollectionQuotaAttribute>()) {
46 const auto quota = collectionFirst.attribute<Akonadi::CollectionQuotaAttribute>();
47
48 if (quota->currentValue() > -1 && quota->maximumValue() > 0) {
49 percentage = (100.0 * quota->currentValue()) / quota->maximumValue();
50 if (percentage >= threshold) {
51 return true;
52 }
53 }
54 }
55 }
56 }
57 }
58 return false;
59 }
60
61 Akonadi::AccountActivitiesAbstract *accountActivities = nullptr;
62 QSet<QString> includedMimeTypes;
64
65 QColor brokenAccountColor;
66 qreal threshold = -1.0;
68 bool enableCheck = false;
69 bool hideVirtualFolder = false;
70 bool hideSpecificFolder = false;
71 bool hideOutboxFolder = false;
72};
73
74FolderTreeWidgetProxyModel::FolderTreeWidgetProxyModel(QObject *parent, FolderTreeWidgetProxyModelOptions option)
75 : Akonadi::EntityRightsFilterModel(parent)
76 , d(new FolderTreeWidgetProxyModelPrivate(this))
77{
78 setFilterCaseSensitivity(Qt::CaseInsensitive);
79
80 if (option & HideVirtualFolder) {
81 d->hideVirtualFolder = true;
82 }
83 if (option & HideSpecificFolder) {
84 d->hideSpecificFolder = true;
85 }
86 if (option & HideOutboxFolder) {
87 d->hideOutboxFolder = true;
88 }
89 readConfig();
90}
91
92FolderTreeWidgetProxyModel::~FolderTreeWidgetProxyModel() = default;
93
94void FolderTreeWidgetProxyModel::setWarningThreshold(qreal threshold)
95{
96 d->threshold = threshold;
97}
98
99void FolderTreeWidgetProxyModel::readConfig()
100{
101 invalidate();
102}
103
104Qt::ItemFlags FolderTreeWidgetProxyModel::flags(const QModelIndex &index) const
105{
106 if (d->enableCheck) {
107 const QModelIndex sourceIndex = mapToSource(index);
108 const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
110 if (!MailCommon::Util::isVirtualCollection(collection)) {
111 const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource());
112 if (instance.status() == Akonadi::AgentInstance::Broken) {
114 }
115 }
117 }
119}
120
121void FolderTreeWidgetProxyModel::setEnabledCheck(bool enable)
122{
123 if (d->enableCheck == enable) {
124 return;
125 }
126
127 d->enableCheck = enable;
128 if (enable) {
130 }
131}
132
133bool FolderTreeWidgetProxyModel::enabledCheck() const
134{
135 return d->enableCheck;
136}
137
138void FolderTreeWidgetProxyModel::setHideVirtualFolder(bool exclude)
139{
140 if (d->hideVirtualFolder != exclude) {
141 d->hideVirtualFolder = exclude;
142 invalidate();
143 }
144}
145
146bool FolderTreeWidgetProxyModel::hideVirtualFolder() const
147{
148 return d->hideVirtualFolder;
149}
150
151void FolderTreeWidgetProxyModel::setHideSpecificFolder(bool hide)
152{
153 if (d->hideSpecificFolder != hide) {
154 d->hideSpecificFolder = hide;
155 invalidate();
156 }
157}
158
159bool FolderTreeWidgetProxyModel::hideSpecificFolder() const
160{
161 return d->hideSpecificFolder;
162}
163
164void FolderTreeWidgetProxyModel::setHideOutboxFolder(bool hide)
165{
166 if (d->hideOutboxFolder != hide) {
167 d->hideOutboxFolder = hide;
168 invalidate();
169 }
170}
171
172bool FolderTreeWidgetProxyModel::hideOutboxFolder() const
173{
174 return d->hideOutboxFolder;
175}
176
177bool FolderTreeWidgetProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
178{
179 const QModelIndex modelIndex = sourceModel()->index(sourceRow, 0, sourceParent);
180
181 const auto collection = sourceModel()->data(modelIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
182 if (d->accountActivities) {
183 const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource());
184 if (instance.activitiesEnabled()) {
185 if (!d->accountActivities->filterAcceptsRow(instance.activities())) {
186 return false;
187 }
188 }
189 }
190 if (!d->checker.isWantedCollection(collection)) {
191 return false;
192 }
193
194 if (d->hideVirtualFolder) {
195 if (Util::isVirtualCollection(collection)) {
196 return false;
197 }
198 }
199
200 if (d->hideSpecificFolder) {
201 const QSharedPointer<FolderSettings> col = FolderSettings::forCollection(collection, false);
202 if (!col.isNull() && col->hideInSelectionDialog()) {
203 return false;
204 }
205 }
206
207 if (d->hideOutboxFolder) {
208 if (collection == Kernel::self()->outboxCollectionFolder()) {
209 return false;
210 }
211 }
212
213 return EntityRightsFilterModel::filterAcceptsRow(sourceRow, sourceParent);
214}
215
216QVariant FolderTreeWidgetProxyModel::data(const QModelIndex &index, int role) const
217{
218 if (role == Qt::ForegroundRole) {
219 const QModelIndex sourceIndex = mapToSource(index);
220 const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
222
223 if (!MailCommon::Util::isVirtualCollection(collection)) {
224 const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource());
225
226 if (instance.status() == Akonadi::AgentInstance::Broken) {
227 if (!d->brokenAccountColor.isValid()) {
229 d->brokenAccountColor = scheme.foreground(KColorScheme::NegativeText).color();
230 }
231 return d->brokenAccountColor;
232 }
233 }
234 } else if (role == Qt::DisplayRole) {
235 const QModelIndex sourceIndex = mapToSource(index);
236 const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
238 if (!MailCommon::Util::isVirtualCollection(collection)) {
239 const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource());
240 if (collection.parentCollection() == Akonadi::Collection::root()) {
241 if (!instance.isOnline()) {
242 return i18n("%1 (Offline)", Akonadi::EntityRightsFilterModel::data(index, role).toString());
243 }
244 qreal percentage = 0.0;
245 if (d->checkQuotaExcedded(index, percentage)) {
246 return i18n("%1 (Reached %2% quota)", Akonadi::EntityRightsFilterModel::data(index, role).toString(), static_cast<int>(percentage));
247 }
248 }
249 }
250 } else if (role == Qt::DecorationRole) {
251 const QModelIndex sourceIndex = mapToSource(index);
252 const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
254 if (!MailCommon::Util::isVirtualCollection(collection)) {
255 if (collection.parentCollection() == Akonadi::Collection::root()) {
256 qreal percentage = 0.0;
257 if (d->checkQuotaExcedded(index, percentage)) {
258 return QIcon::fromTheme(QStringLiteral("emblem-warning"));
259 }
260 }
261 }
262 }
264}
265
266void FolderTreeWidgetProxyModel::updatePalette()
267{
268 if (d->brokenAccountColor.isValid()) {
270 d->brokenAccountColor = scheme.foreground(KColorScheme::NegativeText).color();
271 invalidate();
272 }
273}
274
275void FolderTreeWidgetProxyModel::addContentMimeTypeInclusionFilter(const QString &mimeType)
276{
277 d->includedMimeTypes << mimeType;
278 d->checker.setWantedMimeTypes(d->includedMimeTypes.values());
280}
281
282void FolderTreeWidgetProxyModel::setAccountActivities(Akonadi::AccountActivitiesAbstract *accountActivities)
283{
284 if (d->accountActivities) {
285 disconnect(d->accountActivities, &Akonadi::AccountActivitiesAbstract::activitiesChanged, this, &FolderTreeWidgetProxyModel::invalidateFilter);
286 }
287 d->accountActivities = accountActivities;
288 if (d->accountActivities) {
289 connect(d->accountActivities, &Akonadi::AccountActivitiesAbstract::activitiesChanged, this, &FolderTreeWidgetProxyModel::invalidateFilter);
290 }
292}
293
294#include "moc_foldertreewidgetproxymodel.cpp"
Status status() const
QStringList activities() const
bool activitiesEnabled() const
static AgentManager * self()
AgentInstance instance(const QString &identifier) const
static Collection root()
void setAccessRights(Collection::Rights rights)
Qt::ItemFlags flags(const QModelIndex &index) const override
The FolderTreeWidgetProxyModel class.
QString i18n(const char *text, const TYPE &arg...)
char * toString(const EngineQuery &query)
KCALUTILS_EXPORT QString mimeType()
The filter dialog.
virtual QVariant data(const QModelIndex &index, int role) const const=0
virtual bool hasChildren(const QModelIndex &parent) const const
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
virtual int rowCount(const QModelIndex &parent) const const=0
QIcon fromTheme(const QString &name)
QVariant data(int role) const const
const QAbstractItemModel * model() const const
int row() const const
QModelIndex sibling(int row, int column) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
bool isNull() const const
virtual Qt::ItemFlags flags(const QModelIndex &index) const const override
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const const override
virtual int rowCount(const QModelIndex &parent) const const override
CaseInsensitive
ForegroundRole
typedef ItemFlags
T value() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 13 2024 11:49:10 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.