FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Enhance Password Editing Fields · sourcecodes2/keepassxc@fe1189e · GitHub

Commit fe1189e

Browse files
committed
Enhance Password Editing Fields
* Remove repeat password on entry edit * Move show/hide password and password generator buttons into the field as actions. * Register keyboard shortcut Ctrl+H to toggle password visibility * Register keyboard shortcut Ctrl+G to open the password generator * Cleanup code and improve interactions between elements * Simplify Password Generator button layout; convert advanced mode button to toggle button * Update GUI tests * Fixes keepassxreboot#4120
1 parent 1d7ef5d commit fe1189e

20 files changed

Lines changed: 1358 additions & 1523 deletions

‎COPYING‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ Files: share/icons/application/scalable/categories/preferences-other.svg
180180
share/icons/application/scalable/actions/favicon-download.svg
181181
share/icons/application/scalable/actions/document-open.svg
182182
share/icons/application/scalable/actions/document-save-as.svg
183+
share/icons/application/scalable/actions/refresh.svg
184+
share/icons/application/scalable/actions/clipboard-text.svg
183185
Copyright: 2019 Austin Andrews <http://templarian.com/>
184186
License: SIL OPEN FONT LICENSE Version 1.1
185187
Comment: Taken from Material Design icon set (https://github.com/templarian/MaterialDesign/)
Lines changed: 1 addition & 0 deletions
LoadingViewer requires iframe.
Lines changed: 1 addition & 0 deletions
LoadingViewer requires iframe.

‎src/gui/DatabaseOpenWidget.cpp‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,6 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
5656

5757
m_ui->comboKeyFile->lineEdit()->addAction(m_ui->keyFileClearIcon, QLineEdit::TrailingPosition);
5858

59-
m_ui->buttonTogglePassword->setIcon(filePath()->onOffIcon("actions", "password-show"));
60-
connect(m_ui->buttonTogglePassword, SIGNAL(toggled(bool)), m_ui->editPassword, SLOT(setShowPassword(bool)));
61-
connect(m_ui->buttonTogglePassword, SIGNAL(toggled(bool)), m_ui->editPassword, SLOT(setFocus()));
6259
connect(m_ui->buttonBrowseFile, SIGNAL(clicked()), SLOT(browseKeyFile()));
6360

6461
connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase()));
@@ -166,10 +163,10 @@ void DatabaseOpenWidget::clearForms()
166163
{
167164
if (!m_isOpeningDatabase) {
168165
m_ui->editPassword->setText("");
166+
m_ui->editPassword->setShowPassword(false);
169167
m_ui->comboKeyFile->clear();
170168
m_ui->comboKeyFile->setEditText("");
171169
m_ui->checkTouchID->setChecked(false);
172-
m_ui->buttonTogglePassword->setChecked(false);
173170
m_db.reset();
174171
}
175172
}
@@ -195,7 +192,6 @@ void DatabaseOpenWidget::openDatabase()
195192
}
196193

197194
m_ui->editPassword->setShowPassword(false);
198-
m_ui->buttonTogglePassword->setChecked(false);
199195
QCoreApplication::processEvents();
200196

201197
m_isOpeningDatabase = true;

‎src/gui/DatabaseOpenWidget.ui‎

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
<ui version="4.0">
33
<class>DatabaseOpenWidget</class>
44
<widget class="QWidget" name="DatabaseOpenWidget">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>580</width>
10+
<height>410</height>
11+
</rect>
12+
</property>
513
<property name="accessibleName">
614
<string>Unlock KeePassXC Database</string>
715
</property>
@@ -157,31 +165,14 @@
157165
</widget>
158166
</item>
159167
<item>
160-
<layout class="QHBoxLayout" name="passwordLayout">
161-
<item>
162-
<widget class="PasswordEdit" name="editPassword">
163-
<property name="accessibleName">
164-
<string>Password field</string>
165-
</property>
166-
<property name="echoMode">
167-
<enum>QLineEdit::Password</enum>
168-
</property>
169-
</widget>
170-
</item>
171-
<item>
172-
<widget class="QToolButton" name="buttonTogglePassword">
173-
<property name="toolTip">
174-
<string>Toggle password visibility</string>
175-
</property>
176-
<property name="accessibleName">
177-
<string>Toggle password visibility</string>
178-
</property>
179-
<property name="checkable">
180-
<bool>true</bool>
181-
</property>
182-
</widget>
183-
</item>
184-
</layout>
168+
<widget class="PasswordEdit" name="editPassword">
169+
<property name="accessibleName">
170+
<string>Password field</string>
171+
</property>
172+
<property name="echoMode">
173+
<enum>QLineEdit::Password</enum>
174+
</property>
175+
</widget>
185176
</item>
186177
<item>
187178
<spacer name="verticalSpacer_4">
@@ -612,8 +603,6 @@
612603
</customwidget>
613604
</customwidgets>
614605
<tabstops>
615-
<tabstop>editPassword</tabstop>
616-
<tabstop>buttonTogglePassword</tabstop>
617606
<tabstop>comboKeyFile</tabstop>
618607
<tabstop>buttonBrowseFile</tabstop>
619608
<tabstop>hardwareKeyLabelHelp</tabstop>

‎src/gui/MainWindow.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ MainWindow::MainWindow()
451451

452452
connect(m_ui->actionSettings, SIGNAL(toggled(bool)), SLOT(switchToSettings(bool)));
453453
connect(m_ui->actionPasswordGenerator, SIGNAL(toggled(bool)), SLOT(switchToPasswordGen(bool)));
454-
connect(m_ui->passwordGeneratorWidget, SIGNAL(dialogTerminated()), SLOT(closePasswordGen()));
454+
connect(m_ui->passwordGeneratorWidget, SIGNAL(closePasswordGenerator()), SLOT(closePasswordGen()));
455455

456456
connect(m_ui->welcomeWidget, SIGNAL(newDatabase()), SLOT(switchToNewDatabase()));
457457
connect(m_ui->welcomeWidget, SIGNAL(openDatabase()), SLOT(switchToOpenDatabase()));

‎src/gui/MainWindow.ui‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,35 @@
186186
</widget>
187187
<widget class="QWidget" name="pagePasswordGenerator">
188188
<layout class="QVBoxLayout" name="verticalLayout_6">
189+
<property name="leftMargin">
190+
<number>60</number>
191+
</property>
192+
<property name="topMargin">
193+
<number>30</number>
194+
</property>
195+
<property name="rightMargin">
196+
<number>60</number>
197+
</property>
189198
<item>
190199
<widget class="PasswordGeneratorWidget" name="passwordGeneratorWidget" native="true">
191200
<property name="focusPolicy">
192201
<enum>Qt::TabFocus</enum>
193202
</property>
194203
</widget>
195204
</item>
205+
<item>
206+
<spacer name="verticalSpacer">
207+
<property name="orientation">
208+
<enum>Qt::Vertical</enum>
209+
</property>
210+
<property name="sizeHint" stdset="0">
211+
<size>
212+
<width>20</width>
213+
<height>40</height>
214+
</size>
215+
</property>
216+
</spacer>
217+
</item>
196218
</layout>
197219
</widget>
198220
</widget>

‎src/gui/PasswordEdit.cpp‎

Lines changed: 97 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,24 @@
2020

2121
#include "core/Config.h"
2222
#include "core/FilePath.h"
23+
#include "gui/Application.h"
2324
#include "gui/Font.h"
25+
#include "gui/PasswordGeneratorWidget.h"
2426

25-
const QColor PasswordEdit::CorrectSoFarColor = QColor(255, 205, 15);
26-
const QColor PasswordEdit::ErrorColor = QColor(255, 125, 125);
27+
#include <QDialog>
28+
#include <QVBoxLayout>
29+
30+
namespace
31+
{
32+
const QColor CorrectSoFarColor(255, 205, 15);
33+
const QColor CorrectSoFarColorDark(115, 104, 46);
34+
const QColor ErrorColor(255, 125, 125);
35+
const QColor ErrorColorDark(128, 45, 45);
36+
37+
} // namespace
2738

2839
PasswordEdit::PasswordEdit(QWidget* parent)
2940
: QLineEdit(parent)
30-
, m_basePasswordEdit(nullptr)
3141
{
3242
const QIcon errorIcon = filePath()->icon("status", "dialog-error");
3343
m_errorAction = addAction(errorIcon, QLineEdit::TrailingPosition);
@@ -40,70 +50,122 @@ PasswordEdit::PasswordEdit(QWidget* parent)
4050
m_correctAction->setToolTip(tr("Passwords match so far"));
4151

4252
setEchoMode(QLineEdit::Password);
43-
updateStylesheet();
4453

4554
// use a monospace font for the password field
4655
QFont passwordFont = Font::fixedFont();
4756
passwordFont.setLetterSpacing(QFont::PercentageSpacing, 110);
4857
setFont(passwordFont);
58+
59+
m_toggleVisibleAction = new QAction(
60+
filePath()->icon("actions", "password-show-off"),
61+
tr("Toggle Password (%1)").arg(QKeySequence(Qt::CTRL + Qt::Key_H).toString(QKeySequence::NativeText)),
62+
nullptr);
63+
m_toggleVisibleAction->setCheckable(true);
64+
m_toggleVisibleAction->setShortcut(Qt::CTRL + Qt::Key_H);
65+
m_toggleVisibleAction->setShortcutContext(Qt::WidgetShortcut);
66+
addAction(m_toggleVisibleAction, QLineEdit::TrailingPosition);
67+
connect(m_toggleVisibleAction, &QAction::triggered, this, &PasswordEdit::setShowPassword);
68+
69+
m_passwordGeneratorAction = new QAction(
70+
filePath()->icon("actions", "password-generator"),
71+
tr("Generate Password (%1)").arg(QKeySequence(Qt::CTRL + Qt::Key_G).toString(QKeySequence::NativeText)),
72+
nullptr);
73+
m_passwordGeneratorAction->setShortcut(Qt::CTRL + Qt::Key_G);
74+
m_passwordGeneratorAction->setShortcutContext(Qt::WidgetShortcut);
75+
addAction(m_passwordGeneratorAction, QLineEdit::TrailingPosition);
76+
m_passwordGeneratorAction->setVisible(false);
4977
}
5078

51-
void PasswordEdit::enableVerifyMode(PasswordEdit* basePasswordEdit)
79+
void PasswordEdit::setRepeatPartner(PasswordEdit* repeatEdit)
5280
{
53-
m_basePasswordEdit = basePasswordEdit;
81+
m_repeatPasswordEdit = repeatEdit;
82+
m_repeatPasswordEdit->setParentPasswordEdit(this);
5483

55-
updateStylesheet();
84+
connect(this, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(autocompletePassword(QString)));
85+
connect(this, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(updateRepeatStatus()));
86+
connect(m_repeatPasswordEdit, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(updateRepeatStatus()));
87+
}
88+
89+
void PasswordEdit::setParentPasswordEdit(PasswordEdit* parent)
90+
{
91+
m_parentPasswordEdit = parent;
92+
// Hide actions
93+
m_toggleVisibleAction->setVisible(false);
94+
m_passwordGeneratorAction->setVisible(false);
95+
}
5696

57-
connect(m_basePasswordEdit, SIGNAL(textChanged(QString)), SLOT(autocompletePassword(QString)));
58-
connect(m_basePasswordEdit, SIGNAL(textChanged(QString)), SLOT(updateStylesheet()));
59-
connect(this, SIGNAL(textChanged(QString)), SLOT(updateStylesheet()));
97+
void PasswordEdit::enablePasswordGenerator(bool signalOnly)
98+
{
99+
disconnect(m_passwordGeneratorAction);
100+
m_passwordGeneratorAction->setVisible(true);
60101

61-
connect(m_basePasswordEdit, SIGNAL(showPasswordChanged(bool)), SLOT(setShowPassword(bool)));
102+
if (signalOnly) {
103+
connect(m_passwordGeneratorAction, &QAction::triggered, this, &PasswordEdit::togglePasswordGenerator);
104+
} else {
105+
connect(m_passwordGeneratorAction, &QAction::triggered, this, &PasswordEdit::popupPasswordGenerator);
106+
}
62107
}
63108

64109
void PasswordEdit::setShowPassword(bool show)
65110
{
66111
setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password);
67-
// if I have a parent, I'm the child
68-
if (m_basePasswordEdit) {
112+
m_toggleVisibleAction->setIcon(filePath()->icon("actions", show ? "password-show-on" : "password-show-off"));
113+
m_toggleVisibleAction->setChecked(show);
114+
115+
if (m_repeatPasswordEdit) {
116+
m_repeatPasswordEdit->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password);
69117
if (config()->get("security/passwordsrepeat").toBool()) {
70-
setEnabled(!show);
71-
setReadOnly(show);
72-
setText(m_basePasswordEdit->text());
118+
m_repeatPasswordEdit->setEnabled(!show);
119+
m_repeatPasswordEdit->setText(text());
73120
} else {
74-
// This fix a bug when the QLineEdit is disabled while switching config
75-
if (!isEnabled()) {
76-
setEnabled(true);
77-
setReadOnly(false);
78-
}
121+
m_repeatPasswordEdit->setEnabled(true);
79122
}
80123
}
81-
updateStylesheet();
82-
emit showPasswordChanged(show);
83124
}
84125

85126
bool PasswordEdit::isPasswordVisible() const
86127
{
87-
return isEnabled();
128+
return echoMode() == QLineEdit::Normal;
88129
}
89130

90-
bool PasswordEdit::passwordsEqual() const
131+
void PasswordEdit::popupPasswordGenerator()
91132
{
92-
return text() == m_basePasswordEdit->text();
133+
auto pwGenerator = new PasswordGeneratorWidget();
134+
QDialog pwDialog(this);
135+
pwDialog.setWindowTitle(tr("Generate Password"));
136+
auto layout = new QVBoxLayout();
137+
pwDialog.setLayout(layout);
138+
layout->addWidget(pwGenerator);
139+
140+
pwGenerator->setStandaloneMode(false);
141+
pwGenerator->setPasswordVisible(isPasswordVisible());
142+
143+
connect(pwGenerator, SIGNAL(closePasswordGenerator()), &pwDialog, SLOT(close()));
144+
connect(pwGenerator, SIGNAL(appliedPassword(QString)), SLOT(setText(QString)));
145+
if (m_repeatPasswordEdit) {
146+
connect(pwGenerator, SIGNAL(appliedPassword(QString)), m_repeatPasswordEdit, SLOT(setText(QString)));
147+
}
148+
149+
pwDialog.exec();
93150
}
94151

95-
void PasswordEdit::updateStylesheet()
152+
void PasswordEdit::updateRepeatStatus()
96153
{
97-
const QString stylesheetTemplate("QLineEdit { background: %1; }");
154+
static const auto stylesheetTemplate = QStringLiteral("QLineEdit { background: %1; }");
155+
if (!m_parentPasswordEdit) {
156+
return;
157+
}
98158

99-
if (m_basePasswordEdit && !passwordsEqual()) {
100-
bool isCorrect = true;
101-
if (m_basePasswordEdit->text().startsWith(text())) {
102-
setStyleSheet(stylesheetTemplate.arg(CorrectSoFarColor.name()));
103-
} else {
104-
setStyleSheet(stylesheetTemplate.arg(ErrorColor.name()));
105-
isCorrect = false;
159+
const auto otherPassword = m_parentPasswordEdit->text();
160+
const auto password = text();
161+
if (otherPassword != password) {
162+
bool isCorrect = false;
163+
QColor color = kpxcApp->isDarkTheme() ? ErrorColorDark : ErrorColor;
164+
if (!password.isEmpty() && otherPassword.startsWith(password)) {
165+
color = kpxcApp->isDarkTheme() ? CorrectSoFarColorDark : CorrectSoFarColor;
166+
isCorrect = true;
106167
}
168+
setStyleSheet(stylesheetTemplate.arg(color.name()));
107169
m_correctAction->setVisible(isCorrect);
108170
m_errorAction->setVisible(!isCorrect);
109171
} else {

‎src/gui/PasswordEdit.h‎

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,29 +28,32 @@ class PasswordEdit : public QLineEdit
2828
Q_OBJECT
2929

3030
public:
31-
static const QColor CorrectSoFarColor;
32-
static const QColor ErrorColor;
33-
3431
explicit PasswordEdit(QWidget* parent = nullptr);
35-
void enableVerifyMode(PasswordEdit* baseEdit);
32+
void enablePasswordGenerator(bool signalOnly = false);
33+
void setRepeatPartner(PasswordEdit* repeatEdit);
3634
bool isPasswordVisible() const;
3735

3836
public slots:
3937
void setShowPassword(bool show);
38+
void updateRepeatStatus();
4039

4140
signals:
42-
void showPasswordChanged(bool show);
41+
void togglePasswordGenerator();
4342

4443
private slots:
45-
void updateStylesheet();
4644
void autocompletePassword(const QString& password);
45+
void popupPasswordGenerator();
46+
void setParentPasswordEdit(PasswordEdit* parent);
4747

4848
private:
49-
bool passwordsEqual() const;
50-
5149
QPointer<QAction> m_errorAction;
5250
QPointer<QAction> m_correctAction;
53-
QPointer<PasswordEdit> m_basePasswordEdit;
51+
QPointer<QAction> m_toggleVisibleAction;
52+
QPointer<QAction> m_passwordGeneratorAction;
53+
QPointer<PasswordEdit> m_repeatPasswordEdit;
54+
QPointer<PasswordEdit> m_parentPasswordEdit;
55+
bool m_sendGeneratorSignal = false;
56+
bool m_isRepeatPartner = false;
5457
};
5558

5659
#endif // KEEPASSX_PASSWORDEDIT_H

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL