Add URL auto-type and copy options to auto-type selection popup and menus (#12341)

* Added "Type {URL}" option to the auto-type selection popup right-click context menu
* Added "Copy {URL}" option to the auto-type selection popup right-click context menu
* Added keyboard shortcuts: CTRL+4 for "Type {URL}" and CTRL+SHIFT+4 for "Copy {URL}"
* Updated "Use Virtual Keyboard" shortcut from CTRL+4 to CTRL+5 to avoid inconsistency with order of shortcuts
* Added URL auto-type options "{URL}" and "{URL}{ENTER}" to main window entry view right-click menu
* Added URL auto-type options "{URL}" and "{URL}{ENTER}" to toolbar auto-type button dropdown menu
* Added translation strings for "Type {URL}" and "Copy {URL}" to support internationalization

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: juzu-o <3142026+juzu-o@users.noreply.github.com>
Co-authored-by: Jonathan White <support@dmapps.us>
This commit is contained in:
Juzu-O
2025-08-10 06:10:04 +03:00
committed by GitHub
parent 448165613d
commit 9e8a966c23
7 changed files with 105 additions and 17 deletions

View File

@@ -800,15 +800,6 @@
<source>Double click a row to perform Auto-Type or find an entry using the search:</source> <source>Double click a row to perform Auto-Type or find an entry using the search:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>&lt;p&gt;You can use advanced search queries to find any entry in your open databases. The following shortcuts are useful:&lt;br/&gt;
Ctrl+F - Toggle database search&lt;br/&gt;
Ctrl+1 - Type username&lt;br/&gt;
Ctrl+2 - Type password&lt;br/&gt;
Ctrl+3 - Type TOTP&lt;br/&gt;
Ctrl+4 - Use Virtual Keyboard (Windows Only)&lt;/p&gt;</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Search all open databases</source> <source>Search all open databases</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@@ -853,6 +844,24 @@ Ctrl+4 - Use Virtual Keyboard (Windows Only)&lt;/p&gt;</source>
<source>Use Virtual Keyboard</source> <source>Use Virtual Keyboard</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>&lt;p&gt;You can use advanced search queries to find any entry in your open databases. The following shortcuts are useful:&lt;br/&gt;
Ctrl+F - Toggle database search&lt;br/&gt;
Ctrl+1 - Type username&lt;br/&gt;
Ctrl+2 - Type password&lt;br/&gt;
Ctrl+3 - Type TOTP&lt;br/&gt;
Ctrl+4 - Type URL&lt;br/&gt;
Ctrl+5 - Use Virtual Keyboard (Windows Only)&lt;/p&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Type {URL}</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Copy URL</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>BrowserAccessControlDialog</name> <name>BrowserAccessControlDialog</name>

View File

@@ -37,6 +37,7 @@ enum MENU_FIELD
USERNAME = 1, USERNAME = 1,
PASSWORD, PASSWORD,
TOTP, TOTP,
URL,
}; };
AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent) AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent)
@@ -265,6 +266,7 @@ void AutoTypeSelectDialog::updateActionMenu(const AutoTypeMatch& match)
bool hasUsername = !match.first->username().isEmpty(); bool hasUsername = !match.first->username().isEmpty();
bool hasPassword = !match.first->password().isEmpty(); bool hasPassword = !match.first->password().isEmpty();
bool hasTotp = match.first->hasValidTotp(); bool hasTotp = match.first->hasValidTotp();
bool hasUrl = !match.first->url().isEmpty();
for (auto action : m_actionMenu->actions()) { for (auto action : m_actionMenu->actions()) {
auto prop = action->property(MENU_FIELD_PROP_NAME); auto prop = action->property(MENU_FIELD_PROP_NAME);
@@ -279,6 +281,9 @@ void AutoTypeSelectDialog::updateActionMenu(const AutoTypeMatch& match)
case MENU_FIELD::TOTP: case MENU_FIELD::TOTP:
action->setEnabled(hasTotp); action->setEnabled(hasTotp);
break; break;
case MENU_FIELD::URL:
action->setEnabled(hasUrl);
break;
} }
} }
} }
@@ -290,15 +295,19 @@ void AutoTypeSelectDialog::buildActionMenu()
auto typeUsernameAction = new QAction(icons()->icon("auto-type"), tr("Type {USERNAME}"), this); auto typeUsernameAction = new QAction(icons()->icon("auto-type"), tr("Type {USERNAME}"), this);
auto typePasswordAction = new QAction(icons()->icon("auto-type"), tr("Type {PASSWORD}"), this); auto typePasswordAction = new QAction(icons()->icon("auto-type"), tr("Type {PASSWORD}"), this);
auto typeTotpAction = new QAction(icons()->icon("auto-type"), tr("Type {TOTP}"), this); auto typeTotpAction = new QAction(icons()->icon("auto-type"), tr("Type {TOTP}"), this);
auto typeUrlAction = new QAction(icons()->icon("auto-type"), tr("Type {URL}"), this);
auto copyUsernameAction = new QAction(icons()->icon("username-copy"), tr("Copy Username"), this); auto copyUsernameAction = new QAction(icons()->icon("username-copy"), tr("Copy Username"), this);
auto copyPasswordAction = new QAction(icons()->icon("password-copy"), tr("Copy Password"), this); auto copyPasswordAction = new QAction(icons()->icon("password-copy"), tr("Copy Password"), this);
auto copyTotpAction = new QAction(icons()->icon("totp"), tr("Copy TOTP"), this); auto copyTotpAction = new QAction(icons()->icon("totp"), tr("Copy TOTP"), this);
auto copyUrlAction = new QAction(icons()->icon("url-copy"), tr("Copy URL"), this);
m_actionMenu->addAction(typeUsernameAction); m_actionMenu->addAction(typeUsernameAction);
m_actionMenu->addAction(typePasswordAction); m_actionMenu->addAction(typePasswordAction);
m_actionMenu->addAction(typeTotpAction); m_actionMenu->addAction(typeTotpAction);
m_actionMenu->addAction(typeUrlAction);
m_actionMenu->addAction(copyUsernameAction); m_actionMenu->addAction(copyUsernameAction);
m_actionMenu->addAction(copyPasswordAction); m_actionMenu->addAction(copyPasswordAction);
m_actionMenu->addAction(copyTotpAction); m_actionMenu->addAction(copyTotpAction);
m_actionMenu->addAction(copyUrlAction);
typeUsernameAction->setShortcut(Qt::CTRL + Qt::Key_1); typeUsernameAction->setShortcut(Qt::CTRL + Qt::Key_1);
typeUsernameAction->setProperty(MENU_FIELD_PROP_NAME, MENU_FIELD::USERNAME); typeUsernameAction->setProperty(MENU_FIELD_PROP_NAME, MENU_FIELD::USERNAME);
@@ -324,10 +333,18 @@ void AutoTypeSelectDialog::buildActionMenu()
submitAutoTypeMatch(match); submitAutoTypeMatch(match);
}); });
typeUrlAction->setShortcut(Qt::CTRL + Qt::Key_4);
typeUrlAction->setProperty(MENU_FIELD_PROP_NAME, MENU_FIELD::URL);
connect(typeUrlAction, &QAction::triggered, this, [&] {
auto match = m_ui->view->currentMatch();
match.second = "{URL}";
submitAutoTypeMatch(match);
});
#if defined(Q_OS_WIN) || defined(Q_OS_MAC) #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
auto typeVirtualAction = new QAction(icons()->icon("auto-type"), tr("Use Virtual Keyboard"), nullptr); auto typeVirtualAction = new QAction(icons()->icon("auto-type"), tr("Use Virtual Keyboard"), nullptr);
m_actionMenu->insertAction(copyUsernameAction, typeVirtualAction); m_actionMenu->insertAction(copyUsernameAction, typeVirtualAction);
typeVirtualAction->setShortcut(Qt::CTRL + Qt::Key_4); typeVirtualAction->setShortcut(Qt::CTRL + Qt::Key_5);
connect(typeVirtualAction, &QAction::triggered, this, [&] { connect(typeVirtualAction, &QAction::triggered, this, [&] {
m_virtualMode = true; m_virtualMode = true;
activateCurrentMatch(); activateCurrentMatch();
@@ -364,17 +381,29 @@ void AutoTypeSelectDialog::buildActionMenu()
} }
}); });
copyUrlAction->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_4);
copyUrlAction->setProperty(MENU_FIELD_PROP_NAME, MENU_FIELD::URL);
connect(copyUrlAction, &QAction::triggered, this, [&] {
auto entry = m_ui->view->currentMatch().first;
if (entry) {
clipboard()->setText(entry->resolvePlaceholder(entry->url()));
reject();
}
});
// Qt 5.10 introduced a new "feature" to hide shortcuts in context menus // Qt 5.10 introduced a new "feature" to hide shortcuts in context menus
// Unfortunately, Qt::AA_DontShowShortcutsInContextMenus is broken, have to manually enable them // Unfortunately, Qt::AA_DontShowShortcutsInContextMenus is broken, have to manually enable them
typeUsernameAction->setShortcutVisibleInContextMenu(true); typeUsernameAction->setShortcutVisibleInContextMenu(true);
typePasswordAction->setShortcutVisibleInContextMenu(true); typePasswordAction->setShortcutVisibleInContextMenu(true);
typeTotpAction->setShortcutVisibleInContextMenu(true); typeTotpAction->setShortcutVisibleInContextMenu(true);
typeUrlAction->setShortcutVisibleInContextMenu(true);
#if defined(Q_OS_WIN) || defined(Q_OS_MAC) #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
typeVirtualAction->setShortcutVisibleInContextMenu(true); typeVirtualAction->setShortcutVisibleInContextMenu(true);
#endif #endif
copyUsernameAction->setShortcutVisibleInContextMenu(true); copyUsernameAction->setShortcutVisibleInContextMenu(true);
copyPasswordAction->setShortcutVisibleInContextMenu(true); copyPasswordAction->setShortcutVisibleInContextMenu(true);
copyTotpAction->setShortcutVisibleInContextMenu(true); copyTotpAction->setShortcutVisibleInContextMenu(true);
copyUrlAction->setShortcutVisibleInContextMenu(true);
} }
void AutoTypeSelectDialog::showEvent(QShowEvent* event) void AutoTypeSelectDialog::showEvent(QShowEvent* event)

View File

@@ -50,13 +50,14 @@
<property name="focusPolicy"> <property name="focusPolicy">
<enum>Qt::NoFocus</enum> <enum>Qt::NoFocus</enum>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>&lt;p&gt;You can use advanced search queries to find any entry in your open databases. The following shortcuts are useful:&lt;br/&gt; <string>&lt;p&gt;You can use advanced search queries to find any entry in your open databases. The following shortcuts are useful:&lt;br/&gt;
Ctrl+F - Toggle database search&lt;br/&gt; Ctrl+F - Toggle database search&lt;br/&gt;
Ctrl+1 - Type username&lt;br/&gt; Ctrl+1 - Type username&lt;br/&gt;
Ctrl+2 - Type password&lt;br/&gt; Ctrl+2 - Type password&lt;br/&gt;
Ctrl+3 - Type TOTP&lt;br/&gt; Ctrl+3 - Type TOTP&lt;br/&gt;
Ctrl+4 - Use Virtual Keyboard (Windows Only)&lt;/p&gt;</string> Ctrl+4 - Type URL&lt;br/&gt;
Ctrl+5 - Use Virtual Keyboard (Windows Only)&lt;/p&gt;</string>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QToolButton { <string notr="true">QToolButton {

View File

@@ -924,6 +924,16 @@ void DatabaseWidget::performAutoTypeTOTP()
performAutoType(QStringLiteral("{TOTP}")); performAutoType(QStringLiteral("{TOTP}"));
} }
void DatabaseWidget::performAutoTypeURL()
{
performAutoType(QStringLiteral("{URL}"));
}
void DatabaseWidget::performAutoTypeURLEnter()
{
performAutoType(QStringLiteral("{URL}{ENTER}"));
}
void DatabaseWidget::openUrl() void DatabaseWidget::openUrl()
{ {
auto currentEntry = currentSelectedEntry(); auto currentEntry = currentSelectedEntry();

View File

@@ -214,6 +214,8 @@ public slots:
void performAutoTypePassword(); void performAutoTypePassword();
void performAutoTypePasswordEnter(); void performAutoTypePasswordEnter();
void performAutoTypeTOTP(); void performAutoTypeTOTP();
void performAutoTypeURL();
void performAutoTypeURLEnter();
void setClipboardTextAndMinimize(const QString& text); void setClipboardTextAndMinimize(const QString& text);
void openUrl(); void openUrl();
void downloadSelectedFavicons(); void downloadSelectedFavicons();

View File

@@ -172,6 +172,8 @@ MainWindow::MainWindow()
autotypeMenu->addAction(m_ui->actionEntryAutoTypePassword); autotypeMenu->addAction(m_ui->actionEntryAutoTypePassword);
autotypeMenu->addAction(m_ui->actionEntryAutoTypePasswordEnter); autotypeMenu->addAction(m_ui->actionEntryAutoTypePasswordEnter);
autotypeMenu->addAction(m_ui->actionEntryAutoTypeTOTP); autotypeMenu->addAction(m_ui->actionEntryAutoTypeTOTP);
autotypeMenu->addAction(m_ui->actionEntryAutoTypeURL);
autotypeMenu->addAction(m_ui->actionEntryAutoTypeURLEnter);
m_ui->actionEntryAutoType->setMenu(autotypeMenu); m_ui->actionEntryAutoType->setMenu(autotypeMenu);
auto autoTypeButton = qobject_cast<QToolButton*>(m_ui->toolBar->widgetForAction(m_ui->actionEntryAutoType)); auto autoTypeButton = qobject_cast<QToolButton*>(m_ui->toolBar->widgetForAction(m_ui->actionEntryAutoType));
if (autoTypeButton) { if (autoTypeButton) {
@@ -387,6 +389,8 @@ MainWindow::MainWindow()
m_ui->actionEntryAutoTypePassword->setIcon(icons()->icon("auto-type")); m_ui->actionEntryAutoTypePassword->setIcon(icons()->icon("auto-type"));
m_ui->actionEntryAutoTypePasswordEnter->setIcon(icons()->icon("auto-type")); m_ui->actionEntryAutoTypePasswordEnter->setIcon(icons()->icon("auto-type"));
m_ui->actionEntryAutoTypeTOTP->setIcon(icons()->icon("auto-type")); m_ui->actionEntryAutoTypeTOTP->setIcon(icons()->icon("auto-type"));
m_ui->actionEntryAutoTypeURL->setIcon(icons()->icon("auto-type"));
m_ui->actionEntryAutoTypeURLEnter->setIcon(icons()->icon("auto-type"));
m_ui->actionEntryMoveUp->setIcon(icons()->icon("move-up")); m_ui->actionEntryMoveUp->setIcon(icons()->icon("move-up"));
m_ui->actionEntryMoveDown->setIcon(icons()->icon("move-down")); m_ui->actionEntryMoveDown->setIcon(icons()->icon("move-down"));
m_ui->actionEntryCopyUsername->setIcon(icons()->icon("username-copy")); m_ui->actionEntryCopyUsername->setIcon(icons()->icon("username-copy"));
@@ -526,6 +530,9 @@ MainWindow::MainWindow()
m_actionMultiplexer.connect( m_actionMultiplexer.connect(
m_ui->actionEntryAutoTypePasswordEnter, SIGNAL(triggered()), SLOT(performAutoTypePasswordEnter())); m_ui->actionEntryAutoTypePasswordEnter, SIGNAL(triggered()), SLOT(performAutoTypePasswordEnter()));
m_actionMultiplexer.connect(m_ui->actionEntryAutoTypeTOTP, SIGNAL(triggered()), SLOT(performAutoTypeTOTP())); m_actionMultiplexer.connect(m_ui->actionEntryAutoTypeTOTP, SIGNAL(triggered()), SLOT(performAutoTypeTOTP()));
m_actionMultiplexer.connect(m_ui->actionEntryAutoTypeURL, SIGNAL(triggered()), SLOT(performAutoTypeURL()));
m_actionMultiplexer.connect(
m_ui->actionEntryAutoTypeURLEnter, SIGNAL(triggered()), SLOT(performAutoTypeURLEnter()));
m_actionMultiplexer.connect(m_ui->actionEntryOpenUrl, SIGNAL(triggered()), SLOT(openUrl())); m_actionMultiplexer.connect(m_ui->actionEntryOpenUrl, SIGNAL(triggered()), SLOT(openUrl()));
m_actionMultiplexer.connect(m_ui->actionEntryDownloadIcon, SIGNAL(triggered()), SLOT(downloadSelectedFavicons())); m_actionMultiplexer.connect(m_ui->actionEntryDownloadIcon, SIGNAL(triggered()), SLOT(downloadSelectedFavicons()));
#ifdef WITH_XC_SSHAGENT #ifdef WITH_XC_SSHAGENT
@@ -976,6 +983,8 @@ void MainWindow::updateMenuActionState()
m_ui->actionEntryAutoTypePassword->setEnabled(singleEntrySelected && dbWidget->currentEntryHasPassword()); m_ui->actionEntryAutoTypePassword->setEnabled(singleEntrySelected && dbWidget->currentEntryHasPassword());
m_ui->actionEntryAutoTypePasswordEnter->setEnabled(singleEntrySelected && dbWidget->currentEntryHasPassword()); m_ui->actionEntryAutoTypePasswordEnter->setEnabled(singleEntrySelected && dbWidget->currentEntryHasPassword());
m_ui->actionEntryAutoTypeTOTP->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp()); m_ui->actionEntryAutoTypeTOTP->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp());
m_ui->actionEntryAutoTypeURL->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUrl());
m_ui->actionEntryAutoTypeURLEnter->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUrl());
m_ui->actionEntryAutoTypeTOTP->setVisible(singleEntrySelected && dbWidget->currentEntryHasTotp()); m_ui->actionEntryAutoTypeTOTP->setVisible(singleEntrySelected && dbWidget->currentEntryHasTotp());
m_ui->actionEntryOpenUrl->setEnabled(singleEntryOrEditing && dbWidget->currentEntryHasUrl()); m_ui->actionEntryOpenUrl->setEnabled(singleEntryOrEditing && dbWidget->currentEntryHasUrl());
m_ui->actionEntryTotp->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp()); m_ui->actionEntryTotp->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp());

View File

@@ -859,6 +859,34 @@
<string>Perform Auto-Type: {TOTP}</string> <string>Perform Auto-Type: {TOTP}</string>
</property> </property>
</action> </action>
<action name="actionEntryAutoTypeURL">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string notr="true">{URL}</string>
</property>
<property name="iconText">
<string notr="true">{URL}</string>
</property>
<property name="toolTip">
<string notr="true">{URL}</string>
</property>
</action>
<action name="actionEntryAutoTypeURLEnter">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string notr="true">{URL}{ENTER}</string>
</property>
<property name="iconText">
<string notr="true">{URL}{ENTER}</string>
</property>
<property name="toolTip">
<string notr="true">{URL}{ENTER}</string>
</property>
</action>
<action name="actionEntryDownloadIcon"> <action name="actionEntryDownloadIcon">
<property name="text"> <property name="text">
<string>Download &amp;Favicon</string> <string>Download &amp;Favicon</string>