You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

276 lines
9.2 KiB

/*
SPDX-FileCopyrightText: 2009-2021 Laurent Montel <montel@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "foldertreewidgetproxymodel.h"
#include "foldersettings.h"
#include "kernel/mailkernel.h"
#include "util/mailutil.h"
#include <MessageCore/MessageCoreSettings>
#include <Akonadi/AgentInstance>
#include <Akonadi/AgentManager>
#include <Akonadi/EntityTreeModel>
#include <Akonadi/MimeTypeChecker>
#include <Akonadi/CollectionQuotaAttribute>
#include <KColorScheme>
#include <KLocalizedString>
#include <QIcon>
#include <QPalette>
namespace MailCommon
{
class FolderTreeWidgetProxyModel::Private
{
public:
Private(FolderTreeWidgetProxyModel *qq)
: q(qq)
{
}
bool checkQuotaExcedded(const QModelIndex &index, qreal &percentage)
{
if (threshold >= 0.0) {
if (index.model()->hasChildren(index)) {
const int rowCount = index.model()->rowCount(index);
for (int row = 0; row < rowCount; row++) {
const QModelIndex firstIndex = q->mapToSource(index.model()->index(row, 0, index));
const auto collectionFirst = q->sourceModel()->data(firstIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
if (collectionFirst.isValid() && collectionFirst.hasAttribute<Akonadi::CollectionQuotaAttribute>()) {
const auto *quota = collectionFirst.attribute<Akonadi::CollectionQuotaAttribute>();
if (quota->currentValue() > -1 && quota->maximumValue() > 0) {
percentage = (100.0 * quota->currentValue()) / quota->maximumValue();
if (percentage >= threshold) {
return true;
}
}
}
}
}
}
return false;
}
QSet<QString> includedMimeTypes;
Akonadi::MimeTypeChecker checker;
QColor brokenAccountColor;
qreal threshold = -1.0;
FolderTreeWidgetProxyModel *const q;
bool enableCheck = false;
bool hideVirtualFolder = false;
bool hideSpecificFolder = false;
bool hideOutboxFolder = false;
};
FolderTreeWidgetProxyModel::FolderTreeWidgetProxyModel(QObject *parent, FolderTreeWidgetProxyModelOptions option)
: Akonadi::EntityRightsFilterModel(parent)
, d(new Private(this))
{
setDynamicSortFilter(true);
setFilterCaseSensitivity(Qt::CaseInsensitive);
if (option & HideVirtualFolder) {
d->hideVirtualFolder = true;
}
if (option & HideSpecificFolder) {
d->hideSpecificFolder = true;
}
if (option & HideOutboxFolder) {
d->hideOutboxFolder = true;
}
readConfig();
}
FolderTreeWidgetProxyModel::~FolderTreeWidgetProxyModel()
{
delete d;
}
void FolderTreeWidgetProxyModel::setWarningThreshold(qreal threshold)
{
d->threshold = threshold;
}
void FolderTreeWidgetProxyModel::readConfig()
{
invalidate();
}
Qt::ItemFlags FolderTreeWidgetProxyModel::flags(const QModelIndex &index) const
{
if (d->enableCheck) {
const QModelIndex sourceIndex = mapToSource(index);
const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
if (!MailCommon::Util::isVirtualCollection(collection)) {
const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource());
if (instance.status() == Akonadi::AgentInstance::Broken) {
return QSortFilterProxyModel::flags(sourceIndex) & ~(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
}
}
return Akonadi::EntityRightsFilterModel::flags(index);
}
return QSortFilterProxyModel::flags(index);
}
void FolderTreeWidgetProxyModel::setEnabledCheck(bool enable)
{
if (d->enableCheck == enable) {
return;
}
d->enableCheck = enable;
if (enable) {
setAccessRights(Akonadi::Collection::CanCreateItem | Akonadi::Collection::CanCreateCollection);
}
}
bool FolderTreeWidgetProxyModel::enabledCheck() const
{
return d->enableCheck;
}
void FolderTreeWidgetProxyModel::setHideVirtualFolder(bool exclude)
{
if (d->hideVirtualFolder != exclude) {
d->hideVirtualFolder = exclude;
invalidate();
}
}
bool FolderTreeWidgetProxyModel::hideVirtualFolder() const
{
return d->hideVirtualFolder;
}
void FolderTreeWidgetProxyModel::setHideSpecificFolder(bool hide)
{
if (d->hideSpecificFolder != hide) {
d->hideSpecificFolder = hide;
invalidate();
}
}
bool FolderTreeWidgetProxyModel::hideSpecificFolder() const
{
return d->hideSpecificFolder;
}
void FolderTreeWidgetProxyModel::setHideOutboxFolder(bool hide)
{
if (d->hideOutboxFolder != hide) {
d->hideOutboxFolder = hide;
invalidate();
}
}
bool FolderTreeWidgetProxyModel::hideOutboxFolder() const
{
return d->hideOutboxFolder;
}
bool FolderTreeWidgetProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
const QModelIndex modelIndex = sourceModel()->index(sourceRow, 0, sourceParent);
const auto collection = sourceModel()->data(modelIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
if (!d->checker.isWantedCollection(collection)) {
return false;
}
if (d->hideVirtualFolder) {
if (Util::isVirtualCollection(collection)) {
return false;
}
}
if (d->hideSpecificFolder) {
const QSharedPointer<FolderSettings> col = FolderSettings::forCollection(collection, false);
if (col && col->hideInSelectionDialog()) {
return false;
}
}
if (d->hideOutboxFolder) {
if (collection == Kernel::self()->outboxCollectionFolder()) {
return false;
}
}
return EntityRightsFilterModel::filterAcceptsRow(sourceRow, sourceParent);
}
QVariant FolderTreeWidgetProxyModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::ForegroundRole) {
const QModelIndex sourceIndex = mapToSource(index);
const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
if (!MailCommon::Util::isVirtualCollection(collection)) {
const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource());
if (instance.status() == Akonadi::AgentInstance::Broken) {
if (!d->brokenAccountColor.isValid()) {
const KColorScheme scheme(QPalette::Active, KColorScheme::View);
d->brokenAccountColor = scheme.foreground(KColorScheme::NegativeText).color();
}
return d->brokenAccountColor;
}
}
} else if (role == Qt::DisplayRole) {
const QModelIndex sourceIndex = mapToSource(index);
const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
if (!MailCommon::Util::isVirtualCollection(collection)) {
const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(collection.resource());
if (collection.parentCollection() == Akonadi::Collection::root()) {
if (!instance.isOnline()) {
return i18n("%1 (Offline)", Akonadi::EntityRightsFilterModel::data(index, role).toString());
}
qreal percentage = 0.0;
if (d->checkQuotaExcedded(index, percentage)) {
return i18n("%1 (Reached %2% quota)", Akonadi::EntityRightsFilterModel::data(index, role).toString(), static_cast<int>(percentage));
}
}
}
} else if (role == Qt::DecorationRole) {
const QModelIndex sourceIndex = mapToSource(index);
const QModelIndex rowIndex = sourceIndex.sibling(sourceIndex.row(), 0);
const auto collection = sourceModel()->data(rowIndex, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
if (!MailCommon::Util::isVirtualCollection(collection)) {
if (collection.parentCollection() == Akonadi::Collection::root()) {
qreal percentage = 0.0;
if (d->checkQuotaExcedded(index, percentage)) {
return QIcon::fromTheme(QStringLiteral("emblem-warning"));
}
}
}
}
return Akonadi::EntityRightsFilterModel::data(index, role);
}
void FolderTreeWidgetProxyModel::updatePalette()
{
if (d->brokenAccountColor.isValid()) {
KColorScheme scheme(QPalette::Active, KColorScheme::View);
d->brokenAccountColor = scheme.foreground(KColorScheme::NegativeText).color();
invalidate();
}
}
void FolderTreeWidgetProxyModel::addContentMimeTypeInclusionFilter(const QString &mimeType)
{
d->includedMimeTypes << mimeType;
d->checker.setWantedMimeTypes(d->includedMimeTypes.values());
invalidateFilter();
}
}