┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dolphinviewcontainer.cpp18
-rw-r--r--src/dolphinviewcontainer.h10
-rw-r--r--src/filterbar/filterbar.cpp100
-rw-r--r--src/filterbar/filterbar.h22
-rw-r--r--src/kitemviews/kfileitemmodel.cpp28
-rw-r--r--src/kitemviews/kfileitemmodel.h6
-rw-r--r--src/kitemviews/private/kfileitemmodelfilter.cpp62
-rw-r--r--src/kitemviews/private/kfileitemmodelfilter.h36
-rw-r--r--src/views/dolphinview.cpp20
-rw-r--r--src/views/dolphinview.h13
10 files changed, 293 insertions, 22 deletions
diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp
index 5c054eab8..4d7472ed3 100644
--- a/src/dolphinviewcontainer.cpp
+++ b/src/dolphinviewcontainer.cpp
@@ -110,6 +110,8 @@ DolphinViewContainer::DolphinViewContainer(const QUrl &url, QWidget *parent)
m_filterBar->setVisible(GeneralSettings::filterBar(), WithoutAnimation);
connect(m_filterBar, &FilterBar::filterChanged, this, &DolphinViewContainer::setNameFilter);
+ connect(m_filterBar, &FilterBar::filterModeChanged, this, &DolphinViewContainer::setFilterMode);
+ connect(m_filterBar, &FilterBar::caseSensitiveChanged, this, &DolphinViewContainer::setFilterCaseSensitive);
connect(m_filterBar, &FilterBar::closeRequest, this, &DolphinViewContainer::closeFilterBar);
connect(m_filterBar, &FilterBar::focusViewRequest, this, &DolphinViewContainer::requestFocus);
@@ -208,6 +210,10 @@ DolphinViewContainer::DolphinViewContainer(const QUrl &url, QWidget *parent)
connect(placesModel, &KFilePlacesModel::rowsRemoved, this, &DolphinViewContainer::slotPlacesModelChanged);
QApplication::instance()->installEventFilter(this);
+
+ // Update the view with the current state of the filter bar (from the state config)
+ m_view->setFilterMode(m_filterBar->filterMode());
+ m_view->setFilterCaseSensitive(m_filterBar->isCaseSensitive());
}
DolphinViewContainer::~DolphinViewContainer() = default;
@@ -867,6 +873,18 @@ void DolphinViewContainer::setNameFilter(const QString &nameFilter)
delayedStatusBarUpdate();
}
+void DolphinViewContainer::setFilterMode(const KFileItemModelFilter::FilterMode mode)
+{
+ m_view->setFilterMode(mode);
+ delayedStatusBarUpdate();
+}
+
+void DolphinViewContainer::setFilterCaseSensitive(const bool caseSensitive)
+{
+ m_view->setFilterCaseSensitive(caseSensitive);
+ delayedStatusBarUpdate();
+}
+
void DolphinViewContainer::activate()
{
setActive(true);
diff --git a/src/dolphinviewcontainer.h b/src/dolphinviewcontainer.h
index 3829a4f78..f7ec01885 100644
--- a/src/dolphinviewcontainer.h
+++ b/src/dolphinviewcontainer.h
@@ -372,6 +372,16 @@ private Q_SLOTS:
void setNameFilter(const QString &nameFilter);
/**
+ * Set the filtering mode of the filter.
+ */
+ void setFilterMode(const KFileItemModelFilter::FilterMode mode);
+
+ /**
+ * Enable or disable the case sensitive filtering.
+ */
+ void setFilterCaseSensitive(const bool caseSensitive);
+
+ /**
* Marks the view container as active
* (see DolphinViewContainer::setActive()).
*/
diff --git a/src/filterbar/filterbar.cpp b/src/filterbar/filterbar.cpp
index 6cb8d5e2a..08bff24fc 100644
--- a/src/filterbar/filterbar.cpp
+++ b/src/filterbar/filterbar.cpp
@@ -2,18 +2,25 @@
* SPDX-FileCopyrightText: 2006-2010 Peter Penz <[email protected]>
* SPDX-FileCopyrightText: 2006 Gregor Kališnik <[email protected]>
* SPDX-FileCopyrightText: 2012 Stuart Citrin <[email protected]>
+ * SPDX-FileCopyrightText: 2026 Alessio Bonfiglio <[email protected]>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "filterbar.h"
+#include <KConfigGroup>
#include <KLocalizedString>
+#include <KSharedConfig>
+#include <KColorScheme>
+#include <QAction>
#include <QApplication>
+#include <QComboBox>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QLineEdit>
+#include <QPalette>
#include <QToolButton>
FilterBar::FilterBar(QWidget *parent)
@@ -35,8 +42,35 @@ FilterBar::FilterBar(QWidget *parent)
m_filterInput->setClearButtonEnabled(true);
m_filterInput->setPlaceholderText(i18n("Filter…"));
connect(m_filterInput, &QLineEdit::textChanged, this, &FilterBar::filterChanged);
+ connect(m_filterInput, &QLineEdit::textChanged, this, &FilterBar::updateInvalidPatternView);
setFocusProxy(m_filterInput);
+ m_invalidPatternAction = new QAction(m_filterInput);
+ m_invalidPatternAction->setCheckable(false);
+ m_invalidPatternAction->setIcon(QIcon::fromTheme(QStringLiteral("error-symbolic")));
+ m_invalidPatternAction->setToolTip(i18n("Invalid expression"));
+ m_filterInput->addAction(m_invalidPatternAction, QLineEdit::TrailingPosition);
+ m_invalidPatternAction->setVisible(false);
+
+ // Create case sensitive button
+ m_caseSensitiveButton = new QToolButton(contentsContainer);
+ m_caseSensitiveButton->setAutoRaise(true);
+ m_caseSensitiveButton->setCheckable(true);
+ m_caseSensitiveButton->setIcon(QIcon::fromTheme(QStringLiteral("format-text-superscript"), QIcon::fromTheme(QStringLiteral("format-text-bold"))));
+ m_caseSensitiveButton->setToolTip(i18nc("@info:tooltip", "Match case"));
+ connect(m_caseSensitiveButton, &QToolButton::toggled, this, &FilterBar::caseSensitiveChanged);
+ connect(m_caseSensitiveButton, &QToolButton::toggled, this, &FilterBar::updateInvalidPatternView);
+
+ // Create filter mode combobox
+ m_filterModeComboBox = new QComboBox(contentsContainer);
+ m_filterModeComboBox->addItem(i18nc("@item:inlistbox", "Plain Text"), KFileItemModelFilter::FilterMode::PlainText);
+ m_filterModeComboBox->addItem(i18nc("@item:inlistbox", "Glob Pattern"), KFileItemModelFilter::FilterMode::Glob);
+ m_filterModeComboBox->addItem(i18nc("@item:inlistbox", "Regular Expression"), KFileItemModelFilter::FilterMode::Regex);
+ connect(m_filterModeComboBox, &QComboBox::currentIndexChanged, this, [this](int index) {
+ Q_EMIT filterModeChanged(m_filterModeComboBox->itemData(index).value<KFileItemModelFilter::FilterMode>());
+ });
+ connect(m_filterModeComboBox, &QComboBox::currentIndexChanged, this, &FilterBar::updateInvalidPatternView);
+
// Create close button
QToolButton *closeButton = new QToolButton(contentsContainer);
closeButton->setAutoRaise(true);
@@ -49,13 +83,25 @@ FilterBar::FilterBar(QWidget *parent)
hLayout->setContentsMargins(0, 0, 0, 0);
hLayout->addWidget(m_lockButton);
hLayout->addWidget(m_filterInput);
+ hLayout->addWidget(m_caseSensitiveButton);
+ hLayout->addWidget(m_filterModeComboBox);
hLayout->addWidget(closeButton);
- setTabOrder(m_lockButton, closeButton);
- setTabOrder(closeButton, m_filterInput);
+ setTabOrder({m_lockButton, m_caseSensitiveButton, m_filterModeComboBox, closeButton, m_filterInput});
+
+ KConfigGroup filterBarConfig(KSharedConfig::openStateConfig(), QStringLiteral("FilterBar"));
+ bool caseSensitiveEnabled = filterBarConfig.readEntry("caseSensitive", false);
+ int filterModeComboBoxIndex = filterBarConfig.readEntry("filterMode", m_filterModeComboBox->findData(KFileItemModelFilter::FilterMode::Glob));
+ m_caseSensitiveButton->setChecked(caseSensitiveEnabled);
+ m_filterModeComboBox->setCurrentIndex(filterModeComboBoxIndex);
}
-FilterBar::~FilterBar() = default;
+FilterBar::~FilterBar()
+{
+ KConfigGroup filterBarConfig(KSharedConfig::openStateConfig(), QStringLiteral("FilterBar"));
+ filterBarConfig.writeEntry("caseSensitive", this->m_caseSensitiveButton->isChecked());
+ filterBarConfig.writeEntry("filterMode", this->m_filterModeComboBox->currentIndex());
+}
void FilterBar::closeFilterBar()
{
@@ -71,6 +117,16 @@ void FilterBar::selectAll()
m_filterInput->selectAll();
}
+KFileItemModelFilter::FilterMode FilterBar::filterMode() const
+{
+ return m_filterModeComboBox->itemData(m_filterModeComboBox->currentIndex()).value<KFileItemModelFilter::FilterMode>();
+}
+
+bool FilterBar::isCaseSensitive() const
+{
+ return m_caseSensitiveButton->isChecked();
+}
+
void FilterBar::clear()
{
m_filterInput->clear();
@@ -93,6 +149,39 @@ void FilterBar::slotToggleLockButton(bool checked)
}
}
+void FilterBar::updateInvalidPatternView()
+{
+ bool valid = true;
+
+ KFileItemModelFilter::FilterMode current_filter_mode = filterMode();
+ if (current_filter_mode != KFileItemModelFilter::FilterMode::PlainText) {
+ QRegularExpression regExp = QRegularExpression();
+ QString pattern = m_filterInput->text();
+
+ QRegularExpression::PatternOptions options =
+ m_caseSensitiveButton->isChecked() ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption;
+ if (current_filter_mode == KFileItemModelFilter::FilterMode::Regex) {
+ regExp.setPattern(pattern);
+ regExp.setPatternOptions(options);
+ } else if (current_filter_mode == KFileItemModelFilter::FilterMode::Glob) {
+ regExp.setPattern(QRegularExpression::wildcardToRegularExpression(pattern, QRegularExpression::UnanchoredWildcardConversion));
+ regExp.setPatternOptions(options);
+ }
+
+ valid = regExp.isValid();
+ }
+
+ if (valid) {
+ m_filterInput->setPalette(QPalette());
+ m_invalidPatternAction->setVisible(false);
+ } else {
+ auto pal = m_filterInput->palette();
+ KColorScheme::adjustBackground(pal, KColorScheme::NegativeBackground);
+ m_filterInput->setPalette(pal);
+ m_invalidPatternAction->setVisible(true);
+ }
+}
+
void FilterBar::showEvent(QShowEvent *event)
{
if (!event->spontaneous()) {
@@ -137,7 +226,10 @@ void FilterBar::keyPressEvent(QKeyEvent *event)
int FilterBar::preferredHeight() const
{
- return std::max(m_filterInput->sizeHint().height(), m_lockButton->sizeHint().height());
+ return std::max({m_filterInput->sizeHint().height(),
+ m_lockButton->sizeHint().height(),
+ m_caseSensitiveButton->sizeHint().height(),
+ m_filterModeComboBox->sizeHint().height()});
}
#include "moc_filterbar.cpp"
diff --git a/src/filterbar/filterbar.h b/src/filterbar/filterbar.h
index 1424f4cb8..924c6dba3 100644
--- a/src/filterbar/filterbar.h
+++ b/src/filterbar/filterbar.h
@@ -10,9 +10,12 @@
#define FILTERBAR_H
#include "animatedheightwidget.h"
+#include "kitemviews/private/kfileitemmodelfilter.h"
class QLineEdit;
class QToolButton;
+class QComboBox;
+class QAction;
/**
* @brief Provides an input field for filtering the currently shown items.
@@ -35,6 +38,9 @@ public:
*/
void selectAll();
+ KFileItemModelFilter::FilterMode filterMode() const;
+ bool isCaseSensitive() const;
+
public Q_SLOTS:
/** Clears the input field. */
void clear();
@@ -51,6 +57,16 @@ Q_SIGNALS:
void filterChanged(const QString &nameFilter);
/**
+ * Emitted when the case sensitive mode has been changed
+ */
+ void caseSensitiveChanged(bool caseSensitive);
+
+ /**
+ * Emitted when the filter mode has been changed
+ */
+ void filterModeChanged(KFileItemModelFilter::FilterMode mode);
+
+ /**
* Emitted as soon as the filterbar should get closed.
*/
void closeRequest();
@@ -70,6 +86,12 @@ protected:
private:
QLineEdit *m_filterInput;
QToolButton *m_lockButton;
+ QToolButton *m_caseSensitiveButton;
+ QComboBox *m_filterModeComboBox;
+ QAction *m_invalidPatternAction;
+
+ /** Enable or disable the alterative view for when a pattern is invalid */
+ void updateInvalidPatternView();
};
#endif
diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp
index c8bac0b9d..1f291d40c 100644
--- a/src/kitemviews/kfileitemmodel.cpp
+++ b/src/kitemviews/kfileitemmodel.cpp
@@ -817,6 +817,34 @@ QStringList KFileItemModel::mimeTypeFilters() const
return m_filter.mimeTypes();
}
+void KFileItemModel::setFilterMode(KFileItemModelFilter::FilterMode mode)
+{
+ if (m_filter.filterMode() != mode) {
+ dispatchPendingItemsToInsert();
+ m_filter.setFilterMode(mode);
+ applyFilters();
+ }
+}
+
+KFileItemModelFilter::FilterMode KFileItemModel::filterMode() const
+{
+ return m_filter.filterMode();
+}
+
+void KFileItemModel::setFilterCaseSensitive(bool caseSensitive)
+{
+ if (m_filter.isCaseSensitive() != caseSensitive) {
+ dispatchPendingItemsToInsert();
+ m_filter.setCaseSensitive(caseSensitive);
+ applyFilters();
+ }
+}
+
+bool KFileItemModel::isFilterCaseSensitive() const
+{
+ return m_filter.isCaseSensitive();
+}
+
void KFileItemModel::setExcludeMimeTypeFilter(const QStringList &filters)
{
if (m_filter.excludeMimeTypes() != filters) {
diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h
index 3749b0c1b..2a6e710c3 100644
--- a/src/kitemviews/kfileitemmodel.h
+++ b/src/kitemviews/kfileitemmodel.h
@@ -184,6 +184,12 @@ public:
void setMimeTypeFilters(const QStringList &filters);
QStringList mimeTypeFilters() const;
+ void setFilterMode(KFileItemModelFilter::FilterMode mode);
+ KFileItemModelFilter::FilterMode filterMode() const;
+
+ void setFilterCaseSensitive(bool caseSensitive);
+ bool isFilterCaseSensitive() const;
+
void setExcludeMimeTypeFilter(const QStringList &filters);
QStringList excludeMimeTypeFilter() const;
diff --git a/src/kitemviews/private/kfileitemmodelfilter.cpp b/src/kitemviews/private/kfileitemmodelfilter.cpp
index 45c62e7ca..48d2f6276 100644
--- a/src/kitemviews/private/kfileitemmodelfilter.cpp
+++ b/src/kitemviews/private/kfileitemmodelfilter.cpp
@@ -13,7 +13,8 @@
#include <KFileItem>
KFileItemModelFilter::KFileItemModelFilter()
- : m_useRegExp(false)
+ : m_filterMode(Glob)
+ , m_caseSensitive(false)
, m_regExp(nullptr)
, m_lowerCasePattern()
, m_pattern()
@@ -31,16 +32,29 @@ void KFileItemModelFilter::setPattern(const QString &filter)
m_pattern = filter;
m_lowerCasePattern = filter.toLower();
- if (filter.contains(QLatin1Char('*')) || filter.contains(QLatin1Char('?')) || filter.contains(QLatin1Char('['))) {
- if (!m_regExp) {
- m_regExp = new QRegularExpression();
- m_regExp->setPatternOptions(QRegularExpression::CaseInsensitiveOption);
- }
- m_regExp->setPattern(QRegularExpression::wildcardToRegularExpression(filter));
- m_useRegExp = m_regExp->isValid();
- } else {
- m_useRegExp = false;
- }
+ updateFilter();
+}
+
+void KFileItemModelFilter::setFilterMode(FilterMode mode)
+{
+ m_filterMode = mode;
+ updateFilter();
+}
+
+KFileItemModelFilter::FilterMode KFileItemModelFilter::filterMode() const
+{
+ return m_filterMode;
+}
+
+void KFileItemModelFilter::setCaseSensitive(bool caseSensitive)
+{
+ m_caseSensitive = caseSensitive;
+ updateFilter();
+}
+
+bool KFileItemModelFilter::isCaseSensitive() const
+{
+ return m_caseSensitive;
}
QString KFileItemModelFilter::pattern() const
@@ -48,6 +62,26 @@ QString KFileItemModelFilter::pattern() const
return m_pattern;
}
+void KFileItemModelFilter::updateFilter()
+{
+ if (m_filterMode == PlainText) {
+ return;
+ }
+
+ if (!m_regExp) {
+ m_regExp = new QRegularExpression();
+ }
+
+ QRegularExpression::PatternOptions options = m_caseSensitive ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption;
+ if (m_filterMode == Regex) {
+ m_regExp->setPattern(m_pattern);
+ m_regExp->setPatternOptions(options);
+ } else if (m_filterMode == Glob) {
+ m_regExp->setPattern(QRegularExpression::wildcardToRegularExpression(m_pattern, QRegularExpression::UnanchoredWildcardConversion));
+ m_regExp->setPatternOptions(options);
+ }
+}
+
void KFileItemModelFilter::setMimeTypes(const QStringList &types)
{
m_mimeTypes = types;
@@ -98,8 +132,10 @@ bool KFileItemModelFilter::matches(const KFileItem &item) const
bool KFileItemModelFilter::matchesPattern(const KFileItem &item) const
{
- if (m_useRegExp) {
- return m_regExp->match(item.text()).hasMatch();
+ if (m_filterMode == Glob || m_filterMode == Regex) {
+ return m_regExp->isValid() && m_regExp->match(item.text()).hasMatch();
+ } else if (m_caseSensitive) {
+ return item.text().contains(m_pattern);
} else {
return item.text().toLower().contains(m_lowerCasePattern);
}
diff --git a/src/kitemviews/private/kfileitemmodelfilter.h b/src/kitemviews/private/kfileitemmodelfilter.h
index ce6cbeebb..9d93d42cc 100644
--- a/src/kitemviews/private/kfileitemmodelfilter.h
+++ b/src/kitemviews/private/kfileitemmodelfilter.h
@@ -28,16 +28,36 @@ public:
KFileItemModelFilter();
virtual ~KFileItemModelFilter();
+ /** Filtering modes of KFileItemModelFilter */
+ enum FilterMode {
+ /** Substring matching. */
+ PlainText = 0,
+ /** Matching with glob, default. */
+ Glob,
+ /** Matching with regex. */
+ Regex
+ };
+
/**
* Sets the pattern that is used for a comparison with the item
- * in KFileItemModelFilter::matches(). Per default the pattern
- * defines a sub-string. As soon as the pattern contains at least
- * a '*', '?' or '[' the pattern represents a regular expression.
+ * in KFileItemModelFilter::matches().
*/
void setPattern(const QString &pattern);
QString pattern() const;
/**
+ * Sets the filtering mode used in KFileItemModelFilter::matches().
+ */
+ void setFilterMode(FilterMode mode);
+ FilterMode filterMode() const;
+
+ /**
+ * Enable or disable the case sensitive filtering.
+ */
+ void setCaseSensitive(bool caseSensitive);
+ bool isCaseSensitive() const;
+
+ /**
* Set the list of mimetypes that are used for comparison with the
* item in KFileItemModelFilter::matchesMimeType.
*/
@@ -73,8 +93,14 @@ private:
*/
bool matchesType(const KFileItem &item) const;
- bool m_useRegExp; // If true, m_regExp is used for filtering,
- // otherwise m_lowerCaseFilter is used.
+ /**
+ * Instantiate and configure m_regExp according to m_filterMode and m_caseSensitive.
+ */
+ void updateFilter();
+
+ FilterMode m_filterMode; // The current filtering mode.
+ bool m_caseSensitive; // If true the matching will be case sensitive.
+
QRegularExpression *m_regExp;
QString m_lowerCasePattern; // Lowercase version of m_filter for
// faster comparison in matches().
diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp
index b48e1ae74..2213e2c82 100644
--- a/src/views/dolphinview.cpp
+++ b/src/views/dolphinview.cpp
@@ -639,6 +639,26 @@ QStringList DolphinView::mimeTypeFilters() const
return m_model->mimeTypeFilters();
}
+void DolphinView::setFilterMode(KFileItemModelFilter::FilterMode mode)
+{
+ m_model->setFilterMode(mode);
+}
+
+KFileItemModelFilter::FilterMode DolphinView::filterMode() const
+{
+ return m_model->filterMode();
+}
+
+void DolphinView::setFilterCaseSensitive(bool caseSensitive)
+{
+ m_model->setFilterCaseSensitive(caseSensitive);
+}
+
+bool DolphinView::isFilterCaseSensitive() const
+{
+ return m_model->isFilterCaseSensitive();
+}
+
void DolphinView::requestStatusBarText()
{
if (m_statJobForStatusBarText) {
diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h
index 67233b668..6aa5b595d 100644
--- a/src/views/dolphinview.h
+++ b/src/views/dolphinview.h
@@ -10,6 +10,7 @@
#include "dolphin_export.h"
#include "dolphintabwidget.h"
+#include "kitemviews/private/kfileitemmodelfilter.h"
#include "tooltips/tooltipmanager.h"
#include "config-dolphin.h"
@@ -277,6 +278,18 @@ public:
QStringList mimeTypeFilters() const;
/**
+ * Sets the filtering mode of the currently used nameFilter.
+ */
+ void setFilterMode(KFileItemModelFilter::FilterMode mode);
+ KFileItemModelFilter::FilterMode filterMode() const;
+
+ /**
+ * Enables or disable the caseSensitive matching of the currently used nameFilter.
+ */
+ void setFilterCaseSensitive(bool caseSensitive);
+ bool isFilterCaseSensitive() const;
+
+ /**
* Tells the view to generate an updated status bar text. The result
* is returned through the statusBarTextChanged(QString statusBarText) signal.
* It will carry a textual representation of the state of the current