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);