#include "dolphinquery.h"
+#include <QRegularExpression>
+
#include <config-baloo.h>
#ifdef HAVE_BALOO
#include <Baloo/Query>
#endif
namespace {
- /** Checks if a given term in the Baloo::Query::searchString() is a special search term.
- * This is a copy of `DolphinFacetsWidget::isRatingTerm()` method.
+#ifdef HAVE_BALOO
+ /** Checks if a given term in the Baloo::Query::searchString() is a special search term
+ * @return: the specific search token of the term, or an empty QString() if none is found
*/
- bool isSearchTerm(const QString& term)
+ QString searchTermToken(const QString& term)
{
static const QLatin1String searchTokens[] {
+ QLatin1String("filename:"),
QLatin1String("modified>="),
- QLatin1String("rating>=")
+ QLatin1String("rating>="),
+ QLatin1String("tag:"), QLatin1String("tag=")
};
for (const auto &searchToken : searchTokens) {
if (term.startsWith(searchToken)) {
- return true;
+ return searchToken;
}
}
- return false;
+ return QString();
+ }
+
+ QString stripQuotes(const QString& text)
+ {
+ if (text.length() >= 2 && text.at(0) == QLatin1Char('"')
+ && text.back() == QLatin1Char('"')) {
+ return text.mid(1, text.size() - 2);
+ }
+ return text;
+ }
+
+ QStringList splitOutsideQuotes(const QString& text)
+ {
+ // Match groups on 3 possible conditions:
+ // - Groups with two leading quotes must close both on them (filename:""abc xyz" tuv")
+ // - Groups enclosed in quotes
+ // - Words separated by spaces
+ const QRegularExpression subTermsRegExp("(\\S*?\"\"[^\"]+\"[^\"]+\"+|\\S*?\"[^\"]+\"+|(?<=\\s|^)\\S+(?=\\s|$))");
+ auto subTermsMatchIterator = subTermsRegExp.globalMatch(text);
+
+ QStringList textParts;
+ while (subTermsMatchIterator.hasNext()) {
+ textParts << subTermsMatchIterator.next().captured(0);
+ }
+ return textParts;
}
+#endif
}
-DolphinQuery DolphinQuery::fromBalooSearchUrl(const QUrl& searchUrl)
+
+DolphinQuery DolphinQuery::fromSearchUrl(const QUrl& searchUrl)
{
DolphinQuery model;
model.m_searchUrl = searchUrl;
-#ifdef HAVE_BALOO
- const Baloo::Query query = Baloo::Query::fromSearchUrl(searchUrl);
+ if (searchUrl.scheme() == QLatin1String("baloosearch")) {
+ model.parseBalooQuery();
+ }
- model.m_includeFolder = query.includeFolder();
+ return model;
+}
- model.m_searchText = query.searchString();
+bool DolphinQuery::supportsScheme(const QString& urlScheme)
+{
+ static const QStringList supportedSchemes = {
+ QStringLiteral("baloosearch"),
+ };
+
+ return supportedSchemes.contains(urlScheme);
+}
+
+void DolphinQuery::parseBalooQuery()
+{
+#ifdef HAVE_BALOO
+ const Baloo::Query query = Baloo::Query::fromSearchUrl(m_searchUrl);
+
+ m_includeFolder = query.includeFolder();
const QStringList types = query.types();
- model.m_fileType = types.isEmpty() ? QString() : types.first();
+ m_fileType = types.isEmpty() ? QString() : types.first();
+
+ QStringList textParts;
+ QString fileName;
- const QStringList subTerms = query.searchString().split(' ', QString::SkipEmptyParts);
+ const QStringList subTerms = splitOutsideQuotes(query.searchString());
foreach (const QString& subTerm, subTerms) {
- if (subTerm.startsWith(QLatin1String("filename:"))) {
- const QString value = subTerm.mid(9);
- model.m_searchText = value;
- } else if (isSearchTerm(subTerm)) {
- model.m_searchTerms << subTerm;
+ const QString token = searchTermToken(subTerm);
+ const QString value = stripQuotes(subTerm.mid(token.length()));
+
+ if (token == QLatin1String("filename:")) {
+ if (!value.isEmpty()) {
+ fileName = value;
+ m_hasFileName = true;
+ }
+ continue;
+ } else if (!token.isEmpty()) {
+ m_searchTerms << token + value;
+ continue;
+ } else if (subTerm == QLatin1String("AND") && subTerm != subTerms.at(0) && subTerm != subTerms.back()) {
+ continue;
+ } else if (!value.isEmpty()) {
+ textParts << value;
+ m_hasContentSearch = true;
+ }
+ }
+
+ if (m_hasFileName) {
+ if (m_hasContentSearch) {
+ textParts << QStringLiteral("filename:\"%1\"").arg(fileName);
+ } else {
+ textParts << fileName;
}
}
+
+ m_searchText = textParts.join(QLatin1Char(' '));
#endif
- return model;
}
+
QUrl DolphinQuery::searchUrl() const
{
return m_searchUrl;
{
return m_includeFolder;
}
+
+bool DolphinQuery::hasContentSearch() const
+{
+ return m_hasContentSearch;
+}
+
+bool DolphinQuery::hasFileName() const
+{
+ return m_hasFileName;
+}