Mailcommon

foldertreewidgetproxymodel.cpp
1 /*
2  SPDX-FileCopyrightText: 2009-2023 Laurent Montel <[email protected]>
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/AgentInstance>
15 #include <Akonadi/AgentManager>
16 #include <Akonadi/EntityTreeModel>
17 #include <Akonadi/MimeTypeChecker>
18 
19 #include <Akonadi/CollectionQuotaAttribute>
20 #include <KColorScheme>
21 #include <KLocalizedString>
22 
23 #include <QIcon>
24 #include <QPalette>
25 
26 using namespace MailCommon;
27 class FolderTreeWidgetProxyModel::FolderTreeWidgetProxyModelPrivate
28 {
29 public:
30  FolderTreeWidgetProxyModelPrivate(FolderTreeWidgetProxyModel *qq)
31  : q(qq)
32  {
33  }
34 
35  bool checkQuotaExcedded(const QModelIndex &index, qreal &percentage)
36  {
37  if (threshold >= 0.0) {
38  if (index.model()->hasChildren(index)) {
39  const int rowCount = index.model()->rowCount(index);
40  for (int row = 0; row < rowCount; row++) {
41  const QModelIndex firstIndex = q->mapToSource(index.model()->index(row, 0, index));
42 
43  const auto collectionFirst = q->sourceModel()->data(firstIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
44  if (collectionFirst.isValid() && collectionFirst.hasAttribute<Akonadi::CollectionQuotaAttribute>()) {
45  const auto *quota = collectionFirst.attribute<Akonadi::CollectionQuotaAttribute>();
46 
47  if (quota->currentValue() > -1 && quota->maximumValue() > 0) {
48  percentage = (100.0 * quota->currentValue()) / quota->maximumValue();
49  if (percentage >= threshold) {
50  return true;
51  }
52  }
53  }
54  }
55  }
56  }
57  return false;
58  }
59 
60  QSet<QString> includedMimeTypes;
62 
63  QColor brokenAccountColor;
64  qreal threshold = -1.0;
66  bool enableCheck = false;
67  bool hideVirtualFolder = false;
68  bool hideSpecificFolder = false;
69  bool hideOutboxFolder = false;
70 };
71 
72 FolderTreeWidgetProxyModel::FolderTreeWidgetProxyModel(QObject *parent, FolderTreeWidgetProxyModelOptions option)
73  : Akonadi::EntityRightsFilterModel(parent)
74  , d(new FolderTreeWidgetProxyModelPrivate(this))
75 {
76  setDynamicSortFilter(true);
77  setFilterCaseSensitivity(Qt::CaseInsensitive);
78 
79  if (option & HideVirtualFolder) {
80  d->hideVirtualFolder = true;
81  }
82  if (option & HideSpecificFolder) {
83  d->hideSpecificFolder = true;
84  }
85  if (option & HideOutboxFolder) {
86  d->hideOutboxFolder = true;
87  }
88  readConfig();
89 }
90 
91 FolderTreeWidgetProxyModel::~FolderTreeWidgetProxyModel() = default;
92 
93 void FolderTreeWidgetProxyModel::setWarningThreshold(qreal threshold)
94 {
95  d->threshold = threshold;
96 }
97 
98 void FolderTreeWidgetProxyModel::readConfig()
99 {
100  invalidate();
101 }
102 
103 Qt::ItemFlags FolderTreeWidgetProxyModel::flags(const QModelIndex &index) const
104 {
105  if (d->enableCheck) {
106  const QModelIndex sourceIndex = mapToSource(index);
107  const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
108  const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
109  if (!MailCommon::Util::isVirtualCollection(collection)) {
110  const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource());
111  if (instance.status() == Akonadi::AgentInstance::Broken) {
113  }
114  }
116  }
118 }
119 
120 void FolderTreeWidgetProxyModel::setEnabledCheck(bool enable)
121 {
122  if (d->enableCheck == enable) {
123  return;
124  }
125 
126  d->enableCheck = enable;
127  if (enable) {
129  }
130 }
131 
132 bool FolderTreeWidgetProxyModel::enabledCheck() const
133 {
134  return d->enableCheck;
135 }
136 
137 void FolderTreeWidgetProxyModel::setHideVirtualFolder(bool exclude)
138 {
139  if (d->hideVirtualFolder != exclude) {
140  d->hideVirtualFolder = exclude;
141  invalidate();
142  }
143 }
144 
145 bool FolderTreeWidgetProxyModel::hideVirtualFolder() const
146 {
147  return d->hideVirtualFolder;
148 }
149 
150 void FolderTreeWidgetProxyModel::setHideSpecificFolder(bool hide)
151 {
152  if (d->hideSpecificFolder != hide) {
153  d->hideSpecificFolder = hide;
154  invalidate();
155  }
156 }
157 
158 bool FolderTreeWidgetProxyModel::hideSpecificFolder() const
159 {
160  return d->hideSpecificFolder;
161 }
162 
163 void FolderTreeWidgetProxyModel::setHideOutboxFolder(bool hide)
164 {
165  if (d->hideOutboxFolder != hide) {
166  d->hideOutboxFolder = hide;
167  invalidate();
168  }
169 }
170 
171 bool FolderTreeWidgetProxyModel::hideOutboxFolder() const
172 {
173  return d->hideOutboxFolder;
174 }
175 
176 bool FolderTreeWidgetProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
177 {
178  const QModelIndex modelIndex = sourceModel()->index(sourceRow, 0, sourceParent);
179 
180  const auto collection = sourceModel()->data(modelIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
181  if (!d->checker.isWantedCollection(collection)) {
182  return false;
183  }
184 
185  if (d->hideVirtualFolder) {
186  if (Util::isVirtualCollection(collection)) {
187  return false;
188  }
189  }
190 
191  if (d->hideSpecificFolder) {
192  const QSharedPointer<FolderSettings> col = FolderSettings::forCollection(collection, false);
193  if (!col.isNull() && col->hideInSelectionDialog()) {
194  return false;
195  }
196  }
197 
198  if (d->hideOutboxFolder) {
199  if (collection == Kernel::self()->outboxCollectionFolder()) {
200  return false;
201  }
202  }
203 
204  return EntityRightsFilterModel::filterAcceptsRow(sourceRow, sourceParent);
205 }
206 
207 QVariant FolderTreeWidgetProxyModel::data(const QModelIndex &index, int role) const
208 {
209  if (role == Qt::ForegroundRole) {
210  const QModelIndex sourceIndex = mapToSource(index);
211  const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
212  const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
213 
214  if (!MailCommon::Util::isVirtualCollection(collection)) {
215  const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource());
216 
217  if (instance.status() == Akonadi::AgentInstance::Broken) {
218  if (!d->brokenAccountColor.isValid()) {
220  d->brokenAccountColor = scheme.foreground(KColorScheme::NegativeText).color();
221  }
222  return d->brokenAccountColor;
223  }
224  }
225  } else if (role == Qt::DisplayRole) {
226  const QModelIndex sourceIndex = mapToSource(index);
227  const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
228  const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
229  if (!MailCommon::Util::isVirtualCollection(collection)) {
230  const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource());
231  if (collection.parentCollection() == Akonadi::Collection::root()) {
232  if (!instance.isOnline()) {
233  return i18n("%1 (Offline)", Akonadi::EntityRightsFilterModel::data(index, role).toString());
234  }
235  qreal percentage = 0.0;
236  if (d->checkQuotaExcedded(index, percentage)) {
237  return i18n("%1 (Reached %2% quota)", Akonadi::EntityRightsFilterModel::data(index, role).toString(), static_cast<int>(percentage));
238  }
239  }
240  }
241  } else if (role == Qt::DecorationRole) {
242  const QModelIndex sourceIndex = mapToSource(index);
243  const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
244  const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
245  if (!MailCommon::Util::isVirtualCollection(collection)) {
246  if (collection.parentCollection() == Akonadi::Collection::root()) {
247  qreal percentage = 0.0;
248  if (d->checkQuotaExcedded(index, percentage)) {
249  return QIcon::fromTheme(QStringLiteral("emblem-warning"));
250  }
251  }
252  }
253  }
255 }
256 
257 void FolderTreeWidgetProxyModel::updatePalette()
258 {
259  if (d->brokenAccountColor.isValid()) {
261  d->brokenAccountColor = scheme.foreground(KColorScheme::NegativeText).color();
262  invalidate();
263  }
264 }
265 
266 void FolderTreeWidgetProxyModel::addContentMimeTypeInclusionFilter(const QString &mimeType)
267 {
268  d->includedMimeTypes << mimeType;
269  d->checker.setWantedMimeTypes(d->includedMimeTypes.values());
271 }
virtual bool hasChildren(const QModelIndex &parent) const const
QString toString(const T &enumerator)
ForegroundRole
virtual int rowCount(const QModelIndex &parent) const const=0
bool isNull() const const
CaseInsensitive
QModelIndex sibling(int row, int column) const const
Status status() const
T value() const const
QIcon fromTheme(const QString &name)
KCALUTILS_EXPORT QString mimeType()
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const const override
AgentInstance instance(const QString &identifier) const
QVariant data(int role) const const
typedef ItemFlags
QString i18n(const char *text, const TYPE &arg...)
bool hideInSelectionDialog() const
Returns true if this folder should be hidden from all folder selection dialogs.
virtual Qt::ItemFlags flags(const QModelIndex &index) const const override
const T * attribute() const
The FolderTreeWidgetProxyModel class.
virtual int rowCount(const QModelIndex &parent) const const override
static Collection root()
int row() const const
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
void setAccessRights(Collection::Rights rights)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
virtual QVariant data(const QModelIndex &index, int role) const const override
static AgentManager * self()
Qt::ItemFlags flags(const QModelIndex &index) const override
const QAbstractItemModel * model() const const
The filter dialog.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon May 8 2023 03:58:16 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.