X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/006f667ab14aff2d067373e7e88bde4800b2d9c2..bfc177d3d1bc5a4a241e35d59086e4824e7c0bd3:/src/search/dolphinfacetswidget.cpp diff --git a/src/search/dolphinfacetswidget.cpp b/src/search/dolphinfacetswidget.cpp index b7315a01c..da36caa36 100644 --- a/src/search/dolphinfacetswidget.cpp +++ b/src/search/dolphinfacetswidget.cpp @@ -1,197 +1,312 @@ -/*************************************************************************** -* Copyright (C) 2012 by Peter Penz * -* * -* 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 * -* **************************************************************************/ +/* + * SPDX-FileCopyrightText: 2012 Peter Penz + * SPDX-FileCopyrightText: 2019 Ismael Asensio + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ #include "dolphinfacetswidget.h" -#include -#include -#include +#include +#include + +#include #include -#include +#include #include -#include - -DolphinFacetsWidget::DolphinFacetsWidget(QWidget* parent) : - QWidget(parent), - m_documents(0), - m_images(0), - m_audio(0), - m_videos(0), - m_anytime(0), - m_today(0), - m_yesterday(0), - m_thisWeek(0), - m_thisMonth(0), - m_thisYear(0), - m_anyRating(0), - m_oneOrMore(0), - m_twoOrMore(0), - m_threeOrMore(0), - m_fourOrMore(0), - m_maxRating(0) -{ - m_documents = createCheckBox(i18nc("@option:check", "Documents")); - m_images = createCheckBox(i18nc("@option:check", "Images")); - m_audio = createCheckBox(i18nc("@option:check", "Audio Files")); - m_videos = createCheckBox(i18nc("@option:check", "Videos")); - - QVBoxLayout* typeLayout = new QVBoxLayout(); - typeLayout->setSpacing(0); - typeLayout->addWidget(m_documents); - typeLayout->addWidget(m_images); - typeLayout->addWidget(m_audio); - typeLayout->addWidget(m_videos); - typeLayout->addStretch(); - - QButtonGroup* timespanGroup = new QButtonGroup(this); - m_anytime = createRadioButton(i18nc("@option:option", "Anytime"), timespanGroup); - m_today = createRadioButton(i18nc("@option:option", "Today"), timespanGroup); - m_yesterday = createRadioButton(i18nc("@option:option", "Yesterday"), timespanGroup); - m_thisWeek = createRadioButton(i18nc("@option:option", "This Week"), timespanGroup); - m_thisMonth = createRadioButton(i18nc("@option:option", "This Month"), timespanGroup); - m_thisYear = createRadioButton(i18nc("@option:option", "This Year"), timespanGroup); - - QVBoxLayout* timespanLayout = new QVBoxLayout(); - timespanLayout->setSpacing(0); - timespanLayout->addWidget(m_anytime); - timespanLayout->addWidget(m_today); - timespanLayout->addWidget(m_yesterday); - timespanLayout->addWidget(m_thisWeek); - timespanLayout->addWidget(m_thisMonth); - timespanLayout->addWidget(m_thisYear); - timespanLayout->addStretch(); - - QButtonGroup* ratingGroup = new QButtonGroup(this); - m_anyRating = createRadioButton(i18nc("@option:option", "Any Rating"), ratingGroup); - m_oneOrMore = createRadioButton(i18nc("@option:option", "1 or more"), ratingGroup); - m_twoOrMore = createRadioButton(i18nc("@option:option", "2 or more"), ratingGroup); - m_threeOrMore = createRadioButton(i18nc("@option:option", "3 or more"), ratingGroup); - m_fourOrMore = createRadioButton(i18nc("@option:option", "4 or more"), ratingGroup); - m_maxRating = createRadioButton(i18nc("@option:option", "Highest Rating"), ratingGroup); - - QVBoxLayout* ratingLayout = new QVBoxLayout(); - ratingLayout->setSpacing(0); - ratingLayout->addWidget(m_anyRating); - ratingLayout->addWidget(m_oneOrMore); - ratingLayout->addWidget(m_twoOrMore); - ratingLayout->addWidget(m_threeOrMore); - ratingLayout->addWidget(m_fourOrMore); - ratingLayout->addWidget(m_maxRating); - - QHBoxLayout* topLayout = new QHBoxLayout(this); - topLayout->addLayout(typeLayout); - topLayout->addLayout(timespanLayout); - topLayout->addLayout(ratingLayout); - topLayout->addStretch(); - - m_anytime->setChecked(true); - m_anyRating->setChecked(true); +#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_clearTagsAction = new QAction(QIcon::fromTheme(QStringLiteral("edit-clear-all")), i18nc("@action:inmenu", "Clear Selection"), this); + connect(m_clearTagsAction, &QAction::triggered, this, [this]() { + resetSearchTags(); + Q_EMIT facetChanged(); + }); + + 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() { } -#ifdef HAVE_BALOO -Baloo::Term DolphinFacetsWidget::ratingTerm() const +void DolphinFacetsWidget::changeEvent(QEvent *event) { - if (!m_anyRating->isChecked()) { - int stars = 1; // represents m_oneOrMore - if (m_twoOrMore->isChecked()) { - stars = 2; - } else if (m_threeOrMore->isChecked()) { - stars = 3; - } else if (m_fourOrMore->isChecked()) { - stars = 4; - } else if (m_maxRating->isChecked()) { - stars = 5; + if (event->type() == QEvent::EnabledChange) { + if (isEnabled()) { + updateTagsSelector(); + } else { + resetSearchTerms(); } + } +} + +QSize DolphinFacetsWidget::minimumSizeHint() const +{ + return QSize(0, m_typeSelector->minimumHeight()); +} + +void DolphinFacetsWidget::resetSearchTerms() +{ + m_typeSelector->setCurrentIndex(0); + m_dateSelector->setCurrentIndex(0); + m_ratingSelector->setCurrentIndex(0); - const int rating = stars * 2; + resetSearchTags(); +} - Baloo::Term term("rating", rating, Baloo::Term::GreaterEqual); - return term; +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); } - return Baloo::Term(); + if (m_dateSelector->currentIndex() > 0) { + const QDate date = m_dateSelector->currentData().toDate(); + terms << QStringLiteral("modified>=%1").arg(date.toString(Qt::ISODate)); + } - /* - // FIXME: Handle date time filters - if (!m_anytime->isChecked()) { - QDate date = QDate::currentDate(); // represents m_today - if (m_yesterday->isChecked()) { - date = date.addDays(-1); - } else if (m_thisWeek->isChecked()) { - date = date.addDays(1 - date.dayOfWeek()); - } else if (m_thisMonth->isChecked()) { - date = date.addDays(1 - date.day()); - } else if (m_thisYear->isChecked()) { - date = date.addDays(1 - date.dayOfYear()); + if (!m_searchTags.isEmpty()) { + for (auto const &tag : m_searchTags) { + 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; +} - Nepomuk2::Query::ComparisonTerm term(Nepomuk2::Vocabulary::NIE::lastModified(), - Nepomuk2::Query::LiteralTerm(QDateTime(date)), - Nepomuk2::Query::ComparisonTerm::GreaterOrEqual); - andTerm.addSubTerm(term); +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); } - */ } -QStringList DolphinFacetsWidget::facetTypes() const +void DolphinFacetsWidget::setFacetType(const QString &type) { - QStringList types; - if (m_documents->isChecked()) { - types << "Document"; + for (int index = 0; index <= m_typeSelector->count(); index++) { + if (type == m_typeSelector->itemData(index).toString()) { + m_typeSelector->setCurrentIndex(index); + break; + } } +} - if (m_images->isChecked()) { - types << "Image"; +void DolphinFacetsWidget::setRating(const int stars) +{ + if (stars < 0 || stars > 5) { + return; } + m_ratingSelector->setCurrentIndex(stars); +} - if (m_audio->isChecked()) { - types << "Audio"; +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; + } } +} - if (m_videos->isChecked()) { - types << "Video"; +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::resetSearchTags() +{ + m_searchTags = QStringList(); + updateTagsSelector(); + updateTagsMenu(); +} - return types; +void DolphinFacetsWidget::initComboBox(QComboBox *combo) +{ + combo->setFrame(false); + combo->setMinimumHeight(parentWidget()->height()); + combo->setCurrentIndex(0); + connect(combo, &QComboBox::activated, this, &DolphinFacetsWidget::facetChanged); } -#endif +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")); + } -QCheckBox* DolphinFacetsWidget::createCheckBox(const QString& text) + m_tagsSelector->setEnabled(isEnabled() && (hasListedTags || hasSelectedTags)); + m_clearTagsAction->setEnabled(hasSelectedTags); +} + +void DolphinFacetsWidget::updateTagsMenu() { - QCheckBox* checkBox = new QCheckBox(text); - connect(checkBox, SIGNAL(clicked()), this, SIGNAL(facetChanged())); - return checkBox; + updateTagsMenuItems({}, {}); + if (KProtocolInfo::isKnownProtocol(QStringLiteral("tags"))) { + m_tagsLister.openUrl(QUrl(QStringLiteral("tags:/")), KCoreDirLister::OpenUrlFlag::Reload); + } } -QRadioButton* DolphinFacetsWidget::createRadioButton(const QString& text, - QButtonGroup* group) +void DolphinFacetsWidget::updateTagsMenuItems(const QUrl &, const KFileItemList &items) { - QRadioButton* button = new QRadioButton(text); - connect(button, SIGNAL(clicked()), this, SIGNAL(facetChanged())); - group->addButton(button); - return button; + QMenu *tagsMenu = m_tagsSelector->menu(); + tagsMenu->clear(); + + QStringList allTags = QStringList(m_searchTags); + for (const KFileItem &item : items) { + allTags.append(item.name()); + } + allTags.sort(Qt::CaseInsensitive); + allTags.removeDuplicates(); + + const bool onlyOneTag = allTags.count() == 1; + + for (const QString &tagName : std::as_const(allTags)) { + QAction *action = tagsMenu->addAction(QIcon::fromTheme(QStringLiteral("tag")), tagName); + action->setCheckable(true); + action->setChecked(m_searchTags.contains(tagName)); + + connect(action, &QAction::triggered, this, [this, tagName, onlyOneTag](bool isChecked) { + if (isChecked) { + addSearchTag(tagName); + } else { + removeSearchTag(tagName); + } + Q_EMIT facetChanged(); + + if (!onlyOneTag) { + m_tagsSelector->menu()->show(); + } + }); + } + + if (allTags.count() > 1) { + tagsMenu->addSeparator(); + tagsMenu->addAction(m_clearTagsAction); + } + + updateTagsSelector(); } -#include "dolphinfacetswidget.moc" +#include "moc_dolphinfacetswidget.cpp"