Warning, file /pim/mailcommon/src/folder/foldertreewidgetproxymodel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2009-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "foldertreewidgetproxymodel.h" 0008 #include "foldersettings.h" 0009 #include "kernel/mailkernel.h" 0010 #include "util/mailutil.h" 0011 0012 #include <MessageCore/MessageCoreSettings> 0013 0014 #include <Akonadi/AgentInstance> 0015 #include <Akonadi/AgentManager> 0016 #include <Akonadi/EntityTreeModel> 0017 #include <Akonadi/MimeTypeChecker> 0018 0019 #include <Akonadi/CollectionQuotaAttribute> 0020 #include <KColorScheme> 0021 #include <KLocalizedString> 0022 0023 #include <QIcon> 0024 #include <QPalette> 0025 0026 using namespace MailCommon; 0027 class FolderTreeWidgetProxyModel::FolderTreeWidgetProxyModelPrivate 0028 { 0029 public: 0030 FolderTreeWidgetProxyModelPrivate(FolderTreeWidgetProxyModel *qq) 0031 : q(qq) 0032 { 0033 } 0034 0035 bool checkQuotaExcedded(const QModelIndex &index, qreal &percentage) 0036 { 0037 if (threshold >= 0.0) { 0038 if (index.model()->hasChildren(index)) { 0039 const int rowCount = index.model()->rowCount(index); 0040 for (int row = 0; row < rowCount; row++) { 0041 const QModelIndex firstIndex = q->mapToSource(index.model()->index(row, 0, index)); 0042 0043 const auto collectionFirst = q->sourceModel()->data(firstIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>(); 0044 if (collectionFirst.isValid() && collectionFirst.hasAttribute<Akonadi::CollectionQuotaAttribute>()) { 0045 const auto quota = collectionFirst.attribute<Akonadi::CollectionQuotaAttribute>(); 0046 0047 if (quota->currentValue() > -1 && quota->maximumValue() > 0) { 0048 percentage = (100.0 * quota->currentValue()) / quota->maximumValue(); 0049 if (percentage >= threshold) { 0050 return true; 0051 } 0052 } 0053 } 0054 } 0055 } 0056 } 0057 return false; 0058 } 0059 0060 QSet<QString> includedMimeTypes; 0061 Akonadi::MimeTypeChecker checker; 0062 0063 QColor brokenAccountColor; 0064 qreal threshold = -1.0; 0065 FolderTreeWidgetProxyModel *const q; 0066 bool enableCheck = false; 0067 bool hideVirtualFolder = false; 0068 bool hideSpecificFolder = false; 0069 bool hideOutboxFolder = false; 0070 }; 0071 0072 FolderTreeWidgetProxyModel::FolderTreeWidgetProxyModel(QObject *parent, FolderTreeWidgetProxyModelOptions option) 0073 : Akonadi::EntityRightsFilterModel(parent) 0074 , d(new FolderTreeWidgetProxyModelPrivate(this)) 0075 { 0076 setDynamicSortFilter(true); 0077 setFilterCaseSensitivity(Qt::CaseInsensitive); 0078 0079 if (option & HideVirtualFolder) { 0080 d->hideVirtualFolder = true; 0081 } 0082 if (option & HideSpecificFolder) { 0083 d->hideSpecificFolder = true; 0084 } 0085 if (option & HideOutboxFolder) { 0086 d->hideOutboxFolder = true; 0087 } 0088 readConfig(); 0089 } 0090 0091 FolderTreeWidgetProxyModel::~FolderTreeWidgetProxyModel() = default; 0092 0093 void FolderTreeWidgetProxyModel::setWarningThreshold(qreal threshold) 0094 { 0095 d->threshold = threshold; 0096 } 0097 0098 void FolderTreeWidgetProxyModel::readConfig() 0099 { 0100 invalidate(); 0101 } 0102 0103 Qt::ItemFlags FolderTreeWidgetProxyModel::flags(const QModelIndex &index) const 0104 { 0105 if (d->enableCheck) { 0106 const QModelIndex sourceIndex = mapToSource(index); 0107 const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0); 0108 const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>(); 0109 if (!MailCommon::Util::isVirtualCollection(collection)) { 0110 const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource()); 0111 if (instance.status() == Akonadi::AgentInstance::Broken) { 0112 return QSortFilterProxyModel::flags(sourceIndex) & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled); 0113 } 0114 } 0115 return Akonadi::EntityRightsFilterModel::flags(index); 0116 } 0117 return QSortFilterProxyModel::flags(index); 0118 } 0119 0120 void FolderTreeWidgetProxyModel::setEnabledCheck(bool enable) 0121 { 0122 if (d->enableCheck == enable) { 0123 return; 0124 } 0125 0126 d->enableCheck = enable; 0127 if (enable) { 0128 setAccessRights(Akonadi::Collection::CanCreateItem | Akonadi::Collection::CanCreateCollection); 0129 } 0130 } 0131 0132 bool FolderTreeWidgetProxyModel::enabledCheck() const 0133 { 0134 return d->enableCheck; 0135 } 0136 0137 void FolderTreeWidgetProxyModel::setHideVirtualFolder(bool exclude) 0138 { 0139 if (d->hideVirtualFolder != exclude) { 0140 d->hideVirtualFolder = exclude; 0141 invalidate(); 0142 } 0143 } 0144 0145 bool FolderTreeWidgetProxyModel::hideVirtualFolder() const 0146 { 0147 return d->hideVirtualFolder; 0148 } 0149 0150 void FolderTreeWidgetProxyModel::setHideSpecificFolder(bool hide) 0151 { 0152 if (d->hideSpecificFolder != hide) { 0153 d->hideSpecificFolder = hide; 0154 invalidate(); 0155 } 0156 } 0157 0158 bool FolderTreeWidgetProxyModel::hideSpecificFolder() const 0159 { 0160 return d->hideSpecificFolder; 0161 } 0162 0163 void FolderTreeWidgetProxyModel::setHideOutboxFolder(bool hide) 0164 { 0165 if (d->hideOutboxFolder != hide) { 0166 d->hideOutboxFolder = hide; 0167 invalidate(); 0168 } 0169 } 0170 0171 bool FolderTreeWidgetProxyModel::hideOutboxFolder() const 0172 { 0173 return d->hideOutboxFolder; 0174 } 0175 0176 bool FolderTreeWidgetProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const 0177 { 0178 const QModelIndex modelIndex = sourceModel()->index(sourceRow, 0, sourceParent); 0179 0180 const auto collection = sourceModel()->data(modelIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>(); 0181 if (!d->checker.isWantedCollection(collection)) { 0182 return false; 0183 } 0184 0185 if (d->hideVirtualFolder) { 0186 if (Util::isVirtualCollection(collection)) { 0187 return false; 0188 } 0189 } 0190 0191 if (d->hideSpecificFolder) { 0192 const QSharedPointer<FolderSettings> col = FolderSettings::forCollection(collection, false); 0193 if (!col.isNull() && col->hideInSelectionDialog()) { 0194 return false; 0195 } 0196 } 0197 0198 if (d->hideOutboxFolder) { 0199 if (collection == Kernel::self()->outboxCollectionFolder()) { 0200 return false; 0201 } 0202 } 0203 0204 return EntityRightsFilterModel::filterAcceptsRow(sourceRow, sourceParent); 0205 } 0206 0207 QVariant FolderTreeWidgetProxyModel::data(const QModelIndex &index, int role) const 0208 { 0209 if (role == Qt::ForegroundRole) { 0210 const QModelIndex sourceIndex = mapToSource(index); 0211 const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0); 0212 const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>(); 0213 0214 if (!MailCommon::Util::isVirtualCollection(collection)) { 0215 const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource()); 0216 0217 if (instance.status() == Akonadi::AgentInstance::Broken) { 0218 if (!d->brokenAccountColor.isValid()) { 0219 const KColorScheme scheme(QPalette::Active, KColorScheme::View); 0220 d->brokenAccountColor = scheme.foreground(KColorScheme::NegativeText).color(); 0221 } 0222 return d->brokenAccountColor; 0223 } 0224 } 0225 } else if (role == Qt::DisplayRole) { 0226 const QModelIndex sourceIndex = mapToSource(index); 0227 const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0); 0228 const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>(); 0229 if (!MailCommon::Util::isVirtualCollection(collection)) { 0230 const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource()); 0231 if (collection.parentCollection() == Akonadi::Collection::root()) { 0232 if (!instance.isOnline()) { 0233 return i18n("%1 (Offline)", Akonadi::EntityRightsFilterModel::data(index, role).toString()); 0234 } 0235 qreal percentage = 0.0; 0236 if (d->checkQuotaExcedded(index, percentage)) { 0237 return i18n("%1 (Reached %2% quota)", Akonadi::EntityRightsFilterModel::data(index, role).toString(), static_cast<int>(percentage)); 0238 } 0239 } 0240 } 0241 } else if (role == Qt::DecorationRole) { 0242 const QModelIndex sourceIndex = mapToSource(index); 0243 const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0); 0244 const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>(); 0245 if (!MailCommon::Util::isVirtualCollection(collection)) { 0246 if (collection.parentCollection() == Akonadi::Collection::root()) { 0247 qreal percentage = 0.0; 0248 if (d->checkQuotaExcedded(index, percentage)) { 0249 return QIcon::fromTheme(QStringLiteral("emblem-warning")); 0250 } 0251 } 0252 } 0253 } 0254 return Akonadi::EntityRightsFilterModel::data(index, role); 0255 } 0256 0257 void FolderTreeWidgetProxyModel::updatePalette() 0258 { 0259 if (d->brokenAccountColor.isValid()) { 0260 KColorScheme scheme(QPalette::Active, KColorScheme::View); 0261 d->brokenAccountColor = scheme.foreground(KColorScheme::NegativeText).color(); 0262 invalidate(); 0263 } 0264 } 0265 0266 void FolderTreeWidgetProxyModel::addContentMimeTypeInclusionFilter(const QString &mimeType) 0267 { 0268 d->includedMimeTypes << mimeType; 0269 d->checker.setWantedMimeTypes(d->includedMimeTypes.values()); 0270 invalidateFilter(); 0271 } 0272 0273 #include "moc_foldertreewidgetproxymodel.cpp"