2 * SPDX-FileCopyrightText: 2012 Peter Penz <peter.penz19@gmail.com>
3 * SPDX-FileCopyrightText: 2019 Ismael Asensio <isma.af@mgmail.com>
5 * SPDX-License-Identifier: GPL-2.0-or-later
8 #include "dolphinfacetswidget.h"
10 #include <KLocalizedString>
11 #include <KProtocolInfo>
16 #include <QHBoxLayout>
19 #include <QToolButton>
21 DolphinFacetsWidget::DolphinFacetsWidget(QWidget
*parent
)
23 , m_typeSelector(nullptr)
24 , m_dateSelector(nullptr)
25 , m_ratingSelector(nullptr)
26 , m_tagsSelector(nullptr)
28 m_typeSelector
= new QComboBox(this);
29 m_typeSelector
->addItem(QIcon::fromTheme(QStringLiteral("none")), i18nc("@item:inlistbox", "Any Type"), QString());
30 m_typeSelector
->addItem(QIcon::fromTheme(QStringLiteral("inode-directory")), i18nc("@item:inlistbox", "Folders"), QStringLiteral("Folder"));
31 m_typeSelector
->addItem(QIcon::fromTheme(QStringLiteral("text-x-generic")), i18nc("@item:inlistbox", "Documents"), QStringLiteral("Document"));
32 m_typeSelector
->addItem(QIcon::fromTheme(QStringLiteral("image-x-generic")), i18nc("@item:inlistbox", "Images"), QStringLiteral("Image"));
33 m_typeSelector
->addItem(QIcon::fromTheme(QStringLiteral("audio-x-generic")), i18nc("@item:inlistbox", "Audio Files"), QStringLiteral("Audio"));
34 m_typeSelector
->addItem(QIcon::fromTheme(QStringLiteral("video-x-generic")), i18nc("@item:inlistbox", "Videos"), QStringLiteral("Video"));
35 initComboBox(m_typeSelector
);
37 const QDate currentDate
= QDate::currentDate();
39 m_dateSelector
= new QComboBox(this);
40 m_dateSelector
->addItem(QIcon::fromTheme(QStringLiteral("view-calendar")), i18nc("@item:inlistbox", "Any Date"), QDate());
41 m_dateSelector
->addItem(QIcon::fromTheme(QStringLiteral("go-jump-today")), i18nc("@item:inlistbox", "Today"), currentDate
);
42 m_dateSelector
->addItem(QIcon::fromTheme(QStringLiteral("go-jump-today")), i18nc("@item:inlistbox", "Yesterday"), currentDate
.addDays(-1));
43 m_dateSelector
->addItem(QIcon::fromTheme(QStringLiteral("view-calendar-week")),
44 i18nc("@item:inlistbox", "This Week"),
45 currentDate
.addDays(1 - currentDate
.dayOfWeek()));
46 m_dateSelector
->addItem(QIcon::fromTheme(QStringLiteral("view-calendar-month")),
47 i18nc("@item:inlistbox", "This Month"),
48 currentDate
.addDays(1 - currentDate
.day()));
49 m_dateSelector
->addItem(QIcon::fromTheme(QStringLiteral("view-calendar-year")),
50 i18nc("@item:inlistbox", "This Year"),
51 currentDate
.addDays(1 - currentDate
.dayOfYear()));
52 initComboBox(m_dateSelector
);
54 m_ratingSelector
= new QComboBox(this);
55 m_ratingSelector
->addItem(QIcon::fromTheme(QStringLiteral("non-starred-symbolic")), i18nc("@item:inlistbox", "Any Rating"), 0);
56 m_ratingSelector
->addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "1 or more"), 1);
57 m_ratingSelector
->addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "2 or more"), 2);
58 m_ratingSelector
->addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "3 or more"), 3);
59 m_ratingSelector
->addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "4 or more"), 4);
60 m_ratingSelector
->addItem(QIcon::fromTheme(QStringLiteral("starred-symbolic")), i18nc("@item:inlistbox", "Highest Rating"), 5);
61 initComboBox(m_ratingSelector
);
63 m_clearTagsAction
= new QAction(QIcon::fromTheme(QStringLiteral("edit-clear-all")), i18nc("@action:inmenu", "Clear Selection"), this);
64 connect(m_clearTagsAction
, &QAction::triggered
, this, [this]() {
66 Q_EMIT
facetChanged();
69 m_tagsSelector
= new QToolButton(this);
70 m_tagsSelector
->setIcon(QIcon::fromTheme(QStringLiteral("tag")));
71 m_tagsSelector
->setMenu(new QMenu(this));
72 m_tagsSelector
->setToolButtonStyle(Qt::ToolButtonTextBesideIcon
);
73 m_tagsSelector
->setPopupMode(QToolButton::MenuButtonPopup
);
74 m_tagsSelector
->setAutoRaise(true);
77 connect(m_tagsSelector
, &QToolButton::clicked
, m_tagsSelector
, &QToolButton::showMenu
);
78 connect(m_tagsSelector
->menu(), &QMenu::aboutToShow
, this, &DolphinFacetsWidget::updateTagsMenu
);
79 connect(&m_tagsLister
, &KCoreDirLister::itemsAdded
, this, &DolphinFacetsWidget::updateTagsMenuItems
);
82 QHBoxLayout
*topLayout
= new QHBoxLayout(this);
83 topLayout
->setContentsMargins(0, 0, 0, 0);
84 topLayout
->addWidget(m_typeSelector
);
85 topLayout
->addWidget(m_dateSelector
);
86 topLayout
->addWidget(m_ratingSelector
);
87 topLayout
->addWidget(m_tagsSelector
);
92 DolphinFacetsWidget::~DolphinFacetsWidget()
96 void DolphinFacetsWidget::changeEvent(QEvent
*event
)
98 if (event
->type() == QEvent::EnabledChange
) {
100 updateTagsSelector();
107 QSize
DolphinFacetsWidget::minimumSizeHint() const
109 return QSize(0, m_typeSelector
->minimumHeight());
112 void DolphinFacetsWidget::resetSearchTerms()
114 m_typeSelector
->setCurrentIndex(0);
115 m_dateSelector
->setCurrentIndex(0);
116 m_ratingSelector
->setCurrentIndex(0);
121 QStringList
DolphinFacetsWidget::searchTerms() const
125 if (m_ratingSelector
->currentIndex() > 0) {
126 const int rating
= m_ratingSelector
->currentData().toInt() * 2;
127 terms
<< QStringLiteral("rating>=%1").arg(rating
);
130 if (m_dateSelector
->currentIndex() > 0) {
131 const QDate date
= m_dateSelector
->currentData().toDate();
132 terms
<< QStringLiteral("modified>=%1").arg(date
.toString(Qt::ISODate
));
135 if (!m_searchTags
.isEmpty()) {
136 for (auto const &tag
: m_searchTags
) {
137 if (tag
.contains(QLatin1Char(' '))) {
138 terms
<< QStringLiteral("tag:\"%1\"").arg(tag
);
140 terms
<< QStringLiteral("tag:%1").arg(tag
);
148 QString
DolphinFacetsWidget::facetType() const
150 return m_typeSelector
->currentData().toString();
153 bool DolphinFacetsWidget::isSearchTerm(const QString
&term
) const
155 static const QLatin1String searchTokens
[]{QLatin1String("modified>="), QLatin1String("rating>="), QLatin1String("tag:"), QLatin1String("tag=")};
157 for (const auto &searchToken
: searchTokens
) {
158 if (term
.startsWith(searchToken
)) {
165 void DolphinFacetsWidget::setSearchTerm(const QString
&term
)
167 if (term
.startsWith(QLatin1String("modified>="))) {
168 const QString value
= term
.mid(10);
169 const QDate date
= QDate::fromString(value
, Qt::ISODate
);
171 } else if (term
.startsWith(QLatin1String("rating>="))) {
172 const QString value
= term
.mid(8);
173 const int stars
= value
.toInt() / 2;
175 } else if (term
.startsWith(QLatin1String("tag:")) || term
.startsWith(QLatin1String("tag="))) {
176 const QString value
= term
.mid(4);
181 void DolphinFacetsWidget::setFacetType(const QString
&type
)
183 for (int index
= 0; index
<= m_typeSelector
->count(); index
++) {
184 if (type
== m_typeSelector
->itemData(index
).toString()) {
185 m_typeSelector
->setCurrentIndex(index
);
191 void DolphinFacetsWidget::setRating(const int stars
)
193 if (stars
< 0 || stars
> 5) {
196 m_ratingSelector
->setCurrentIndex(stars
);
199 void DolphinFacetsWidget::setTimespan(const QDate
&date
)
201 if (!date
.isValid()) {
204 m_dateSelector
->setCurrentIndex(0);
205 for (int index
= 1; index
<= m_dateSelector
->count(); index
++) {
206 if (date
>= m_dateSelector
->itemData(index
).toDate()) {
207 m_dateSelector
->setCurrentIndex(index
);
213 void DolphinFacetsWidget::addSearchTag(const QString
&tag
)
215 if (tag
.isEmpty() || m_searchTags
.contains(tag
)) {
218 m_searchTags
.append(tag
);
220 updateTagsSelector();
223 void DolphinFacetsWidget::removeSearchTag(const QString
&tag
)
225 if (tag
.isEmpty() || !m_searchTags
.contains(tag
)) {
228 m_searchTags
.removeAll(tag
);
229 updateTagsSelector();
232 void DolphinFacetsWidget::resetSearchTags()
234 m_searchTags
= QStringList();
235 updateTagsSelector();
239 void DolphinFacetsWidget::initComboBox(QComboBox
*combo
)
241 combo
->setFrame(false);
242 combo
->setMinimumHeight(parentWidget()->height());
243 combo
->setCurrentIndex(0);
244 connect(combo
, &QComboBox::activated
, this, &DolphinFacetsWidget::facetChanged
);
247 void DolphinFacetsWidget::updateTagsSelector()
249 const bool hasListedTags
= !m_tagsSelector
->menu()->isEmpty();
250 const bool hasSelectedTags
= !m_searchTags
.isEmpty();
252 if (hasSelectedTags
) {
253 const QString tagsText
= m_searchTags
.join(i18nc("String list separator", ", "));
254 m_tagsSelector
->setText(i18ncp("@action:button %2 is a list of tags", "Tag: %2", "Tags: %2", m_searchTags
.count(), tagsText
));
256 m_tagsSelector
->setText(i18nc("@action:button", "Add Tags"));
259 m_tagsSelector
->setEnabled(isEnabled() && (hasListedTags
|| hasSelectedTags
));
260 m_clearTagsAction
->setEnabled(hasSelectedTags
);
263 void DolphinFacetsWidget::updateTagsMenu()
265 updateTagsMenuItems({}, {});
266 if (KProtocolInfo::isKnownProtocol(QStringLiteral("tags"))) {
267 m_tagsLister
.openUrl(QUrl(QStringLiteral("tags:/")), KCoreDirLister::OpenUrlFlag::Reload
);
271 void DolphinFacetsWidget::updateTagsMenuItems(const QUrl
&, const KFileItemList
&items
)
273 QMenu
*tagsMenu
= m_tagsSelector
->menu();
276 QStringList allTags
= QStringList(m_searchTags
);
277 for (const KFileItem
&item
: items
) {
278 allTags
.append(item
.name());
280 allTags
.sort(Qt::CaseInsensitive
);
281 allTags
.removeDuplicates();
283 const bool onlyOneTag
= allTags
.count() == 1;
285 for (const QString
&tagName
: qAsConst(allTags
)) {
286 QAction
*action
= tagsMenu
->addAction(QIcon::fromTheme(QStringLiteral("tag")), tagName
);
287 action
->setCheckable(true);
288 action
->setChecked(m_searchTags
.contains(tagName
));
290 connect(action
, &QAction::triggered
, this, [this, tagName
, onlyOneTag
](bool isChecked
) {
292 addSearchTag(tagName
);
294 removeSearchTag(tagName
);
296 Q_EMIT
facetChanged();
299 m_tagsSelector
->menu()->show();
304 if (allTags
.count() > 1) {
305 tagsMenu
->addSeparator();
306 tagsMenu
->addAction(m_clearTagsAction
);
309 updateTagsSelector();
312 #include "moc_dolphinfacetswidget.cpp"