Merge branch 'release/19.12'

This commit is contained in:
Elvis Angelaccio 2019-11-17 18:54:40 +01:00
commit 6bcdb62429
9 changed files with 328 additions and 29 deletions

View file

@ -216,6 +216,7 @@ set(dolphinstatic_SRCS
panels/folders/folderspanel.cpp
panels/terminal/terminalpanel.cpp
search/dolphinfacetswidget.cpp
search/dolphinquery.cpp
search/dolphinsearchbox.cpp
settings/general/behaviorsettingspage.cpp
settings/general/configurepreviewplugindialog.cpp

View file

@ -523,7 +523,7 @@
<li xml:lang="zh-TW">復原支援</li>
</ul>
</description>
<url type="homepage">https://dolphin.kde.org/</url>
<url type="homepage">https://kde.org/applications/system/dolphin</url>
<url type="bugtracker">https://bugs.kde.org/enter_bug.cgi?format=guided&amp;product=dolphin</url>
<url type="help">https://docs.kde.org/?application=dolphin</url>
<url type="donation">https://www.kde.org/community/donations/?app=dolphin&amp;source=appdata</url>

View file

@ -153,7 +153,7 @@ void DolphinFacetsWidget::setRatingTerm(const QString& term)
void DolphinFacetsWidget::setFacetType(const QString& type)
{
for (int index = 1; index <= m_typeSelector->count(); index++) {
for (int index = 0; index <= m_typeSelector->count(); index++) {
if (type == m_typeSelector->itemData(index).toString()) {
m_typeSelector->setCurrentIndex(index);
break;

View file

@ -0,0 +1,98 @@
/***************************************************************************
* Copyright (C) 2019 by Ismael Asensio <isma.af@mgmail.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#include "dolphinquery.h"
#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.
*/
bool isSearchTerm(const QString& term)
{
static const QLatin1String searchTokens[] {
QLatin1String("modified>="),
QLatin1String("rating>=")
};
for (const auto &searchToken : searchTokens) {
if (term.startsWith(searchToken)) {
return true;
}
}
return false;
}
}
DolphinQuery DolphinQuery::fromBalooSearchUrl(const QUrl& searchUrl)
{
DolphinQuery model;
model.m_searchUrl = searchUrl;
#ifdef HAVE_BALOO
const Baloo::Query query = Baloo::Query::fromSearchUrl(searchUrl);
model.m_includeFolder = query.includeFolder();
model.m_searchText = query.searchString();
const QStringList types = query.types();
model.m_fileType = types.isEmpty() ? QString() : types.first();
const QStringList subTerms = query.searchString().split(' ', QString::SkipEmptyParts);
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;
}
}
#endif
return model;
}
QUrl DolphinQuery::searchUrl() const
{
return m_searchUrl;
}
QString DolphinQuery::text() const
{
return m_searchText;
}
QString DolphinQuery::type() const
{
return m_fileType;
}
QStringList DolphinQuery::searchTerms() const
{
return m_searchTerms;
}
QString DolphinQuery::includeFolder() const
{
return m_includeFolder;
}

60
src/search/dolphinquery.h Normal file
View file

@ -0,0 +1,60 @@
/***************************************************************************
* Copyright (C) 2019 by Ismael Asensio <isma.af@mgmail.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#ifndef DOLPHINQUERY_H
#define DOLPHINQUERY_H
#include "dolphin_export.h"
#include <QString>
#include <QUrl>
/**
* @brief Simple query model that parses a Baloo search Url and extracts its
* separate components to be displayed on dolphin search box.
*/
class DolphinQuery
{
public:
/** Calls Baloo::Query::fromSearchUrl() with the given @p searchUrl
* and parses the result to extract its separate components */
static DolphinQuery fromBalooSearchUrl(const QUrl& searchUrl);
/** @return the \a searchUrl passed to Baloo::Query::fromSearchUrl() */
QUrl searchUrl() const;
/** @return the user text part of the query, to be shown in the searchbar */
QString text() const;
/** @return the first of Baloo::Query::types(), or an empty string */
QString type() const;
/** @return a list of the search terms of the Baloo::Query that act as a filter,
* such as \"rating>= <i>value<i>\" or \"modified>= <i>date<i>\"*/
QStringList searchTerms() const;
/** @return Baloo::Query::includeFolder(), that is, the initial directory
* for the query or an empty string if its a global search" */
QString includeFolder() const;
private:
QUrl m_searchUrl;
QString m_searchText;
QString m_fileType;
QStringList m_searchTerms;
QString m_includeFolder;
};
#endif //DOLPHINQUERY_H

View file

@ -22,6 +22,7 @@
#include "dolphin_searchsettings.h"
#include "dolphinfacetswidget.h"
#include "dolphinquery.h"
#include "panels/places/placesitemmodel.h"
#include <KLocalizedString>
@ -143,7 +144,8 @@ QUrl DolphinSearchBox::urlForSearching() const
void DolphinSearchBox::fromSearchUrl(const QUrl& url)
{
if (url.scheme() == QLatin1String("baloosearch")) {
fromBalooSearchUrl(url);
const DolphinQuery query = DolphinQuery::fromBalooSearchUrl(url);
updateFromQuery(query);
} else if (url.scheme() == QLatin1String("filenamesearch")) {
const QUrlQuery query(url);
setText(query.queryItemValue(QStringLiteral("search")));
@ -498,11 +500,8 @@ QUrl DolphinSearchBox::balooUrlForSearching() const
#endif
}
void DolphinSearchBox::fromBalooSearchUrl(const QUrl& url)
void DolphinSearchBox::updateFromQuery(const DolphinQuery& query)
{
#ifdef HAVE_BALOO
const Baloo::Query query = Baloo::Query::fromSearchUrl(url);
// Block all signals to avoid unnecessary "searchRequest" signals
// while we adjust the search text and the facet widget.
blockSignals(true);
@ -514,30 +513,17 @@ void DolphinSearchBox::fromBalooSearchUrl(const QUrl& url)
setSearchPath(QUrl::fromLocalFile(QDir::homePath()));
}
setText(query.text());
m_facetsWidget->resetOptions();
setText(query.searchString());
QStringList types = query.types();
if (!types.isEmpty()) {
m_facetsWidget->setFacetType(types.first());
}
const QStringList subTerms = query.searchString().split(' ', QString::SkipEmptyParts);
foreach (const QString& subTerm, subTerms) {
if (subTerm.startsWith(QLatin1String("filename:"))) {
const QString value = subTerm.mid(9);
setText(value);
} else if (m_facetsWidget->isRatingTerm(subTerm)) {
m_facetsWidget->setRatingTerm(subTerm);
}
m_facetsWidget->setFacetType(query.type());
const QStringList searchTerms = query.searchTerms();
for (const QString& searchTerm : searchTerms) {
m_facetsWidget->setRatingTerm(searchTerm);
}
m_startSearchTimer->stop();
blockSignals(false);
#else
Q_UNUSED(url)
#endif
}
void DolphinSearchBox::updateFacetsVisible()

View file

@ -24,6 +24,7 @@
#include <QWidget>
class DolphinFacetsWidget;
class DolphinQuery;
class QLineEdit;
class KSeparator;
class QToolButton;
@ -152,10 +153,9 @@ private:
QUrl balooUrlForSearching() const;
/**
* Extracts information from the given Baloo search \a url to
* initialize the search box properly.
* Sets the searchbox UI with the parameters established by the \a query
*/
void fromBalooSearchUrl(const QUrl& url);
void updateFromQuery(const DolphinQuery& query);
void updateFacetsVisible();

View file

@ -49,6 +49,13 @@ if (KF5Baloo_FOUND)
LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test)
endif()
# DolphinQuery
if (KF5Baloo_FOUND)
ecm_add_test(dolphinquerytest.cpp
TEST_NAME dolphinquerytest
LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test)
endif()
# KStandardItemModelTest
ecm_add_test(kstandarditemmodeltest.cpp
TEST_NAME kstandarditemmodeltest

View file

@ -0,0 +1,147 @@
/***************************************************************************
* Copyright (C) 2019 by Ismael Asensio <isma.af@gmail.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#include "search/dolphinquery.h"
#include <QTest>
#include <QJsonDocument>
#include <QJsonObject>
#include <QStringList>
#include <QUrl>
#include <QUrlQuery>
class DolphinSearchBoxTest : public QObject
{
Q_OBJECT
private slots:
void testBalooSearchParsing_data();
void testBalooSearchParsing();
};
/**
* Defines the parameters for the test cases in testBalooSearchParsing()
*/
void DolphinSearchBoxTest::testBalooSearchParsing_data()
{
const QString text = QStringLiteral("xyz");
const QString filename = QStringLiteral("filename:\"xyz\"");
const QString rating = QStringLiteral("rating>=2");
const QString modified = QString("modified>=2019-08-07");
QTest::addColumn<QString>("searchString");
QTest::addColumn<QString>("expectedText");
QTest::addColumn<QStringList>("expectedTerms");
// Test for "Content"
QTest::newRow("content") << text << text << QStringList();
QTest::newRow("content/empty") << "" << "" << QStringList();
QTest::newRow("content/singleQuote") << "\"" << "" << QStringList();
QTest::newRow("content/doubleQuote") << "\"\"" << "" << QStringList();
// Test for empty `filename`
QTest::newRow("filename") << filename << text << QStringList();
QTest::newRow("filename/empty") << "filename:" << "" << QStringList();
QTest::newRow("filename/singleQuote") << "filename:\"" << "" << QStringList();
QTest::newRow("filename/doubleQuote") << "filename:\"\"" << "" << QStringList();
// Test for rating
QTest::newRow("rating") << rating << "" << QStringList({rating});
QTest::newRow("rating+content") << rating + " " + text << text << QStringList({rating});
QTest::newRow("rating+filename") << rating + " " + filename << text << QStringList({rating});
// Test for modified date
QTest::newRow("modified") << modified << "" << QStringList({modified});
QTest::newRow("modified+content") << modified + " " + text << text << QStringList({modified});
QTest::newRow("modified+filename") << modified + " " + filename << text << QStringList({modified});
// Combined tests
QTest::newRow("rating+modified") << rating + " AND " + modified << "" << QStringList({modified, rating});
QTest::newRow("rating+modified+content") << rating + " AND " + modified + " " + text << text << QStringList({modified, rating});
QTest::newRow("rating+modified+filename") << rating + " AND " + modified + " " + filename << text << QStringList({modified, rating});
}
/**
* Helper function to compose the baloo query URL used for searching
*/
QUrl composeQueryUrl(const QString& searchString)
{
const QJsonObject jsonObject {
{"searchString", searchString}
};
const QJsonDocument doc(jsonObject);
const QString queryString = QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
QUrlQuery urlQuery;
urlQuery.addQueryItem(QStringLiteral("json"), queryString);
QUrl searchUrl;
searchUrl.setScheme(QLatin1String("baloosearch"));
searchUrl.setQuery(urlQuery);
return searchUrl;
}
/**
* The test verifies whether the different terms of a Baloo search URL ("baloosearch:") are
* properly handled by the searchbox, and only "user" or filename terms are added to the
* text bar of the searchbox.
*/
void DolphinSearchBoxTest::testBalooSearchParsing()
{
QFETCH(QString, searchString);
QFETCH(QString, expectedText);
QFETCH(QStringList, expectedTerms);
const QUrl testUrl = composeQueryUrl(searchString);
const DolphinQuery query = DolphinQuery::fromBalooSearchUrl(testUrl);
QStringList searchTerms = query.searchTerms();
searchTerms.sort();
// FIXME: Current parsing bugs
QEXPECT_FAIL("content/singleQuote", "Quotes around text are shown", Continue);
QEXPECT_FAIL("content/doubleQuote", "Quotes around text are shown", Continue);
QEXPECT_FAIL("filename", "Quotes around text are shown", Continue);
QEXPECT_FAIL("filename/singleQuote", "Quotes around text are shown", Continue);
QEXPECT_FAIL("filename/doubleQuote", "Quotes around text are shown", Continue);
QEXPECT_FAIL("rating" , "Text includes also search terms", Continue);
QEXPECT_FAIL("rating+content" , "Text includes also search terms", Continue);
QEXPECT_FAIL("rating+filename" , "Text includes also search terms", Continue);
QEXPECT_FAIL("modified" , "Text includes also search terms", Continue);
QEXPECT_FAIL("modified+content" , "Text includes also search terms", Continue);
QEXPECT_FAIL("modified+filename" , "Text includes also search terms", Continue);
QEXPECT_FAIL("rating+modified" , "Text includes also search terms", Continue);
QEXPECT_FAIL("rating+modified+content" , "Text includes also search terms", Continue);
QEXPECT_FAIL("rating+modified+filename", "Text includes also search terms", Continue);
// Check for parsed text (would be displayed on the input search bar)
QCOMPARE(query.text(), expectedText);
// Check for parsed search terms (would be displayed by the facetsWidget)
QCOMPARE(searchTerms.count(), expectedTerms.count());
for (int i = 0; i < expectedTerms.count(); i++) {
QCOMPARE(searchTerms.at(i), expectedTerms.at(i));
}
}
QTEST_MAIN(DolphinSearchBoxTest)
#include "dolphinquerytest.moc"