File indexing completed on 2025-01-05 04:46:24

0001 /*
0002     SPDX-FileCopyrightText: 2009 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "agentsearchinterface.h"
0008 #include "agentbase.h"
0009 #include "agentsearchinterface_p.h"
0010 #include "akonadiagentbase_debug.h"
0011 #include "collection.h"
0012 #include "collectionfetchjob.h"
0013 #include "collectionfetchscope.h"
0014 #include "private/imapset_p.h"
0015 #include "searchadaptor.h"
0016 #include "searchresultjob_p.h"
0017 #include "servermanager.h"
0018 #include <QDBusConnection>
0019 
0020 using namespace Akonadi;
0021 using namespace std::chrono_literals;
0022 AgentSearchInterfacePrivate::AgentSearchInterfacePrivate(AgentSearchInterface *qq)
0023     : q(qq)
0024 {
0025     new Akonadi__SearchAdaptor(this);
0026     QDBusConnection::sessionBus().registerObject(QStringLiteral("/Search"), this, QDBusConnection::ExportAdaptors);
0027 
0028     QTimer::singleShot(0s, this, &AgentSearchInterfacePrivate::delayedInit);
0029 }
0030 
0031 void AgentSearchInterfacePrivate::delayedInit()
0032 {
0033     QDBusInterface iface(ServerManager::serviceName(ServerManager::Server),
0034                          QStringLiteral("/SearchManager"),
0035                          QStringLiteral("org.freedesktop.Akonadi.SearchManager"),
0036                          QDBusConnection::sessionBus(),
0037                          this);
0038     QDBusMessage msg = iface.call(QStringLiteral("registerInstance"), dynamic_cast<AgentBase *>(q)->identifier());
0039     // TODO ?
0040 }
0041 
0042 void AgentSearchInterfacePrivate::addSearch(const QString &query, const QString &queryLanguage, quint64 resultCollectionId)
0043 {
0044     q->addSearch(query, queryLanguage, Collection(resultCollectionId));
0045 }
0046 
0047 void AgentSearchInterfacePrivate::removeSearch(quint64 resultCollectionId)
0048 {
0049     q->removeSearch(Collection(resultCollectionId));
0050 }
0051 
0052 void AgentSearchInterfacePrivate::search(const QByteArray &searchId, const QString &query, quint64 collectionId)
0053 {
0054     mSearchId = searchId;
0055     mCollectionId = collectionId;
0056 
0057     auto fetchJob = new CollectionFetchJob(Collection(mCollectionId), CollectionFetchJob::Base, this);
0058     fetchJob->fetchScope().setAncestorRetrieval(CollectionFetchScope::All);
0059     fetchJob->setProperty("query", query);
0060     connect(fetchJob, &KJob::finished, this, &AgentSearchInterfacePrivate::collectionReceived);
0061 }
0062 
0063 void AgentSearchInterfacePrivate::collectionReceived(KJob *job)
0064 {
0065     auto fetchJob = qobject_cast<CollectionFetchJob *>(job);
0066     if (fetchJob->error()) {
0067         qCCritical(AKONADIAGENTBASE_LOG) << fetchJob->errorString();
0068         new SearchResultJob(fetchJob->property("searchId").toByteArray(), Collection(mCollectionId), this);
0069         return;
0070     }
0071 
0072     if (fetchJob->collections().count() != 1) {
0073         qCDebug(AKONADIAGENTBASE_LOG) << "Server requested search in invalid collection, or collection was removed in the meanwhile";
0074         // Tell server we are done
0075         new SearchResultJob(fetchJob->property("searchId").toByteArray(), Collection(mCollectionId), this);
0076         return;
0077     }
0078 
0079     const Collection collection = fetchJob->collections().at(0);
0080     q->search(fetchJob->property("query").toString(), collection);
0081 }
0082 
0083 AgentSearchInterface::AgentSearchInterface()
0084     : d(new AgentSearchInterfacePrivate(this))
0085 {
0086 }
0087 
0088 AgentSearchInterface::~AgentSearchInterface() = default;
0089 
0090 void AgentSearchInterface::searchFinished(const QList<qint64> &result, ResultScope scope)
0091 {
0092     if (scope == Akonadi::AgentSearchInterface::Rid) {
0093         QList<QByteArray> rids;
0094         rids.reserve(result.size());
0095         for (qint64 rid : result) {
0096             rids << QByteArray::number(rid);
0097         }
0098 
0099         searchFinished(rids);
0100         return;
0101     }
0102 
0103     auto resultJob = new SearchResultJob(d->mSearchId, Collection(d->mCollectionId), d.get());
0104     resultJob->setResult(result);
0105 }
0106 
0107 void AgentSearchInterface::searchFinished(const ImapSet &result, ResultScope scope)
0108 {
0109     if (scope == Akonadi::AgentSearchInterface::Rid) {
0110         QList<QByteArray> rids;
0111         const ImapInterval::List lstInterval = result.intervals();
0112         for (const ImapInterval &interval : lstInterval) {
0113             const int endInterval(interval.end());
0114             for (int i = interval.begin(); i <= endInterval; ++i) {
0115                 rids << QByteArray::number(i);
0116             }
0117         }
0118 
0119         searchFinished(rids);
0120         return;
0121     }
0122 
0123     auto resultJob = new SearchResultJob(d->mSearchId, Collection(d->mCollectionId), d.get());
0124     resultJob->setResult(result);
0125 }
0126 
0127 void AgentSearchInterface::searchFinished(const QList<QByteArray> &result)
0128 {
0129     auto resultJob = new SearchResultJob(d->mSearchId, Collection(d->mCollectionId), d.get());
0130     resultJob->setResult(result);
0131 }
0132 
0133 #include "moc_agentsearchinterface_p.cpp"