diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6612ed7..da06e19 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,120 +1,120 @@
cmake_minimum_required(VERSION 3.0)
-set(PIM_VERSION "5.6.41")
+set(PIM_VERSION "5.6.42")
project(mailcommon VERSION ${PIM_VERSION})
set(KF5_VERSION "5.36.0")
find_package(ECM ${KF5_VERSION} CONFIG REQUIRED)
set(CMAKE_MODULE_PATH ${mailcommon_SOURCE_DIR}/cmake/modules/ ${ECM_MODULE_PATH})
set(LIBRARY_NAMELINK)
include(GenerateExportHeader)
include(ECMGenerateHeaders)
include(ECMGeneratePriFile)
include(CMakePackageConfigHelpers)
include(ECMSetupVersion)
include(FeatureSummary)
include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
include(ECMQtDeclareLoggingCategory)
include(ECMAddTests)
include(ECMCoverageOption)
set(MAILCOMMON_LIB_VERSION ${PIM_VERSION})
set(AKONADIMIME_LIB_VERSION "5.6.40")
set(MESSAGELIB_LIB_VERSION "5.6.42")
set(QT_REQUIRED_VERSION "5.7.0")
set(KMIME_LIB_VERSION "5.6.41")
set(KMAILTRANSPORT_LIB_VERSION "5.6.40")
set(MAILIMPORTER_LIB_VERSION "5.6.40")
set(LIBKDEPIM_LIB_VERSION "5.6.40")
set(PIMCOMMON_LIB_VERSION "5.6.40")
set(AKONADI_VERSION "5.6.40")
find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Widgets DBus Test Xml)
find_package(KF5Archive ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5Codecs ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5Completion ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5Config ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5ConfigWidgets ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5I18n ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5IconThemes ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5ItemModels ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5ItemViews ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5KIO ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5TextWidgets ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5WidgetsAddons ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5WindowSystem ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5XmlGui ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5DBusAddons ${KF5_VERSION} CONFIG REQUIRED)
find_package(KF5Akonadi ${AKONADI_VERSION} CONFIG REQUIRED)
find_package(KF5AkonadiMime ${AKONADIMIME_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5LibkdepimAkonadi ${LIBKDEPIM_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5MailImporter ${MAILIMPORTER_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5MailTransport ${KMAILTRANSPORT_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5MessageComposer ${MESSAGELIB_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5MessageCore ${MESSAGELIB_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5MessageViewer ${MESSAGELIB_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5Mime ${KMIME_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5PimCommonAkonadi ${PIMCOMMON_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5TemplateParser ${MESSAGELIB_LIB_VERSION} CONFIG REQUIRED)
find_package(Phonon4Qt5 CONFIG REQUIRED)
find_package(Qt5Designer CONFIG)
set_package_properties(Qt5Designer PROPERTIES
PURPOSE "Required to build the Qt Designer plugins"
TYPE OPTIONAL
)
if (Qt5Designer_FOUND)
find_package(KF5DesignerPlugin ${KF5_VERSION} CONFIG REQUIRED)
endif()
ecm_setup_version(PROJECT VARIABLE_PREFIX MAILCOMMON
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/mailcommon_version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5MailCommonConfigVersion.cmake"
SOVERSION 5
)
find_package(Xsltproc)
set_package_properties(Xsltproc PROPERTIES DESCRIPTION "XSLT processor from libxslt" TYPE REQUIRED PURPOSE "Required to generate D-Bus interfaces for all Akonadi resources.")
########### Targets ###########
#add_definitions("-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII")
add_definitions(-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT)
add_definitions("-DQT_NO_CAST_TO_ASCII")
remove_definitions( -DQT_NO_CAST_FROM_ASCII )
#add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000)
add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
########### CMake Config Files ###########
set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5MailCommon")
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/KF5MailCommonConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/KF5MailCommonConfig.cmake"
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/KF5MailCommonConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/KF5MailCommonConfigVersion.cmake"
DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
COMPONENT Devel
)
install(EXPORT KF5MailCommonTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5MailCommonTargets.cmake NAMESPACE KF5::)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/mailcommon_version.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel
)
add_subdirectory(src)
add_subdirectory(autotests)
install( FILES mailcommon.renamecategories mailcommon.categories DESTINATION ${KDE_INSTALL_CONFDIR} )
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
diff --git a/src/dbusinterfaces/org.freedesktop.Akonadi.MailFilterAgent.xml b/src/dbusinterfaces/org.freedesktop.Akonadi.MailFilterAgent.xml
index e51212e..baa5c63 100644
--- a/src/dbusinterfaces/org.freedesktop.Akonadi.MailFilterAgent.xml
+++ b/src/dbusinterfaces/org.freedesktop.Akonadi.MailFilterAgent.xml
@@ -1,38 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/filter/filtermanager.cpp b/src/filter/filtermanager.cpp
index 33950c2..41a8716 100644
--- a/src/filter/filtermanager.cpp
+++ b/src/filter/filtermanager.cpp
@@ -1,316 +1,350 @@
/*
Copyright (C) 2011 Tobias Koenig
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library 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 Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#include "filtermanager.h"
#include "mailcommon_debug.h"
#include "filteractions/filteraction.h"
#include "filteractions/filteractiondict.h"
#include "filterimporterexporter.h"
#include "mailfilteragentinterface.h"
#include
#include
#include
#include
#include
#include
#include
namespace MailCommon {
class Q_DECL_HIDDEN FilterManager::Private
{
public:
Private(FilterManager *qq)
: q(qq)
, mMailFilterAgentInterface(nullptr)
, mMonitor(new Akonadi::Monitor)
, mInitialized(false)
{
const auto service = Akonadi::ServerManager::agentServiceName(Akonadi::ServerManager::Agent,
QStringLiteral("akonadi_mailfilter_agent"));
mMailFilterAgentInterface = new org::freedesktop::Akonadi::MailFilterAgent(service,
QStringLiteral("/MailFilterAgent"),
QDBusConnection::sessionBus(), q);
}
void readConfig();
void writeConfig(bool withSync = true) const;
void clear();
QMap mTagList;
static FilterManager *mInstance;
static FilterActionDict *mFilterActionDict;
FilterManager *q;
OrgFreedesktopAkonadiMailFilterAgentInterface *mMailFilterAgentInterface;
QList mFilters;
Akonadi::Monitor *mMonitor;
bool mInitialized;
};
void FilterManager::Private::readConfig()
{
KSharedConfig::Ptr config = KSharedConfig::openConfig(
Akonadi::ServerManager::addNamespace(QStringLiteral("akonadi_mailfilter_agent")) + QStringLiteral("rc"));
clear();
QStringList emptyFilters;
mFilters = FilterImporterExporter::readFiltersFromConfig(config, emptyFilters);
Q_EMIT q->filtersChanged();
}
void FilterManager::Private::writeConfig(bool withSync) const
{
KSharedConfig::Ptr config = KSharedConfig::openConfig(
Akonadi::ServerManager::addNamespace(QStringLiteral("akonadi_mailfilter_agent")) + QStringLiteral("rc"));
// Now, write out the new stuff:
FilterImporterExporter::writeFiltersToConfig(mFilters, config);
KConfigGroup group = config->group("General");
if (withSync) {
group.sync();
}
}
void FilterManager::Private::clear()
{
qDeleteAll(mFilters);
mFilters.clear();
}
}
using namespace MailCommon;
FilterManager *FilterManager::Private::mInstance = nullptr;
FilterActionDict *FilterManager::Private::mFilterActionDict = nullptr;
FilterManager *FilterManager::instance()
{
if (!FilterManager::Private::mInstance) {
FilterManager::Private::mInstance = new FilterManager;
}
return FilterManager::Private::mInstance;
}
FilterActionDict *FilterManager::filterActionDict()
{
if (!FilterManager::Private::mFilterActionDict) {
FilterManager::Private::mFilterActionDict = new FilterActionDict;
}
return FilterManager::Private::mFilterActionDict;
}
FilterManager::FilterManager()
: d(new Private(this))
{
updateTagList();
d->mMonitor->setTypeMonitored(Akonadi::Monitor::Tags);
d->mMonitor->tagFetchScope().fetchAttribute();
connect(d->mMonitor, &Akonadi::Monitor::tagAdded, this, &FilterManager::slotTagAdded);
connect(d->mMonitor, &Akonadi::Monitor::tagRemoved, this, &FilterManager::slotTagRemoved);
connect(d->mMonitor, &Akonadi::Monitor::tagChanged, this, &FilterManager::slotTagChanged);
qDBusRegisterMetaType >();
Akonadi::ServerManager::State state = Akonadi::ServerManager::self()->state();
if (state == Akonadi::ServerManager::Running) {
QTimer::singleShot(0, this, &FilterManager::slotReadConfig);
} else {
connect(Akonadi::ServerManager::self(), &Akonadi::ServerManager::stateChanged, this, &FilterManager::slotServerStateChanged);
}
}
FilterManager::~FilterManager()
{
cleanup();
}
void FilterManager::cleanup()
{
d->clear();
}
void FilterManager::slotServerStateChanged(Akonadi::ServerManager::State state)
{
if (state == Akonadi::ServerManager::Running) {
d->readConfig();
disconnect(Akonadi::ServerManager::self(), SIGNAL(stateChanged(Akonadi::ServerManager::State)));
}
}
void FilterManager::updateTagList()
{
Akonadi::TagFetchJob *fetchJob = new Akonadi::TagFetchJob(this);
fetchJob->fetchScope().fetchAttribute();
connect(fetchJob, &Akonadi::TagFetchJob::result, this, &FilterManager::slotFinishedTagListing);
}
bool FilterManager::initialized() const
{
return d->mInitialized;
}
void FilterManager::slotReadConfig()
{
d->readConfig();
d->mInitialized = true;
Q_EMIT loadingFiltersDone();
}
void FilterManager::slotFinishedTagListing(KJob *job)
{
if (job->error()) {
qCWarning(MAILCOMMON_LOG) << "failed to retrieve tags " << job->errorString();
}
Akonadi::TagFetchJob *fetchJob = static_cast(job);
const Akonadi::Tag::List lstTags = fetchJob->tags();
for (const Akonadi::Tag &tag : lstTags) {
d->mTagList.insert(tag.url(), tag.name());
}
Q_EMIT tagListingFinished();
}
void FilterManager::slotTagAdded(const Akonadi::Tag &tag)
{
d->mTagList.insert(tag.url(), tag.name());
Q_EMIT tagListingFinished();
}
void FilterManager::slotTagChanged(const Akonadi::Tag &tag)
{
if (d->mTagList.contains(tag.url())) {
d->mTagList.insert(tag.url(), tag.name());
}
Q_EMIT tagListingFinished();
}
void FilterManager::slotTagRemoved(const Akonadi::Tag &tag)
{
d->mTagList.remove(tag.url());
Q_EMIT tagListingFinished();
}
QMap FilterManager::tagList() const
{
return d->mTagList;
}
bool FilterManager::isValid() const
{
return d->mMailFilterAgentInterface->isValid();
}
QString FilterManager::createUniqueFilterName(const QString &name) const
{
return d->mMailFilterAgentInterface->createUniqueName(name);
}
void FilterManager::showFilterLogDialog(qlonglong windowId)
{
d->mMailFilterAgentInterface->showFilterLogDialog(windowId);
}
void FilterManager::filter(const Akonadi::Item &item, const QString &identifier, const QString &resourceId) const
{
d->mMailFilterAgentInterface->filter(item.id(), identifier, resourceId);
}
void FilterManager::filter(const Akonadi::Item &item, FilterSet set, bool account, const QString &resourceId) const
{
d->mMailFilterAgentInterface->filterItem(item.id(), static_cast(set), account ? resourceId : QString());
}
+void FilterManager::filter(const Akonadi::Collection &collection, MailCommon::FilterManager::FilterSet set) const
+{
+ filter({ collection }, set);
+}
+
+void FilterManager::filter(const Akonadi::Collection::List &collections, FilterManager::FilterSet set) const
+{
+ QList colIds;
+ colIds.reserve(collections.size());
+ for (const auto col : collections) {
+ colIds << col.id();
+ }
+
+ d->mMailFilterAgentInterface->filterCollections(colIds, static_cast(set));
+}
+
+void FilterManager::filter(const Akonadi::Collection &collection, const QStringList &listFilters) const
+{
+ filter({ collection }, listFilters);
+}
+
+
+void FilterManager::filter(const Akonadi::Collection::List &collections, const QStringList &listFilters) const
+{
+ QList colIds;
+ colIds.reserve(collections.size());
+ for (const auto col : collections) {
+ colIds << col.id();
+ }
+
+ d->mMailFilterAgentInterface->applySpecificFiltersOnCollections(colIds, listFilters);
+}
+
+
void FilterManager::filter(const Akonadi::Item::List &messages, FilterManager::FilterSet set) const
{
QList itemIds;
itemIds.reserve(messages.size());
for (const Akonadi::Item &item : messages) {
itemIds << item.id();
}
d->mMailFilterAgentInterface->filterItems(itemIds, static_cast(set));
}
void FilterManager::filter(const Akonadi::Item::List &messages, SearchRule::RequiredPart requiredPart, const QStringList &listFilters) const
{
QList itemIds;
itemIds.reserve(messages.size());
for (const Akonadi::Item &item : messages) {
itemIds << item.id();
}
d->mMailFilterAgentInterface->applySpecificFilters(itemIds, static_cast(requiredPart), listFilters);
}
void FilterManager::setFilters(const QList &filters)
{
beginUpdate();
d->clear();
d->mFilters = filters;
endUpdate();
}
QList FilterManager::filters() const
{
return d->mFilters;
}
void FilterManager::appendFilters(const QList &filters, bool replaceIfNameExists)
{
beginUpdate();
if (replaceIfNameExists) {
for (const MailCommon::MailFilter *newFilter : filters) {
int numberOfFilters = d->mFilters.count();
for (int i = 0; i < numberOfFilters; ++i) {
MailCommon::MailFilter *filter = d->mFilters.at(i);
if (newFilter->name() == filter->name()) {
d->mFilters.removeAll(filter);
i = 0;
numberOfFilters = d->mFilters.count();
}
}
}
}
d->mFilters += filters;
endUpdate();
}
void FilterManager::removeFilter(MailCommon::MailFilter *filter)
{
beginUpdate();
d->mFilters.removeAll(filter);
endUpdate();
}
void FilterManager::beginUpdate()
{
}
void FilterManager::endUpdate()
{
d->writeConfig(true);
d->mMailFilterAgentInterface->reload();
Q_EMIT filtersChanged();
}
diff --git a/src/filter/filtermanager.h b/src/filter/filtermanager.h
index fcc3981..1939006 100644
--- a/src/filter/filtermanager.h
+++ b/src/filter/filtermanager.h
@@ -1,187 +1,211 @@
/*
Copyright (C) 2011 Tobias Koenig
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This library 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 Library General Public
License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
#ifndef MAILCOMMON_FILTERMANAGER_H
#define MAILCOMMON_FILTERMANAGER_H
#include "mailcommon_export.h"
#include "mailfilter.h"
#include -
#include
#include
namespace MailCommon {
class FilterActionDict;
/**
* @short A wrapper class that allows easy access to the mail filters
*
* This class communicates with the mailfilter agent via DBus.
*/
class MAILCOMMON_EXPORT FilterManager : public QObject
{
Q_OBJECT
public:
~FilterManager();
/**
* Describes the list of filters.
*/
enum FilterSet {
NoSet = 0x0,
Inbound = 0x1,
Outbound = 0x2,
Explicit = 0x4,
BeforeOutbound = 0x8,
AllFolders = 0x16, ///< Apply the filter on all folders, not just inbox
All = Inbound | BeforeOutbound | Outbound | Explicit | AllFolders
};
/**
* Returns the global filter manager object.
*/
static FilterManager *instance();
/**
* Returns whether the filter manager is in a usable state.
*/
bool isValid() const;
/**
* Checks for existing filters with the @p name and extend the
* "name" to "name (i)" until no match is found for i=1..n
*/
QString createUniqueFilterName(const QString &name) const;
/**
* Returns the global filter action dictionary.
*/
static FilterActionDict *filterActionDict();
/**
* Shows the filter log dialog.
*
* This is used to debug problems with filters.
*/
void showFilterLogDialog(qlonglong windowId);
/// Apply filters interface
/**
* Applies filter with the given @p identifier on the message @p item.
* @return @c true on success, @c false otherwise.
*/
void filter(const Akonadi::Item &item, const QString &identifier, const QString &resourceId) const;
/**
* Process given message item by applying the filter rules one by
* one. You can select which set of filters (incoming or outgoing)
* should be used.
*
* @param item The message item to process.
* @param set Select the filter set to use.
* @param account @c true if an account id is specified else @c false
* @param accountId The id of the resource that the message was retrieved from
*/
void filter(const Akonadi::Item &item, FilterSet set = Inbound, bool account = false, const QString &resourceId = QString()) const;
+ /**
+ * Process all messages in given collection by applying the filters rules one
+ * by one. You can select which set of filters (incoming or outgoing)
+ * should be used.
+ */
+ void filter(const Akonadi::Collection &collection, FilterSet set = Inbound) const;
+
+ /**
+ * Apply specified filters on all messages in given collection
+ */
+ void filter(const Akonadi::Collection &collection, const QStringList &listFilters) const;
+
+ /**
+ * Process all messages in given collections by applying the filters rules one
+ * by one. You can select which set of filters (incoming or outgoing)
+ * should be used.
+ */
+ void filter(const Akonadi::Collection::List &collections, FilterSet set = Inbound) const;
+
+ /**
+ * Apply specified filters on all messages in given collection
+ */
+ void filter(const Akonadi::Collection::List &collections, const QStringList &listFilters) const;
+
/**
* Process given @p messages by applying the filter rules one by
* one. You can select which set of filters (incoming or outgoing)
* should be used.
*
* @param item The message item to process.
* @param set Select the filter set to use.
*/
void filter(const Akonadi::Item::List &messages, FilterSet set = Explicit) const;
void filter(const Akonadi::Item::List &messages, SearchRule::RequiredPart requiredPart, const QStringList &listFilters) const;
/// Manage filters interface
/**
* Appends the list of @p filters to the current list of filters and
* write everything back into the configuration. The filter manager
* takes ownership of the filters in the list.
*/
void appendFilters(const QList &filters, bool replaceIfNameExists = false);
/**
* Removes the given @p filter from the list.
* The filter object is not deleted.
*/
void removeFilter(MailCommon::MailFilter *filter);
/**
* Replace the list of filters of the filter manager with the given list of @p filters.
* The manager takes ownership of the filters.
*/
void setFilters(const QList &filters);
/**
* Returns the filter list of the manager.
*/
QList filters() const;
/**
* Should be called at the beginning of an filter list update.
*/
void beginUpdate();
/**
* Should be called at the end of an filter list update.
*/
void endUpdate();
QMap tagList() const;
bool initialized() const;
void cleanup();
private Q_SLOTS:
void slotServerStateChanged(Akonadi::ServerManager::State);
void slotFinishedTagListing(KJob *);
void slotReadConfig();
void updateTagList();
void slotTagAdded(const Akonadi::Tag &);
void slotTagChanged(const Akonadi::Tag &);
void slotTagRemoved(const Akonadi::Tag &);
Q_SIGNALS:
/**
* This signal is emitted whenever the filter list has been updated.
*/
void filtersChanged();
void tagListingFinished();
void loadingFiltersDone();
private:
FilterManager();
class Private;
Private *const d;
};
}
#endif