Akonadi Calendar

searchcollectionhelper.cpp
1/*
2 This file is part of KOrganizer.
3
4 SPDX-FileCopyrightText: 2015 Sandro KnauƟ <knauss@kolabsys.com>
5
6 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
7*/
8
9#include "searchcollectionhelper.h"
10using namespace Qt::Literals::StringLiterals;
11
12#include "akonadicalendar_debug.h"
13
14#include <Akonadi/CollectionDeleteJob>
15#include <Akonadi/CollectionFetchJob>
16#include <Akonadi/CollectionFetchScope>
17#include <Akonadi/CollectionModifyJob>
18#include <Akonadi/EntityDisplayAttribute>
19#include <Akonadi/PersistentSearchAttribute>
20#include <Akonadi/SearchCreateJob>
21#include <Akonadi/SearchQuery>
22
23#include <KCalendarCore/Event>
24#include <KCalendarCore/Journal>
25#include <KCalendarCore/Todo>
26
27#include <KIdentityManagementCore/IdentityManager>
28
29#include <KLocalizedString>
30
31using namespace Akonadi;
32
33namespace Akonadi
34{
35
36class SearchCollectionHelperPrivate
37{
38public:
40 Akonadi::Collection openInvitationCollection;
41 Akonadi::Collection declineInvitationCollection;
42 bool enabled = false;
43};
44
45}
46
47SearchCollectionHelper::SearchCollectionHelper(QObject *parent)
48 : QObject(parent)
49 , d(std::make_unique<SearchCollectionHelperPrivate>())
50{
51 fetchSearchCollections();
52}
53
54SearchCollectionHelper::~SearchCollectionHelper() = default;
55
56void SearchCollectionHelper::setEnabled(bool enabled)
57{
58 if (d->enabled == enabled) {
59 return;
60 }
61
62 d->enabled = enabled;
63 if (d->enabled) {
64 init();
65 } else {
66 deinit();
67 }
68}
69
70bool SearchCollectionHelper::enabled() const
71{
72 return d->enabled;
73}
74
75void SearchCollectionHelper::init()
76{
77 fetchSearchCollections();
78 connect(d->identityManager, qOverload<>(&KIdentityManagementCore::IdentityManager::changed), this, &SearchCollectionHelper::updateOpenInvitation);
79 connect(d->identityManager, qOverload<>(&KIdentityManagementCore::IdentityManager::changed), this, &SearchCollectionHelper::updateDeclinedInvitation);
80}
81
82void SearchCollectionHelper::deinit()
83{
84 d->identityManager->disconnect(this);
85 removeSearchCollections();
86}
87
88void SearchCollectionHelper::fetchSearchCollections()
89{
90 // Collection "Search", has always ID 1
92 fetchJob->fetchScope().setListFilter(Akonadi::CollectionFetchScope::NoFilter);
93 connect(fetchJob, &Akonadi::CollectionFetchJob::result, this, &SearchCollectionHelper::onSearchCollectionsFetched);
94}
95
96void SearchCollectionHelper::onSearchCollectionsFetched(KJob *job)
97{
98 if (job->error()) {
99 qCWarning(AKONADICALENDAR_LOG) << "Search failed: " << job->errorString();
100 } else {
101 auto fetchJob = static_cast<Akonadi::CollectionFetchJob *>(job);
102 const Akonadi::Collection::List lstCols = fetchJob->collections();
103 for (const Akonadi::Collection &col : lstCols) {
104 const QString collectionName = col.name();
105 if (collectionName == "OpenInvitations"_L1) {
106 d->openInvitationCollection = col;
107 } else if (collectionName == "DeclinedInvitations"_L1) {
108 d->declineInvitationCollection = col;
109 }
110 }
111 }
112
113 if (d->enabled) {
114 updateOpenInvitation();
115 updateDeclinedInvitation();
116 } else {
117 // When disabled, make sure the collections are not shown
118 removeSearchCollections();
119 }
120}
121
122void SearchCollectionHelper::updateSearchCollection(Akonadi::Collection col,
124 const QString &name,
125 const QString &displayName)
126{
127 // Update or create search collections
128
129 Akonadi::SearchQuery query(Akonadi::SearchTerm::RelOr);
130 const QStringList lstEmails = d->identityManager->allEmails();
131 for (const QString &email : lstEmails) {
132 if (!email.isEmpty()) {
133 query.addTerm(Akonadi::IncidenceSearchTerm(Akonadi::IncidenceSearchTerm::PartStatus, QString(email + QString::number(status))));
134 }
135 }
136
137 if (!col.isValid()) {
138 auto job = new Akonadi::SearchCreateJob(name, query);
139 job->setRemoteSearchEnabled(false);
140 job->setSearchMimeTypes({
144 });
145 connect(job, &Akonadi::SearchCreateJob::result, this, &SearchCollectionHelper::createSearchJobFinished);
146 qCDebug(AKONADICALENDAR_LOG) << "We have to create a " << name << " virtual Collection";
147 } else {
150 attribute->setQueryString(QString::fromLatin1(query.toJSON()));
151 attribute->setRemoteSearchEnabled(false);
152 attribute->setRecursive(true);
153 displayname->setDisplayName(displayName);
154 col.setEnabled(true);
155 auto job = new Akonadi::CollectionModifyJob(col, this);
156 connect(job, &Akonadi::CollectionModifyJob::result, this, &SearchCollectionHelper::modifyResult);
157 qCDebug(AKONADICALENDAR_LOG) << "updating " << name << " (" << col.id() << ") virtual Collection";
158 qCDebug(AKONADICALENDAR_LOG) << "query" << query.toJSON();
159 }
160}
161
162void SearchCollectionHelper::removeSearchCollections()
163{
164 if (d->openInvitationCollection.isValid()) {
165 new Akonadi::CollectionDeleteJob(d->openInvitationCollection, this);
166 d->openInvitationCollection = {};
167 }
168 if (d->declineInvitationCollection.isValid()) {
169 new Akonadi::CollectionDeleteJob(d->declineInvitationCollection, this);
170 d->declineInvitationCollection = {};
171 }
172}
173
174void SearchCollectionHelper::updateDeclinedInvitation()
175{
176 updateSearchCollection(d->declineInvitationCollection,
178 QStringLiteral("DeclinedInvitations"),
179 i18nc("A collection of all declined invidations.", "Declined Invitations"));
180}
181
182void SearchCollectionHelper::updateOpenInvitation()
183{
184 updateSearchCollection(d->openInvitationCollection,
186 QStringLiteral("OpenInvitations"),
187 i18nc("A collection of all open invidations.", "Open Invitations"));
188}
189
190void SearchCollectionHelper::createSearchJobFinished(KJob *job)
191{
192 auto createJob = qobject_cast<Akonadi::SearchCreateJob *>(job);
193 const Akonadi::Collection searchCollection = createJob->createdCollection();
194 if (job->error()) {
195 qCWarning(AKONADICALENDAR_LOG) << "Error occurred " << searchCollection.name() << job->errorString();
196 return;
197 }
198 qCDebug(AKONADICALENDAR_LOG) << "Created search folder successfully " << searchCollection.name();
199
200 const QString searchCollectionName = searchCollection.name();
201 if (searchCollectionName == "OpenInvitations"_L1) {
202 d->openInvitationCollection = searchCollection;
203 updateOpenInvitation();
204 } else if (searchCollectionName == "DeclinedInvitations"_L1) {
205 d->declineInvitationCollection = searchCollection;
206 updateDeclinedInvitation();
207 }
208}
209
210void SearchCollectionHelper::modifyResult(KJob *job)
211{
212 if (job->error()) {
213 qCWarning(AKONADICALENDAR_LOG) << "Error occurred " << job->errorString();
214 } else {
215 qCDebug(AKONADICALENDAR_LOG) << "modify was successful";
216 }
217}
218
219#include "moc_searchcollectionhelper.cpp"
bool isValid() const
const T * attribute() const
QString name() const
void setEnabled(bool enabled)
static QLatin1String eventMimeType()
static QLatin1String journalMimeType()
static QLatin1String todoMimeType()
static IdentityManager * self()
virtual QString errorString() const
int error() const
void result(KJob *job)
Q_SCRIPTABLE CaptureState status()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
std::optional< QSqlQuery > query(const QString &queryStatement)
FreeBusyManager::Singleton.
QString name(StandardAction id)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T qobject_cast(QObject *object)
QString fromLatin1(QByteArrayView str)
QString number(double n, char format, int precision)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 19 2024 11:52:11 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.