Mailcommon

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

KDE's Doxygen guidelines are available online.