From 6182b605c01a8c9116f1fd6048f3f51e64607e10 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 15 Apr 2023 21:35:54 -0400 Subject: [PATCH] Fix various accessibility issues (#9138) Enable buddy fields in group and entry edit pages * Fixes #9060, you can now press Alt + [letter] to skip between fields on the group and entry edit pages. * Move the expire checkbox to the right hand column and use the standard eye icon button for notes reveal. Only show notes reveal button if the hide notes setting is enabled. Fix overflow of text in default auto-type sequence preview * Fixes #9083 Add copy title shortcut (Ctrl + I) * Closes #9109 Fix issues with menu actions being enabled incorrectly Add accessibility description to password widget to explain how to hide/show passwords and open the generator * Closes #9059 Add F6 shortcut to focus search * Closes #9163 --- share/translations/keepassxc_en.ts | 72 +++---- src/gui/EntryPreviewWidget.ui | 9 +- src/gui/MainWindow.cpp | 36 ++-- src/gui/PasswordWidget.ui | 6 +- src/gui/entry/EditEntryWidget.cpp | 8 +- src/gui/entry/EditEntryWidgetMain.ui | 281 ++++++++++++++++----------- 6 files changed, 239 insertions(+), 173 deletions(-) diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index 259675e78..63786afcf 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -2895,22 +2895,10 @@ Would you like to correct it? Notes field - - Toggle the checkbox to reveal the notes section. - - Username field - - Toggle notes visible - - - - Notes: - - Expiration field @@ -2927,14 +2915,6 @@ Would you like to correct it? Presets - - Password: - - - - URL: - - Url field @@ -2943,18 +2923,10 @@ Would you like to correct it? Download favicon for URL - - Title: - - Title field - - Username: - - Password field @@ -2963,18 +2935,42 @@ Would you like to correct it? Toggle expiration - - Expires: - - - - Tags: - - Tags list + + &Username: + + + + &Title: + + + + &Password: + + + + UR&L: + + + + &Notes: + + + + Toggle notes visibility + + + + T&ags: + + + + &Expires: + + EditEntryWidgetSSHAgent @@ -6239,6 +6235,10 @@ Do you want to overwrite it? Password quality + + Toggle password visibilty using Control + H. Open the password generator using Control + G. + + PickcharsDialog diff --git a/src/gui/EntryPreviewWidget.ui b/src/gui/EntryPreviewWidget.ui index 6e0ce5ec9..c251da3f5 100644 --- a/src/gui/EntryPreviewWidget.ui +++ b/src/gui/EntryPreviewWidget.ui @@ -6,7 +6,7 @@ 0 0 - 508 + 530 257 @@ -177,7 +177,7 @@ - 0 + 2 false @@ -753,7 +753,7 @@ Default Sequence - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing @@ -771,6 +771,9 @@ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + true + diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 160fac3d0..bb82b184b 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -146,6 +146,9 @@ MainWindow::MainWindow() m_entryContextMenu->addAction(m_ui->actionEntryOpenUrl); m_entryContextMenu->addAction(m_ui->actionEntryDownloadIcon); m_entryContextMenu->addSeparator(); + m_entryContextMenu->addAction(m_ui->actionEntryAddToAgent); + m_entryContextMenu->addAction(m_ui->actionEntryRemoveFromAgent); + m_entryContextMenu->addSeparator(); m_entryContextMenu->addAction(m_ui->actionEntryRestore); m_entryNewContextMenu = new QMenu(this); @@ -192,18 +195,8 @@ MainWindow::MainWindow() connect(sshAgent(), SIGNAL(error(QString)), this, SLOT(showErrorMessage(QString))); connect(sshAgent(), SIGNAL(enabledChanged(bool)), this, SLOT(agentEnabled(bool))); m_ui->settingsWidget->addSettingsPage(new AgentSettingsPage()); - - m_entryContextMenu->addSeparator(); - m_entryContextMenu->addAction(m_ui->actionEntryAddToAgent); - m_entryContextMenu->addAction(m_ui->actionEntryRemoveFromAgent); - - m_ui->actionEntryAddToAgent->setIcon(icons()->icon("utilities-terminal")); - m_ui->actionEntryRemoveFromAgent->setIcon(icons()->icon("utilities-terminal")); #endif - m_ui->actionEntryAddToAgent->setVisible(false); - m_ui->actionEntryRemoveFromAgent->setVisible(false); - initViewMenu(); #if defined(WITH_XC_KEESHARE) @@ -289,6 +282,7 @@ MainWindow::MainWindow() m_ui->actionEntryMoveDown->setShortcut(Qt::CTRL + Qt::ALT + Qt::Key_Down); m_ui->actionEntryCopyUsername->setShortcut(Qt::CTRL + Qt::Key_B); m_ui->actionEntryCopyPassword->setShortcut(Qt::CTRL + Qt::Key_C); + m_ui->actionEntryCopyTitle->setShortcut(Qt::CTRL + Qt::Key_I); m_ui->actionEntryAutoTypeSequence->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_V); m_ui->actionEntryOpenUrl->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_U); m_ui->actionEntryCopyURL->setShortcut(Qt::CTRL + Qt::Key_U); @@ -322,6 +316,7 @@ MainWindow::MainWindow() m_ui->actionEntryAutoTypeSequence->setShortcutVisibleInContextMenu(true); m_ui->actionEntryOpenUrl->setShortcutVisibleInContextMenu(true); m_ui->actionEntryCopyURL->setShortcutVisibleInContextMenu(true); + m_ui->actionEntryCopyTitle->setShortcutVisibleInContextMenu(true); m_ui->actionEntryAddToAgent->setShortcutVisibleInContextMenu(true); m_ui->actionEntryRemoveFromAgent->setShortcutVisibleInContextMenu(true); #endif @@ -416,6 +411,8 @@ MainWindow::MainWindow() m_ui->actionEntryCopyPasswordTotp->setIcon(icons()->icon("totp-copy-password")); m_ui->actionEntryTotpQRCode->setIcon(icons()->icon("qrcode")); m_ui->actionEntrySetupTotp->setIcon(icons()->icon("totp-edit")); + m_ui->actionEntryAddToAgent->setIcon(icons()->icon("utilities-terminal")); + m_ui->actionEntryRemoveFromAgent->setIcon(icons()->icon("utilities-terminal")); m_ui->menuTags->setIcon(icons()->icon("tag-multiple")); m_ui->actionEntryDownloadIcon->setIcon(icons()->icon("favicon-download")); m_ui->actionGroupSortAsc->setIcon(icons()->icon("sort-alphabetical-ascending")); @@ -695,6 +692,7 @@ MainWindow::MainWindow() statusBar()->addPermanentWidget(m_statusBarLabel); restoreConfigState(); + setMenuActionState(); } MainWindow::~MainWindow() @@ -885,6 +883,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) bool inWelcomeWidget = (currentIndex == WelcomeScreen); bool inDatabaseTabWidgetOrWelcomeWidget = inDatabaseTabWidget || inWelcomeWidget; + m_ui->actionDatabaseClose->setEnabled(true); m_ui->actionDatabaseMerge->setEnabled(inDatabaseTabWidget); m_ui->actionDatabaseNew->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->actionDatabaseOpen->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); @@ -1042,6 +1041,13 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) // Only disable the action in the database menu so that the // menu remains active in the toolbar, if necessary m_ui->actionLockDatabase->setEnabled(false); + // Never show in these modes + m_ui->actionEntryMoveUp->setVisible(false); + m_ui->actionEntryMoveDown->setVisible(false); + m_ui->actionEntryRestore->setVisible(false); + m_ui->actionEntryAddToAgent->setVisible(false); + m_ui->actionEntryRemoveFromAgent->setVisible(false); + m_ui->actionGroupEmptyRecycleBin->setVisible(false); m_searchWidgetAction->setEnabled(false); break; @@ -1049,7 +1055,6 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) default: Q_ASSERT(false); } - m_ui->actionDatabaseClose->setEnabled(true); } else { const auto entryActions = m_ui->menuEntries->actions(); for (auto action : entryActions) { @@ -1072,6 +1077,13 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionExportCsv->setEnabled(false); m_ui->actionExportHtml->setEnabled(false); m_ui->actionDatabaseMerge->setEnabled(false); + // Hide entry-specific actions + m_ui->actionEntryMoveUp->setVisible(false); + m_ui->actionEntryMoveDown->setVisible(false); + m_ui->actionEntryRestore->setVisible(false); + m_ui->actionEntryAddToAgent->setVisible(false); + m_ui->actionEntryRemoveFromAgent->setVisible(false); + m_ui->actionGroupEmptyRecycleBin->setVisible(false); m_searchWidgetAction->setEnabled(false); } @@ -1415,7 +1427,7 @@ void MainWindow::keyPressEvent(QKeyEvent* event) } else if (event->key() == Qt::Key_F2) { dbWidget->focusOnEntries(true); return; - } else if (event->key() == Qt::Key_F3) { + } else if (event->key() == Qt::Key_F3 || event->key() == Qt::Key_F6) { focusSearchWidget(); return; } else if (event->key() == Qt::Key_Escape && dbWidget->isSearchActive()) { diff --git a/src/gui/PasswordWidget.ui b/src/gui/PasswordWidget.ui index 4419ad79b..34cae29e1 100644 --- a/src/gui/PasswordWidget.ui +++ b/src/gui/PasswordWidget.ui @@ -27,7 +27,11 @@ 0 - + + + Toggle password visibilty using Control + H. Open the password generator using Control + G. + + diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 306a43829..263122ae2 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -169,7 +169,7 @@ void EditEntryWidget::setupMain() } }); - connect(m_mainUi->notesEnabled, SIGNAL(toggled(bool)), this, SLOT(toggleHideNotes(bool))); + connect(m_mainUi->revealNotesButton, &QToolButton::clicked, this, &EditEntryWidget::toggleHideNotes); m_mainUi->expirePresets->setMenu(createPresetsMenu()); connect(m_mainUi->expirePresets->menu(), SIGNAL(triggered(QAction*)), this, SLOT(useExpiryPreset(QAction*))); @@ -800,7 +800,7 @@ void EditEntryWidget::useExpiryPreset(QAction* action) void EditEntryWidget::toggleHideNotes(bool visible) { m_mainUi->notesEdit->setVisible(visible); - m_mainUi->notesHint->setVisible(!visible); + m_mainUi->revealNotesButton->setIcon(icons()->onOffIcon("password-show", visible)); } Entry* EditEntryWidget::currentEntry() const @@ -859,10 +859,10 @@ void EditEntryWidget::setForms(Entry* entry, bool restore) m_mainUi->tagsList->completion(m_db->tagList()); m_mainUi->expireCheck->setEnabled(!m_history); m_mainUi->expireDatePicker->setReadOnly(m_history); - m_mainUi->notesEnabled->setChecked(!config()->get(Config::Security_HideNotes).toBool()); + m_mainUi->revealNotesButton->setIcon(icons()->onOffIcon("password-show", false)); + m_mainUi->revealNotesButton->setVisible(config()->get(Config::Security_HideNotes).toBool()); m_mainUi->notesEdit->setReadOnly(m_history); m_mainUi->notesEdit->setVisible(!config()->get(Config::Security_HideNotes).toBool()); - m_mainUi->notesHint->setVisible(config()->get(Config::Security_HideNotes).toBool()); if (config()->get(Config::GUI_MonospaceNotes).toBool()) { m_mainUi->notesEdit->setFont(Font::fixedFont()); } else { diff --git a/src/gui/entry/EditEntryWidgetMain.ui b/src/gui/entry/EditEntryWidgetMain.ui index 19dbf31fd..6fe6637e7 100644 --- a/src/gui/entry/EditEntryWidgetMain.ui +++ b/src/gui/entry/EditEntryWidgetMain.ui @@ -6,7 +6,7 @@ 0 0 - 539 + 400 523 @@ -33,11 +33,11 @@ 0 0 - 539 + 400 523 - + 0 @@ -56,7 +56,37 @@ 8 - + + + + Title field + + + + + + + &Username: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + usernameComboBox + + + + + + + Qt::StrongFocus + + + Password field + + + + @@ -77,21 +107,34 @@ - - - - true - - - Toggle the checkbox to reveal the notes section. - - - Qt::AlignTop - - - + + + + &Title: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + titleEdit + + + + + + + &Password: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + passwordEdit + + + @@ -99,41 +142,34 @@ - - - - - - Toggle notes visible - - - Toggle notes visible - - - Notes: - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + + + + Qt::StrongFocus + + + Tags list + + - - + + 8 + + + + Toggle expiration + + + Toggle expiration + + + + + + @@ -168,24 +204,17 @@ - - - - Password: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - URL: + UR&L: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + urlEdit + @@ -215,80 +244,98 @@ - - - - Title: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Title field - - - - - - - Username: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Qt::StrongFocus - - - Password field - - - - - - - 0 - + + - - - Toggle expiration - - - Toggle expiration - + - Expires: + &Notes: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + notesEdit + + + + 6 + + + + + Qt::Horizontal + + + + 5 + 20 + + + + + + + + Toggle notes visibility + + + Toggle notes visibility + + + + 14 + 14 + + + + true + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + - Tags: + T&ags: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + tagsList + - - - - Qt::StrongFocus + + + + &Expires: - - Tags list + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + expireCheck @@ -325,7 +372,7 @@ expireCheck expireDatePicker expirePresets - notesEnabled + revealNotesButton notesEdit