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