┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/search/dolphinquery.h
blob: 6893e1855cc5fde95abfd5b754ea982aa6ad3af3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/*
    SPDX-FileCopyrightText: 2019 Ismael Asensio <[email protected]>
    SPDX-FileCopyrightText: 2025 Felix Ernst <[email protected]>

    SPDX-License-Identifier: GPL-2.0-or-later
*/

#ifndef DOLPHINQUERY_H
#define DOLPHINQUERY_H

#include "config-dolphin.h"
#include "dolphin_export.h"
#include "dolphin_searchsettings.h"

#include <KFileMetaData/Types>

#include <QString>
#include <QUrl>

#if HAVE_BALOO
namespace Baloo
{
class Query;
}
#endif

class DolphinQueryTest;

namespace Search
{

/** Specifies which locations the user expects to be searched for matches. */
enum class SearchLocations {
    FromHere, /// Search in m_searchUrl and its sub-folders.
    Everywhere, /// Search "Everywhere" as far as possible.
};

/** Specifies if items should be added to the search results when their file names or contents matches the search term. */
enum class SearchThrough {
    FileNames,
    FileContents, // This option currently also includes any searches that search both through FileContents and FileNames at once because we currently provide
                  // no option to toggle between only searching FileContents or FileContents & FileNames for any search tool.
};

enum class SearchTool {
    Filenamesearch, // Contrary to its name, it can actually also search in file contents.
#if HAVE_BALOO
    Baloo,
#endif
};

/** @returns whether Baloo is configured to have indexed the @p directory. */
bool isIndexingEnabledIn(QUrl directory);

/** @returns whether Baloo is configured to index file contents. */
bool isContentIndexingEnabled();

/** @returns whether the @p urlScheme should be considered a search scheme. */
bool isSupportedSearchScheme(const QString &urlScheme);

/**
 * @brief An object that fully specifies a search configuration.
 *
 * A DolphinQuery encompasses all state information to uniquely identify a search. It describes the search term, search tool, search options, and requirements
 * towards results. As such it can fully contain all state information of the Search::Bar because the search bars only goal is configuring and then triggering
 * a search.
 *
 * The @a toUrl() method constructs a search URL from the DolphinQuery which Dolphin can open to start searching. Such a search URL can also be transformed
 * back into a DolphinQuery object through the DolphinQuery constructor.
 *
 * When a DolphinQuery object is constructed or changed with incompatible conditions, like asking to search with an index-based search tool in a search path
 * which is not indexed, DolphinQuery tries to fix itself so the final search can give meaningful results.
 * Another example of this would be a DolphinQuery that is restricted to only search for images, which is then changed to use a search tool which does not
 * allow restricting results to images. In that case the DolphinQuery object would not necessarily need to fix itself, but the exported search URL will ignore
 * the image restriction, and the search user interface will need to update itself to make clear that the image restriction is ignored.
 *
 * Most widgets in the search UI have a `updateState()` method that takes a DolphinQuery as an argument. These methods will update the components' state to be
 * in line with the DolphinQuery object's configuration.
 */
class DolphinQuery
{
public:
    /**
     * @brief Automagically constructs a DolphinQuery based on the given @p url.
     * @param url In the most usual case @p url is considered the search path and the DolphinQuery object is initialized based on saved user preferences.
     *            However, if the @p url has query information encoded in itself, which is supposed to be the case if the QUrl::scheme() of the @p url is
     *            "baloosearch", "tags", or "filenamesearch", this constructor retrieves all the information from the @p url and initializes the DolphinQuery
     *            with it.
     * @param backupSearchPath The last non-search location the user was on.
     *                         A DolphinQuery object should always be fully constructible from the main @p url parameter. However, the data encoded in @url
     *                         might not contain any search path, for example because the constructed DolphinQuery object is supposed to search "everywhere".
     *                         This is fine until this DolphinQuery object is switched to search in a specific location instead. In that case, this
     *                         @p backupSearchPath will become the new searchPath() of this DolphinQuery.
     */
    explicit DolphinQuery(const QUrl &url, const QUrl &backupSearchPath);

    /**
     * @returns a representation of this DolphinQuery as a QUrl. This QUrl can be opened in Dolphin to trigger a search that is identical to the conditions
     *          provided by this DolphinQuery object.
     */
    QUrl toUrl() const;

    void setSearchLocations(SearchLocations searchLocations);
    inline SearchLocations searchLocations() const
    {
        return m_searchLocations;
    };

    /**
     * Set this query to search in @p searchPath. However, if @a searchLocations() is set to "Everywhere", @p searchPath is effectively ignored because it is
     * assumed that searching everywhere also includes @p searchPath.
     */
    void setSearchPath(const QUrl &searchPath);
    /**
     * @returns in which specific directory this query will search if the search location is not set to "Everywhere". When searching "Everywhere" this url is
     *          ignored completely.
     */
    inline QUrl searchPath() const
    {
        return m_searchPath;
    };

    /**
     * Set whether search results should match the search term with their names or contain it in their file contents.
     */
    void setSearchThrough(SearchThrough searchThrough);
    inline SearchThrough searchThrough() const
    {
        return m_searchThrough;
    };

    /**
     * Set the search tool or backend that will be used to @p searchTool.
     */
    inline void setSearchTool(SearchTool searchTool)
    {
        m_searchTool = searchTool;
        // We do not remove any search parameters here, even if the new search tool does not support them. This is an attempt to avoid that we unnecessarily
        // throw away configuration data. Non-applicable search parameters will be lost when exporting this DolphinQuery to a URL,
        // but such an export won't happen if the changed DolphinQuery is not a valid search e.g. because the searchTerm().isEmpty() and every other search
        // parameter is not supported by the new search tool.
    };
    /** @returns the search tool to be used for this search. */
    inline SearchTool searchTool() const
    {
        return m_searchTool;
    };

    /**
     * Sets the search text the user entered into the search field to @p searchTerm.
     */
    inline void setSearchTerm(const QString &searchTerm)
    {
        m_searchTerm = searchTerm;
    };
    /** @return the search text the user entered into the search field. */
    inline QString searchTerm() const
    {
        return m_searchTerm;
    };

    /**
     * Sets the type every search result should have.
     */
    inline void setFileType(const KFileMetaData::Type::Type &fileType)
    {
        m_fileType = fileType;
    };
    /**
     * @return the requested file type this search will be restricted to.
     */
    inline KFileMetaData::Type::Type fileType() const
    {
        return m_fileType;
    };

    /**
     * Sets the date since when every search result needs to have been modified.
     */
    inline void setModifiedSinceDate(const QDate &modifiedLaterThanDate)
    {
        m_modifiedSinceDate = modifiedLaterThanDate;
    };
    /**
     * @return the date since when every search result needs to have been modified.
     */
    inline QDate modifiedSinceDate() const
    {
        return m_modifiedSinceDate;
    };

    /**
     * @param minimumRating the minimum rating value every search result needs to at least have to be considered a valid result of this query.
     *                      Values <= 0 mean no restriction. 1 is half a star, 2 one full star, etc. 10 is typically the maximum in KDE software.
     */
    inline void setMinimumRating(int minimumRating)
    {
        m_minimumRating = minimumRating;
    };
    /**
     * @returns the minimum rating every search result is requested to have.
     * @see setMinimumRating().
     */
    inline int minimumRating() const
    {
        return m_minimumRating;
    };

    /**
     * @param requiredTags All the tags every search result is required to have.
     */
    inline void setRequiredTags(const QStringList &requiredTags)
    {
        m_requiredTags = requiredTags;
    };
    /**
     * @returns all the tags every search result is required to have.
     */
    inline QStringList requiredTags() const
    {
        return m_requiredTags;
    };

    bool operator==(const DolphinQuery &) const = default;

    /**
     * @returns a title to be used in user-facing situations to represent this DolphinQuery, such as "Query Results from 'importantFile'".
     */
    QString title() const;

private:
#if HAVE_BALOO
    /** Parses a Baloo::Query to extract its separate components */
    void initializeFromBalooQuery(const Baloo::Query &balooQuery, const QUrl &backupSearchPath);
#endif

    /**
     * Switches to the user's preferred search tool if this is possible. If the preferred search tool cannot perform a search within this DolphinQuery's
     * conditions, a different search tool will be used instead.
     */
    void switchToPreferredSearchTool();

private:
    /** Specifies which locations will be searched for the search terms. */
    SearchLocations m_searchLocations = SearchSettings::location() == QLatin1String("Everywhere") ? SearchLocations::Everywhere : SearchLocations::FromHere;

    /**
     * Specifies where searching will begin.
     * @note The value of this variable is ignored when this query is set to search "Everywhere".
     */
    QUrl m_searchPath;

    /** Specifies whether file names, file contents, or both will be searched for the search terms. */
    SearchThrough m_searchThrough = SearchSettings::what() == QLatin1String("FileContents") ? SearchThrough::FileContents : SearchThrough::FileNames;

    /** Specifies which search tool will be used for the search. */
#if HAVE_BALOO
    SearchTool m_searchTool = SearchSettings::searchTool() == QLatin1String("Baloo") ? SearchTool::Baloo : SearchTool::Filenamesearch;
#else
    SearchTool m_searchTool = SearchTool::Filenamesearch;
#endif

    QString m_searchTerm;
    /** Specifies which file type all search results should have. "Empty" means there is no restriction on file type. */
    KFileMetaData::Type::Type m_fileType = KFileMetaData::Type::Empty;

    /** All search results are requested to be modified later than or equal to this date. Null or invalid dates mean no restriction. */
    QDate m_modifiedSinceDate;

    /**
     * All search results are requested to have at least this rating.
     * If the minimum rating is less than or equal to 0, this variable is ignored.
     * 1 is generally considered half a star in KDE software, 2 a full star, etc. Generally 10 is considered the max rating i.e. 5/5 stars or a song marked as
     * one of your favourites in a music application. Higher values are AFAIK not used in KDE applications but other software might use a different scale.
     */
    int m_minimumRating = 0;

    /** All the tags every search result is required to have. */
    QStringList m_requiredTags;

    /**
     * @brief Any imported Baloo search parameters (token:value pairs) which Dolphin does not understand are stored in this list unmodified.
     * Dolphin only allows modifying a certain selection of search parameters, but there are more. This is a bit of an unfortunate situation because we can not
     * represent every single query in the user interface without creating a mess of a UI. However, we also don't want to drop these extra parameters because
     * that would unexpectedly modify the query.
     * So this variable simply stores anything we don't recognize and reproduces it when exporting to a Baloo URL.
     */
    QStringList m_unrecognizedBalooQueryStrings;

    friend DolphinQueryTest;
};

/**
 * For testing Baloo in DolphinQueryTest even if it is not indexing any locations yet.
 * The test mode makes sure that DolphinQuery can be set to use Baloo even if Baloo has not indexed any locations yet.
 */
void setTestMode();
}

#endif //DOLPHINQUERY_H