Commit d7f2aa6d authored by Waqar Ahmed's avatar Waqar Ahmed
Browse files

Improve the UI for quick-open

The UI for quick-open is now smaller, takes 1 / 3 of the editor
window. Both path and file name are taken into account when filtering
for a match by default now.
parent c98b06a5
......@@ -100,22 +100,10 @@ void KateConfigDialog::addBehaviorPage()
buttonGroup = new QGroupBox(i18n("&Quick Open"), generalFrame);
vbox = new QVBoxLayout;
buttonGroup->setLayout(vbox);
// quick open match mode
auto hlayout = new QHBoxLayout;
auto label = new QLabel(i18n("&Match Mode:"), buttonGroup);
hlayout->addWidget(label);
m_cmbQuickOpenMatchMode = new QComboBox(buttonGroup);
hlayout->addWidget(m_cmbQuickOpenMatchMode);
label->setBuddy(m_cmbQuickOpenMatchMode);
m_cmbQuickOpenMatchMode->addItem(i18n("Filename"), QVariant(KateQuickOpenModel::Columns::FileName));
m_cmbQuickOpenMatchMode->addItem(i18n("Filepath"), QVariant(KateQuickOpenModel::Columns::FilePath));
m_cmbQuickOpenMatchMode->setCurrentIndex(m_cmbQuickOpenMatchMode->findData(m_mainWindow->quickOpenMatchMode()));
m_mainWindow->setQuickOpenMatchMode(m_cmbQuickOpenMatchMode->currentData().toInt());
connect(m_cmbQuickOpenMatchMode, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &KateConfigDialog::slotChanged);
vbox->addLayout(hlayout);
// quick open list mode
hlayout = new QHBoxLayout;
label = new QLabel(i18n("&List Mode:"), buttonGroup);
auto hlayout = new QHBoxLayout;
auto label = new QLabel(i18n("&List Mode:"), buttonGroup);
hlayout->addWidget(label);
m_cmbQuickOpenListMode = new QComboBox(buttonGroup);
hlayout->addWidget(m_cmbQuickOpenListMode);
......@@ -360,9 +348,6 @@ void KateConfigDialog::slotApply()
cg.writeEntry("Close After Last", sessionConfigUi.modCloseAfterLast->isChecked());
m_mainWindow->setModCloseAfterLast(sessionConfigUi.modCloseAfterLast->isChecked());
cg.writeEntry("Quick Open Search Mode", m_cmbQuickOpenMatchMode->currentData().toInt());
m_mainWindow->setQuickOpenMatchMode(m_cmbQuickOpenMatchMode->currentData().toInt());
cg.writeEntry("Quick Open List Mode", m_cmbQuickOpenListMode->currentData().toInt());
m_mainWindow->setQuickOpenListMode(static_cast<KateQuickOpenModel::List>(m_cmbQuickOpenListMode->currentData().toInt()));
......
......@@ -79,7 +79,6 @@ private:
bool m_dataChanged = false;
QCheckBox *m_modNotifications;
QComboBox *m_cmbQuickOpenMatchMode;
QComboBox *m_cmbQuickOpenListMode;
QSpinBox *m_tabLimit;
QCheckBox *m_showTabCloseButton;
......
......@@ -266,8 +266,7 @@ void KateMainWindow::setupMainWindow()
centralWidget()->layout()->addWidget(m_mainStackedWidget);
(static_cast<QBoxLayout *>(centralWidget()->layout()))->setStretchFactor(m_mainStackedWidget, 100);
m_quickOpen = new KateQuickOpen(m_mainStackedWidget, this);
m_mainStackedWidget->addWidget(m_quickOpen);
m_quickOpen = new KateQuickOpen(this);
m_viewManager = new KateViewManager(m_mainStackedWidget, this);
m_mainStackedWidget->addWidget(m_viewManager);
......@@ -606,7 +605,6 @@ void KateMainWindow::readOptions()
m_paShowMenuBar->setChecked(generalGroup.readEntry("Show Menu Bar", true));
m_paShowTabBar->setChecked(generalGroup.readEntry("Show Tab Bar", true));
m_quickOpen->setMatchMode(generalGroup.readEntry("Quick Open Search Mode", static_cast<int>(KateQuickOpenModel::Columns::FileName)));
int listMode = generalGroup.readEntry("Quick Open List Mode", static_cast<int>(KateQuickOpenModel::List::CurrentProject));
m_quickOpen->setListMode(static_cast<KateQuickOpenModel::List>(listMode));
......@@ -1129,6 +1127,7 @@ void KateMainWindow::queueModifiedOnDisc(KTextEditor::Document *doc)
if (!m_modNotification) {
return;
}
KateDocumentInfo *docInfo = KateApp::self()->documentManager()->documentInfo(doc);
if (!docInfo) {
return;
......@@ -1198,22 +1197,11 @@ void KateMainWindow::slotFocusNextTab()
void KateMainWindow::slotQuickOpen()
{
/**
* toggle back to view manager when when quick open is already shown
*/
if (m_mainStackedWidget->currentWidget() == m_quickOpen) {
m_mainStackedWidget->setCurrentWidget(m_viewManager);
centralWidget()->setFocusProxy(m_viewManager);
return;
}
/**
* show quick open and pass focus to it
*/
m_quickOpen->update();
m_mainStackedWidget->setCurrentWidget(m_quickOpen);
centralWidget()->setFocusProxy(m_quickOpen);
m_quickOpen->setFocus();
}
QWidget *KateMainWindow::createToolView(KTextEditor::Plugin *plugin, const QString &identifier, KTextEditor::MainWindow::ToolViewPosition pos, const QIcon &icon, const QString &text)
......@@ -1248,16 +1236,6 @@ bool KateMainWindow::hideToolView(QWidget *widget)
return KateMDI::MainWindow::hideToolView(qobject_cast<KateMDI::ToolView *>(widget));
}
void KateMainWindow::setQuickOpenMatchMode(int mode)
{
m_quickOpen->setMatchMode(mode);
}
int KateMainWindow::quickOpenMatchMode()
{
return m_quickOpen->matchMode();
}
void KateMainWindow::setQuickOpenListMode(KateQuickOpenModel::List mode)
{
m_quickOpen->setListMode(mode);
......
......@@ -296,9 +296,6 @@ public:
m_modCloseAfterLast = e;
}
void setQuickOpenMatchMode(int mode);
int quickOpenMatchMode();
void setQuickOpenListMode(KateQuickOpenModelList mode);
KateQuickOpenModelList quickOpenListMode() const;
......
......@@ -58,16 +58,20 @@ protected:
if (pattern.isEmpty())
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 score = 0;
auto res = kfts::fuzzy_match(pattern, fileName, score);
int score1 = 0;
auto res = kfts::fuzzy_match(pattern, name, score1);
int score2 = 0;
auto res1 = kfts::fuzzy_match(pattern, path, score2);
// store the score for sorting later
auto idx = sourceModel()->index(sourceRow, 0, sourceParent);
sourceModel()->setData(idx, score, KateQuickOpenModel::Score);
sourceModel()->setData(idx, score1 + score2, KateQuickOpenModel::Score);
return res;
return res || res1;
}
public Q_SLOTS:
......@@ -98,9 +102,14 @@ public:
QString str = index.data().toString();
kfts::to_fuzzy_matched_display_string(m_filterString, str, QStringLiteral("<b>"), QStringLiteral("</b>"));
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>"));
doc.setHtml(str);
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>"));
doc.setDocumentMargin(2);
painter->save();
......@@ -116,7 +125,7 @@ public:
options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter, options.widget);
// draw text
painter->translate(option.rect.x(), option.rect.y());
painter->translate(option.rect.x() + 5, option.rect.y());
doc.drawContents(painter);
painter->restore();
......@@ -130,12 +139,30 @@ public Q_SLOTS:
private:
QString m_filterString;
// QAbstractItemDelegate interface
public:
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
QSize size = this->QStyledItemDelegate::sizeHint(option, index);
static int height = -1;
if (height > -1) {
size.setHeight(height);
return size;
}
QFontMetrics metrics(option.font);
QRect outRect = metrics.boundingRect(QRect(QPoint(0, 0), size), Qt::AlignLeft, option.text);
height = outRect.height() * 2 + 4;
size.setHeight(outRect.height() * 2 + 4);
return size;
}
};
Q_DECLARE_METATYPE(QPointer<KTextEditor::Document>)
KateQuickOpen::KateQuickOpen(QWidget *parent, KateMainWindow *mainWindow)
: QWidget(parent)
KateQuickOpen::KateQuickOpen(KateMainWindow *mainWindow)
: QWidget(mainWindow)
, m_mainWindow(mainWindow)
{
QVBoxLayout *layout = new QVBoxLayout();
......@@ -173,6 +200,7 @@ KateQuickOpen::KateQuickOpen(QWidget *parent, KateMainWindow *mainWindow)
connect(m_model, &QSortFilterProxyModel::rowsRemoved, this, &KateQuickOpen::reselectFirst);
connect(m_listView, &QTreeView::activated, this, &KateQuickOpen::slotReturnPressed);
connect(m_listView, &QTreeView::clicked, this, &KateQuickOpen::slotReturnPressed); // for single click
m_listView->setModel(m_model);
m_listView->setSortingEnabled(true);
......@@ -182,6 +210,9 @@ KateQuickOpen::KateQuickOpen(QWidget *parent, KateMainWindow *mainWindow)
m_listView->installEventFilter(this);
m_listView->setHeaderHidden(true);
m_listView->setRootIsDecorated(false);
m_listView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHidden(true);
}
bool KateQuickOpen::eventFilter(QObject *obj, QEvent *event)
......@@ -200,6 +231,7 @@ bool KateQuickOpen::eventFilter(QObject *obj, QEvent *event)
m_mainWindow->slotWindowActivated();
m_inputLine->clear();
keyEvent->accept();
hide();
return true;
}
} else {
......@@ -216,6 +248,7 @@ bool KateQuickOpen::eventFilter(QObject *obj, QEvent *event)
else if (event->type() == QEvent::FocusOut && !(m_inputLine->hasFocus() || m_listView->hasFocus())) {
m_mainWindow->slotWindowActivated();
m_inputLine->clear();
hide();
return true;
}
......@@ -237,27 +270,22 @@ void KateQuickOpen::update()
m_base_model->refresh();
m_listView->resizeColumnToContents(0);
reselectFirst();
updateViewGeometry();
show();
setFocus();
}
void KateQuickOpen::slotReturnPressed()
{
const auto index = m_listView->model()->index(m_listView->currentIndex().row(), KateQuickOpenModel::Columns::FilePath);
const auto index = m_listView->model()->index(m_listView->currentIndex().row(), 0);
auto url = index.data(Qt::UserRole).toUrl();
m_mainWindow->wrapper()->openUrl(url);
hide();
m_mainWindow->slotWindowActivated();
m_inputLine->clear();
}
void KateQuickOpen::setMatchMode(int mode)
{
m_model->setFilterKeyColumn(mode);
}
int KateQuickOpen::matchMode()
{
return m_model->filterKeyColumn();
}
void KateQuickOpen::setListMode(KateQuickOpenModel::List mode)
{
m_base_model->setListMode(mode);
......@@ -267,3 +295,37 @@ KateQuickOpenModel::List KateQuickOpen::listMode() const
{
return m_base_model->listMode();
}
void KateQuickOpen::updateViewGeometry()
{
QWidget *window = m_mainWindow->window();
const QSize centralSize = window->size();
// width: 1/3 of editor, height: 1/2 of editor
const QSize viewMaxSize(centralSize.width() / 3, centralSize.height() / 2);
const int rowHeight = m_listView->sizeHintForRow(0) == -1 ? 0 : m_listView->sizeHintForRow(0);
int frameWidth = this->frameSize().width();
frameWidth = frameWidth > centralSize.width() / 3 ? centralSize.width() / 3 : frameWidth;
const int width = viewMaxSize.width();
const QSize viewSize(width,
std::min(std::max(rowHeight * m_base_model->rowCount() + 2 * frameWidth, rowHeight * 6), viewMaxSize.height()));
// Position should be central over the editor area, so map to global from
// parent of central widget since the view is positioned in global coords
const QPoint centralWidgetPos = window->parentWidget() ? window->mapToGlobal(window->pos()) : window->pos();
const int xPos = std::max(0, centralWidgetPos.x() + (centralSize.width() - viewSize.width()) / 2);
const int yPos = std::max(0, centralWidgetPos.y() + (centralSize.height() - viewSize.height()) * 1 / 4);
move(xPos, yPos);
QPointer<QPropertyAnimation> animation = new QPropertyAnimation(this, "size");
animation->setDuration(150);
animation->setStartValue(this->size());
animation->setEndValue(viewSize);
animation->start();
}
......@@ -26,16 +26,13 @@ class KateQuickOpen : public QWidget
{
Q_OBJECT
public:
KateQuickOpen(QWidget *parent, KateMainWindow *mainWindow);
KateQuickOpen(KateMainWindow *mainWindow);
/**
* update state
* will fill model with current open documents, project documents, ...
*/
void update();
int matchMode();
void setMatchMode(int mode);
KateQuickOpenModelList listMode() const;
void setListMode(KateQuickOpenModelList mode);
......@@ -65,6 +62,7 @@ private:
* filtered model we search in
*/
QuickOpenFilterProxyModel *m_model;
void updateViewGeometry();
};
#endif
......@@ -31,7 +31,7 @@ int KateQuickOpenModel::rowCount(const QModelIndex &parent) const
int KateQuickOpenModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 2;
return 1;
}
QVariant KateQuickOpenModel::data(const QModelIndex &idx, int role) const
......@@ -48,9 +48,7 @@ QVariant KateQuickOpenModel::data(const QModelIndex &idx, int role) const
if (role == Qt::DisplayRole) {
switch (idx.column()) {
case Columns::FileName:
return entry.fileName;
case Columns::FilePath:
return entry.filePath;
return QString(entry.fileName + QStringLiteral("{[split]}") + entry.filePath);
}
} else if (role == Qt::FontRole) {
if (entry.bold) {
......@@ -73,7 +71,19 @@ void KateQuickOpenModel::refresh()
const QList<KTextEditor::View *> sortedViews = m_mainWindow->viewManager()->sortedViews();
const QList<KTextEditor::Document *> openDocs = KateApp::self()->documentManager()->documentList();
const QStringList projectDocs = projectView ? (m_listMode == CurrentProject ? projectView->property("projectFiles") : projectView->property("allProjectsFiles")).toStringList() : QStringList();
const QString projectBase = projectView ? (m_listMode == CurrentProject ? projectView->property("projectBaseDir") : projectView->property("allProjectsCommonBaseDir")).toString() + QStringLiteral("/") : QString();
const QString projectBase = [this, projectView]() -> QString {
if (!projectView)
return QString();
QString ret;
if (m_listMode == CurrentProject) {
ret = projectView->property("projectBaseDir").toString();
} else {
ret = projectView->property("allProjectsCommonBaseDir").toString();
}
if (!ret.endsWith(QLatin1Char('/')))
ret.append(QLatin1Char('/'));
return ret;
}();
QVector<ModelEntry> allDocuments;
allDocuments.reserve(sortedViews.size() + openDocs.size() + projectDocs.size());
......
......@@ -34,7 +34,7 @@ public:
enum Columns : int { FileName, FilePath, Bold };
enum Role { Score = Qt::UserRole + 1 };
explicit KateQuickOpenModel(KateMainWindow *mainWindow, QObject *parent = nullptr);
int rowCount(const QModelIndex &parent) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &idx, int role) const override;
void refresh();
......
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