From d0a3c0884037c0ad5d8871b9bb945f7d50e6539e Mon Sep 17 00:00:00 2001 From: Akinori MUSHA Date: Thu, 22 Dec 2016 16:21:52 +0900 Subject: [PATCH] Improve UI of the search edit (resurrecting 5c7c7f54) - The copy action (Control+C) when no text is selected copies the password of the current entry. This should be reasonable when Control+B copies the username. - Down at EOL moves the focus to the entry view. Enter and Tab should do that, but it would be handy for user to be able to get to the third entry by hitting Down three times. --- src/gui/DatabaseWidget.cpp | 5 +++++ src/gui/DatabaseWidget.h | 1 + src/gui/SearchWidget.cpp | 41 +++++++++++++++++++++++++++++++++++--- src/gui/SearchWidget.h | 21 ++++++++++--------- tests/gui/TestGui.cpp | 7 +++++++ 5 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index f880b9e6..263bc43f 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -385,6 +385,11 @@ void DatabaseWidget::deleteEntries() } } +void DatabaseWidget::setFocus() +{ + m_entryView->setFocus(); +} + void DatabaseWidget::copyTitle() { Entry* currentEntry = m_entryView->currentEntry(); diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 2fd37354..f55fa202 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -116,6 +116,7 @@ public Q_SLOTS: void createEntry(); void cloneEntry(); void deleteEntries(); + void setFocus(); void copyTitle(); void copyUsername(); void copyPassword(); diff --git a/src/gui/SearchWidget.cpp b/src/gui/SearchWidget.cpp index 3d9325a0..af4970fe 100644 --- a/src/gui/SearchWidget.cpp +++ b/src/gui/SearchWidget.cpp @@ -24,7 +24,7 @@ #include "core/FilePath.h" -bool SearchEventFilter::eventFilter(QObject *obj, QEvent *event) +bool SearchWidget::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); @@ -32,6 +32,25 @@ bool SearchEventFilter::eventFilter(QObject *obj, QEvent *event) 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); @@ -51,11 +70,13 @@ SearchWidget::SearchWidget(QWidget *parent) connect(m_ui->searchEdit, SIGNAL(returnPressed()), SLOT(startSearch())); connect(m_ui->searchIcon, SIGNAL(triggered(QAction*)), m_ui->searchEdit, SLOT(setFocus())); 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())); + connect(this, SIGNAL(copyPressed()), SLOT(copyPassword())); + connect(this, SIGNAL(downPressed()), SLOT(setFocusToEntry())); 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(); m_actionCaseSensitive = searchMenu->addAction(tr("Case Sensitive"), this, SLOT(updateCaseSensitive())); @@ -80,6 +101,8 @@ void SearchWidget::connectSignals(SignalMultiplexer& mx) void SearchWidget::databaseChanged(DatabaseWidget *dbWidget) { + m_dbWidget = dbWidget; + if (dbWidget != nullptr) { // Set current search text from this database m_ui->searchEdit->setText(dbWidget->getCurrentSearch()); @@ -118,3 +141,15 @@ void SearchWidget::setCaseSensitive(bool state) m_actionCaseSensitive->setChecked(state); updateCaseSensitive(); } + +void SearchWidget::copyPassword() +{ + if (m_dbWidget) + m_dbWidget->copyPassword(); +} + +void SearchWidget::setFocusToEntry() +{ + if (m_dbWidget) + m_dbWidget->setFocus(); +} diff --git a/src/gui/SearchWidget.h b/src/gui/SearchWidget.h index 844cfb0d..35433906 100644 --- a/src/gui/SearchWidget.h +++ b/src/gui/SearchWidget.h @@ -28,16 +28,6 @@ namespace Ui { class SearchWidget; } -class SearchEventFilter : public QObject -{ - Q_OBJECT -signals: - void escapePressed(); - -protected: - virtual bool eventFilter(QObject *obj, QEvent *event) override; -}; - class SearchWidget : public QWidget { @@ -53,6 +43,9 @@ public: signals: void search(const QString &text); void caseSensitiveChanged(bool state); + void escapePressed(); + void copyPressed(); + void downPressed(); public slots: void databaseChanged(DatabaseWidget* dbWidget); @@ -61,15 +54,21 @@ private slots: void startSearchTimer(); void startSearch(); void updateCaseSensitive(); + void copyPassword(); + void setFocusToEntry(); private: const QScopedPointer m_ui; QTimer* m_searchTimer; - SearchEventFilter m_searchEventFilter; + DatabaseWidget *m_dbWidget; QAction *m_actionCaseSensitive; Q_DISABLE_COPY(SearchWidget) + +protected: + bool eventFilter(QObject *obj, QEvent *event); + }; #endif // SEARCHWIDGET_H diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 41059276..9e4ef75b 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -406,6 +406,13 @@ void TestGui::testSearch() // Search for "someTHING" QTest::keyClicks(searchTextEdit, "THING"); QTRY_COMPARE(entryView->model()->rowCount(), 2); + // Press Down to focus on the entry view if at EOL + QTest::keyClick(searchTextEdit, Qt::Key_Left); + QTest::keyClick(searchTextEdit, Qt::Key_Down); + QTRY_VERIFY(searchTextEdit->hasFocus()); + QTest::keyClick(searchTextEdit, Qt::Key_Down); + QTRY_VERIFY(entryView->hasFocus()); + QTest::mouseClick(searchTextEdit, Qt::LeftButton); // Test case sensitive search searchWidget->setCaseSensitive(true);