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
This commit is contained in:
Jonathan White 2023-04-15 21:35:54 -04:00 committed by GitHub
parent fb2672e910
commit 52775d4a3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 239 additions and 173 deletions

View File

@ -2840,22 +2840,10 @@ Would you like to correct it?</source>
<source>Notes field</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toggle the checkbox to reveal the notes section.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Username field</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toggle notes visible</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Notes:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Expiration field</source>
<translation type="unfinished"></translation>
@ -2872,14 +2860,6 @@ Would you like to correct it?</source>
<source>Presets</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Password:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>URL:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Url field</source>
<translation type="unfinished"></translation>
@ -2888,18 +2868,10 @@ Would you like to correct it?</source>
<source>Download favicon for URL</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Title:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Title field</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Username:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Password field</source>
<translation type="unfinished"></translation>
@ -2908,18 +2880,42 @@ Would you like to correct it?</source>
<source>Toggle expiration</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Expires:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Tags:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Tags list</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Username:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Title:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Password:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>UR&amp;L:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Notes:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toggle notes visibility</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>T&amp;ags:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Expires:</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditEntryWidgetSSHAgent</name>
@ -6207,6 +6203,10 @@ Do you want to overwrite it?</source>
<comment>Password quality</comment>
<translation type="unfinished"></translation>
</message>
<message>
<source>Toggle password visibilty using Control + H. Open the password generator using Control + G.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PickcharsDialog</name>

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>508</width>
<width>530</width>
<height>257</height>
</rect>
</property>
@ -177,7 +177,7 @@
<item>
<widget class="QTabWidget" name="entryTabWidget">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<property name="documentMode">
<bool>false</bool>
@ -753,7 +753,7 @@
<string>Default Sequence</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
</property>
</widget>
</item>
@ -771,6 +771,9 @@
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>

View File

@ -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()) {

View File

@ -27,7 +27,11 @@
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="passwordEdit"/>
<widget class="QLineEdit" name="passwordEdit">
<property name="accessibleDescription">
<string>Toggle password visibilty using Control + H. Open the password generator using Control + G.</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="qualityProgressBar">

View File

@ -168,7 +168,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*)));
@ -839,7 +839,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
@ -898,10 +898,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 {

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>539</width>
<width>400</width>
<height>523</height>
</rect>
</property>
@ -33,11 +33,11 @@
<rect>
<x>0</x>
<y>0</y>
<width>539</width>
<width>400</width>
<height>523</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<layout class="QGridLayout" name="gridLayout" columnstretch="0,1">
<property name="leftMargin">
<number>0</number>
</property>
@ -56,7 +56,37 @@
<property name="verticalSpacing">
<number>8</number>
</property>
<item row="7" column="1">
<item row="0" column="1">
<widget class="QLineEdit" name="titleEdit">
<property name="accessibleName">
<string>Title field</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="usernameLabel">
<property name="text">
<string>&amp;Username:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>usernameComboBox</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="PasswordWidget" name="passwordEdit" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="accessibleName">
<string>Password field</string>
</property>
</widget>
</item>
<item row="8" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPlainTextEdit" name="notesEdit">
@ -77,21 +107,34 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="notesHint">
<property name="visible">
<bool>true</bool>
</property>
<property name="text">
<string>Toggle the checkbox to reveal the notes section.</string>
</property>
<property name="alignment">
<set>Qt::AlignTop</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="titleLabel">
<property name="text">
<string>&amp;Title:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>titleEdit</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="passwordLabel">
<property name="text">
<string>&amp;Password:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>passwordEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="usernameComboBox">
<property name="accessibleName">
@ -99,41 +142,34 @@
</property>
</widget>
</item>
<item row="7" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="notesEnabled">
<property name="toolTip">
<string>Toggle notes visible</string>
</property>
<property name="accessibleName">
<string>Toggle notes visible</string>
</property>
<property name="text">
<string>Notes:</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
<item row="5" column="1">
<widget class="TagsEdit" name="tagsList" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="accessibleName">
<string>Tags list</string>
</property>
</widget>
</item>
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item row="7" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1,0">
<property name="spacing">
<number>8</number>
</property>
<item>
<widget class="QCheckBox" name="expireCheck">
<property name="toolTip">
<string>Toggle expiration</string>
</property>
<property name="accessibleName">
<string>Toggle expiration</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QDateTimeEdit" name="expireDatePicker">
<property name="enabled">
@ -168,24 +204,17 @@
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="passwordLabel">
<property name="text">
<string>Password:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="urlLabel">
<property name="text">
<string>URL:</string>
<string>UR&amp;L:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>urlEdit</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
@ -215,80 +244,98 @@
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="titleLabel">
<property name="text">
<string>Title:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="titleEdit">
<property name="accessibleName">
<string>Title field</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="usernameLabel">
<property name="text">
<string>Username:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="PasswordWidget" name="passwordEdit" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="accessibleName">
<string>Password field</string>
</property>
</widget>
</item>
<item row="6" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<item row="8" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="expireCheck">
<property name="toolTip">
<string>Toggle expiration</string>
</property>
<property name="accessibleName">
<string>Toggle expiration</string>
</property>
<widget class="QLabel" name="notesLabel">
<property name="text">
<string>Expires:</string>
<string>&amp;Notes:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>notesEdit</cstring>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="topMargin">
<number>6</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="revealNotesButton">
<property name="toolTip">
<string>Toggle notes visibility</string>
</property>
<property name="accessibleName">
<string>Toggle notes visibility</string>
</property>
<property name="iconSize">
<size>
<width>14</width>
<height>14</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="5" column="0">
<widget class="QLabel" name="tagsLabel">
<property name="text">
<string>Tags:</string>
<string>T&amp;ags:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>tagsList</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="TagsEdit" name="tagsList" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
<item row="7" column="0">
<widget class="QLabel" name="expireLabel">
<property name="text">
<string>&amp;Expires:</string>
</property>
<property name="accessibleName">
<string>Tags list</string>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>expireCheck</cstring>
</property>
</widget>
</item>
@ -325,7 +372,7 @@
<tabstop>expireCheck</tabstop>
<tabstop>expireDatePicker</tabstop>
<tabstop>expirePresets</tabstop>
<tabstop>notesEnabled</tabstop>
<tabstop>revealNotesButton</tabstop>
<tabstop>notesEdit</tabstop>
</tabstops>
<resources/>