File indexing completed on 2024-05-12 05:10:49

0001 /*
0002   This file is part of KOrganizer.
0003 
0004   SPDX-FileCopyrightText: 2015 Sandro Knauß <knauss@kolabsys.com>
0005 
0006   SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0007 */
0008 
0009 #include "searchcollectionhelper.h"
0010 #include "akonadicalendar_debug.h"
0011 
0012 #include <Akonadi/CollectionFetchJob>
0013 #include <Akonadi/CollectionFetchScope>
0014 #include <Akonadi/CollectionModifyJob>
0015 #include <Akonadi/EntityDisplayAttribute>
0016 #include <Akonadi/PersistentSearchAttribute>
0017 #include <Akonadi/SearchCreateJob>
0018 #include <Akonadi/SearchQuery>
0019 
0020 #include <KCalendarCore/Event>
0021 #include <KCalendarCore/Journal>
0022 #include <KCalendarCore/Todo>
0023 
0024 #include <KLocalizedString>
0025 
0026 using namespace Akonadi;
0027 
0028 SearchCollectionHelper::SearchCollectionHelper(QObject *parent)
0029     : QObject(parent)
0030     , mIdentityManager(KIdentityManagementCore::IdentityManager::self())
0031 {
0032     setupSearchCollections();
0033     connect(mIdentityManager, qOverload<>(&KIdentityManagementCore::IdentityManager::changed), this, &SearchCollectionHelper::updateOpenInvitation);
0034     connect(mIdentityManager, qOverload<>(&KIdentityManagementCore::IdentityManager::changed), this, &SearchCollectionHelper::updateDeclinedInvitation);
0035 
0036     updateOpenInvitation();
0037     updateDeclinedInvitation();
0038 }
0039 
0040 void SearchCollectionHelper::setupSearchCollections()
0041 {
0042     // Collection "Search", has always ID 1
0043     auto fetchJob = new Akonadi::CollectionFetchJob(Akonadi::Collection(1), Akonadi::CollectionFetchJob::FirstLevel);
0044     fetchJob->fetchScope().setListFilter(Akonadi::CollectionFetchScope::NoFilter);
0045     connect(fetchJob, &Akonadi::CollectionFetchJob::result, this, &SearchCollectionHelper::onSearchCollectionsFetched);
0046 }
0047 
0048 void SearchCollectionHelper::onSearchCollectionsFetched(KJob *job)
0049 {
0050     if (job->error()) {
0051         qCWarning(AKONADICALENDAR_LOG) << "Search failed: " << job->errorString();
0052     } else {
0053         auto fetchJob = static_cast<Akonadi::CollectionFetchJob *>(job);
0054         const Akonadi::Collection::List lstCols = fetchJob->collections();
0055         for (const Akonadi::Collection &col : lstCols) {
0056             const QString collectionName = col.name();
0057             if (collectionName == QLatin1StringView("OpenInvitations")) {
0058                 mOpenInvitationCollection = col;
0059             } else if (collectionName == QLatin1StringView("DeclinedInvitations")) {
0060                 mDeclineCollection = col;
0061             }
0062         }
0063     }
0064     updateOpenInvitation();
0065     updateDeclinedInvitation();
0066 }
0067 
0068 void SearchCollectionHelper::updateSearchCollection(Akonadi::Collection col,
0069                                                     KCalendarCore::Attendee::PartStat status,
0070                                                     const QString &name,
0071                                                     const QString &displayName)
0072 {
0073     // Update or create search collections
0074 
0075     Akonadi::SearchQuery query(Akonadi::SearchTerm::RelOr);
0076     const QStringList lstEmails = mIdentityManager->allEmails();
0077     for (const QString &email : lstEmails) {
0078         if (!email.isEmpty()) {
0079             query.addTerm(Akonadi::IncidenceSearchTerm(Akonadi::IncidenceSearchTerm::PartStatus, QString(email + QString::number(status))));
0080         }
0081     }
0082 
0083     if (!col.isValid()) {
0084         auto job = new Akonadi::SearchCreateJob(name, query);
0085         job->setRemoteSearchEnabled(false);
0086         job->setSearchMimeTypes({
0087             KCalendarCore::Event::eventMimeType(),
0088             KCalendarCore::Todo::todoMimeType(),
0089             KCalendarCore::Journal::journalMimeType(),
0090         });
0091         connect(job, &Akonadi::SearchCreateJob::result, this, &SearchCollectionHelper::createSearchJobFinished);
0092         qCDebug(AKONADICALENDAR_LOG) << "We have to create a " << name << " virtual Collection";
0093     } else {
0094         auto attribute = col.attribute<Akonadi::PersistentSearchAttribute>(Akonadi::Collection::AddIfMissing);
0095         auto displayname = col.attribute<Akonadi::EntityDisplayAttribute>(Akonadi::Collection::AddIfMissing);
0096         attribute->setQueryString(QString::fromLatin1(query.toJSON()));
0097         attribute->setRemoteSearchEnabled(false);
0098         attribute->setRecursive(true);
0099         displayname->setDisplayName(displayName);
0100         col.setEnabled(true);
0101         auto job = new Akonadi::CollectionModifyJob(col, this);
0102         connect(job, &Akonadi::CollectionModifyJob::result, this, &SearchCollectionHelper::modifyResult);
0103         qCDebug(AKONADICALENDAR_LOG) << "updating " << name << " (" << col.id() << ") virtual Collection";
0104         qCDebug(AKONADICALENDAR_LOG) << "query" << query.toJSON();
0105     }
0106 }
0107 
0108 void SearchCollectionHelper::updateDeclinedInvitation()
0109 {
0110     updateSearchCollection(mDeclineCollection,
0111                            KCalendarCore::Attendee::Declined,
0112                            QStringLiteral("DeclinedInvitations"),
0113                            i18nc("A collection of all declined invidations.", "Declined Invitations"));
0114 }
0115 
0116 void SearchCollectionHelper::updateOpenInvitation()
0117 {
0118     updateSearchCollection(mOpenInvitationCollection,
0119                            KCalendarCore::Attendee::NeedsAction,
0120                            QStringLiteral("OpenInvitations"),
0121                            i18nc("A collection of all open invidations.", "Open Invitations"));
0122 }
0123 
0124 void SearchCollectionHelper::createSearchJobFinished(KJob *job)
0125 {
0126     auto createJob = qobject_cast<Akonadi::SearchCreateJob *>(job);
0127     const Akonadi::Collection searchCollection = createJob->createdCollection();
0128     if (job->error()) {
0129         qCWarning(AKONADICALENDAR_LOG) << "Error occurred " << searchCollection.name() << job->errorString();
0130         return;
0131     }
0132     qCDebug(AKONADICALENDAR_LOG) << "Created search folder successfully " << searchCollection.name();
0133 
0134     const QString searchCollectionName = searchCollection.name();
0135     if (searchCollectionName == QLatin1StringView("OpenInvitations")) {
0136         mOpenInvitationCollection = searchCollection;
0137         updateOpenInvitation();
0138     } else if (searchCollectionName == QLatin1StringView("DeclinedInvitations")) {
0139         mDeclineCollection = searchCollection;
0140         updateDeclinedInvitation();
0141     }
0142 }
0143 
0144 void SearchCollectionHelper::modifyResult(KJob *job)
0145 {
0146     if (job->error()) {
0147         qCWarning(AKONADICALENDAR_LOG) << "Error occurred " << job->errorString();
0148     } else {
0149         qCDebug(AKONADICALENDAR_LOG) << "modify was successful";
0150     }
0151 }
0152 
0153 #include "moc_searchcollectionhelper.cpp"