diff --git a/src/folder/entitycollectionorderproxymodel.cpp b/src/folder/entitycollectionorderproxymodel.cpp index 4f97b98..133c813 100644 --- a/src/folder/entitycollectionorderproxymodel.cpp +++ b/src/folder/entitycollectionorderproxymodel.cpp @@ -1,159 +1,165 @@ /* Copyright (c) 2010-2018 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "entitycollectionorderproxymodel.h" #include "kernel/mailkernel.h" #include "util/mailutil.h" #include "mailcommon_debug.h" #include #include #include #include namespace MailCommon { class Q_DECL_HIDDEN EntityCollectionOrderProxyModel::EntityCollectionOrderProxyModelPrivate { public: EntityCollectionOrderProxyModelPrivate() : manualSortingActive(false) { } int collectionRank(const Akonadi::Collection &collection) { const Akonadi::Collection::Id id = collection.id(); const int cachedRank = collectionRanks.value(id, -1); if (cachedRank != -1) { return cachedRank; } int rank = 100; if (Kernel::folderIsInbox(collection)) { rank = 1; } else if (Kernel::self()->folderIsDraftOrOutbox(collection)) { if (Kernel::self()->folderIsDrafts(collection)) { rank = 5; } else { rank = 2; } } else if (Kernel::self()->folderIsSentMailFolder(collection)) { rank = 3; } else if (Kernel::self()->folderIsTrash(collection)) { rank = 4; } else if (Kernel::self()->folderIsTemplates(collection)) { rank = 6; } else if (MailCommon::Util::isVirtualCollection(collection)) { rank = 200; + } else if (collection.parentCollection() == Akonadi::Collection::root() && MailCommon::Util::isUnifiedMailboxesAgent(collection)) { + // special treatment for Unified Mailboxes: they are *always* on top + rank = 0; } else if (!topLevelOrder.isEmpty()) { if (collection.parentCollection() == Akonadi::Collection::root()) { const QString resource = collection.resource(); if (resource.isEmpty()) { qCDebug(MAILCOMMON_LOG) << " collection has not resource: " << collection; //Don't save in collectionranks because we don't have resource name => pb. return rank; } const int order = topLevelOrder.indexOf(resource); if (order != -1) { - rank = order; + rank = order + 1; /* top-level rank "0" belongs to Unified Mailboxes */ } } } collectionRanks.insert(id, rank); return rank; } QMap collectionRanks; QStringList topLevelOrder; bool manualSortingActive; }; EntityCollectionOrderProxyModel::EntityCollectionOrderProxyModel(QObject *parent) : EntityOrderProxyModel(parent) , d(new EntityCollectionOrderProxyModelPrivate()) { setSortCaseSensitivity(Qt::CaseInsensitive); connect(Akonadi::SpecialMailCollections::self(), &Akonadi::SpecialMailCollections::defaultCollectionsChanged, this, &EntityCollectionOrderProxyModel::slotSpecialCollectionsChanged); connect(Akonadi::SpecialMailCollections::self(), &Akonadi::SpecialMailCollections::collectionsChanged, this, &EntityCollectionOrderProxyModel::slotSpecialCollectionsChanged); } EntityCollectionOrderProxyModel::~EntityCollectionOrderProxyModel() { if (d->manualSortingActive) { saveOrder(); } delete d; } void EntityCollectionOrderProxyModel::slotSpecialCollectionsChanged() { if (!d->manualSortingActive) { d->collectionRanks.clear(); invalidate(); } } void EntityCollectionOrderProxyModel::setTopLevelOrder(const QStringList &list) { d->topLevelOrder = list; clearRanks(); } void EntityCollectionOrderProxyModel::clearRanks() { d->collectionRanks.clear(); invalidate(); } bool EntityCollectionOrderProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { + const auto leftData = left.data(Akonadi::EntityTreeModel::CollectionRole).value(); + const auto rightData = right.data(Akonadi::EntityTreeModel::CollectionRole).value(); if (!d->manualSortingActive) { - Akonadi::Collection leftData - = left.data(Akonadi::EntityTreeModel::CollectionRole).value(); - Akonadi::Collection rightData - = right.data(Akonadi::EntityTreeModel::CollectionRole).value(); const int rankLeft = d->collectionRank(leftData); const int rankRight = d->collectionRank(rightData); if (rankLeft < rankRight) { return true; } else if (rankLeft > rankRight) { return false; } return QSortFilterProxyModel::lessThan(left, right); } - return EntityOrderProxyModel::lessThan(left, right); + + if (MailCommon::Util::isUnifiedMailboxesAgent(leftData)) { + return true; + } else { + return EntityOrderProxyModel::lessThan(left, right); + } } void EntityCollectionOrderProxyModel::setManualSortingActive(bool active) { if (d->manualSortingActive == active) { return; } d->manualSortingActive = active; d->collectionRanks.clear(); invalidate(); } bool EntityCollectionOrderProxyModel::isManualSortingActive() const { return d->manualSortingActive; } } diff --git a/src/util/mailutil.cpp b/src/util/mailutil.cpp index e7f38c4..a6e5578 100644 --- a/src/util/mailutil.cpp +++ b/src/util/mailutil.cpp @@ -1,308 +1,313 @@ /******************************************************************************* ** ** Filename : util ** Created on : 03 April, 2005 ** Copyright : (c) 2005 Till Adam ** Email : ** *******************************************************************************/ /******************************************************************************* ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** It is distributed in the hope that it will be useful, but ** WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** In addition, as a special exception, the copyright holders give ** permission to link the code of this program with any edition of ** the Qt library by Trolltech AS, Norway (or with modified versions ** of Qt that use the same license as Qt), and distribute linked ** combinations including the two. You must obey the GNU General ** Public License in all respects for all of the code used other than ** Qt. If you modify this file, you may extend this exception to ** your version of the file, but you are not obligated to do so. If ** you do not wish to do so, delete this exception statement from ** your version. ** *******************************************************************************/ #include "mailutil.h" #include "mailutil_p.h" #include "mailcommon_debug.h" #include "calendarinterface.h" #include "job/expirejob.h" #include "folder/foldersettings.h" #include "pop3settings.h" #include "kernel/mailkernel.h" #include "filter/dialog/filteractionmissingfolderdialog.h" #include "mailimporter/filterbalsa.h" #include "mailimporter/filterevolution.h" #include "mailimporter/filterevolution_v2.h" #include "mailimporter/filterevolution_v3.h" #include "mailimporter/filterclawsmail.h" #include "mailimporter/filtersylpheed.h" #include "mailimporter/filterthunderbird.h" #include "mailimporter/filteropera.h" #include "mailimporter/filtericedove.h" #include "mailimporter/othermailerutil.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include OrgKdeAkonadiPOP3SettingsInterface *MailCommon::Util::createPop3SettingsInterface( const QString &ident) { const auto service = Akonadi::ServerManager::agentServiceName(Akonadi::ServerManager::Resource, ident); return new OrgKdeAkonadiPOP3SettingsInterface(service, QStringLiteral("/Settings"), QDBusConnection::sessionBus()); } bool MailCommon::Util::isVirtualCollection(const Akonadi::Collection &collection) { return collection.isVirtual() || MailCommon::Util::isVirtualCollection(collection.resource()); } bool MailCommon::Util::isVirtualCollection(const QString &resource) { if (resource == QLatin1String("akonadi_search_resource")) { return true; } const auto type = Akonadi::AgentManager::self()->type(resource); return type.capabilities().contains(QLatin1String("Virtual")); } bool MailCommon::Util::isLocalCollection(const QString &resource) { auto type = Akonadi::AgentManager::self()->type(resource); return type.customProperties().value(QStringLiteral("HasLocalStorage"), false).toBool(); } QString MailCommon::Util::fullCollectionPath(const Akonadi::Collection &collection, bool addAccountName) { QString fullPath; QModelIndex idx = Akonadi::EntityTreeModel::modelIndexForCollection(KernelIf->collectionModel(), collection); if (!idx.isValid()) { return fullPath; } fullPath = idx.data().toString(); idx = idx.parent(); while (idx != QModelIndex()) { const QString tmp = idx.data().toString() + QLatin1Char('/') + fullPath; idx = idx.parent(); if (idx != QModelIndex()) { fullPath = tmp; } else { if (!addAccountName) { break; } else { fullPath = tmp; break; } } } return fullPath; } bool MailCommon::Util::showJobErrorMessage(KJob *job) { if (job->error()) { if (auto uidelegate = static_cast(job)->uiDelegate()) { uidelegate->showErrorMessage(); } else { qCDebug(MAILCOMMON_LOG) << " job->errorString() :" << job->errorString(); } return true; } return false; } Akonadi::AgentInstance::List MailCommon::Util::agentInstances(bool excludeMailDispacher) { Akonadi::AgentInstance::List relevantInstances; const Akonadi::AgentInstance::List agentList = Akonadi::AgentManager::self()->instances(); std::copy_if(agentList.cbegin(), agentList.cend(), std::back_inserter(relevantInstances), [excludeMailDispacher](const Akonadi::AgentInstance &instance) { return isMailAgent(instance, excludeMailDispacher); }); return relevantInstances; } bool MailCommon::Util::isMailAgent(const Akonadi::AgentInstance &instance, bool excludeMailTransport) { if (!instance.type().mimeTypes().contains(KMime::Message::mimeType())) { return false; } const QStringList capabilities(instance.type().capabilities()); if (capabilities.contains(QLatin1String("Resource")) && !capabilities.contains(QLatin1String("Virtual")) && !capabilities.contains(QLatin1String("MailTransport")) && !capabilities.contains(QLatin1String("Autostart"))) { return true; } else if (!excludeMailTransport && instance.identifier() == QLatin1String("akonadi_maildispatcher_agent")) { return true; } return false; } +bool MailCommon::Util::isUnifiedMailboxesAgent(const Akonadi::Collection &col) +{ + return col.resource() == QLatin1String("akonadi_unifiedmailbox_agent"); +} + uint MailCommon::Util::folderIdentity(const Akonadi::Item &item) { uint id = 0; if (item.isValid() && item.parentCollection().isValid()) { Akonadi::Collection col = item.parentCollection(); if (col.resource().isEmpty()) { col = CommonKernel->collectionFromId(col.id()); } const QSharedPointer fd = FolderSettings::forCollection(col, false); id = fd->identity(); } return id; } bool MailCommon::Util::ignoreNewMailInFolder(const Akonadi::Collection &collection) { if (collection.hasAttribute()) { if (collection.attribute()->ignoreNewMail()) { return true; } } return false; } QString MailCommon::Util::realFolderPath(const QString &path) { QString realPath(path); realPath.remove(QStringLiteral(".directory")); realPath.replace(QLatin1String("/."), QStringLiteral("/")); if (!realPath.isEmpty() && (realPath.at(0) == QLatin1Char('.'))) { realPath.remove(0, 1); //remove first "." } return realPath; } QColor MailCommon::Util::defaultQuotaColor() { KColorScheme scheme(QPalette::Active, KColorScheme::View); return scheme.foreground(KColorScheme::NegativeText).color(); } void MailCommon::Util::expireOldMessages(const Akonadi::Collection &collection, bool immediate) { ScheduledExpireTask *task = new ScheduledExpireTask(collection, immediate); KernelIf->jobScheduler()->registerTask(task); } Akonadi::Collection::Id MailCommon::Util::convertFolderPathToCollectionId(const QString &folder) { Akonadi::Collection::Id newFolderId = -1; bool exactPath = false; Akonadi::Collection::List lst = FilterActionMissingFolderDialog::potentialCorrectFolders(folder, exactPath); if (lst.count() == 1 && exactPath) { newFolderId = lst.at(0).id(); } else { QPointer dlg = new FilterActionMissingFolderDialog(lst, QString(), folder); if (dlg->exec()) { newFolderId = dlg->selectedCollection().id(); } delete dlg; } return newFolderId; } QString MailCommon::Util::convertFolderPathToCollectionStr(const QString &folder) { Akonadi::Collection::Id newFolderId = MailCommon::Util::convertFolderPathToCollectionId(folder); if (newFolderId == -1) { return QString(); } return QString::number(newFolderId); } void MailCommon::Util::foundMailer(QStringList &lst, const QString &name) { if (!name.isEmpty()) { lst.append(name); } } QStringList MailCommon::Util::foundMailer() { QStringList lst; MailCommon::Util::foundMailer(lst, MailImporter::FilterEvolution::isMailerFound()); MailCommon::Util::foundMailer(lst, MailImporter::FilterEvolution_v2::isMailerFound()); MailCommon::Util::foundMailer(lst, MailImporter::FilterEvolution_v3::isMailerFound()); MailCommon::Util::foundMailer(lst, MailImporter::FilterBalsa::isMailerFound()); MailCommon::Util::foundMailer(lst, MailImporter::FilterClawsMail::isMailerFound()); MailCommon::Util::foundMailer(lst, MailImporter::FilterOpera::isMailerFound()); MailCommon::Util::foundMailer(lst, MailImporter::FilterSylpheed::isMailerFound()); MailCommon::Util::foundMailer(lst, MailImporter::FilterThunderbird::isMailerFound()); MailCommon::Util::foundMailer(lst, MailImporter::FilterIcedove::isMailerFound()); const QStringList otherMailer = MailImporter::OtherMailerUtil::isMailerFound(); if (!otherMailer.isEmpty()) { lst << otherMailer; } return lst; } MailCommon::ExpireCollectionAttribute *MailCommon::Util::expirationCollectionAttribute(const Akonadi::Collection &collection, bool &mustDeleteExpirationAttribute) { MailCommon::ExpireCollectionAttribute *attr = nullptr; if (collection.hasAttribute()) { attr = collection.attribute(); mustDeleteExpirationAttribute = false; } else { attr = new MailCommon::ExpireCollectionAttribute(); KConfigGroup configGroup(KernelIf->config(), MailCommon::FolderSettings::configGroupName(collection)); if (configGroup.hasKey("ExpireMessages")) { attr->setAutoExpire(configGroup.readEntry("ExpireMessages", false)); attr->setReadExpireAge(configGroup.readEntry("ReadExpireAge", 3)); attr->setReadExpireUnits((MailCommon::ExpireCollectionAttribute::ExpireUnits)configGroup.readEntry("ReadExpireUnits", (int)MailCommon::ExpireCollectionAttribute::ExpireMonths)); attr->setUnreadExpireAge(configGroup.readEntry("UnreadExpireAge", 12)); attr->setUnreadExpireUnits((MailCommon::ExpireCollectionAttribute::ExpireUnits)configGroup.readEntry("UnreadExpireUnits", (int)MailCommon::ExpireCollectionAttribute::ExpireNever)); attr->setExpireAction(configGroup.readEntry("ExpireAction", "Delete") == QLatin1String("Move") ? MailCommon::ExpireCollectionAttribute::ExpireMove : MailCommon::ExpireCollectionAttribute::ExpireDelete); attr->setExpireToFolderId(configGroup.readEntry("ExpireToFolder", -1)); } mustDeleteExpirationAttribute = true; } return attr; } diff --git a/src/util/mailutil.h b/src/util/mailutil.h index 2087f4f..58c6b24 100644 --- a/src/util/mailutil.h +++ b/src/util/mailutil.h @@ -1,98 +1,100 @@ /******************************************************************************* ** ** Filename : util ** Created on : 03 April, 2005 ** Copyright : (c) 2005 Till Adam ** Email : ** *******************************************************************************/ /******************************************************************************* ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** It is distributed in the hope that it will be useful, but ** WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** In addition, as a special exception, the copyright holders give ** permission to link the code of this program with any edition of ** the Qt library by Trolltech AS, Norway (or with modified versions ** of Qt that use the same license as Qt), and distribute linked ** combinations including the two. You must obey the GNU General ** Public License in all respects for all of the code used other than ** Qt. If you modify this file, you may extend this exception to ** your version of the file, but you are not obligated to do so. If ** you do not wish to do so, delete this exception statement from ** your version. ** *******************************************************************************/ #ifndef MAILCOMMON_MAILUTIL_H #define MAILCOMMON_MAILUTIL_H #include "mailcommon_export.h" #include #include class OrgKdeAkonadiPOP3SettingsInterface; namespace Akonadi { class Item; } class KJob; class QString; namespace MailCommon { class ExpireCollectionAttribute; /** * The Util namespace contains a collection of helper functions use in * various places. */ namespace Util { Q_REQUIRED_RESULT MAILCOMMON_EXPORT OrgKdeAkonadiPOP3SettingsInterface *createPop3SettingsInterface( const QString &ident); Q_REQUIRED_RESULT MAILCOMMON_EXPORT bool isVirtualCollection(const Akonadi::Collection &col); Q_REQUIRED_RESULT MAILCOMMON_EXPORT bool isVirtualCollection(const QString &resource); Q_REQUIRED_RESULT MAILCOMMON_EXPORT QString fullCollectionPath(const Akonadi::Collection &collection, bool addAccountName = true); Q_REQUIRED_RESULT MAILCOMMON_EXPORT bool showJobErrorMessage(KJob *job); Q_REQUIRED_RESULT MAILCOMMON_EXPORT Akonadi::AgentInstance::List agentInstances(bool excludeMailTransport = true); Q_REQUIRED_RESULT MAILCOMMON_EXPORT bool isMailAgent(const Akonadi::AgentInstance &instance, bool excludeMailTransport = true); +Q_REQUIRED_RESULT MAILCOMMON_EXPORT bool isUnifiedMailboxesAgent(const Akonadi::Collection &col); + /** * Returns the identity of the folder that contains the given Akonadi::Item. */ Q_REQUIRED_RESULT MAILCOMMON_EXPORT uint folderIdentity(const Akonadi::Item &item); Q_REQUIRED_RESULT MAILCOMMON_EXPORT QString realFolderPath(const QString &path); Q_REQUIRED_RESULT MAILCOMMON_EXPORT QColor defaultQuotaColor(); MAILCOMMON_EXPORT void expireOldMessages(const Akonadi::Collection &collection, bool immediate); Q_REQUIRED_RESULT MAILCOMMON_EXPORT Akonadi::Collection::Id convertFolderPathToCollectionId(const QString &folder); Q_REQUIRED_RESULT MAILCOMMON_EXPORT QString convertFolderPathToCollectionStr(const QString &folder); MAILCOMMON_EXPORT void foundMailer(QStringList &lst, const QString &name); Q_REQUIRED_RESULT MAILCOMMON_EXPORT QStringList foundMailer(); Q_REQUIRED_RESULT MAILCOMMON_EXPORT bool isLocalCollection(const QString &resource); Q_REQUIRED_RESULT MAILCOMMON_EXPORT MailCommon::ExpireCollectionAttribute *expirationCollectionAttribute(const Akonadi::Collection &collection, bool &mustDeleteExpirationAttribute); } } #endif