]> cloud.milkyroute.net Git - dolphin.git/blob - src/search/dolphinquery.cpp
Use cmakedefine01
[dolphin.git] / src / search / dolphinquery.cpp
1 /*
2 * SPDX-FileCopyrightText: 2019 Ismael Asensio <isma.af@mgmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "dolphinquery.h"
8
9 #include <QRegularExpression>
10
11 #include <config-dolphin.h>
12 #if HAVE_BALOO
13 #include <Baloo/Query>
14 #endif
15
16 namespace {
17 #if HAVE_BALOO
18 /** Checks if a given term in the Baloo::Query::searchString() is a special search term
19 * @return: the specific search token of the term, or an empty QString() if none is found
20 */
21 QString searchTermToken(const QString& term)
22 {
23 static const QLatin1String searchTokens[] {
24 QLatin1String("filename:"),
25 QLatin1String("modified>="),
26 QLatin1String("rating>="),
27 QLatin1String("tag:"), QLatin1String("tag=")
28 };
29
30 for (const auto &searchToken : searchTokens) {
31 if (term.startsWith(searchToken)) {
32 return searchToken;
33 }
34 }
35 return QString();
36 }
37
38 QString stripQuotes(const QString& text)
39 {
40 if (text.length() >= 2 && text.at(0) == QLatin1Char('"')
41 && text.back() == QLatin1Char('"')) {
42 return text.mid(1, text.size() - 2);
43 }
44 return text;
45 }
46
47 QStringList splitOutsideQuotes(const QString& text)
48 {
49 // Match groups on 3 possible conditions:
50 // - Groups with two leading quotes must close both on them (filename:""abc xyz" tuv")
51 // - Groups enclosed in quotes
52 // - Words separated by spaces
53 const QRegularExpression subTermsRegExp("(\\S*?\"\"[^\"]+\"[^\"]+\"+|\\S*?\"[^\"]+\"+|(?<=\\s|^)\\S+(?=\\s|$))");
54 auto subTermsMatchIterator = subTermsRegExp.globalMatch(text);
55
56 QStringList textParts;
57 while (subTermsMatchIterator.hasNext()) {
58 textParts << subTermsMatchIterator.next().captured(0);
59 }
60 return textParts;
61 }
62 #endif
63
64 QString trimChar(const QString& text, const QLatin1Char aChar)
65 {
66 const int start = text.startsWith(aChar) ? 1 : 0;
67 const int end = (text.length() > 1 && text.endsWith(aChar)) ? 1 : 0;
68
69 return text.mid(start, text.length() - start - end);
70 }
71 }
72
73
74 DolphinQuery DolphinQuery::fromSearchUrl(const QUrl& searchUrl)
75 {
76 DolphinQuery model;
77 model.m_searchUrl = searchUrl;
78
79 if (searchUrl.scheme() == QLatin1String("baloosearch")) {
80 model.parseBalooQuery();
81 } else if (searchUrl.scheme() == QLatin1String("tags")) {
82 // tags can contain # symbols or slashes within the Url
83 QString tag = trimChar(searchUrl.toString(QUrl::RemoveScheme), QLatin1Char('/'));
84 model.m_searchTerms << QStringLiteral("tag:%1").arg(tag);
85 }
86
87 return model;
88 }
89
90 bool DolphinQuery::supportsScheme(const QString& urlScheme)
91 {
92 static const QStringList supportedSchemes = {
93 QStringLiteral("baloosearch"),
94 QStringLiteral("tags"),
95 };
96
97 return supportedSchemes.contains(urlScheme);
98 }
99
100 void DolphinQuery::parseBalooQuery()
101 {
102 #if HAVE_BALOO
103 const Baloo::Query query = Baloo::Query::fromSearchUrl(m_searchUrl);
104
105 m_includeFolder = query.includeFolder();
106
107 const QStringList types = query.types();
108 m_fileType = types.isEmpty() ? QString() : types.first();
109
110 QStringList textParts;
111 QString fileName;
112
113 const QStringList subTerms = splitOutsideQuotes(query.searchString());
114 for (const QString& subTerm : subTerms) {
115 const QString token = searchTermToken(subTerm);
116 const QString value = stripQuotes(subTerm.mid(token.length()));
117
118 if (token == QLatin1String("filename:")) {
119 if (!value.isEmpty()) {
120 fileName = value;
121 m_hasFileName = true;
122 }
123 continue;
124 } else if (!token.isEmpty()) {
125 m_searchTerms << token + value;
126 continue;
127 } else if (subTerm == QLatin1String("AND") && subTerm != subTerms.at(0) && subTerm != subTerms.back()) {
128 continue;
129 } else if (!value.isEmpty()) {
130 textParts << value;
131 m_hasContentSearch = true;
132 }
133 }
134
135 if (m_hasFileName) {
136 if (m_hasContentSearch) {
137 textParts << QStringLiteral("filename:\"%1\"").arg(fileName);
138 } else {
139 textParts << fileName;
140 }
141 }
142
143 m_searchText = textParts.join(QLatin1Char(' '));
144 #endif
145 }
146
147
148 QUrl DolphinQuery::searchUrl() const
149 {
150 return m_searchUrl;
151 }
152
153 QString DolphinQuery::text() const
154 {
155 return m_searchText;
156 }
157
158 QString DolphinQuery::type() const
159 {
160 return m_fileType;
161 }
162
163 QStringList DolphinQuery::searchTerms() const
164 {
165 return m_searchTerms;
166 }
167
168 QString DolphinQuery::includeFolder() const
169 {
170 return m_includeFolder;
171 }
172
173 bool DolphinQuery::hasContentSearch() const
174 {
175 return m_hasContentSearch;
176 }
177
178 bool DolphinQuery::hasFileName() const
179 {
180 return m_hasFileName;
181 }