Mailcommon

filtermanager.cpp
1/*
2 SPDX-FileCopyrightText: 2011 Tobias Koenig <tokoe@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "filtermanager.h"
8#include "mailcommon_debug.h"
9
10#include "filteractions/filteractiondict.h"
11#include "filterimporterexporter.h"
12#include "mailfilteragentinterface.h"
13#include <Akonadi/Monitor>
14#include <Akonadi/Tag>
15#include <Akonadi/TagAttribute>
16#include <Akonadi/TagFetchJob>
17#include <Akonadi/TagFetchScope>
18#include <KConfigGroup>
19
20#include <QTimer>
21
22namespace MailCommon
23{
24class FilterManager::FilterManagerPrivate
25{
26public:
27 FilterManagerPrivate(FilterManager *qq)
28 : q(qq)
29 , mMonitor(new Akonadi::Monitor)
30 {
31 const auto service = Akonadi::ServerManager::agentServiceName(Akonadi::ServerManager::Agent, QStringLiteral("akonadi_mailfilter_agent"));
32 mMailFilterAgentInterface =
33 new org::freedesktop::Akonadi::MailFilterAgent(service, QStringLiteral("/MailFilterAgent"), QDBusConnection::sessionBus(), q);
34 }
35
36 void readConfig();
37 void writeConfig(bool withSync = true) const;
38 void clear();
39
40 QMap<QUrl, QString> mTagList;
41 static FilterManager *mInstance;
42 static FilterActionDict *mFilterActionDict;
43
44 FilterManager *const q;
45 OrgFreedesktopAkonadiMailFilterAgentInterface *mMailFilterAgentInterface = nullptr;
47 Akonadi::Monitor *const mMonitor;
48 bool mInitialized = false;
49};
50
51void FilterManager::FilterManagerPrivate::readConfig()
52{
53 KSharedConfig::Ptr config =
54 KSharedConfig::openConfig(Akonadi::ServerManager::addNamespace(QStringLiteral("akonadi_mailfilter_agent")) + QStringLiteral("rc"));
55 clear();
56 QStringList emptyFilters;
57 mFilters = FilterImporterExporter::readFiltersFromConfig(config, emptyFilters);
59}
60
61void FilterManager::FilterManagerPrivate::writeConfig(bool withSync) const
62{
63 KSharedConfig::Ptr config =
64 KSharedConfig::openConfig(Akonadi::ServerManager::addNamespace(QStringLiteral("akonadi_mailfilter_agent")) + QStringLiteral("rc"));
65
66 // Now, write out the new stuff:
68 KConfigGroup group = config->group("General");
69
70 if (withSync) {
71 group.sync();
72 }
73}
74
75void FilterManager::FilterManagerPrivate::clear()
76{
77 qDeleteAll(mFilters);
78 mFilters.clear();
79}
80}
81
82using namespace MailCommon;
83
84FilterManager *FilterManager::FilterManagerPrivate::mInstance = nullptr;
85FilterActionDict *FilterManager::FilterManagerPrivate::mFilterActionDict = nullptr;
86
88{
89 if (!FilterManager::FilterManagerPrivate::mInstance) {
90 FilterManager::FilterManagerPrivate::mInstance = new FilterManager;
91 }
92
93 return FilterManager::FilterManagerPrivate::mInstance;
94}
95
97{
98 if (!FilterManager::FilterManagerPrivate::mFilterActionDict) {
99 FilterManager::FilterManagerPrivate::mFilterActionDict = new FilterActionDict;
100 }
101
102 return FilterManager::FilterManagerPrivate::mFilterActionDict;
103}
104
105FilterManager::FilterManager()
106 : d(new FilterManagerPrivate(this))
107{
108 updateTagList();
109
110 d->mMonitor->setObjectName(QLatin1StringView("FilterManagerTagMonitor"));
111 d->mMonitor->setTypeMonitored(Akonadi::Monitor::Tags);
113 connect(d->mMonitor, &Akonadi::Monitor::tagAdded, this, &FilterManager::slotTagAdded);
114 connect(d->mMonitor, &Akonadi::Monitor::tagRemoved, this, &FilterManager::slotTagRemoved);
115 connect(d->mMonitor, &Akonadi::Monitor::tagChanged, this, &FilterManager::slotTagChanged);
116
117 qDBusRegisterMetaType<QList<qint64>>();
119 if (state == Akonadi::ServerManager::Running) {
120 QTimer::singleShot(0, this, &FilterManager::slotReadConfig);
121 } else {
122 connect(Akonadi::ServerManager::self(), &Akonadi::ServerManager::stateChanged, this, &FilterManager::slotServerStateChanged);
123 }
124}
125
126FilterManager::~FilterManager()
127{
128 cleanup();
129}
130
131void FilterManager::cleanup()
132{
133 d->clear();
134}
135
136void FilterManager::slotServerStateChanged(Akonadi::ServerManager::State state)
137{
138 if (state == Akonadi::ServerManager::Running) {
139 d->readConfig();
141 }
142}
143
144void FilterManager::updateTagList()
145{
146 auto fetchJob = new Akonadi::TagFetchJob(this);
147 fetchJob->fetchScope().fetchAttribute<Akonadi::TagAttribute>();
148 connect(fetchJob, &Akonadi::TagFetchJob::result, this, &FilterManager::slotFinishedTagListing);
149}
150
151bool FilterManager::initialized() const
152{
153 return d->mInitialized;
154}
155
156void FilterManager::slotReadConfig()
157{
158 d->readConfig();
159 d->mInitialized = true;
160 Q_EMIT loadingFiltersDone();
161}
162
163void FilterManager::slotFinishedTagListing(KJob *job)
164{
165 if (job->error()) {
166 qCWarning(MAILCOMMON_LOG) << "failed to retrieve tags " << job->errorString();
167 }
168 auto fetchJob = static_cast<Akonadi::TagFetchJob *>(job);
169 const Akonadi::Tag::List lstTags = fetchJob->tags();
170 for (const Akonadi::Tag &tag : lstTags) {
171 d->mTagList.insert(tag.url(), tag.name());
172 }
173
174 Q_EMIT tagListingFinished();
175}
176
177void FilterManager::slotTagAdded(const Akonadi::Tag &tag)
178{
179 d->mTagList.insert(tag.url(), tag.name());
180 Q_EMIT tagListingFinished();
181}
182
183void FilterManager::slotTagChanged(const Akonadi::Tag &tag)
184{
185 if (d->mTagList.contains(tag.url())) {
186 d->mTagList.insert(tag.url(), tag.name());
187 }
188 Q_EMIT tagListingFinished();
189}
190
191void FilterManager::slotTagRemoved(const Akonadi::Tag &tag)
192{
193 d->mTagList.remove(tag.url());
194 Q_EMIT tagListingFinished();
195}
196
197QMap<QUrl, QString> FilterManager::tagList() const
198{
199 return d->mTagList;
200}
201
203{
204 return d->mMailFilterAgentInterface->isValid();
205}
206
208{
209 return d->mMailFilterAgentInterface->createUniqueName(name);
210}
211
213{
214 d->mMailFilterAgentInterface->showFilterLogDialog(windowId);
215}
216
217void FilterManager::filter(const Akonadi::Item &item, const QString &identifier, const QString &resourceId) const
218{
219 d->mMailFilterAgentInterface->filter(item.id(), identifier, resourceId);
220}
221
222void FilterManager::filter(const Akonadi::Item &item, FilterSet set, bool account, const QString &resourceId) const
223{
224 d->mMailFilterAgentInterface->filterItem(item.id(), static_cast<int>(set), account ? resourceId : QString());
225}
226
227void FilterManager::filter(const Akonadi::Collection &collection, FilterSet set) const
228{
229 filter(Akonadi::Collection::List{collection}, set);
230}
231
233{
234 QList<qint64> colIds;
235 colIds.reserve(collections.size());
236 for (const auto &col : collections) {
237 colIds << col.id();
238 }
239
240 d->mMailFilterAgentInterface->filterCollections(colIds, static_cast<int>(set));
241}
242
243void FilterManager::filter(const Akonadi::Collection &collection, const QStringList &listFilters) const
244{
245 filter(Akonadi::Collection::List{collection}, listFilters);
246}
247
248void FilterManager::filter(const Akonadi::Collection::List &collections, const QStringList &listFilters, FilterSet set) const
249{
250 QList<qint64> colIds;
251 colIds.reserve(collections.size());
252 for (const auto &col : collections) {
253 colIds << col.id();
254 }
255
256 d->mMailFilterAgentInterface->applySpecificFiltersOnCollections(colIds, listFilters, static_cast<int>(set));
257}
258
260{
261 QList<qint64> itemIds;
262
263 itemIds.reserve(messages.size());
264 for (const Akonadi::Item &item : messages) {
265 itemIds << item.id();
266 }
267
268 d->mMailFilterAgentInterface->filterItems(itemIds, static_cast<int>(set));
269}
270
271void FilterManager::filter(const Akonadi::Item::List &messages, SearchRule::RequiredPart requiredPart, const QStringList &listFilters) const
272{
273 QList<qint64> itemIds;
274
275 itemIds.reserve(messages.size());
276 for (const Akonadi::Item &item : messages) {
277 itemIds << item.id();
278 }
279 d->mMailFilterAgentInterface->applySpecificFilters(itemIds, static_cast<int>(requiredPart), listFilters);
280}
281
283{
284 beginUpdate();
285 d->clear();
286 d->mFilters = filters;
287 endUpdate();
288}
289
291{
292 return d->mFilters;
293}
294
295void FilterManager::appendFilters(const QList<MailCommon::MailFilter *> &filters, bool replaceIfNameExists)
296{
297 beginUpdate();
298 if (replaceIfNameExists) {
299 for (const MailCommon::MailFilter *newFilter : filters) {
300 int numberOfFilters = d->mFilters.count();
301 for (int i = 0; i < numberOfFilters; ++i) {
302 MailCommon::MailFilter *filter = d->mFilters.at(i);
303 if (newFilter->name() == filter->name()) {
304 d->mFilters.removeAll(filter);
305 i = 0;
306 numberOfFilters = d->mFilters.count();
307 }
308 }
309 }
310 }
311
312 d->mFilters += filters;
313 endUpdate();
314}
315
317{
318 beginUpdate();
319 d->mFilters.removeAll(filter);
320 endUpdate();
321}
322
326
328{
329 d->writeConfig(true);
330 d->mMailFilterAgentInterface->reload();
332}
333
334#include "moc_filtermanager.cpp"
Id id() const
void tagRemoved(const Akonadi::Tag &tag)
TagFetchScope & tagFetchScope()
void tagChanged(const Akonadi::Tag &tag)
void tagAdded(const Akonadi::Tag &tag)
void setTypeMonitored(Type type, bool monitored=true)
static State state()
static QString agentServiceName(ServiceAgentType agentType, const QString &identifier)
static QString addNamespace(const QString &string)
void stateChanged(Akonadi::ServerManager::State state)
static ServerManager * self()
Tag::List tags() const
void fetchAttribute(bool fetch=true)
QUrl url() const
KConfigGroup group(const QString &group)
bool sync() override
virtual QString errorString() const
int error() const
void result(KJob *job)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
List of known FilterAction-types.
static void writeFiltersToConfig(const QList< MailFilter * > &filters, KSharedConfig::Ptr config, bool exportFilter=false)
Writes the given list of filters to the given config file.
static QList< MailFilter * > readFiltersFromConfig(const KSharedConfig::Ptr &config, QStringList &emptyFilter)
Reads a list of filters from the given config file.
A wrapper class that allows easy access to the mail filters.
void filter(const Akonadi::Item &item, const QString &identifier, const QString &resourceId) const
Apply filters interface.
void filtersChanged()
This signal is emitted whenever the filter list has been updated.
static FilterActionDict * filterActionDict()
Returns the global filter action dictionary.
void appendFilters(const QList< MailCommon::MailFilter * > &filters, bool replaceIfNameExists=false)
Manage filters interface.
void removeFilter(MailCommon::MailFilter *filter)
Removes the given filter from the list.
void setFilters(const QList< MailCommon::MailFilter * > &filters)
Replace the list of filters of the filter manager with the given list of filters.
void showFilterLogDialog(qlonglong windowId)
Shows the filter log dialog.
QList< MailCommon::MailFilter * > filters() const
Returns the filter list of the manager.
void endUpdate()
Should be called at the end of an filter list update.
FilterSet
Describes the list of filters.
QString createUniqueFilterName(const QString &name) const
Checks for existing filters with the name and extend the "name" to "name (i)" until no match is found...
static FilterManager * instance()
Returns the global filter manager object.
void beginUpdate()
Should be called at the beginning of an filter list update.
bool isValid() const
Returns whether the filter manager is in a usable state.
The MailFilter class.
Definition mailfilter.h:29
RequiredPart
Possible required parts.
Definition searchrule.h:68
The filter dialog.
QDBusConnection sessionBus()
const_reference at(qsizetype i) const const
qsizetype count() const const
qsizetype removeAll(const AT &t)
void reserve(qsizetype size)
qsizetype size() const const
bool contains(const Key &key) const const
iterator insert(const Key &key, const T &value)
size_type remove(const Key &key)
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
void setObjectName(QAnyStringView name)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 6 2024 12:02:04 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.