diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d8eb681e3..ef12fadb2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -232,6 +232,7 @@ set(autotype_SOURCES core/Tools.cpp autotype/AutoType.cpp autotype/AutoTypeAction.cpp + autotype/AutoTypeFilterLineEdit.cpp autotype/AutoTypeSelectDialog.cpp autotype/AutoTypeSelectView.cpp autotype/ShortcutWidget.cpp diff --git a/src/autotype/AutoTypeFilterLineEdit.cpp b/src/autotype/AutoTypeFilterLineEdit.cpp new file mode 100644 index 000000000..09b902e7a --- /dev/null +++ b/src/autotype/AutoTypeFilterLineEdit.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 KeePassXC Team + * + * 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 or (at your option) + * version 3 of the License. + * + * 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, see . + */ + +#include "AutoTypeFilterLineEdit.h" +#include + +void AutoTypeFilterLineEdit::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Up) { + emit keyUpPressed(); + } else if (event->key() == Qt::Key_Down) { + emit keyDownPressed(); + } else { + QLineEdit::keyPressEvent(event); + } +} + +void AutoTypeFilterLineEdit::keyReleaseEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Escape) { + emit escapeReleased(); + } else { + QLineEdit::keyReleaseEvent(event); + } +} diff --git a/src/autotype/AutoTypeFilterLineEdit.h b/src/autotype/AutoTypeFilterLineEdit.h new file mode 100644 index 000000000..7e7169816 --- /dev/null +++ b/src/autotype/AutoTypeFilterLineEdit.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 KeePassXC Team + * + * 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 or (at your option) + * version 3 of the License. + * + * 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, see . + */ + +#ifndef KEEPASSX_AUTOTYPEFILTERLINEEDIT_H +#define KEEPASSX_AUTOTYPEFILTERLINEEDIT_H + +#include + +class AutoTypeFilterLineEdit : public QLineEdit +{ + Q_OBJECT + +public: + AutoTypeFilterLineEdit(QWidget* widget) : QLineEdit(widget) {} +protected: + virtual void keyPressEvent(QKeyEvent *event); + virtual void keyReleaseEvent(QKeyEvent *event); +signals: + void keyUpPressed(); + void keyDownPressed(); + void escapeReleased(); +}; + +#endif // KEEPASSX_AUTOTYPEFILTERLINEEDIT_H diff --git a/src/autotype/AutoTypeSelectDialog.cpp b/src/autotype/AutoTypeSelectDialog.cpp index 1449f9e02..6fa3af7e1 100644 --- a/src/autotype/AutoTypeSelectDialog.cpp +++ b/src/autotype/AutoTypeSelectDialog.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include "autotype/AutoTypeSelectView.h" #include "core/AutoTypeMatch.h" @@ -38,6 +40,7 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent) : QDialog(parent) , m_view(new AutoTypeSelectView(this)) + , m_filterLineEdit(new AutoTypeFilterLineEdit(this)) , m_matchActivatedEmitted(false) , m_rejected(false) { @@ -74,11 +77,28 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent) connect(m_view, SIGNAL(rejected()), SLOT(reject())); // clang-format on + QSortFilterProxyModel *proxy = qobject_cast(m_view->model()); + if (proxy) { + proxy->setFilterKeyColumn(-1); + proxy->setFilterCaseSensitivity(Qt::CaseInsensitive); + } + layout->addWidget(m_view); + connect(m_filterLineEdit, SIGNAL(textChanged(QString)), SLOT(filterList(QString))); + connect(m_filterLineEdit, SIGNAL(returnPressed()), SLOT(activateCurrentIndex())); + connect(m_filterLineEdit, SIGNAL(keyUpPressed()), SLOT(moveSelectionUp())); + connect(m_filterLineEdit, SIGNAL(keyDownPressed()), SLOT(moveSelectionDown())); + connect(m_filterLineEdit, SIGNAL(escapeReleased()), SLOT(reject())); + + m_filterLineEdit->setPlaceholderText(tr("Search...")); + layout->addWidget(m_filterLineEdit); + QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, Qt::Horizontal, this); connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); layout->addWidget(buttonBox); + + m_filterLineEdit->setFocus(); } void AutoTypeSelectDialog::setMatchList(const QList& matchList) @@ -121,7 +141,44 @@ void AutoTypeSelectDialog::matchRemoved() return; } - if (m_view->model()->rowCount() == 0) { + if (m_view->model()->rowCount() == 0 && m_filterLineEdit->text().isEmpty()) { reject(); } } + + +void AutoTypeSelectDialog::filterList(QString filterString) +{ + QSortFilterProxyModel *proxy = qobject_cast(m_view->model()); + if (proxy) { + proxy->setFilterWildcard(filterString); + if (!m_view->currentIndex().isValid()) { + m_view->setCurrentIndex(m_view->model()->index(0, 0)); + } + } +} + +void AutoTypeSelectDialog::moveSelectionUp() +{ + auto current = m_view->currentIndex(); + auto previous = current.sibling(current.row() - 1, 0); + + if (previous.isValid()) { + m_view->setCurrentIndex(previous); + } +} + +void AutoTypeSelectDialog::moveSelectionDown() +{ + auto current = m_view->currentIndex(); + auto next = current.sibling(current.row() + 1, 0); + + if (next.isValid()) { + m_view->setCurrentIndex(next); + } +} + +void AutoTypeSelectDialog::activateCurrentIndex() +{ + emitMatchActivated(m_view->currentIndex()); +} diff --git a/src/autotype/AutoTypeSelectDialog.h b/src/autotype/AutoTypeSelectDialog.h index cee3c4087..a22218f1f 100644 --- a/src/autotype/AutoTypeSelectDialog.h +++ b/src/autotype/AutoTypeSelectDialog.h @@ -22,6 +22,7 @@ #include #include +#include "autotype/AutoTypeFilterLineEdit.h" #include "core/AutoTypeMatch.h" class AutoTypeSelectView; @@ -44,9 +45,14 @@ public slots: private slots: void emitMatchActivated(const QModelIndex& index); void matchRemoved(); + void filterList(QString filterString); + void moveSelectionUp(); + void moveSelectionDown(); + void activateCurrentIndex(); private: AutoTypeSelectView* const m_view; + AutoTypeFilterLineEdit* const m_filterLineEdit; bool m_matchActivatedEmitted; bool m_rejected; };