mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-02-17 13:02:49 -05:00
Merge pull request #132 from keepassxreboot/improve_search_ui
Improve UI of the search edit widget
This commit is contained in:
commit
5b04e195b0
@ -385,6 +385,11 @@ void DatabaseWidget::deleteEntries()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DatabaseWidget::setFocus()
|
||||||
|
{
|
||||||
|
m_entryView->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
void DatabaseWidget::copyTitle()
|
void DatabaseWidget::copyTitle()
|
||||||
{
|
{
|
||||||
Entry* currentEntry = m_entryView->currentEntry();
|
Entry* currentEntry = m_entryView->currentEntry();
|
||||||
|
@ -116,6 +116,7 @@ public Q_SLOTS:
|
|||||||
void createEntry();
|
void createEntry();
|
||||||
void cloneEntry();
|
void cloneEntry();
|
||||||
void deleteEntries();
|
void deleteEntries();
|
||||||
|
void setFocus();
|
||||||
void copyTitle();
|
void copyTitle();
|
||||||
void copyUsername();
|
void copyUsername();
|
||||||
void copyPassword();
|
void copyPassword();
|
||||||
|
@ -24,20 +24,6 @@
|
|||||||
|
|
||||||
#include "core/FilePath.h"
|
#include "core/FilePath.h"
|
||||||
|
|
||||||
bool SearchEventFilter::eventFilter(QObject *obj, QEvent *event)
|
|
||||||
{
|
|
||||||
if (event->type() == QEvent::KeyPress) {
|
|
||||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
|
||||||
if (keyEvent->key() == Qt::Key_Escape) {
|
|
||||||
emit escapePressed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return QObject::eventFilter(obj, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SearchWidget::SearchWidget(QWidget *parent)
|
SearchWidget::SearchWidget(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, m_ui(new Ui::SearchWidget())
|
, m_ui(new Ui::SearchWidget())
|
||||||
@ -51,11 +37,11 @@ SearchWidget::SearchWidget(QWidget *parent)
|
|||||||
connect(m_ui->searchEdit, SIGNAL(returnPressed()), SLOT(startSearch()));
|
connect(m_ui->searchEdit, SIGNAL(returnPressed()), SLOT(startSearch()));
|
||||||
connect(m_ui->searchIcon, SIGNAL(triggered(QAction*)), m_ui->searchEdit, SLOT(setFocus()));
|
connect(m_ui->searchIcon, SIGNAL(triggered(QAction*)), m_ui->searchEdit, SLOT(setFocus()));
|
||||||
connect(m_searchTimer, SIGNAL(timeout()), this, SLOT(startSearch()));
|
connect(m_searchTimer, SIGNAL(timeout()), this, SLOT(startSearch()));
|
||||||
connect(&m_searchEventFilter, SIGNAL(escapePressed()), m_ui->searchEdit, SLOT(clear()));
|
connect(this, SIGNAL(escapePressed()), m_ui->searchEdit, SLOT(clear()));
|
||||||
|
|
||||||
new QShortcut(Qt::CTRL + Qt::Key_F, m_ui->searchEdit, SLOT(setFocus()), nullptr, Qt::ApplicationShortcut);
|
new QShortcut(Qt::CTRL + Qt::Key_F, m_ui->searchEdit, SLOT(setFocus()), nullptr, Qt::ApplicationShortcut);
|
||||||
|
|
||||||
m_ui->searchEdit->installEventFilter(&m_searchEventFilter);
|
m_ui->searchEdit->installEventFilter(this);
|
||||||
|
|
||||||
QMenu *searchMenu = new QMenu();
|
QMenu *searchMenu = new QMenu();
|
||||||
m_actionCaseSensitive = searchMenu->addAction(tr("Case Sensitive"), this, SLOT(updateCaseSensitive()));
|
m_actionCaseSensitive = searchMenu->addAction(tr("Case Sensitive"), this, SLOT(updateCaseSensitive()));
|
||||||
@ -72,10 +58,44 @@ SearchWidget::~SearchWidget()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SearchWidget::eventFilter(QObject *obj, QEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::KeyPress) {
|
||||||
|
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
||||||
|
if (keyEvent->key() == Qt::Key_Escape) {
|
||||||
|
emit escapePressed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (keyEvent->matches(QKeySequence::Copy)) {
|
||||||
|
// If Control+C is pressed in the search edit when no
|
||||||
|
// text is selected, copy the password of the current
|
||||||
|
// entry.
|
||||||
|
if (!m_ui->searchEdit->hasSelectedText()) {
|
||||||
|
emit copyPressed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (keyEvent->matches(QKeySequence::MoveToNextLine)) {
|
||||||
|
// If Down is pressed at EOL in the search edit, move
|
||||||
|
// the focus to the entry view.
|
||||||
|
QLineEdit* searchEdit = m_ui->searchEdit;
|
||||||
|
if (!searchEdit->hasSelectedText() &&
|
||||||
|
searchEdit->cursorPosition() == searchEdit->text().length()) {
|
||||||
|
emit downPressed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QObject::eventFilter(obj, event);
|
||||||
|
}
|
||||||
|
|
||||||
void SearchWidget::connectSignals(SignalMultiplexer& mx)
|
void SearchWidget::connectSignals(SignalMultiplexer& mx)
|
||||||
{
|
{
|
||||||
mx.connect(this, SIGNAL(search(QString)), SLOT(search(QString)));
|
mx.connect(this, SIGNAL(search(QString)), SLOT(search(QString)));
|
||||||
mx.connect(this, SIGNAL(caseSensitiveChanged(bool)), SLOT(setSearchCaseSensitive(bool)));
|
mx.connect(this, SIGNAL(caseSensitiveChanged(bool)), SLOT(setSearchCaseSensitive(bool)));
|
||||||
|
mx.connect(this, SIGNAL(copyPressed()), SLOT(copyPassword()));
|
||||||
|
mx.connect(this, SIGNAL(downPressed()), SLOT(setFocus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchWidget::databaseChanged(DatabaseWidget *dbWidget)
|
void SearchWidget::databaseChanged(DatabaseWidget *dbWidget)
|
||||||
|
@ -28,17 +28,6 @@ namespace Ui {
|
|||||||
class SearchWidget;
|
class SearchWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SearchEventFilter : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
signals:
|
|
||||||
void escapePressed();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool eventFilter(QObject *obj, QEvent *event) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class SearchWidget : public QWidget
|
class SearchWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -50,9 +39,15 @@ public:
|
|||||||
void connectSignals(SignalMultiplexer& mx);
|
void connectSignals(SignalMultiplexer& mx);
|
||||||
void setCaseSensitive(bool state);
|
void setCaseSensitive(bool state);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void search(const QString &text);
|
void search(const QString &text);
|
||||||
void caseSensitiveChanged(bool state);
|
void caseSensitiveChanged(bool state);
|
||||||
|
void escapePressed();
|
||||||
|
void copyPressed();
|
||||||
|
void downPressed();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void databaseChanged(DatabaseWidget* dbWidget);
|
void databaseChanged(DatabaseWidget* dbWidget);
|
||||||
@ -65,8 +60,6 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
const QScopedPointer<Ui::SearchWidget> m_ui;
|
const QScopedPointer<Ui::SearchWidget> m_ui;
|
||||||
QTimer* m_searchTimer;
|
QTimer* m_searchTimer;
|
||||||
SearchEventFilter m_searchEventFilter;
|
|
||||||
|
|
||||||
QAction *m_actionCaseSensitive;
|
QAction *m_actionCaseSensitive;
|
||||||
|
|
||||||
Q_DISABLE_COPY(SearchWidget)
|
Q_DISABLE_COPY(SearchWidget)
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QSignalSpy>
|
#include <QSignalSpy>
|
||||||
|
#include <QClipboard>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include "config-keepassx-tests.h"
|
#include "config-keepassx-tests.h"
|
||||||
#include "core/Config.h"
|
#include "core/Config.h"
|
||||||
@ -287,6 +289,10 @@ void TestGui::testAddEntry()
|
|||||||
// Add entry "something 2"
|
// Add entry "something 2"
|
||||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||||
QTest::keyClicks(titleEdit, "something 2");
|
QTest::keyClicks(titleEdit, "something 2");
|
||||||
|
QLineEdit* passwordEdit = editEntryWidget->findChild<QLineEdit*>("passwordEdit");
|
||||||
|
QLineEdit* passwordRepeatEdit = editEntryWidget->findChild<QLineEdit*>("passwordRepeatEdit");
|
||||||
|
QTest::keyClicks(passwordEdit, "something 2");
|
||||||
|
QTest::keyClicks(passwordRepeatEdit, "something 2");
|
||||||
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
|
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
|
||||||
|
|
||||||
// Add entry "something 3"
|
// Add entry "something 3"
|
||||||
@ -406,6 +412,19 @@ void TestGui::testSearch()
|
|||||||
// Search for "someTHING"
|
// Search for "someTHING"
|
||||||
QTest::keyClicks(searchTextEdit, "THING");
|
QTest::keyClicks(searchTextEdit, "THING");
|
||||||
QTRY_COMPARE(entryView->model()->rowCount(), 2);
|
QTRY_COMPARE(entryView->model()->rowCount(), 2);
|
||||||
|
// Press Down to focus on the entry view if at EOL
|
||||||
|
QTest::keyClick(searchTextEdit, Qt::Key_Right, Qt::ControlModifier);
|
||||||
|
QTRY_VERIFY(searchTextEdit->hasFocus());
|
||||||
|
QTest::keyClick(searchTextEdit, Qt::Key_Down);
|
||||||
|
QTRY_VERIFY(entryView->hasFocus());
|
||||||
|
// Test clipboard
|
||||||
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
|
QTest::keyClick(entryView, Qt::Key_C, Qt::ControlModifier);
|
||||||
|
QModelIndex searchedItem = entryView->model()->index(0, 1);
|
||||||
|
Entry* searchedEntry = entryView->entryFromIndex(searchedItem);
|
||||||
|
QTRY_COMPARE(searchedEntry->password(), clipboard->text());
|
||||||
|
// Restore focus
|
||||||
|
QTest::mouseClick(searchTextEdit, Qt::LeftButton);
|
||||||
|
|
||||||
// Test case sensitive search
|
// Test case sensitive search
|
||||||
searchWidget->setCaseSensitive(true);
|
searchWidget->setCaseSensitive(true);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user