1 /*
2     SPDX-FileCopyrightText: 2009 Tobias Koenig <tokoe@kde.org>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #pragma once
8 
9 #include "akonadicore_export.h"
10 #include "collection.h"
11 #include "item.h"
12 #include "job.h"
13 
14 namespace Akonadi
15 {
16 class TagFetchScope;
17 class ItemFetchScope;
18 class ItemSearchJobPrivate;
19 class SearchQuery;
20 
21 /**
22  * @short Job that searches for items in the Akonadi storage.
23  *
24  * This job searches for items that match a given search query and returns
25  * the list of matching item.
26  *
27  * @code
28  *
29  * SearchQuery query;
30  * query.addTerm( SearchTerm( "From", "user1@domain.example", SearchTerm::CondEqual ) );
31  * query.addTerm( SearchTerm( "Date", QDateTime( QDate( 2014, 01, 27 ), QTime( 00, 00, 00 ) ), SearchTerm::CondGreaterThan );
32  *
33  * Akonadi::ItemSearchJob *job = new Akonadi::ItemSearchJob( query );
34  * job->fetchScope().fetchFullPayload();
35  * connect( job, SIGNAL(result(KJob*)), this, SLOT(searchResult(KJob*)) );
36  *
37  * ...
38  *
39  * MyClass::searchResult( KJob *job )
40  * {
41  *   Akonadi::ItemSearchJob *searchJob = qobject_cast<Akonadi::ItemSearchJob*>( job );
42  *   const Akonadi::Item::List items = searchJob->items();
43  *   for ( const Akonadi::Item &item : items ) {
44  *     // extract the payload and do further stuff
45  *   }
46  * }
47  *
48  * @endcode
49  *
50  * @author Tobias Koenig <tokoe@kde.org>
51  * @since 4.4
52  */
53 class AKONADICORE_EXPORT ItemSearchJob : public Job
54 {
55     Q_OBJECT
56 
57 public:
58     /**
59      * Creates an invalid search job.
60      *
61      * @param parent The parent object.
62      * @since 5.1
63      */
64     explicit ItemSearchJob(QObject *parent = nullptr);
65 
66     /**
67      * Creates an item search job.
68      *
69      * @param query The search query.
70      * @param parent The parent object.
71      * @since 4.13
72      */
73     explicit ItemSearchJob(const SearchQuery &query, QObject *parent = nullptr);
74 
75     /**
76      * Destroys the item search job.
77      */
78     ~ItemSearchJob() override;
79 
80     /**
81      * Sets the search @p query.
82      *
83      * @since 4.13
84      */
85     void setQuery(const SearchQuery &query);
86 
87     /**
88      * Sets the item fetch scope.
89      *
90      * The ItemFetchScope controls how much of an matching item's data is fetched
91      * from the server, e.g. whether to fetch the full item payload or
92      * only meta data.
93      *
94      * @param fetchScope The new scope for item fetch operations.
95      *
96      * @see fetchScope()
97      */
98     void setFetchScope(const ItemFetchScope &fetchScope);
99 
100     /**
101      * Returns the item fetch scope.
102      *
103      * Since this returns a reference it can be used to conveniently modify the
104      * current scope in-place, i.e. by calling a method on the returned reference
105      * without storing it in a local variable. See the ItemFetchScope documentation
106      * for an example.
107      *
108      * @return a reference to the current item fetch scope
109      *
110      * @see setFetchScope() for replacing the current item fetch scope
111      */
112     ItemFetchScope &fetchScope();
113 
114     /**
115      * Sets the tag fetch scope.
116      *
117      * The tag fetch scope affects what scope of tags for each Item will be
118      * retrieved.
119      */
120     void setTagFetchScope(const TagFetchScope &fetchScope);
121 
122     /**
123      * Returns the tag fetch scope.
124      *
125      * Since this returns a reference it can be used to conveniently modify
126      * the current scope in-place.
127      */
128     TagFetchScope &tagFetchScope();
129 
130     /**
131      * Returns the items that matched the search query.
132      */
133     Q_REQUIRED_RESULT Item::List items() const;
134 
135     /**
136      * Search only for items of given mime types.
137      *
138      * @since 4.13
139      */
140     void setMimeTypes(const QStringList &mimeTypes);
141 
142     /**
143      * Returns list of mime types to search in
144      *
145      * @since 4.13
146      */
147     Q_REQUIRED_RESULT QStringList mimeTypes() const;
148 
149     /**
150      * Search only in given collections.
151      *
152      * When recursive search is enabled, all child collections of each specified
153      * collection will be searched too
154      *
155      * By default all collections are be searched.
156      *
157      * @param collections Collections to search
158      * @since 4.13
159      */
160     void setSearchCollections(const Collection::List &collections);
161 
162     /**
163      * Returns list of collections to search.
164      *
165      * This list does not include child collections that will be searched when
166      * recursive search is enabled
167      *
168      * @since 4.13
169      */
170     Q_REQUIRED_RESULT Collection::List searchCollections() const;
171 
172     /**
173      * Sets whether the search should recurse into collections
174      *
175      * When set to true, all child collections of the specific collections will
176      * be search recursively.
177      *
178      * @param recursive Whether to search recursively
179      * @since 4.13
180      */
181     void setRecursive(bool recursive);
182 
183     /**
184      * Returns whether the search is recursive
185      *
186      * @since 4.13
187      */
188     bool isRecursive() const;
189 
190     /**
191      * Sets whether resources should be queried too.
192      *
193      * When set to true, Akonadi will search local indexed items and will also
194      * query resources that support server-side search, to forward the query
195      * to remote storage (for example using SEARCH feature on IMAP servers) and
196      * merge their results with results from local index.
197      *
198      * This is useful especially when searching resources, that don't fetch full
199      * payload by default, for example the IMAP resource, which only fetches headers
200      * by default and the body is fetched on demand, which means that emails that
201      * were not yet fully fetched cannot be indexed in local index, and thus cannot
202      * be searched. With remote search, even those emails can be included in search
203      * results.
204      *
205      * This feature is disabled by default.
206      *
207      * Results are streamed back to client as they are received from queried sources,
208      * so this job can take some time to finish, but will deliver initial results
209      * from local index fairly quickly.
210      *
211      * @param enabled Whether remote search is enabled
212      * @since 4.13
213      */
214     void setRemoteSearchEnabled(bool enabled);
215 
216     /**
217      * Returns whether remote search is enabled.
218      *
219      * @since 4.13
220      */
221     Q_REQUIRED_RESULT bool isRemoteSearchEnabled() const;
222 
223 Q_SIGNALS:
224     /**
225      * This signal is emitted whenever new matching items have been fetched completely.
226      *
227      * @note This is an optimization, instead of waiting for the end of the job
228      *       and calling items(), you can connect to this signal and get the items
229      *       incrementally.
230      *
231      * @param items The matching items.
232      */
233     void itemsReceived(const Akonadi::Item::List &items);
234 
235 protected:
236     void doStart() override;
237     bool doHandleResponse(qint64 tag, const Protocol::CommandPtr &response) override;
238 
239 private:
240     /// @cond PRIVATE
241     Q_DECLARE_PRIVATE(ItemSearchJob)
242 
243     Q_PRIVATE_SLOT(d_func(), void timeout())
244     /// @endcond
245 };
246 
247 }
248 
249