diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index a8d1ed091..d23300dc5 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -509,6 +509,11 @@ void AutoType::resetAutoTypeState() QList> AutoType::parseSequence(const QString& entrySequence, const Entry* entry, QString& error, bool syntaxOnly) { + if (!entry) { + error = tr("Invalid entry provided"); + return {}; + } + const int maxTypeDelay = 100; const int maxWaitDelay = 10000; const int maxRepetition = 100; diff --git a/src/autotype/AutoTypeMatchView.cpp b/src/autotype/AutoTypeMatchView.cpp index 453d9072e..45231f110 100644 --- a/src/autotype/AutoTypeMatchView.cpp +++ b/src/autotype/AutoTypeMatchView.cpp @@ -78,14 +78,20 @@ void AutoTypeMatchView::keyPressEvent(QKeyEvent* event) QTableView::keyPressEvent(event); } -void AutoTypeMatchView::setMatchList(const QList& matches) +void AutoTypeMatchView::setMatchList(const QList& matches, bool selectFirst) { m_model->setMatchList(matches); m_sortModel->setFilterWildcard({}); horizontalHeader()->resizeSections(QHeaderView::ResizeToContents); - selectionModel()->setCurrentIndex(m_sortModel->index(0, 0), - QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + + if (selectFirst) { + selectionModel()->setCurrentIndex(m_sortModel->index(0, 0), + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + } else { + selectionModel()->clear(); + } + emit currentMatchChanged(currentMatch()); } diff --git a/src/autotype/AutoTypeMatchView.h b/src/autotype/AutoTypeMatchView.h index 90442baa6..d7de35cdb 100644 --- a/src/autotype/AutoTypeMatchView.h +++ b/src/autotype/AutoTypeMatchView.h @@ -34,7 +34,7 @@ public: explicit AutoTypeMatchView(QWidget* parent = nullptr); AutoTypeMatch currentMatch(); AutoTypeMatch matchFromIndex(const QModelIndex& index); - void setMatchList(const QList& matches); + void setMatchList(const QList& matches, bool selectFirst); void filterList(const QString& filter); signals: diff --git a/src/autotype/AutoTypeSelectDialog.cpp b/src/autotype/AutoTypeSelectDialog.cpp index 8b80f491c..348396ea4 100644 --- a/src/autotype/AutoTypeSelectDialog.cpp +++ b/src/autotype/AutoTypeSelectDialog.cpp @@ -67,16 +67,14 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent) connect(m_ui->search, SIGNAL(returnPressed()), SLOT(activateCurrentMatch())); connect(&m_searchTimer, SIGNAL(timeout()), SLOT(performSearch())); - connect(m_ui->filterRadio, &QRadioButton::toggled, this, [this](bool checked) { + m_ui->searchCheckBox->setShortcut(Qt::CTRL + Qt::Key_F); + connect(m_ui->searchCheckBox, &QCheckBox::toggled, this, [this](bool checked) { if (checked) { - // Reset to original match list - m_ui->view->setMatchList(m_matches); performSearch(); m_ui->search->setFocus(); - } - }); - connect(m_ui->searchRadio, &QRadioButton::toggled, this, [this](bool checked) { - if (checked) { + } else { + // Reset to original match list + m_ui->view->setMatchList(m_matches, true); performSearch(); m_ui->search->setFocus(); } @@ -100,24 +98,22 @@ void AutoTypeSelectDialog::setMatches(const QList& matches, const m_matches = matches; m_dbs = dbs; - m_ui->view->setMatchList(m_matches); - if (m_matches.isEmpty()) { - m_ui->searchRadio->setChecked(true); - } else { - m_ui->filterRadio->setChecked(true); - } + m_ui->view->setMatchList(m_matches, !m_matches.isEmpty() || !m_ui->search->text().isEmpty()); + m_ui->searchCheckBox->setChecked(m_matches.isEmpty()); } void AutoTypeSelectDialog::submitAutoTypeMatch(AutoTypeMatch match) { - m_accepted = true; - accept(); - emit matchActivated(std::move(match)); + if (match.first) { + m_accepted = true; + accept(); + emit matchActivated(std::move(match)); + } } void AutoTypeSelectDialog::performSearch() { - if (m_ui->filterRadio->isChecked()) { + if (!m_ui->searchCheckBox->isChecked()) { m_ui->view->filterList(m_ui->search->text()); return; } @@ -148,7 +144,7 @@ void AutoTypeSelectDialog::performSearch() } } - m_ui->view->setMatchList(matches); + m_ui->view->setMatchList(matches, !m_ui->search->text().isEmpty()); } void AutoTypeSelectDialog::moveSelectionUp() @@ -164,6 +160,13 @@ void AutoTypeSelectDialog::moveSelectionUp() void AutoTypeSelectDialog::moveSelectionDown() { auto current = m_ui->view->currentIndex(); + + // special case where we have no default selection (empty search) + if (!current.isValid()) { + m_ui->view->setCurrentIndex(m_ui->view->indexAt({0, 0})); + return; + } + auto next = current.sibling(current.row() + 1, 0); if (next.isValid()) { @@ -274,16 +277,24 @@ void AutoTypeSelectDialog::buildActionMenu() m_actionMenu->addAction(copyPasswordAction); m_actionMenu->addAction(copyTotpAction); + auto shortcut = new QShortcut(Qt::CTRL + Qt::Key_1, this); + connect(shortcut, &QShortcut::activated, typeUsernameAction, &QAction::trigger); connect(typeUsernameAction, &QAction::triggered, this, [&] { auto match = m_ui->view->currentMatch(); match.second = "{USERNAME}"; submitAutoTypeMatch(match); }); + + shortcut = new QShortcut(Qt::CTRL + Qt::Key_2, this); + connect(shortcut, &QShortcut::activated, typePasswordAction, &QAction::trigger); connect(typePasswordAction, &QAction::triggered, this, [&] { auto match = m_ui->view->currentMatch(); match.second = "{PASSWORD}"; submitAutoTypeMatch(match); }); + + shortcut = new QShortcut(Qt::CTRL + Qt::Key_3, this); + connect(shortcut, &QShortcut::activated, typeTotpAction, &QAction::trigger); connect(typeTotpAction, &QAction::triggered, this, [&] { auto match = m_ui->view->currentMatch(); match.second = "{TOTP}"; diff --git a/src/autotype/AutoTypeSelectDialog.ui b/src/autotype/AutoTypeSelectDialog.ui index 2f77bd2b2..cac656d60 100644 --- a/src/autotype/AutoTypeSelectDialog.ui +++ b/src/autotype/AutoTypeSelectDialog.ui @@ -7,19 +7,74 @@ 0 0 418 - 295 + 303 Auto-Type - KeePassXC + + 6 + + + 6 + - - - Double click a row to perform Auto-Type or find an entry using the search: - - + + + + + Double click a row to perform Auto-Type or find an entry using the search: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 14 + 14 + + + + <p>You can use advanced search queries to find any entry in your open databases. The following shortcuts are useful:<br/> +Ctrl+F - Toggle database search<br/> +Ctrl+1 - Type username<br/> +Ctrl+2 - Type password<br/> +Ctrl+3 - Type TOTP</p> + + + + + + :/icons/application/scalable/actions/system-help.svg + + + true + + + + @@ -86,19 +141,9 @@ 0 - + - &Filter Matches - - - true - - - - - - - &Search Database + Search all open databases @@ -133,7 +178,7 @@ - Filter or Search… + Search… true @@ -188,10 +233,11 @@ view - filterRadio - searchRadio + searchCheckBox search - + + +