┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/search/selectors
diff options
context:
space:
mode:
Diffstat (limited to 'src/search/selectors')
-rw-r--r--src/search/selectors/dateselector.cpp61
-rw-r--r--src/search/selectors/dateselector.h42
-rw-r--r--src/search/selectors/filetypeselector.cpp81
-rw-r--r--src/search/selectors/filetypeselector.h36
-rw-r--r--src/search/selectors/minimumratingselector.cpp51
-rw-r--r--src/search/selectors/minimumratingselector.h42
-rw-r--r--src/search/selectors/tagsselector.cpp189
-rw-r--r--src/search/selectors/tagsselector.h45
8 files changed, 547 insertions, 0 deletions
diff --git a/src/search/selectors/dateselector.cpp b/src/search/selectors/dateselector.cpp
new file mode 100644
index 000000000..2951b1dc4
--- /dev/null
+++ b/src/search/selectors/dateselector.cpp
@@ -0,0 +1,61 @@
+/*
+ SPDX-FileCopyrightText: 2025 Felix Ernst <[email protected]>
+
+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#include "dateselector.h"
+
+#include "../dolphinquery.h"
+
+#include <KDatePicker>
+#include <KDatePickerPopup>
+#include <KFormat>
+#include <KLocalizedString>
+
+using namespace Search;
+
+Search::DateSelector::DateSelector(std::shared_ptr<const DolphinQuery> dolphinQuery, QWidget *parent)
+ : QToolButton{parent}
+ , UpdatableStateInterface{dolphinQuery}
+ , m_datePickerPopup{
+ new KDatePickerPopup{KDatePickerPopup::NoDate | KDatePickerPopup::DatePicker | KDatePickerPopup::Words, dolphinQuery->modifiedSinceDate(), this}}
+{
+ setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ setPopupMode(QToolButton::InstantPopup);
+
+ m_datePickerPopup->setDateRange(QDate{}, QDate::currentDate());
+ connect(m_datePickerPopup, &KDatePickerPopup::dateChanged, this, [this](const QDate &activatedDate) {
+ if (activatedDate == m_searchConfiguration->modifiedSinceDate()) {
+ return; // Already selected.
+ }
+ DolphinQuery searchConfigurationCopy = *m_searchConfiguration;
+ searchConfigurationCopy.setModifiedSinceDate(activatedDate);
+ Q_EMIT configurationChanged(std::move(searchConfigurationCopy));
+ });
+ setMenu(m_datePickerPopup);
+
+ updateStateToMatch(std::move(dolphinQuery));
+}
+
+void DateSelector::removeRestriction()
+{
+ Q_ASSERT(m_searchConfiguration->modifiedSinceDate().isValid());
+ DolphinQuery searchConfigurationCopy = *m_searchConfiguration;
+ searchConfigurationCopy.setModifiedSinceDate(QDate{});
+ Q_EMIT configurationChanged(std::move(searchConfigurationCopy));
+}
+
+void DateSelector::updateState(const std::shared_ptr<const DolphinQuery> &dolphinQuery)
+{
+ m_datePickerPopup->setDate(dolphinQuery->modifiedSinceDate());
+ if (!dolphinQuery->modifiedSinceDate().isValid()) {
+ setIcon(QIcon{}); // No icon for the empty state
+ setText(i18nc("@item:inlistbox", "Any Date"));
+ return;
+ }
+ setIcon(QIcon::fromTheme(QStringLiteral("view-calendar")));
+ QLocale local;
+ KFormat formatter(local);
+ setText(formatter.formatRelativeDate(dolphinQuery->modifiedSinceDate(), QLocale::ShortFormat));
+}
diff --git a/src/search/selectors/dateselector.h b/src/search/selectors/dateselector.h
new file mode 100644
index 000000000..99cecec06
--- /dev/null
+++ b/src/search/selectors/dateselector.h
@@ -0,0 +1,42 @@
+/*
+ SPDX-FileCopyrightText: 2025 Felix Ernst <[email protected]>
+
+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#ifndef DATESELECTOR_H
+#define DATESELECTOR_H
+
+#include "../updatablestateinterface.h"
+
+#include <QToolButton>
+
+class KDatePickerPopup;
+
+namespace Search
+{
+
+class DateSelector : public QToolButton, public UpdatableStateInterface
+{
+ Q_OBJECT
+
+public:
+ explicit DateSelector(std::shared_ptr<const DolphinQuery> dolphinQuery, QWidget *parent = nullptr);
+
+ /** Causes configurationChanged() to be emitted with a DolphinQuery object that does not contain any restriction settable by this class. */
+ void removeRestriction();
+
+Q_SIGNALS:
+ /** Is emitted whenever settings have changed and a new search might be necessary. */
+ void configurationChanged(const DolphinQuery &dolphinQuery);
+
+private:
+ void updateState(const std::shared_ptr<const DolphinQuery> &dolphinQuery) override;
+
+private:
+ KDatePickerPopup *m_datePickerPopup = nullptr;
+};
+
+}
+
+#endif // DATESELECTOR_H
diff --git a/src/search/selectors/filetypeselector.cpp b/src/search/selectors/filetypeselector.cpp
new file mode 100644
index 000000000..7852aced2
--- /dev/null
+++ b/src/search/selectors/filetypeselector.cpp
@@ -0,0 +1,81 @@
+/*
+ SPDX-FileCopyrightText: 2025 Felix Ernst <[email protected]>
+
+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#include "filetypeselector.h"
+
+#include "../dolphinquery.h"
+
+#include <KFileMetaData/TypeInfo>
+#include <KLocalizedString>
+
+using namespace Search;
+
+FileTypeSelector::FileTypeSelector(std::shared_ptr<const DolphinQuery> dolphinQuery, QWidget *parent)
+ : QComboBox{parent}
+ , UpdatableStateInterface{dolphinQuery}
+{
+ for (KFileMetaData::Type::Type type = KFileMetaData::Type::FirstType; type <= KFileMetaData::Type::LastType; type = KFileMetaData::Type::Type(type + 1)) {
+ switch (type) {
+ case KFileMetaData::Type::Empty:
+ addItem(/** No icon for the empty state */ i18nc("@item:inlistbox", "Any Type"), type);
+ continue;
+ case KFileMetaData::Type::Archive:
+ addItem(QIcon::fromTheme(QStringLiteral("package-x-generic")), KFileMetaData::TypeInfo{type}.displayName(), type);
+ continue;
+ case KFileMetaData::Type::Audio:
+ addItem(QIcon::fromTheme(QStringLiteral("audio-x-generic")), KFileMetaData::TypeInfo{type}.displayName(), type);
+ continue;
+ case KFileMetaData::Type::Video:
+ addItem(QIcon::fromTheme(QStringLiteral("video-x-generic")), KFileMetaData::TypeInfo{type}.displayName(), type);
+ continue;
+ case KFileMetaData::Type::Image:
+ addItem(QIcon::fromTheme(QStringLiteral("image-x-generic")), KFileMetaData::TypeInfo{type}.displayName(), type);
+ continue;
+ case KFileMetaData::Type::Document:
+ addItem(QIcon::fromTheme(QStringLiteral("text-x-generic")), KFileMetaData::TypeInfo{type}.displayName(), type);
+ continue;
+ case KFileMetaData::Type::Spreadsheet:
+ addItem(QIcon::fromTheme(QStringLiteral("table")), KFileMetaData::TypeInfo{type}.displayName(), type);
+ continue;
+ case KFileMetaData::Type::Presentation:
+ addItem(QIcon::fromTheme(QStringLiteral("view-presentation")), KFileMetaData::TypeInfo{type}.displayName(), type);
+ continue;
+ case KFileMetaData::Type::Text:
+ addItem(QIcon::fromTheme(QStringLiteral("text-x-generic")), KFileMetaData::TypeInfo{type}.displayName(), type);
+ continue;
+ case KFileMetaData::Type::Folder:
+ addItem(QIcon::fromTheme(QStringLiteral("inode-directory")), KFileMetaData::TypeInfo{type}.displayName(), type);
+ continue;
+ default:
+ addItem(QIcon(), KFileMetaData::TypeInfo{type}.displayName(), type);
+ }
+ }
+
+ connect(this, &QComboBox::activated, this, [this](int activatedIndex) {
+ auto activatedType = itemData(activatedIndex).value<KFileMetaData::Type::Type>();
+ if (activatedType == m_searchConfiguration->fileType()) {
+ return; // Already selected.
+ }
+ DolphinQuery searchConfigurationCopy = *m_searchConfiguration;
+ searchConfigurationCopy.setFileType(activatedType);
+ Q_EMIT configurationChanged(std::move(searchConfigurationCopy));
+ });
+
+ updateStateToMatch(std::move(dolphinQuery));
+}
+
+void Search::FileTypeSelector::removeRestriction()
+{
+ Q_ASSERT(m_searchConfiguration->fileType() != KFileMetaData::Type::Empty);
+ DolphinQuery searchConfigurationCopy = *m_searchConfiguration;
+ searchConfigurationCopy.setFileType(KFileMetaData::Type::Empty);
+ Q_EMIT configurationChanged(std::move(searchConfigurationCopy));
+}
+
+void FileTypeSelector::updateState(const std::shared_ptr<const DolphinQuery> &dolphinQuery)
+{
+ setCurrentIndex(findData(dolphinQuery->fileType()));
+}
diff --git a/src/search/selectors/filetypeselector.h b/src/search/selectors/filetypeselector.h
new file mode 100644
index 000000000..bfc827344
--- /dev/null
+++ b/src/search/selectors/filetypeselector.h
@@ -0,0 +1,36 @@
+/*
+ SPDX-FileCopyrightText: 2025 Felix Ernst <[email protected]>
+
+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#ifndef FILETYPESELECTOR_H
+#define FILETYPESELECTOR_H
+
+#include "../updatablestateinterface.h"
+
+#include <QComboBox>
+
+namespace Search
+{
+
+class FileTypeSelector : public QComboBox, public UpdatableStateInterface
+{
+ Q_OBJECT
+
+public:
+ explicit FileTypeSelector(std::shared_ptr<const DolphinQuery> dolphinQuery, QWidget *parent = nullptr);
+
+ /** Causes configurationChanged() to be emitted with a DolphinQuery object that does not contain any restriction settable by this class. */
+ void removeRestriction();
+
+Q_SIGNALS:
+ /** Is emitted whenever settings have changed and a new search might be necessary. */
+ void configurationChanged(const DolphinQuery &dolphinQuery);
+
+private:
+ void updateState(const std::shared_ptr<const DolphinQuery> &dolphinQuery) override;
+};
+}
+
+#endif // FILETYPESELECTOR_H
diff --git a/src/search/selectors/minimumratingselector.cpp b/src/search/selectors/minimumratingselector.cpp
new file mode 100644
index 000000000..e46dfd4e0
--- /dev/null
+++ b/src/search/selectors/minimumratingselector.cpp
@@ -0,0 +1,51 @@
+/*
+ SPDX-FileCopyrightText: 2012 Peter Penz <[email protected]>
+ SPDX-FileCopyrightText: 2025 Felix Ernst <[email protected]>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "minimumratingselector.h"
+
+#include "../dolphinquery.h"
+
+#include <KLocalizedString>
+
+using namespace Search;
+
+MinimumRatingSelector::MinimumRatingSelector(std::shared_ptr<const DolphinQuery> dolphinQuery, QWidget *parent)
+ : QComboBox{parent}
+ , UpdatableStateInterface{dolphinQuery}
+{
+ addItem(/** No icon for the empty state */ i18nc("@item:inlistbox", "Any Rating"), 0);
+ addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "1 or more"), 2);
+ addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "2 or more"), 4);
+ addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "3 or more"), 6);
+ addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "4 or more"), 8);
+ addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox 5 star rating, has a star icon in front", "5"), 10);
+
+ connect(this, &QComboBox::activated, this, [this](int activatedIndex) {
+ auto activatedMinimumRating = itemData(activatedIndex).value<int>();
+ if (activatedMinimumRating == m_searchConfiguration->minimumRating()) {
+ return; // Already selected.
+ }
+ DolphinQuery searchConfigurationCopy = *m_searchConfiguration;
+ searchConfigurationCopy.setMinimumRating(activatedMinimumRating);
+ Q_EMIT configurationChanged(std::move(searchConfigurationCopy));
+ });
+
+ updateStateToMatch(std::move(dolphinQuery));
+}
+
+void MinimumRatingSelector::removeRestriction()
+{
+ Q_ASSERT(m_searchConfiguration->minimumRating() > 0);
+ DolphinQuery searchConfigurationCopy = *m_searchConfiguration;
+ searchConfigurationCopy.setMinimumRating(0);
+ Q_EMIT configurationChanged(std::move(searchConfigurationCopy));
+}
+
+void MinimumRatingSelector::updateState(const std::shared_ptr<const DolphinQuery> &dolphinQuery)
+{
+ setCurrentIndex(findData(dolphinQuery->minimumRating()));
+}
diff --git a/src/search/selectors/minimumratingselector.h b/src/search/selectors/minimumratingselector.h
new file mode 100644
index 000000000..02364cd1a
--- /dev/null
+++ b/src/search/selectors/minimumratingselector.h
@@ -0,0 +1,42 @@
+/*
+ SPDX-FileCopyrightText: 2025 Felix Ernst <[email protected]>
+
+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#ifndef MINIMUMRATINGSELECTOR_H
+#define MINIMUMRATINGSELECTOR_H
+
+#include "../updatablestateinterface.h"
+
+#include <QComboBox>
+
+namespace Search
+{
+
+/**
+ * @brief Select the minimum rating search results should have.
+ * Values <= 0 mean no restriction. 1 is half a star, 2 one full star, etc. 10 is typically the maximum in KDE software.
+ * Since this box only allows selecting full star ratings, the possible values are 0, 2, 4, 6, 8, 10.
+ */
+class MinimumRatingSelector : public QComboBox, public UpdatableStateInterface
+{
+ Q_OBJECT
+
+public:
+ explicit MinimumRatingSelector(std::shared_ptr<const DolphinQuery> dolphinQuery, QWidget *parent = nullptr);
+
+ /** Causes configurationChanged() to be emitted with a DolphinQuery object that does not contain any restriction settable by this class. */
+ void removeRestriction();
+
+Q_SIGNALS:
+ /** Is emitted whenever settings have changed and a new search might be necessary. */
+ void configurationChanged(const DolphinQuery &dolphinQuery);
+
+private:
+ void updateState(const std::shared_ptr<const DolphinQuery> &dolphinQuery) override;
+};
+
+}
+
+#endif // MINIMUMRATINGSELECTOR_H
diff --git a/src/search/selectors/tagsselector.cpp b/src/search/selectors/tagsselector.cpp
new file mode 100644
index 000000000..95d7ff52a
--- /dev/null
+++ b/src/search/selectors/tagsselector.cpp
@@ -0,0 +1,189 @@
+/*
+ SPDX-FileCopyrightText: 2019 Ismael Asensio <[email protected]>
+ SPDX-FileCopyrightText: 2025 Felix Ernst <[email protected]>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "tagsselector.h"
+
+#include "../dolphinquery.h"
+
+#include <KCoreDirLister>
+#include <KLocalizedString>
+#include <KProtocolInfo>
+
+#include <QMenu>
+#include <QStringList>
+
+using namespace Search;
+
+namespace
+{
+/**
+ * @brief Provides the list of tags to all TagsSelectors.
+ *
+ * This QStringList of tags populates itself. Additional tags the user is actively searching for can be added with addTag() even though we assume that no file
+ * with such a tag exists if we did not find it automatically.
+ * @note Use the tagsList() function below instead of constructing TagsList objects yourself.
+ */
+class TagsList : public QStringList, public QObject
+{
+public:
+ TagsList()
+ : QStringList{}
+ {
+ m_tagsLister->openUrl(QUrl(QStringLiteral("tags:/")), KCoreDirLister::OpenUrlFlag::Reload);
+ connect(m_tagsLister.get(), &KCoreDirLister::itemsAdded, this, [this](const QUrl &, const KFileItemList &items) {
+ for (const KFileItem &item : items) {
+ append(item.text());
+ }
+ removeDuplicates();
+ sort(Qt::CaseInsensitive);
+ });
+ };
+
+ virtual ~TagsList() = default;
+
+ void addTag(const QString &tag)
+ {
+ if (contains(tag)) {
+ return;
+ }
+ append(tag);
+ sort(Qt::CaseInsensitive);
+ };
+
+ /** Used to access to the itemsAdded signal so outside users of this class know when items were added. */
+ KCoreDirLister *tagsLister() const
+ {
+ return m_tagsLister.get();
+ };
+
+private:
+ std::unique_ptr<KCoreDirLister> m_tagsLister = std::make_unique<KCoreDirLister>();
+};
+
+/**
+ * @returns a list of all tags found since the construction of the first TagsSelector object.
+ * @note Use this function instead of constructing additional TagsList objects.
+ */
+TagsList *tagsList()
+{
+ static TagsList *g_tagsList = new TagsList;
+ return g_tagsList;
+}
+}
+
+Search::TagsSelector::TagsSelector(std::shared_ptr<const DolphinQuery> dolphinQuery, QWidget *parent)
+ : QToolButton{parent}
+ , UpdatableStateInterface{dolphinQuery}
+{
+ setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ setPopupMode(QToolButton::InstantPopup);
+
+ auto menu = new QMenu{this};
+ setMenu(menu);
+ connect(menu, &QMenu::aboutToShow, this, [this]() {
+ TagsList *tags = tagsList();
+ // The TagsList might not have been updated for a while and new tags might be available. We update now, but this is unfortunately not instant.
+ // However this selector is connected to the itemsAdded() signal, so we will add any new tags eventually.
+ tags->tagsLister()->updateDirectory(tags->tagsLister()->url());
+ updateMenu(m_searchConfiguration);
+ });
+
+ TagsList *tags = tagsList();
+ if (tags->isEmpty()) {
+ // Either there really are no tags or the TagsList has not loaded the tags yet. It only begins loading the first time tagsList() is globally called.
+ setEnabled(false);
+ connect(
+ tags->tagsLister(),
+ &KCoreDirLister::itemsAdded,
+ this,
+ [this]() {
+ setEnabled(true);
+ },
+ Qt::SingleShotConnection);
+ }
+
+ connect(tags->tagsLister(), &KCoreDirLister::itemsAdded, this, [this, menu]() {
+ if (menu->isVisible()) {
+ updateMenu(m_searchConfiguration);
+ }
+ });
+
+ updateStateToMatch(std::move(dolphinQuery));
+}
+
+void TagsSelector::removeRestriction()
+{
+ Q_ASSERT(!m_searchConfiguration->requiredTags().isEmpty());
+ DolphinQuery searchConfigurationCopy = *m_searchConfiguration;
+ searchConfigurationCopy.setRequiredTags({});
+ Q_EMIT configurationChanged(std::move(searchConfigurationCopy));
+}
+
+void TagsSelector::updateMenu(const std::shared_ptr<const DolphinQuery> &dolphinQuery)
+{
+ if (!KProtocolInfo::isKnownProtocol(QStringLiteral("tags"))) {
+ return;
+ }
+ const bool menuWasVisible = menu()->isVisible();
+ if (menuWasVisible) {
+ menu()->hide(); // The menu needs to be hidden now, then updated, and then shown again.
+ }
+ // Delete all existing actions in the menu
+ for (QAction *action : menu()->actions()) {
+ action->deleteLater();
+ }
+ menu()->clear();
+ // Populate the menu
+ const TagsList *tags = tagsList();
+ const bool onlyOneTagExists = tags->count() == 1;
+
+ for (const QString &tag : *tags) {
+ QAction *tagAction = new QAction{QIcon::fromTheme(QStringLiteral("tag")), tag, menu()};
+ tagAction->setCheckable(true);
+ tagAction->setChecked(dolphinQuery->requiredTags().contains(tag));
+ connect(tagAction, &QAction::triggered, this, [this, tag, onlyOneTagExists](bool checked) {
+ QStringList requiredTags = m_searchConfiguration->requiredTags();
+ if (checked == requiredTags.contains(tag)) {
+ return; // Already selected.
+ }
+ if (checked) {
+ requiredTags.append(tag);
+ } else {
+ requiredTags.removeOne(tag);
+ }
+ DolphinQuery searchConfigurationCopy = *m_searchConfiguration;
+ searchConfigurationCopy.setRequiredTags(requiredTags);
+ Q_EMIT configurationChanged(std::move(searchConfigurationCopy));
+
+ if (!onlyOneTagExists) {
+ // Keep the menu open to allow easier tag multi-selection.
+ menu()->show();
+ }
+ });
+ menu()->addAction(tagAction);
+ }
+ if (menuWasVisible) {
+ menu()->show();
+ }
+}
+
+void TagsSelector::updateState(const std::shared_ptr<const DolphinQuery> &dolphinQuery)
+{
+ if (dolphinQuery->requiredTags().count()) {
+ setIcon(QIcon::fromTheme(QStringLiteral("tag")));
+ setText(dolphinQuery->requiredTags().join(i18nc("list separator for file tags e.g. all images tagged 'family & party & 2025'", " && ")));
+ } else {
+ setIcon(QIcon{}); // No icon for the empty state
+ setText(i18nc("@action:button Required tags for search results: None", "None"));
+ }
+ for (const auto &tag : dolphinQuery->requiredTags()) {
+ tagsList()->addTag(tag); // We add it just in case this tag is not (or no longer) available on the system. This way the UI always works as expected.
+ }
+ if (menu()->isVisible()) {
+ updateMenu(dolphinQuery);
+ }
+}
diff --git a/src/search/selectors/tagsselector.h b/src/search/selectors/tagsselector.h
new file mode 100644
index 000000000..386cbb924
--- /dev/null
+++ b/src/search/selectors/tagsselector.h
@@ -0,0 +1,45 @@
+/*
+ SPDX-FileCopyrightText: 2019 Ismael Asensio <[email protected]>
+ SPDX-FileCopyrightText: 2025 Felix Ernst <[email protected]>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifndef TAGSSELECTOR_H
+#define TAGSSELECTOR_H
+
+#include "../updatablestateinterface.h"
+
+#include <QToolButton>
+
+namespace Search
+{
+
+class TagsSelector : public QToolButton, public UpdatableStateInterface
+{
+ Q_OBJECT
+
+public:
+ explicit TagsSelector(std::shared_ptr<const DolphinQuery> dolphinQuery, QWidget *parent = nullptr);
+
+ /** Causes configurationChanged() to be emitted with a DolphinQuery object that does not contain any restriction settable by this class. */
+ void removeRestriction();
+
+Q_SIGNALS:
+ /** Is emitted whenever settings have changed and a new search might be necessary. */
+ void configurationChanged(const DolphinQuery &dolphinQuery);
+
+private:
+ /**
+ * Updates the menu items for the various tags based on @p dolphinQuery and the available tags.
+ * This method should only be called when the menu is QMenu::aboutToShow() or the menu is currently visible already while this selector's state changes.
+ * If the menu is open when this method is called, the menu will automatically be reopened to reflect the updated contents.
+ */
+ void updateMenu(const std::shared_ptr<const DolphinQuery> &dolphinQuery);
+
+ void updateState(const std::shared_ptr<const DolphinQuery> &dolphinQuery) override;
+};
+
+}
+
+#endif // TAGSSELECTOR_H