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/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 
22 namespace MailCommon
23 {
24 class FilterManager::FilterManagerPrivate
25 {
26 public:
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 
51 void 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);
58  Q_EMIT q->filtersChanged();
59 }
60 
61 void 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 
75 void FilterManager::FilterManagerPrivate::clear()
76 {
77  qDeleteAll(mFilters);
78  mFilters.clear();
79 }
80 }
81 
82 using namespace MailCommon;
83 
84 FilterManager *FilterManager::FilterManagerPrivate::mInstance = nullptr;
85 FilterActionDict *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 
105 FilterManager::FilterManager()
106  : d(new FilterManagerPrivate(this))
107 {
108  updateTagList();
109 
110  d->mMonitor->setObjectName(QStringLiteral("FilterManagerTagMonitor"));
111  d->mMonitor->setTypeMonitored(Akonadi::Monitor::Tags);
112  d->mMonitor->tagFetchScope().fetchAttribute<Akonadi::TagAttribute>();
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 
126 FilterManager::~FilterManager()
127 {
128  cleanup();
129 }
130 
131 void FilterManager::cleanup()
132 {
133  d->clear();
134 }
135 
136 void FilterManager::slotServerStateChanged(Akonadi::ServerManager::State state)
137 {
138  if (state == Akonadi::ServerManager::Running) {
139  d->readConfig();
141  }
142 }
143 
144 void 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 
151 bool FilterManager::initialized() const
152 {
153  return d->mInitialized;
154 }
155 
156 void FilterManager::slotReadConfig()
157 {
158  d->readConfig();
159  d->mInitialized = true;
160  Q_EMIT loadingFiltersDone();
161 }
162 
163 void 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 
177 void FilterManager::slotTagAdded(const Akonadi::Tag &tag)
178 {
179  d->mTagList.insert(tag.url(), tag.name());
180  Q_EMIT tagListingFinished();
181 }
182 
183 void 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 
191 void FilterManager::slotTagRemoved(const Akonadi::Tag &tag)
192 {
193  d->mTagList.remove(tag.url());
194  Q_EMIT tagListingFinished();
195 }
196 
197 QMap<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 
212 void FilterManager::showFilterLogDialog(qlonglong windowId)
213 {
214  d->mMailFilterAgentInterface->showFilterLogDialog(windowId);
215 }
216 
217 void FilterManager::filter(const Akonadi::Item &item, const QString &identifier, const QString &resourceId) const
218 {
219  d->mMailFilterAgentInterface->filter(item.id(), identifier, resourceId);
220 }
221 
222 void 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 
227 void FilterManager::filter(const Akonadi::Collection &collection, FilterSet set) const
228 {
229  filter(Akonadi::Collection::List{collection}, set);
230 }
231 
232 void FilterManager::filter(const Akonadi::Collection::List &collections, FilterSet set) const
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 
243 void FilterManager::filter(const Akonadi::Collection &collection, const QStringList &listFilters) const
244 {
245  filter(Akonadi::Collection::List{collection}, listFilters);
246 }
247 
248 void 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 
271 void 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 
295 void FilterManager::appendFilters(const QVector<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 
324 {
325 }
326 
328 {
329  d->writeConfig(true);
330  d->mMailFilterAgentInterface->reload();
332 }
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 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.
KConfigGroup group(const char *group)
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-2023 The KDE developers.
Generated on Sun Jun 4 2023 03:58:00 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.