Commit 536f0664 authored by Waqar Ahmed's avatar Waqar Ahmed
Browse files

Allow filtering by path / name and allow changing modes on the fly

parent d26ec7ce
......@@ -86,6 +86,7 @@ target_sources(
kateviewmanager.cpp
kateviewspace.cpp
katewaiter.cpp
katequickopenlineedit.cpp
)
# Executable only adds the main definition.
......
......@@ -17,7 +17,7 @@
#include <KAboutData>
#include <KActionCollection>
#include <KLineEdit>
//#include <KLineEdit>
#include <KLocalizedString>
#include <KPluginFactory>
......@@ -45,6 +45,11 @@ public:
QuickOpenFilterProxyModel(QObject *parent = nullptr) : QSortFilterProxyModel(parent)
{}
void changeMode(FilterModes m)
{
mode = m;
}
protected:
bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override
{
......@@ -59,19 +64,30 @@ protected:
return true;
const QString fileName = sourceModel()->index(sourceRow, 0, sourceParent).data().toString();
const auto nameAndPath = fileName.splitRef(QStringLiteral("{[split]}"));
const auto name = nameAndPath.at(0);
const auto path = nameAndPath.at(1);
// match
int score1 = 0;
auto res = kfts::fuzzy_match(pattern, name, score1);
int score2 = 0;
auto res1 = kfts::fuzzy_match(pattern, path, score2);
int score = 0;
bool res = false;
if (mode == FilterMode::FilterByName) {
res = filterByName(name, score);
} else if (mode == FilterMode::FilterByPath) {
res = filterByPath(path, score);
} else {
int scorep= 0, scoren = 0;
bool resp = filterByPath(path, scorep);
bool resn = filterByName(name, scoren);
// store the score for sorting later
score = scoren + scorep;
res = resp || resn;
}
// store the score for sorting later
auto idx = sourceModel()->index(sourceRow, 0, sourceParent);
sourceModel()->setData(idx, score1 + score2, KateQuickOpenModel::Score);
sourceModel()->setData(idx, score, KateQuickOpenModel::Score);
return res || res1;
return res;
}
public Q_SLOTS:
......@@ -82,8 +98,20 @@ public Q_SLOTS:
endResetModel();
}
private:
inline bool filterByPath(const QStringRef& path, int& score) const
{
return kfts::fuzzy_match(pattern, path, score);
}
inline bool filterByName(const QStringRef& name, int& score) const
{
return kfts::fuzzy_match(pattern, name, score);
}
private:
QString pattern;
FilterModes mode;
};
class QuickOpenStyleDelegate : public QStyledItemDelegate {
......@@ -103,10 +131,17 @@ public:
QString str = index.data().toString();
auto namePath = str.split(QStringLiteral("{[split]}"));
auto name = namePath.at(0);
auto path = namePath.at(1);
kfts::to_fuzzy_matched_display_string(m_filterString, name, QStringLiteral("<b>"), QStringLiteral("</b>"));
kfts::to_fuzzy_matched_display_string(m_filterString, path, QStringLiteral("<b>"), QStringLiteral("</b>"));
QString name = namePath.at(0);
QString path = namePath.at(1);
if (mode == FilterMode::FilterByName) {
kfts::to_fuzzy_matched_display_string(m_filterString, name, QStringLiteral("<b>"), QStringLiteral("</b>"));
} else if (mode == FilterMode::FilterByPath) {
kfts::to_fuzzy_matched_display_string(m_filterString, path, QStringLiteral("<b>"), QStringLiteral("</b>"));
} else {
kfts::to_fuzzy_matched_display_string(m_filterString, name, QStringLiteral("<b>"), QStringLiteral("</b>"));
kfts::to_fuzzy_matched_display_string(m_filterString, path, QStringLiteral("<b>"), QStringLiteral("</b>"));
}
const auto pathFontsize = option.font.pointSize();
doc.setHtml(QStringLiteral("<span style=\"font-size: %1pt;\">").arg(pathFontsize + 1) + name + QStringLiteral("</span>") + QStringLiteral("<br>") + QStringLiteral("<span style=\"color: gray; font-size: %1pt;\">").arg(pathFontsize) + path + QStringLiteral("</span>"));
......@@ -131,6 +166,11 @@ public:
painter->restore();
}
void changeMode(FilterModes m)
{
mode = m;
}
public Q_SLOTS:
void setFilterString(const QString& text)
{
......@@ -139,6 +179,7 @@ public Q_SLOTS:
private:
QString m_filterString;
FilterModes mode;
// QAbstractItemDelegate interface
public:
......@@ -170,7 +211,7 @@ KateQuickOpen::KateQuickOpen(KateMainWindow *mainWindow)
layout->setContentsMargins(0, 0, 0, 0);
setLayout(layout);
m_inputLine = new KLineEdit();
m_inputLine = new QuickOpenLineEdit(this);
setFocusProxy(m_inputLine);
m_inputLine->setPlaceholderText(i18n("Quick Open Search"));
......@@ -189,13 +230,14 @@ KateQuickOpen::KateQuickOpen(KateMainWindow *mainWindow)
m_model->setSortCaseSensitivity(Qt::CaseInsensitive);
m_model->setFilterKeyColumn(Qt::DisplayRole);
QuickOpenStyleDelegate* delegate = new QuickOpenStyleDelegate(this);
m_listView->setItemDelegateForColumn(0, delegate);
m_styleDelegate = new QuickOpenStyleDelegate(this);
m_listView->setItemDelegate(m_styleDelegate);
connect(m_inputLine, &KLineEdit::textChanged, m_model, &QuickOpenFilterProxyModel::setFilterText);
connect(m_inputLine, &KLineEdit::textChanged, delegate, &QuickOpenStyleDelegate::setFilterString);
connect(m_inputLine, &KLineEdit::textChanged, this, [this](){ m_listView->viewport()->update(); });
connect(m_inputLine, &KLineEdit::returnPressed, this, &KateQuickOpen::slotReturnPressed);
connect(m_inputLine, &QuickOpenLineEdit::textChanged, m_model, &QuickOpenFilterProxyModel::setFilterText);
connect(m_inputLine, &QuickOpenLineEdit::textChanged, m_styleDelegate, &QuickOpenStyleDelegate::setFilterString);
connect(m_inputLine, &QuickOpenLineEdit::textChanged, this, [this](){ m_listView->viewport()->update(); });
connect(m_inputLine, &QuickOpenLineEdit::returnPressed, this, &KateQuickOpen::slotReturnPressed);
connect(m_inputLine, &QuickOpenLineEdit::filterModeChanged, this, &KateQuickOpen::slotfilterModeChanged);
connect(m_model, &QSortFilterProxyModel::rowsInserted, this, &KateQuickOpen::reselectFirst);
connect(m_model, &QSortFilterProxyModel::rowsRemoved, this, &KateQuickOpen::reselectFirst);
......@@ -213,6 +255,8 @@ KateQuickOpen::KateQuickOpen(KateMainWindow *mainWindow)
m_listView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHidden(true);
m_filterMode = m_inputLine->filterMode();
}
bool KateQuickOpen::eventFilter(QObject *obj, QEvent *event)
......@@ -286,6 +330,14 @@ void KateQuickOpen::slotReturnPressed()
m_inputLine->clear();
}
void KateQuickOpen::slotfilterModeChanged(FilterModes mode)
{
m_filterMode = mode;
m_model->changeMode(mode);
m_styleDelegate->changeMode(mode);
m_model->invalidate();
}
void KateQuickOpen::setListMode(KateQuickOpenModel::List mode)
{
m_base_model->setListMode(mode);
......
......@@ -10,12 +10,14 @@
#include <QWidget>
#include "katequickopenlineedit.h"
class KateMainWindow;
class KLineEdit;
class QModelIndex;
class QStandardItemModel;
class QSortFilterProxyModel;
class QuickOpenStyleDelegate;
class QTreeView;
class KateQuickOpenModel;
enum KateQuickOpenModelList : int;
......@@ -49,10 +51,14 @@ private Q_SLOTS:
*/
void slotReturnPressed();
void slotfilterModeChanged(FilterModes mode);
private:
KateMainWindow *m_mainWindow;
QTreeView *m_listView;
KLineEdit *m_inputLine;
QuickOpenLineEdit *m_inputLine;
QuickOpenStyleDelegate* m_styleDelegate;
FilterModes m_filterMode;
/**
* our model we search in
......
/* SPDX-License-Identifier: LGPL-2.0-or-later
SPDX-FileCopyrightText: 2020 Waqar Ahmed <waqar.17a@gmail.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "katequickopenlineedit.h"
#include <QStyleOptionFocusRect>
#include <QStylePainter>
#include <QtDebug>
#include <QWindow>
#include <QMenu>
SwitchModeButton::SwitchModeButton(QWidget *parent)
: QAbstractButton(parent)
{
setCursor(Qt::CursorShape::PointingHandCursor);
setFocusPolicy(Qt::NoFocus);
m_icon = QIcon::fromTheme(QStringLiteral("settings-configure"));
}
void SwitchModeButton::paintEvent(QPaintEvent *)
{
const QPixmap iconPixmap = m_icon.pixmap(sizeHint(), QIcon::Normal);
QStylePainter painter(this);
QRect pixmapRect(QPoint(0,0), iconPixmap.size() / devicePixelRatio());
pixmapRect.moveCenter(rect().center());
painter.drawPixmap(pixmapRect, iconPixmap);
}
QuickOpenLineEdit::QuickOpenLineEdit(QWidget* parent)
: QLineEdit(parent)
{
m_button = new SwitchModeButton(this);
m_menu = new QMenu(this);
auto act = m_menu->addAction(QStringLiteral("Filter By Path"));
act->setCheckable(true);
connect(act, &QAction::toggled, this, [this](bool checked){
m_mode.setFlag(FilterMode::FilterByPath, checked);
emit filterModeChanged(m_mode);
});
act->setChecked(true);
act = m_menu->addAction(QStringLiteral("Filter By Name"));
act->setCheckable(true);
connect(act, &QAction::toggled, this, [this](bool checked){
m_mode.setFlag(FilterMode::FilterByName, checked);
emit filterModeChanged(m_mode);
});
act->setChecked(true);
connect(m_button, &SwitchModeButton::clicked, this, &QuickOpenLineEdit::openMenu);
}
void QuickOpenLineEdit::updateViewGeometry()
{
QMargins margins(0, 0, m_button->sizeHint().width(), 0);
setTextMargins(margins);
auto iconOffset = textMargins().right() + 8;
m_button->setGeometry(rect().adjusted(width() - iconOffset, 0, 0, 0));
}
void QuickOpenLineEdit::resizeEvent(QResizeEvent*)
{
updateViewGeometry();
}
void QuickOpenLineEdit::openMenu()
{
m_menu->exec(QWidget::cursor().pos());
}
/* SPDX-License-Identifier: LGPL-2.0-or-later
SPDX-FileCopyrightText: 2020 Waqar Ahmed <waqar.17a@gmail.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef QUICKOPENLINEEDIT_H
#define QUICKOPENLINEEDIT_H
#include <QLineEdit>
#include <QAbstractButton>
#include <QIcon>
class SwitchModeButton : public QAbstractButton
{
public:
explicit SwitchModeButton(QWidget *parent);
QSize sizeHint() const override
{
return m_icon.actualSize(QSize(24, 24));
}
protected:
void paintEvent(QPaintEvent *) override;
private:
QIcon m_icon;
};
enum FilterMode : uint8_t
{
FilterByName = 0x01, /* By File Name */
FilterByPath = 0x02 /* By File Path */
};
Q_DECLARE_FLAGS(FilterModes, FilterMode)
Q_FLAGS(FilterModes)
class QuickOpenLineEdit : public QLineEdit
{
Q_OBJECT
public:
explicit QuickOpenLineEdit(QWidget *parent);
FilterModes filterMode()
{
return m_mode;
}
void updateViewGeometry();
protected:
void resizeEvent(QResizeEvent *event) override;
private:
SwitchModeButton* m_button;
QMenu* m_menu;
FilterModes m_mode = (FilterMode)(FilterMode::FilterByName | FilterMode::FilterByPath);
private Q_SLOTS:
void openMenu();
Q_SIGNALS:
void filterModeChanged(FilterModes mode);
};
#endif // QUICKOPENLINEEDIT_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment