File indexing completed on 2024-11-10 04:40:30

0001 /*
0002     SPDX-FileCopyrightText: 2009 Tobias Koenig <tokoe@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "akonadicore_export.h"
0010 #include "collection.h"
0011 #include "item.h"
0012 #include "job.h"
0013 
0014 namespace Akonadi
0015 {
0016 class TagFetchScope;
0017 class ItemFetchScope;
0018 class ItemSearchJobPrivate;
0019 class SearchQuery;
0020 
0021 /**
0022  * @short Job that searches for items in the Akonadi storage.
0023  *
0024  * This job searches for items that match a given search query and returns
0025  * the list of matching item.
0026  *
0027  * @code
0028  *
0029  * SearchQuery query;
0030  * query.addTerm(SearchTerm("From", "user1@domain.example", SearchTerm::CondEqual));
0031  * query.addTerm(SearchTerm("Date", QDateTime(QDate( 2014, 01, 27), QTime(00, 00, 00)), SearchTerm::CondGreaterThan);
0032  *
0033  * auto job = new Akonadi::ItemSearchJob(query);
0034  * job->fetchScope().fetchFullPayload();
0035  * connect(job, &Akonadi::ItemSearchJob::result, this, &MyClass::searchResult));
0036  *
0037  * ...
0038  *
0039  * MyClass::searchResult(KJob *job)
0040  * {
0041  *   auto searchJob = qobject_cast<Akonadi::ItemSearchJob*>(job);
0042  *   const Akonadi::Item::List items = searchJob->items();
0043  *   for (const Akonadi::Item &item : items) {
0044  *     // extract the payload and do further stuff
0045  *   }
0046  * }
0047  *
0048  * @endcode
0049  *
0050  * @author Tobias Koenig <tokoe@kde.org>
0051  * @since 4.4
0052  */
0053 class AKONADICORE_EXPORT ItemSearchJob : public Job
0054 {
0055     Q_OBJECT
0056 
0057 public:
0058     /**
0059      * Creates an invalid search job.
0060      *
0061      * @param parent The parent object.
0062      * @since 5.1
0063      */
0064     explicit ItemSearchJob(QObject *parent = nullptr);
0065 
0066     /**
0067      * Creates an item search job.
0068      *
0069      * @param query The search query.
0070      * @param parent The parent object.
0071      * @since 4.13
0072      */
0073     explicit ItemSearchJob(const SearchQuery &query, QObject *parent = nullptr);
0074 
0075     /**
0076      * Destroys the item search job.
0077      */
0078     ~ItemSearchJob() override;
0079 
0080     /**
0081      * Sets the search @p query.
0082      *
0083      * @since 4.13
0084      */
0085     void setQuery(const SearchQuery &query);
0086 
0087     /**
0088      * Sets the item fetch scope.
0089      *
0090      * The ItemFetchScope controls how much of an matching item's data is fetched
0091      * from the server, e.g. whether to fetch the full item payload or
0092      * only meta data.
0093      *
0094      * @param fetchScope The new scope for item fetch operations.
0095      *
0096      * @see fetchScope()
0097      */
0098     void setFetchScope(const ItemFetchScope &fetchScope);
0099 
0100     /**
0101      * Returns the item fetch scope.
0102      *
0103      * Since this returns a reference it can be used to conveniently modify the
0104      * current scope in-place, i.e. by calling a method on the returned reference
0105      * without storing it in a local variable. See the ItemFetchScope documentation
0106      * for an example.
0107      *
0108      * @return a reference to the current item fetch scope
0109      *
0110      * @see setFetchScope() for replacing the current item fetch scope
0111      */
0112     ItemFetchScope &fetchScope();
0113 
0114     /**
0115      * Sets the tag fetch scope.
0116      *
0117      * The tag fetch scope affects what scope of tags for each Item will be
0118      * retrieved.
0119      */
0120     void setTagFetchScope(const TagFetchScope &fetchScope);
0121 
0122     /**
0123      * Returns the tag fetch scope.
0124      *
0125      * Since this returns a reference it can be used to conveniently modify
0126      * the current scope in-place.
0127      */
0128     TagFetchScope &tagFetchScope();
0129 
0130     /**
0131      * Returns the items that matched the search query.
0132      */
0133     [[nodiscard]] Item::List items() const;
0134 
0135     /**
0136      * Search only for items of given mime types.
0137      *
0138      * @since 4.13
0139      */
0140     void setMimeTypes(const QStringList &mimeTypes);
0141 
0142     /**
0143      * Returns list of mime types to search in
0144      *
0145      * @since 4.13
0146      */
0147     [[nodiscard]] QStringList mimeTypes() const;
0148 
0149     /**
0150      * Search only in given collections.
0151      *
0152      * When recursive search is enabled, all child collections of each specified
0153      * collection will be searched too
0154      *
0155      * By default all collections are be searched.
0156      *
0157      * @param collections Collections to search
0158      * @since 4.13
0159      */
0160     void setSearchCollections(const Collection::List &collections);
0161 
0162     /**
0163      * Returns list of collections to search.
0164      *
0165      * This list does not include child collections that will be searched when
0166      * recursive search is enabled
0167      *
0168      * @since 4.13
0169      */
0170     [[nodiscard]] Collection::List searchCollections() const;
0171 
0172     /**
0173      * Sets whether the search should recurse into collections
0174      *
0175      * When set to true, all child collections of the specific collections will
0176      * be search recursively.
0177      *
0178      * @param recursive Whether to search recursively
0179      * @since 4.13
0180      */
0181     void setRecursive(bool recursive);
0182 
0183     /**
0184      * Returns whether the search is recursive
0185      *
0186      * @since 4.13
0187      */
0188     [[nodiscard]] bool isRecursive() const;
0189 
0190     /**
0191      * Sets whether resources should be queried too.
0192      *
0193      * When set to true, Akonadi will search local indexed items and will also
0194      * query resources that support server-side search, to forward the query
0195      * to remote storage (for example using SEARCH feature on IMAP servers) and
0196      * merge their results with results from local index.
0197      *
0198      * This is useful especially when searching resources, that don't fetch full
0199      * payload by default, for example the IMAP resource, which only fetches headers
0200      * by default and the body is fetched on demand, which means that emails that
0201      * were not yet fully fetched cannot be indexed in local index, and thus cannot
0202      * be searched. With remote search, even those emails can be included in search
0203      * results.
0204      *
0205      * This feature is disabled by default.
0206      *
0207      * Results are streamed back to client as they are received from queried sources,
0208      * so this job can take some time to finish, but will deliver initial results
0209      * from local index fairly quickly.
0210      *
0211      * @param enabled Whether remote search is enabled
0212      * @since 4.13
0213      */
0214     void setRemoteSearchEnabled(bool enabled);
0215 
0216     /**
0217      * Returns whether remote search is enabled.
0218      *
0219      * @since 4.13
0220      */
0221     [[nodiscard]] bool isRemoteSearchEnabled() const;
0222 
0223 Q_SIGNALS:
0224     /**
0225      * This signal is emitted whenever new matching items have been fetched completely.
0226      *
0227      * @note This is an optimization, instead of waiting for the end of the job
0228      *       and calling items(), you can connect to this signal and get the items
0229      *       incrementally.
0230      *
0231      * @param items The matching items.
0232      */
0233     void itemsReceived(const Akonadi::Item::List &items);
0234 
0235 protected:
0236     void doStart() override;
0237     bool doHandleResponse(qint64 tag, const Protocol::CommandPtr &response) override;
0238 
0239 private:
0240     /// @cond PRIVATE
0241     Q_DECLARE_PRIVATE(ItemSearchJob)
0242 
0243     Q_PRIVATE_SLOT(d_func(), void timeout())
0244     /// @endcond
0245 };
0246 
0247 }