2 * SPDX-FileCopyrightText: 2019 Ismael Asensio <isma.af@mgmail.com>
4 * SPDX-License-Identifier: GPL-2.0-or-later
7 #include "dolphinquery.h"
9 #include <QRegularExpression>
11 #include <config-baloo.h>
13 #include <Baloo/Query>
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
21 QString
searchTermToken(const QString
& term
)
23 static const QLatin1String searchTokens
[] {
24 QLatin1String("filename:"),
25 QLatin1String("modified>="),
26 QLatin1String("rating>="),
27 QLatin1String("tag:"), QLatin1String("tag=")
30 for (const auto &searchToken
: searchTokens
) {
31 if (term
.startsWith(searchToken
)) {
38 QString
stripQuotes(const QString
& text
)
40 if (text
.length() >= 2 && text
.at(0) == QLatin1Char('"')
41 && text
.back() == QLatin1Char('"')) {
42 return text
.mid(1, text
.size() - 2);
47 QStringList
splitOutsideQuotes(const QString
& text
)
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
);
56 QStringList textParts
;
57 while (subTermsMatchIterator
.hasNext()) {
58 textParts
<< subTermsMatchIterator
.next().captured(0);
64 QString
trimChar(const QString
& text
, const QLatin1Char aChar
)
66 const int start
= text
.startsWith(aChar
) ? 1 : 0;
67 const int end
= (text
.length() > 1 && text
.endsWith(aChar
)) ? 1 : 0;
69 return text
.mid(start
, text
.length() - start
- end
);
74 DolphinQuery
DolphinQuery::fromSearchUrl(const QUrl
& searchUrl
)
77 model
.m_searchUrl
= searchUrl
;
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
);
90 bool DolphinQuery::supportsScheme(const QString
& urlScheme
)
92 static const QStringList supportedSchemes
= {
93 QStringLiteral("baloosearch"),
94 QStringLiteral("tags"),
97 return supportedSchemes
.contains(urlScheme
);
100 void DolphinQuery::parseBalooQuery()
103 const Baloo::Query query
= Baloo::Query::fromSearchUrl(m_searchUrl
);
105 m_includeFolder
= query
.includeFolder();
107 const QStringList types
= query
.types();
108 m_fileType
= types
.isEmpty() ? QString() : types
.first();
110 QStringList textParts
;
113 const QStringList subTerms
= splitOutsideQuotes(query
.searchString());
114 foreach (const QString
& subTerm
, subTerms
) {
115 const QString token
= searchTermToken(subTerm
);
116 const QString value
= stripQuotes(subTerm
.mid(token
.length()));
118 if (token
== QLatin1String("filename:")) {
119 if (!value
.isEmpty()) {
121 m_hasFileName
= true;
124 } else if (!token
.isEmpty()) {
125 m_searchTerms
<< token
+ value
;
127 } else if (subTerm
== QLatin1String("AND") && subTerm
!= subTerms
.at(0) && subTerm
!= subTerms
.back()) {
129 } else if (!value
.isEmpty()) {
131 m_hasContentSearch
= true;
136 if (m_hasContentSearch
) {
137 textParts
<< QStringLiteral("filename:\"%1\"").arg(fileName
);
139 textParts
<< fileName
;
143 m_searchText
= textParts
.join(QLatin1Char(' '));
148 QUrl
DolphinQuery::searchUrl() const
153 QString
DolphinQuery::text() const
158 QString
DolphinQuery::type() const
163 QStringList
DolphinQuery::searchTerms() const
165 return m_searchTerms
;
168 QString
DolphinQuery::includeFolder() const
170 return m_includeFolder
;
173 bool DolphinQuery::hasContentSearch() const
175 return m_hasContentSearch
;
178 bool DolphinQuery::hasFileName() const
180 return m_hasFileName
;