diff --git a/src/search/dolphinfacetswidget.cpp b/src/search/dolphinfacetswidget.cpp index 33c3cea24..d9943abcd 100644 --- a/src/search/dolphinfacetswidget.cpp +++ b/src/search/dolphinfacetswidget.cpp @@ -1,289 +1,293 @@ /*************************************************************************** * Copyright (C) 2012 by Peter Penz * * Copyright (C) 2019 by Ismael Asensio * * * * 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 "dolphinfacetswidget.h" #include #include #include #include #include #include #include #include DolphinFacetsWidget::DolphinFacetsWidget(QWidget* parent) : QWidget(parent), m_typeSelector(nullptr), m_dateSelector(nullptr), m_ratingSelector(nullptr), m_tagsSelector(nullptr) { m_typeSelector = new QComboBox(this); m_typeSelector->addItem(QIcon::fromTheme(QStringLiteral("none")), i18nc("@item:inlistbox", "Any Type"), QString()); m_typeSelector->addItem(QIcon::fromTheme(QStringLiteral("inode-directory")), i18nc("@item:inlistbox", "Folders") , QStringLiteral("Folder")); m_typeSelector->addItem(QIcon::fromTheme(QStringLiteral("text-x-generic")), i18nc("@item:inlistbox", "Documents") , QStringLiteral("Document")); m_typeSelector->addItem(QIcon::fromTheme(QStringLiteral("image-x-generic")), i18nc("@item:inlistbox", "Images") , QStringLiteral("Image")); m_typeSelector->addItem(QIcon::fromTheme(QStringLiteral("audio-x-generic")), i18nc("@item:inlistbox", "Audio Files"), QStringLiteral("Audio")); m_typeSelector->addItem(QIcon::fromTheme(QStringLiteral("video-x-generic")), i18nc("@item:inlistbox", "Videos") , QStringLiteral("Video")); initComboBox(m_typeSelector); const QDate currentDate = QDate::currentDate(); m_dateSelector = new QComboBox(this); m_dateSelector->addItem(QIcon::fromTheme(QStringLiteral("view-calendar")), i18nc("@item:inlistbox", "Any Date"), QDate()); m_dateSelector->addItem(QIcon::fromTheme(QStringLiteral("go-jump-today")), i18nc("@item:inlistbox", "Today") , currentDate); m_dateSelector->addItem(QIcon::fromTheme(QStringLiteral("go-jump-today")), i18nc("@item:inlistbox", "Yesterday") , currentDate.addDays(-1)); m_dateSelector->addItem(QIcon::fromTheme(QStringLiteral("view-calendar-week")), i18nc("@item:inlistbox", "This Week") , currentDate.addDays(1 - currentDate.dayOfWeek())); m_dateSelector->addItem(QIcon::fromTheme(QStringLiteral("view-calendar-month")), i18nc("@item:inlistbox", "This Month"), currentDate.addDays(1 - currentDate.day())); m_dateSelector->addItem(QIcon::fromTheme(QStringLiteral("view-calendar-year")), i18nc("@item:inlistbox", "This Year") , currentDate.addDays(1 - currentDate.dayOfYear())); initComboBox(m_dateSelector); m_ratingSelector = new QComboBox(this); m_ratingSelector->addItem(QIcon::fromTheme(QStringLiteral("non-starred-symbolic")), i18nc("@item:inlistbox", "Any Rating"), 0); m_ratingSelector->addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "1 or more"), 1); m_ratingSelector->addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "2 or more"), 2); m_ratingSelector->addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "3 or more"), 3); m_ratingSelector->addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "4 or more"), 4); m_ratingSelector->addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "Highest Rating"), 5); initComboBox(m_ratingSelector); m_tagsSelector = new QToolButton(this); m_tagsSelector->setIcon(QIcon::fromTheme(QStringLiteral("tag"))); m_tagsSelector->setMenu(new QMenu(this)); m_tagsSelector->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); m_tagsSelector->setPopupMode(QToolButton::MenuButtonPopup); m_tagsSelector->setAutoRaise(true); updateTagsSelector(); connect(m_tagsSelector, &QToolButton::clicked, m_tagsSelector, &QToolButton::showMenu); connect(m_tagsSelector->menu(), &QMenu::aboutToShow, this, &DolphinFacetsWidget::updateTagsMenu); connect(&m_tagsLister, &KCoreDirLister::itemsAdded, this, &DolphinFacetsWidget::updateTagsMenuItems); updateTagsMenu(); QHBoxLayout* topLayout = new QHBoxLayout(this); topLayout->setContentsMargins(0, 0, 0, 0); topLayout->addWidget(m_typeSelector); topLayout->addWidget(m_dateSelector); topLayout->addWidget(m_ratingSelector); topLayout->addWidget(m_tagsSelector); resetSearchTerms(); } DolphinFacetsWidget::~DolphinFacetsWidget() { } void DolphinFacetsWidget::changeEvent(QEvent *event) { if (event->type() == QEvent::EnabledChange) { if (isEnabled()) { updateTagsSelector(); } else { resetSearchTerms(); } } } void DolphinFacetsWidget::resetSearchTerms() { m_typeSelector->setCurrentIndex(0); m_dateSelector->setCurrentIndex(0); m_ratingSelector->setCurrentIndex(0); m_searchTags = QStringList(); updateTagsSelector(); updateTagsMenu(); } QStringList DolphinFacetsWidget::searchTerms() const { QStringList terms; if (m_ratingSelector->currentIndex() > 0) { const int rating = m_ratingSelector->currentData().toInt() * 2; terms << QStringLiteral("rating>=%1").arg(rating); } if (m_dateSelector->currentIndex() > 0) { const QDate date = m_dateSelector->currentData().toDate(); terms << QStringLiteral("modified>=%1").arg(date.toString(Qt::ISODate)); } if (!m_searchTags.isEmpty()) { for (auto const &tag : m_searchTags) { - terms << QStringLiteral("tag:%1").arg(tag); + if (tag.contains(QLatin1Char(' '))) { + terms << QStringLiteral("tag:\"%1\"").arg(tag); + } else { + terms << QStringLiteral("tag:%1").arg(tag); + } } } return terms; } QString DolphinFacetsWidget::facetType() const { return m_typeSelector->currentData().toString(); } bool DolphinFacetsWidget::isSearchTerm(const QString& term) const { static const QLatin1String searchTokens[] { QLatin1String("modified>="), QLatin1String("rating>="), QLatin1String("tag:"), QLatin1String("tag=") }; for (const auto &searchToken : searchTokens) { if (term.startsWith(searchToken)) { return true; } } return false; } void DolphinFacetsWidget::setSearchTerm(const QString& term) { if (term.startsWith(QLatin1String("modified>="))) { const QString value = term.mid(10); const QDate date = QDate::fromString(value, Qt::ISODate); setTimespan(date); } else if (term.startsWith(QLatin1String("rating>="))) { const QString value = term.mid(8); const int stars = value.toInt() / 2; setRating(stars); } else if (term.startsWith(QLatin1String("tag:")) || term.startsWith(QLatin1String("tag="))) { const QString value = term.mid(4); addSearchTag(value); } } void DolphinFacetsWidget::setFacetType(const QString& type) { for (int index = 0; index <= m_typeSelector->count(); index++) { if (type == m_typeSelector->itemData(index).toString()) { m_typeSelector->setCurrentIndex(index); break; } } } void DolphinFacetsWidget::setRating(const int stars) { if (stars < 0 || stars > 5) { return; } m_ratingSelector->setCurrentIndex(stars); } void DolphinFacetsWidget::setTimespan(const QDate& date) { if (!date.isValid()) { return; } m_dateSelector->setCurrentIndex(0); for (int index = 1; index <= m_dateSelector->count(); index++) { if (date >= m_dateSelector->itemData(index).toDate()) { m_dateSelector->setCurrentIndex(index); break; } } } void DolphinFacetsWidget::addSearchTag(const QString& tag) { if (tag.isEmpty() || m_searchTags.contains(tag)) { return; } m_searchTags.append(tag); m_searchTags.sort(); updateTagsSelector(); } void DolphinFacetsWidget::removeSearchTag(const QString& tag) { if (tag.isEmpty() || !m_searchTags.contains(tag)) { return; } m_searchTags.removeAll(tag); updateTagsSelector(); } void DolphinFacetsWidget::initComboBox(QComboBox* combo) { combo->setFrame(false); combo->setMinimumHeight(parentWidget()->height()); combo->setCurrentIndex(0); connect(combo, QOverload::of(&QComboBox::activated), this, &DolphinFacetsWidget::facetChanged); } void DolphinFacetsWidget::updateTagsSelector() { const bool hasListedTags = !m_tagsSelector->menu()->isEmpty(); const bool hasSelectedTags = !m_searchTags.isEmpty(); if (hasSelectedTags) { const QString tagsText = m_searchTags.join(i18nc("String list separator", ", ")); m_tagsSelector->setText(i18ncp("@action:button %2 is a list of tags", "Tag: %2", "Tags: %2",m_searchTags.count(), tagsText)); } else { m_tagsSelector->setText(i18nc("@action:button", "Add Tags")); } m_tagsSelector->setEnabled(isEnabled() && (hasListedTags || hasSelectedTags)); } void DolphinFacetsWidget::updateTagsMenu() { updateTagsMenuItems({}, {}); m_tagsLister.openUrl(QUrl(QStringLiteral("tags:/")), KCoreDirLister::OpenUrlFlag::Reload); } void DolphinFacetsWidget::updateTagsMenuItems(const QUrl&, const KFileItemList& items) { m_tagsSelector->menu()->clear(); QStringList allTags = QStringList(m_searchTags); for (const KFileItem &item: items) { allTags.append(item.name()); } allTags.sort(Qt::CaseInsensitive); allTags.removeDuplicates(); for (const QString& tagName : qAsConst(allTags)) { QAction* action = m_tagsSelector->menu()->addAction(QIcon::fromTheme(QStringLiteral("tag")), tagName); action->setCheckable(true); action->setChecked(m_searchTags.contains(tagName)); connect(action, &QAction::triggered, this, [this, tagName](bool isChecked) { if (isChecked) { addSearchTag(tagName); } else { removeSearchTag(tagName); } emit facetChanged(); m_tagsSelector->menu()->show(); }); } updateTagsSelector(); } diff --git a/src/search/dolphinquery.cpp b/src/search/dolphinquery.cpp index 95efe9162..ab107f43f 100644 --- a/src/search/dolphinquery.cpp +++ b/src/search/dolphinquery.cpp @@ -1,159 +1,157 @@ /*************************************************************************** * Copyright (C) 2019 by Ismael Asensio * * * * 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 #include #ifdef HAVE_BALOO #include #endif namespace { - /** Checks if a given term in the Baloo::Query::searchString() is a special search term. - * This is a copy of `DolphinFacetsWidget::isSearchTerm()` method. + /** 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("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) { - QString cleanedText = text; - if (!cleanedText.isEmpty() && cleanedText.at(0) == QLatin1Char('"')) { - cleanedText = cleanedText.mid(1); + if (text.length() >= 2 && text.at(0) == QLatin1Char('"') + && text.back() == QLatin1Char('"')) { + return text.mid(1, text.size() - 2); } - if (!cleanedText.isEmpty() && cleanedText.back() == QLatin1Char('"')) { - cleanedText = cleanedText.mid(0, cleanedText.size() - 1); - } - return cleanedText; + return text; } QStringList splitOutsideQuotes(const QString& text) { - const QRegularExpression subTermsRegExp("([^ ]*\"[^\"]*\"|(?<= |^)[^ ]+(?= |$))"); + const QRegularExpression subTermsRegExp("(\\S*?\"[^\"]*?\"|(?<=\\s|^)\\S+(?=\\s|$))"); auto subTermsMatchIterator = subTermsRegExp.globalMatch(text); QStringList textParts; while (subTermsMatchIterator.hasNext()) { textParts << subTermsMatchIterator.next().captured(0); } return textParts; } } 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(); const QStringList types = query.types(); model.m_fileType = types.isEmpty() ? QString() : types.first(); QStringList textParts; QString fileName; const QStringList subTerms = splitOutsideQuotes(query.searchString()); foreach (const QString& subTerm, subTerms) { - if (subTerm.startsWith(QLatin1String("filename:"))) { - fileName = stripQuotes(subTerm.mid(9)); - if (!fileName.isEmpty()) { + const QString token = searchTermToken(subTerm); + const QString value = stripQuotes(subTerm.mid(token.length())); + + if (token == QLatin1String("filename:")) { + if (!value.isEmpty()) { + fileName = value; model.m_hasFileName = true; } continue; - } else if (isSearchTerm(subTerm)) { - model.m_searchTerms << subTerm; + } else if (!token.isEmpty()) { + model.m_searchTerms << token + value; continue; } else if (subTerm == QLatin1String("AND") && subTerm != subTerms.at(0) && subTerm != subTerms.back()) { continue; - } else { - const QString cleanedTerm = stripQuotes(subTerm); - if (!cleanedTerm.isEmpty()) { - textParts << cleanedTerm; - model.m_hasContentSearch = true; - } + } else if (!value.isEmpty()) { + textParts << value; + model.m_hasContentSearch = true; } } if (model.m_hasFileName) { if (model.m_hasContentSearch) { textParts << QStringLiteral("filename:\"%1\"").arg(fileName); } else { textParts << fileName; } } model.m_searchText = textParts.join(QLatin1Char(' ')); #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; } bool DolphinQuery::hasContentSearch() const { return m_hasContentSearch; } bool DolphinQuery::hasFileName() const { return m_hasFileName; } diff --git a/src/tests/dolphinquerytest.cpp b/src/tests/dolphinquerytest.cpp index 65dc7350e..b65ee037f 100644 --- a/src/tests/dolphinquerytest.cpp +++ b/src/tests/dolphinquerytest.cpp @@ -1,163 +1,177 @@ /*************************************************************************** * Copyright (C) 2019 by Ismael Asensio * * * * 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 #include #include #include #include #include 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("abc xyz"); + const QString text = QStringLiteral("abc"); + const QString textS = QStringLiteral("abc xyz"); const QString filename = QStringLiteral("filename:\"%1\"").arg(text); + const QString filenameS = QStringLiteral("filename:\"%1\"").arg(textS); + const QString rating = QStringLiteral("rating>=2"); - const QString modified = QString("modified>=2019-08-07"); - const QString tagA = QString("tag:tagA"); - const QString tagB = QString("tag:tagB"); + const QString modified = QStringLiteral("modified>=2019-08-07"); + + const QString tag = QStringLiteral("tag:tagA"); + const QString tagS = QStringLiteral("tag:\"tagB with spaces\""); // in search url + const QString tagR = QStringLiteral("tag:tagB with spaces"); // in result term QTest::addColumn("searchString"); QTest::addColumn("expectedText"); QTest::addColumn("expectedTerms"); QTest::addColumn("hasContent"); QTest::addColumn("hasFileName"); // Test for "Content" - QTest::newRow("content") << text << text << QStringList() << true << false; - QTest::newRow("content/empty") << "" << "" << QStringList() << false << false; - QTest::newRow("content/singleQuote") << "\"" << "" << QStringList() << false << false; - QTest::newRow("content/doubleQuote") << "\"\"" << "" << QStringList() << false << false; + QTest::newRow("content") << text << text << QStringList() << true << false; + QTest::newRow("content/space") << textS << textS << QStringList() << true << false; + QTest::newRow("content/empty") << "" << "" << QStringList() << false << false; + QTest::newRow("content/single_quote") << "\"" << "\"" << QStringList() << true << false; + QTest::newRow("content/double_quote") << "\"\"" << "" << QStringList() << false << false; // Test for "FileName" - QTest::newRow("filename") << filename << text << QStringList() << false << true; - QTest::newRow("filename/empty") << "filename:" << "" << QStringList() << false << false; - QTest::newRow("filename/singleQuote") << "filename:\"" << "" << QStringList() << false << false; - QTest::newRow("filename/doubleQuote") << "filename:\"\"" << "" << QStringList() << false << false; + QTest::newRow("filename") << filename << text << QStringList() << false << true; + QTest::newRow("filename/space") << filenameS << textS << QStringList() << false << true; + QTest::newRow("filename/empty") << "filename:" << "" << QStringList() << false << false; + QTest::newRow("filename/single_quote") << "filename:\"" << "\"" << QStringList() << false << true; + QTest::newRow("filename/double_quote") << "filename:\"\"" << "" << QStringList() << false << false; // Combined content and filename search - QTest::newRow("content+filename") << text + " " + filename << text + " " + filename << QStringList() << true << true; + QTest::newRow("content+filename") + << text + " " + filename + << text + " " + filename << QStringList() << true << true; // Test for rating QTest::newRow("rating") << rating << "" << QStringList({rating}) << false << false; QTest::newRow("rating+content") << rating + " " + text << text << QStringList({rating}) << true << false; QTest::newRow("rating+filename") << rating + " " + filename << text << QStringList({rating}) << false << true; // Test for modified date QTest::newRow("modified") << modified << "" << QStringList({modified}) << false << false; QTest::newRow("modified+content") << modified + " " + text << text << QStringList({modified}) << true << false; QTest::newRow("modified+filename") << modified + " " + filename << text << QStringList({modified}) << false << true; // Test for tags - QTest::newRow("tag") << tagA << "" << QStringList({tagA}) << false << false; - QTest::newRow("tag/double") << tagA + " " + tagB << "" << QStringList({tagA, tagB}) << false << false; - QTest::newRow("tag+content") << tagA + " " + text << text << QStringList({tagA}) << true << false; - QTest::newRow("tag+filename") << tagA + " " + filename << text << QStringList({tagA}) << false << true; + QTest::newRow("tag") << tag << "" << QStringList({tag}) << false << false; + QTest::newRow("tag/space" ) << tagS << "" << QStringList({tagR}) << false << false; + QTest::newRow("tag/double") << tag + " " + tagS << "" << QStringList({tag, tagR}) << false << false; + QTest::newRow("tag+content") << tag + " " + text << text << QStringList({tag}) << true << false; + QTest::newRow("tag+filename") << tag + " " + filename << text << QStringList({tag}) << false << true; // Combined search terms - QTest::newRow("allTerms") - << rating + " AND " + modified + " AND " + tagA + " AND " + tagB - << "" << QStringList({modified, rating, tagA, tagB}) << false << false; + QTest::newRow("searchTerms") + << rating + " AND " + modified + " AND " + tag + " AND " + tagS + << "" << QStringList({modified, rating, tag, tagR}) << false << false; - QTest::newRow("allTerms+content") - << rating + " AND " + modified + " " + text + " " + tagA + " AND " + tagB - << text << QStringList({modified, rating, tagA, tagB}) << true << false; + QTest::newRow("searchTerms+content") + << rating + " AND " + modified + " " + text + " " + tag + " AND " + tagS + << text << QStringList({modified, rating, tag, tagR}) << true << false; - QTest::newRow("allTerms+filename") - << rating + " AND " + modified + " " + filename + " " + tagA + " AND " + tagB - << text << QStringList({modified, rating, tagA, tagB}) << false << true; + QTest::newRow("searchTerms+filename") + << rating + " AND " + modified + " " + filename + " " + tag + " AND " + tagS + << text << QStringList({modified, rating, tag, tagR}) << false << true; + + QTest::newRow("allTerms") + << text + " " + filename + " " + rating + " AND " + modified + " AND " + tag + << text + " " + filename << QStringList({modified, rating, tag}) << true << true; - QTest::newRow("allTerms+content+filename") - << text + " " + filename + " " + rating + " AND " + modified + " AND " + tagA + " AND " + tagB - << text + " " + filename << QStringList({modified, rating, tagA, tagB}) << true << true; + QTest::newRow("allTerms/space") + << textS + " " + filenameS + " " + rating + " AND " + modified + " AND " + tagS + << textS + " " + filenameS << QStringList({modified, rating, tagR}) << true << true; } /** * 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); QFETCH(bool, hasContent); QFETCH(bool, hasFileName); const QUrl testUrl = composeQueryUrl(searchString); const DolphinQuery query = DolphinQuery::fromBalooSearchUrl(testUrl); QStringList searchTerms = query.searchTerms(); searchTerms.sort(); // 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)); } // Check for filename and content detection QCOMPARE(query.hasContentSearch(), hasContent); QCOMPARE(query.hasFileName(), hasFileName); } QTEST_MAIN(DolphinSearchBoxTest) #include "dolphinquerytest.moc"