mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-27 00:09:53 -05:00
Auto-Type: Shortcuts for selection dialog (#6361)
* Shortcut to toggle search all entries * Select first match only when we have a window match When we default to full database search it's possible the user would select the first match without by accident. In this case when our query is empty we don't select anything and you need to either type something or press down to select the first item. * Added username, password, and TOTP keyboard shortcuts and a help tip * Closes #6176 Co-authored-by: Jonathan White <support@dmapps.us>
This commit is contained in:
parent
c19efb5b19
commit
371bd2e51b
@ -509,6 +509,11 @@ void AutoType::resetAutoTypeState()
|
||||
QList<QSharedPointer<AutoTypeAction>>
|
||||
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;
|
||||
|
@ -78,14 +78,20 @@ void AutoTypeMatchView::keyPressEvent(QKeyEvent* event)
|
||||
QTableView::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void AutoTypeMatchView::setMatchList(const QList<AutoTypeMatch>& matches)
|
||||
void AutoTypeMatchView::setMatchList(const QList<AutoTypeMatch>& 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());
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
explicit AutoTypeMatchView(QWidget* parent = nullptr);
|
||||
AutoTypeMatch currentMatch();
|
||||
AutoTypeMatch matchFromIndex(const QModelIndex& index);
|
||||
void setMatchList(const QList<AutoTypeMatch>& matches);
|
||||
void setMatchList(const QList<AutoTypeMatch>& matches, bool selectFirst);
|
||||
void filterList(const QString& filter);
|
||||
|
||||
signals:
|
||||
|
@ -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<AutoTypeMatch>& 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}";
|
||||
|
@ -7,19 +7,74 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>418</width>
|
||||
<height>295</height>
|
||||
<height>303</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Auto-Type - KeePassXC</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Double click a row to perform Auto-Type or find an entry using the search:</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Double click a row to perform Auto-Type or find an entry using the search:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>14</width>
|
||||
<height>14</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><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></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../../share/icons/icons.qrc">:/icons/application/scalable/actions/system-help.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AutoTypeMatchView" name="view">
|
||||
@ -86,19 +141,9 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="filterRadio">
|
||||
<widget class="QCheckBox" name="searchCheckBox">
|
||||
<property name="text">
|
||||
<string>&Filter Matches</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="searchRadio">
|
||||
<property name="text">
|
||||
<string>&Search Database</string>
|
||||
<string>Search all open databases</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -133,7 +178,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>Filter or Search…</string>
|
||||
<string>Search…</string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
@ -188,10 +233,11 @@
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>view</tabstop>
|
||||
<tabstop>filterRadio</tabstop>
|
||||
<tabstop>searchRadio</tabstop>
|
||||
<tabstop>searchCheckBox</tabstop>
|
||||
<tabstop>search</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<resources>
|
||||
<include location="../../share/icons/icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
Loading…
Reference in New Issue
Block a user