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 #4120
This commit is contained in:
Jonathan White 2020-03-08 22:22:01 -04:00
parent 1d7ef5d4eb
commit fe1189ea79
20 changed files with 1459 additions and 1624 deletions

View File

@ -180,6 +180,8 @@ Files: share/icons/application/scalable/categories/preferences-other.svg
share/icons/application/scalable/actions/favicon-download.svg share/icons/application/scalable/actions/favicon-download.svg
share/icons/application/scalable/actions/document-open.svg share/icons/application/scalable/actions/document-open.svg
share/icons/application/scalable/actions/document-save-as.svg share/icons/application/scalable/actions/document-save-as.svg
share/icons/application/scalable/actions/refresh.svg
share/icons/application/scalable/actions/clipboard-text.svg
Copyright: 2019 Austin Andrews <http://templarian.com/> Copyright: 2019 Austin Andrews <http://templarian.com/>
License: SIL OPEN FONT LICENSE Version 1.1 License: SIL OPEN FONT LICENSE Version 1.1
Comment: Taken from Material Design icon set (https://github.com/templarian/MaterialDesign/) Comment: Taken from Material Design icon set (https://github.com/templarian/MaterialDesign/)

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M19,3H14.82C14.25,1.44 12.53,0.64 11,1.2C10.14,1.5 9.5,2.16 9.18,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M12,3A1,1 0 0,1 13,4A1,1 0 0,1 12,5A1,1 0 0,1 11,4A1,1 0 0,1 12,3M7,7H17V5H19V19H5V5H7V7M17,11H7V9H17V11M15,15H7V13H15V15Z" /></svg>

After

Width:  |  Height:  |  Size: 553 B

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z" /></svg>

After

Width:  |  Height:  |  Size: 505 B

View File

@ -56,9 +56,6 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
m_ui->comboKeyFile->lineEdit()->addAction(m_ui->keyFileClearIcon, QLineEdit::TrailingPosition); m_ui->comboKeyFile->lineEdit()->addAction(m_ui->keyFileClearIcon, QLineEdit::TrailingPosition);
m_ui->buttonTogglePassword->setIcon(filePath()->onOffIcon("actions", "password-show"));
connect(m_ui->buttonTogglePassword, SIGNAL(toggled(bool)), m_ui->editPassword, SLOT(setShowPassword(bool)));
connect(m_ui->buttonTogglePassword, SIGNAL(toggled(bool)), m_ui->editPassword, SLOT(setFocus()));
connect(m_ui->buttonBrowseFile, SIGNAL(clicked()), SLOT(browseKeyFile())); connect(m_ui->buttonBrowseFile, SIGNAL(clicked()), SLOT(browseKeyFile()));
connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase())); connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase()));
@ -166,10 +163,10 @@ void DatabaseOpenWidget::clearForms()
{ {
if (!m_isOpeningDatabase) { if (!m_isOpeningDatabase) {
m_ui->editPassword->setText(""); m_ui->editPassword->setText("");
m_ui->editPassword->setShowPassword(false);
m_ui->comboKeyFile->clear(); m_ui->comboKeyFile->clear();
m_ui->comboKeyFile->setEditText(""); m_ui->comboKeyFile->setEditText("");
m_ui->checkTouchID->setChecked(false); m_ui->checkTouchID->setChecked(false);
m_ui->buttonTogglePassword->setChecked(false);
m_db.reset(); m_db.reset();
} }
} }
@ -195,7 +192,6 @@ void DatabaseOpenWidget::openDatabase()
} }
m_ui->editPassword->setShowPassword(false); m_ui->editPassword->setShowPassword(false);
m_ui->buttonTogglePassword->setChecked(false);
QCoreApplication::processEvents(); QCoreApplication::processEvents();
m_isOpeningDatabase = true; m_isOpeningDatabase = true;

View File

@ -2,6 +2,14 @@
<ui version="4.0"> <ui version="4.0">
<class>DatabaseOpenWidget</class> <class>DatabaseOpenWidget</class>
<widget class="QWidget" name="DatabaseOpenWidget"> <widget class="QWidget" name="DatabaseOpenWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>580</width>
<height>410</height>
</rect>
</property>
<property name="accessibleName"> <property name="accessibleName">
<string>Unlock KeePassXC Database</string> <string>Unlock KeePassXC Database</string>
</property> </property>
@ -157,31 +165,14 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="passwordLayout"> <widget class="PasswordEdit" name="editPassword">
<item> <property name="accessibleName">
<widget class="PasswordEdit" name="editPassword"> <string>Password field</string>
<property name="accessibleName"> </property>
<string>Password field</string> <property name="echoMode">
</property> <enum>QLineEdit::Password</enum>
<property name="echoMode"> </property>
<enum>QLineEdit::Password</enum> </widget>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonTogglePassword">
<property name="toolTip">
<string>Toggle password visibility</string>
</property>
<property name="accessibleName">
<string>Toggle password visibility</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item>
<spacer name="verticalSpacer_4"> <spacer name="verticalSpacer_4">
@ -612,8 +603,6 @@
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>editPassword</tabstop>
<tabstop>buttonTogglePassword</tabstop>
<tabstop>comboKeyFile</tabstop> <tabstop>comboKeyFile</tabstop>
<tabstop>buttonBrowseFile</tabstop> <tabstop>buttonBrowseFile</tabstop>
<tabstop>hardwareKeyLabelHelp</tabstop> <tabstop>hardwareKeyLabelHelp</tabstop>

View File

@ -451,7 +451,7 @@ MainWindow::MainWindow()
connect(m_ui->actionSettings, SIGNAL(toggled(bool)), SLOT(switchToSettings(bool))); connect(m_ui->actionSettings, SIGNAL(toggled(bool)), SLOT(switchToSettings(bool)));
connect(m_ui->actionPasswordGenerator, SIGNAL(toggled(bool)), SLOT(switchToPasswordGen(bool))); connect(m_ui->actionPasswordGenerator, SIGNAL(toggled(bool)), SLOT(switchToPasswordGen(bool)));
connect(m_ui->passwordGeneratorWidget, SIGNAL(dialogTerminated()), SLOT(closePasswordGen())); connect(m_ui->passwordGeneratorWidget, SIGNAL(closePasswordGenerator()), SLOT(closePasswordGen()));
connect(m_ui->welcomeWidget, SIGNAL(newDatabase()), SLOT(switchToNewDatabase())); connect(m_ui->welcomeWidget, SIGNAL(newDatabase()), SLOT(switchToNewDatabase()));
connect(m_ui->welcomeWidget, SIGNAL(openDatabase()), SLOT(switchToOpenDatabase())); connect(m_ui->welcomeWidget, SIGNAL(openDatabase()), SLOT(switchToOpenDatabase()));

View File

@ -186,6 +186,15 @@
</widget> </widget>
<widget class="QWidget" name="pagePasswordGenerator"> <widget class="QWidget" name="pagePasswordGenerator">
<layout class="QVBoxLayout" name="verticalLayout_6"> <layout class="QVBoxLayout" name="verticalLayout_6">
<property name="leftMargin">
<number>60</number>
</property>
<property name="topMargin">
<number>30</number>
</property>
<property name="rightMargin">
<number>60</number>
</property>
<item> <item>
<widget class="PasswordGeneratorWidget" name="passwordGeneratorWidget" native="true"> <widget class="PasswordGeneratorWidget" name="passwordGeneratorWidget" native="true">
<property name="focusPolicy"> <property name="focusPolicy">
@ -193,6 +202,19 @@
</property> </property>
</widget> </widget>
</item> </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> </layout>
</widget> </widget>
</widget> </widget>

View File

@ -20,14 +20,24 @@
#include "core/Config.h" #include "core/Config.h"
#include "core/FilePath.h" #include "core/FilePath.h"
#include "gui/Application.h"
#include "gui/Font.h" #include "gui/Font.h"
#include "gui/PasswordGeneratorWidget.h"
const QColor PasswordEdit::CorrectSoFarColor = QColor(255, 205, 15); #include <QDialog>
const QColor PasswordEdit::ErrorColor = QColor(255, 125, 125); #include <QVBoxLayout>
namespace
{
const QColor CorrectSoFarColor(255, 205, 15);
const QColor CorrectSoFarColorDark(115, 104, 46);
const QColor ErrorColor(255, 125, 125);
const QColor ErrorColorDark(128, 45, 45);
} // namespace
PasswordEdit::PasswordEdit(QWidget* parent) PasswordEdit::PasswordEdit(QWidget* parent)
: QLineEdit(parent) : QLineEdit(parent)
, m_basePasswordEdit(nullptr)
{ {
const QIcon errorIcon = filePath()->icon("status", "dialog-error"); const QIcon errorIcon = filePath()->icon("status", "dialog-error");
m_errorAction = addAction(errorIcon, QLineEdit::TrailingPosition); m_errorAction = addAction(errorIcon, QLineEdit::TrailingPosition);
@ -40,70 +50,122 @@ PasswordEdit::PasswordEdit(QWidget* parent)
m_correctAction->setToolTip(tr("Passwords match so far")); m_correctAction->setToolTip(tr("Passwords match so far"));
setEchoMode(QLineEdit::Password); setEchoMode(QLineEdit::Password);
updateStylesheet();
// use a monospace font for the password field // use a monospace font for the password field
QFont passwordFont = Font::fixedFont(); QFont passwordFont = Font::fixedFont();
passwordFont.setLetterSpacing(QFont::PercentageSpacing, 110); passwordFont.setLetterSpacing(QFont::PercentageSpacing, 110);
setFont(passwordFont); setFont(passwordFont);
m_toggleVisibleAction = new QAction(
filePath()->icon("actions", "password-show-off"),
tr("Toggle Password (%1)").arg(QKeySequence(Qt::CTRL + Qt::Key_H).toString(QKeySequence::NativeText)),
nullptr);
m_toggleVisibleAction->setCheckable(true);
m_toggleVisibleAction->setShortcut(Qt::CTRL + Qt::Key_H);
m_toggleVisibleAction->setShortcutContext(Qt::WidgetShortcut);
addAction(m_toggleVisibleAction, QLineEdit::TrailingPosition);
connect(m_toggleVisibleAction, &QAction::triggered, this, &PasswordEdit::setShowPassword);
m_passwordGeneratorAction = new QAction(
filePath()->icon("actions", "password-generator"),
tr("Generate Password (%1)").arg(QKeySequence(Qt::CTRL + Qt::Key_G).toString(QKeySequence::NativeText)),
nullptr);
m_passwordGeneratorAction->setShortcut(Qt::CTRL + Qt::Key_G);
m_passwordGeneratorAction->setShortcutContext(Qt::WidgetShortcut);
addAction(m_passwordGeneratorAction, QLineEdit::TrailingPosition);
m_passwordGeneratorAction->setVisible(false);
} }
void PasswordEdit::enableVerifyMode(PasswordEdit* basePasswordEdit) void PasswordEdit::setRepeatPartner(PasswordEdit* repeatEdit)
{ {
m_basePasswordEdit = basePasswordEdit; m_repeatPasswordEdit = repeatEdit;
m_repeatPasswordEdit->setParentPasswordEdit(this);
updateStylesheet(); connect(this, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(autocompletePassword(QString)));
connect(this, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(updateRepeatStatus()));
connect(m_repeatPasswordEdit, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(updateRepeatStatus()));
}
connect(m_basePasswordEdit, SIGNAL(textChanged(QString)), SLOT(autocompletePassword(QString))); void PasswordEdit::setParentPasswordEdit(PasswordEdit* parent)
connect(m_basePasswordEdit, SIGNAL(textChanged(QString)), SLOT(updateStylesheet())); {
connect(this, SIGNAL(textChanged(QString)), SLOT(updateStylesheet())); m_parentPasswordEdit = parent;
// Hide actions
m_toggleVisibleAction->setVisible(false);
m_passwordGeneratorAction->setVisible(false);
}
connect(m_basePasswordEdit, SIGNAL(showPasswordChanged(bool)), SLOT(setShowPassword(bool))); void PasswordEdit::enablePasswordGenerator(bool signalOnly)
{
disconnect(m_passwordGeneratorAction);
m_passwordGeneratorAction->setVisible(true);
if (signalOnly) {
connect(m_passwordGeneratorAction, &QAction::triggered, this, &PasswordEdit::togglePasswordGenerator);
} else {
connect(m_passwordGeneratorAction, &QAction::triggered, this, &PasswordEdit::popupPasswordGenerator);
}
} }
void PasswordEdit::setShowPassword(bool show) void PasswordEdit::setShowPassword(bool show)
{ {
setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password);
// if I have a parent, I'm the child m_toggleVisibleAction->setIcon(filePath()->icon("actions", show ? "password-show-on" : "password-show-off"));
if (m_basePasswordEdit) { m_toggleVisibleAction->setChecked(show);
if (m_repeatPasswordEdit) {
m_repeatPasswordEdit->setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password);
if (config()->get("security/passwordsrepeat").toBool()) { if (config()->get("security/passwordsrepeat").toBool()) {
setEnabled(!show); m_repeatPasswordEdit->setEnabled(!show);
setReadOnly(show); m_repeatPasswordEdit->setText(text());
setText(m_basePasswordEdit->text());
} else { } else {
// This fix a bug when the QLineEdit is disabled while switching config m_repeatPasswordEdit->setEnabled(true);
if (!isEnabled()) {
setEnabled(true);
setReadOnly(false);
}
} }
} }
updateStylesheet();
emit showPasswordChanged(show);
} }
bool PasswordEdit::isPasswordVisible() const bool PasswordEdit::isPasswordVisible() const
{ {
return isEnabled(); return echoMode() == QLineEdit::Normal;
} }
bool PasswordEdit::passwordsEqual() const void PasswordEdit::popupPasswordGenerator()
{ {
return text() == m_basePasswordEdit->text(); auto pwGenerator = new PasswordGeneratorWidget();
QDialog pwDialog(this);
pwDialog.setWindowTitle(tr("Generate Password"));
auto layout = new QVBoxLayout();
pwDialog.setLayout(layout);
layout->addWidget(pwGenerator);
pwGenerator->setStandaloneMode(false);
pwGenerator->setPasswordVisible(isPasswordVisible());
connect(pwGenerator, SIGNAL(closePasswordGenerator()), &pwDialog, SLOT(close()));
connect(pwGenerator, SIGNAL(appliedPassword(QString)), SLOT(setText(QString)));
if (m_repeatPasswordEdit) {
connect(pwGenerator, SIGNAL(appliedPassword(QString)), m_repeatPasswordEdit, SLOT(setText(QString)));
}
pwDialog.exec();
} }
void PasswordEdit::updateStylesheet() void PasswordEdit::updateRepeatStatus()
{ {
const QString stylesheetTemplate("QLineEdit { background: %1; }"); static const auto stylesheetTemplate = QStringLiteral("QLineEdit { background: %1; }");
if (!m_parentPasswordEdit) {
return;
}
if (m_basePasswordEdit && !passwordsEqual()) { const auto otherPassword = m_parentPasswordEdit->text();
bool isCorrect = true; const auto password = text();
if (m_basePasswordEdit->text().startsWith(text())) { if (otherPassword != password) {
setStyleSheet(stylesheetTemplate.arg(CorrectSoFarColor.name())); bool isCorrect = false;
} else { QColor color = kpxcApp->isDarkTheme() ? ErrorColorDark : ErrorColor;
setStyleSheet(stylesheetTemplate.arg(ErrorColor.name())); if (!password.isEmpty() && otherPassword.startsWith(password)) {
isCorrect = false; color = kpxcApp->isDarkTheme() ? CorrectSoFarColorDark : CorrectSoFarColor;
isCorrect = true;
} }
setStyleSheet(stylesheetTemplate.arg(color.name()));
m_correctAction->setVisible(isCorrect); m_correctAction->setVisible(isCorrect);
m_errorAction->setVisible(!isCorrect); m_errorAction->setVisible(!isCorrect);
} else { } else {

View File

@ -28,29 +28,32 @@ class PasswordEdit : public QLineEdit
Q_OBJECT Q_OBJECT
public: public:
static const QColor CorrectSoFarColor;
static const QColor ErrorColor;
explicit PasswordEdit(QWidget* parent = nullptr); explicit PasswordEdit(QWidget* parent = nullptr);
void enableVerifyMode(PasswordEdit* baseEdit); void enablePasswordGenerator(bool signalOnly = false);
void setRepeatPartner(PasswordEdit* repeatEdit);
bool isPasswordVisible() const; bool isPasswordVisible() const;
public slots: public slots:
void setShowPassword(bool show); void setShowPassword(bool show);
void updateRepeatStatus();
signals: signals:
void showPasswordChanged(bool show); void togglePasswordGenerator();
private slots: private slots:
void updateStylesheet();
void autocompletePassword(const QString& password); void autocompletePassword(const QString& password);
void popupPasswordGenerator();
void setParentPasswordEdit(PasswordEdit* parent);
private: private:
bool passwordsEqual() const;
QPointer<QAction> m_errorAction; QPointer<QAction> m_errorAction;
QPointer<QAction> m_correctAction; QPointer<QAction> m_correctAction;
QPointer<PasswordEdit> m_basePasswordEdit; QPointer<QAction> m_toggleVisibleAction;
QPointer<QAction> m_passwordGeneratorAction;
QPointer<PasswordEdit> m_repeatPasswordEdit;
QPointer<PasswordEdit> m_parentPasswordEdit;
bool m_sendGeneratorSignal = false;
bool m_isRepeatPartner = false;
}; };
#endif // KEEPASSX_PASSWORDEDIT_H #endif // KEEPASSX_PASSWORDEDIT_H

View File

@ -27,36 +27,38 @@
#include "core/FilePath.h" #include "core/FilePath.h"
#include "core/PasswordGenerator.h" #include "core/PasswordGenerator.h"
#include "core/PasswordHealth.h" #include "core/PasswordHealth.h"
#include "gui/Application.h"
#include "gui/Clipboard.h" #include "gui/Clipboard.h"
#include "gui/osutils/OSUtils.h"
PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent) PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent)
: QWidget(parent) : QWidget(parent)
, m_updatingSpinBox(false)
, m_passwordGenerator(new PasswordGenerator()) , m_passwordGenerator(new PasswordGenerator())
, m_dicewareGenerator(new PassphraseGenerator()) , m_dicewareGenerator(new PassphraseGenerator())
, m_ui(new Ui::PasswordGeneratorWidget()) , m_ui(new Ui::PasswordGeneratorWidget())
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show")); m_ui->buttonGenerate->setIcon(filePath()->icon("actions", "refresh"));
m_ui->buttonGenerate->setToolTip(
tr("Regenerate password (%1)").arg(m_ui->buttonGenerate->shortcut().toString(QKeySequence::NativeText)));
m_ui->buttonCopy->setIcon(filePath()->icon("actions", "clipboard-text"));
m_ui->buttonClose->setShortcut(Qt::Key_Escape);
connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updateButtonsEnabled(QString))); connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updateButtonsEnabled(QString)));
connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updatePasswordStrength(QString))); connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updatePasswordStrength(QString)));
connect(m_ui->togglePasswordButton, SIGNAL(toggled(bool)), SLOT(setPasswordVisible(bool))); connect(m_ui->buttonAdvancedMode, SIGNAL(toggled(bool)), SLOT(setAdvancedMode(bool)));
connect(m_ui->buttonSimpleMode, SIGNAL(clicked()), SLOT(selectSimpleMode()));
connect(m_ui->buttonAdvancedMode, SIGNAL(clicked()), SLOT(selectAdvancedMode()));
connect(m_ui->buttonAddHex, SIGNAL(clicked()), SLOT(excludeHexChars())); connect(m_ui->buttonAddHex, SIGNAL(clicked()), SLOT(excludeHexChars()));
connect(m_ui->editExcludedChars, SIGNAL(textChanged(QString)), SLOT(updateGenerator())); connect(m_ui->editExcludedChars, SIGNAL(textChanged(QString)), SLOT(updateGenerator()));
connect(m_ui->buttonApply, SIGNAL(clicked()), SLOT(applyPassword())); connect(m_ui->buttonApply, SIGNAL(clicked()), SLOT(applyPassword()));
connect(m_ui->buttonCopy, SIGNAL(clicked()), SLOT(copyPassword())); connect(m_ui->buttonCopy, SIGNAL(clicked()), SLOT(copyPassword()));
connect(m_ui->buttonGenerate, SIGNAL(clicked()), SLOT(regeneratePassword())); connect(m_ui->buttonGenerate, SIGNAL(clicked()), SLOT(regeneratePassword()));
connect(m_ui->buttonClose, SIGNAL(clicked()), SIGNAL(closePasswordGenerator()));
connect(m_ui->sliderLength, SIGNAL(valueChanged(int)), SLOT(passwordSliderMoved())); connect(m_ui->sliderLength, SIGNAL(valueChanged(int)), SLOT(passwordLengthChanged(int)));
connect(m_ui->spinBoxLength, SIGNAL(valueChanged(int)), SLOT(passwordSpinBoxChanged())); connect(m_ui->spinBoxLength, SIGNAL(valueChanged(int)), SLOT(passwordLengthChanged(int)));
connect(m_ui->sliderWordCount, SIGNAL(valueChanged(int)), SLOT(dicewareSliderMoved())); connect(m_ui->sliderWordCount, SIGNAL(valueChanged(int)), SLOT(passphraseLengthChanged(int)));
connect(m_ui->spinBoxWordCount, SIGNAL(valueChanged(int)), SLOT(dicewareSpinBoxChanged())); connect(m_ui->spinBoxWordCount, SIGNAL(valueChanged(int)), SLOT(passphraseLengthChanged(int)));
connect(m_ui->editWordSeparator, SIGNAL(textChanged(QString)), SLOT(updateGenerator())); connect(m_ui->editWordSeparator, SIGNAL(textChanged(QString)), SLOT(updateGenerator()));
connect(m_ui->comboBoxWordList, SIGNAL(currentIndexChanged(int)), SLOT(updateGenerator())); connect(m_ui->comboBoxWordList, SIGNAL(currentIndexChanged(int)), SLOT(updateGenerator()));
@ -100,12 +102,6 @@ PasswordGeneratorWidget::~PasswordGeneratorWidget()
{ {
} }
void PasswordGeneratorWidget::showEvent(QShowEvent* event)
{
QWidget::showEvent(event);
reset();
}
void PasswordGeneratorWidget::loadSettings() void PasswordGeneratorWidget::loadSettings()
{ {
// Password config // Password config
@ -118,19 +114,13 @@ void PasswordGeneratorWidget::loadSettings()
config()->get("generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool()); config()->get("generator/SpecialChars", PasswordGenerator::DefaultSpecial).toBool());
m_ui->checkBoxNumbersAdv->setChecked( m_ui->checkBoxNumbersAdv->setChecked(
config()->get("generator/Numbers", PasswordGenerator::DefaultNumbers).toBool()); config()->get("generator/Numbers", PasswordGenerator::DefaultNumbers).toBool());
m_ui->advancedBar->setVisible(
config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool());
m_ui->excludedChars->setVisible(
config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool());
m_ui->checkBoxExcludeAlike->setVisible(
config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool());
m_ui->checkBoxEnsureEvery->setVisible(
config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool());
m_ui->editExcludedChars->setText( m_ui->editExcludedChars->setText(
config()->get("generator/ExcludedChars", PasswordGenerator::DefaultExcludedChars).toString()); config()->get("generator/ExcludedChars", PasswordGenerator::DefaultExcludedChars).toString());
m_ui->simpleBar->setVisible( m_ui->buttonAdvancedMode->setChecked(
!(config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool())); config()->get("generator/AdvancedMode", PasswordGenerator::DefaultAdvancedMode).toBool());
setAdvancedMode(m_ui->buttonAdvancedMode->isChecked());
m_ui->checkBoxBraces->setChecked(config()->get("generator/Braces", PasswordGenerator::DefaultBraces).toBool()); m_ui->checkBoxBraces->setChecked(config()->get("generator/Braces", PasswordGenerator::DefaultBraces).toBool());
m_ui->checkBoxQuotes->setChecked(config()->get("generator/Quotes", PasswordGenerator::DefaultQuotes).toBool()); m_ui->checkBoxQuotes->setChecked(config()->get("generator/Quotes", PasswordGenerator::DefaultQuotes).toBool());
m_ui->checkBoxPunctuation->setChecked( m_ui->checkBoxPunctuation->setChecked(
@ -174,7 +164,7 @@ void PasswordGeneratorWidget::saveSettings()
config()->set("generator/Numbers", m_ui->checkBoxNumbersAdv->isChecked()); config()->set("generator/Numbers", m_ui->checkBoxNumbersAdv->isChecked());
config()->set("generator/EASCII", m_ui->checkBoxExtASCIIAdv->isChecked()); config()->set("generator/EASCII", m_ui->checkBoxExtASCIIAdv->isChecked());
} }
config()->set("generator/AdvancedMode", m_ui->advancedBar->isVisible()); config()->set("generator/AdvancedMode", m_ui->buttonAdvancedMode->isChecked());
config()->set("generator/SpecialChars", m_ui->checkBoxSpecialChars->isChecked()); config()->set("generator/SpecialChars", m_ui->checkBoxSpecialChars->isChecked());
config()->set("generator/Braces", m_ui->checkBoxBraces->isChecked()); config()->set("generator/Braces", m_ui->checkBoxBraces->isChecked());
config()->set("generator/Punctuation", m_ui->checkBoxPunctuation->isChecked()); config()->set("generator/Punctuation", m_ui->checkBoxPunctuation->isChecked());
@ -215,10 +205,10 @@ void PasswordGeneratorWidget::setStandaloneMode(bool standalone)
{ {
m_standalone = standalone; m_standalone = standalone;
if (standalone) { if (standalone) {
m_ui->buttonApply->setText(tr("Close")); m_ui->buttonApply->setVisible(false);
setPasswordVisible(true); setPasswordVisible(true);
} else { } else {
m_ui->buttonApply->setText(tr("Accept")); m_ui->buttonApply->setVisible(true);
} }
} }
@ -230,7 +220,7 @@ QString PasswordGeneratorWidget::getGeneratedPassword()
void PasswordGeneratorWidget::keyPressEvent(QKeyEvent* e) void PasswordGeneratorWidget::keyPressEvent(QKeyEvent* e)
{ {
if (e->key() == Qt::Key_Escape && m_standalone) { if (e->key() == Qt::Key_Escape && m_standalone) {
emit dialogTerminated(); emit closePasswordGenerator();
} else { } else {
e->ignore(); e->ignore();
} }
@ -280,7 +270,7 @@ void PasswordGeneratorWidget::applyPassword()
{ {
saveSettings(); saveSettings();
emit appliedPassword(m_ui->editNewPassword->text()); emit appliedPassword(m_ui->editNewPassword->text());
emit dialogTerminated(); emit closePasswordGenerator();
} }
void PasswordGeneratorWidget::copyPassword() void PasswordGeneratorWidget::copyPassword()
@ -288,43 +278,30 @@ void PasswordGeneratorWidget::copyPassword()
clipboard()->setText(m_ui->editNewPassword->text()); clipboard()->setText(m_ui->editNewPassword->text());
} }
void PasswordGeneratorWidget::passwordSliderMoved() void PasswordGeneratorWidget::passwordLengthChanged(int length)
{ {
if (m_updatingSpinBox) { m_ui->spinBoxLength->blockSignals(true);
return; m_ui->sliderLength->blockSignals(true);
}
m_ui->spinBoxLength->setValue(m_ui->sliderLength->value()); m_ui->spinBoxLength->setValue(length);
m_ui->sliderLength->setValue(length);
m_ui->spinBoxLength->blockSignals(false);
m_ui->sliderLength->blockSignals(false);
updateGenerator(); updateGenerator();
} }
void PasswordGeneratorWidget::passwordSpinBoxChanged() void PasswordGeneratorWidget::passphraseLengthChanged(int length)
{ {
if (m_updatingSpinBox) { m_ui->spinBoxWordCount->blockSignals(true);
return; m_ui->sliderWordCount->blockSignals(true);
}
// Interlock so that we don't update twice - this causes issues as the spinbox can go higher than slider m_ui->spinBoxWordCount->setValue(length);
m_updatingSpinBox = true; m_ui->sliderWordCount->setValue(length);
m_ui->sliderLength->setValue(m_ui->spinBoxLength->value()); m_ui->spinBoxWordCount->blockSignals(false);
m_ui->sliderWordCount->blockSignals(false);
m_updatingSpinBox = false;
updateGenerator();
}
void PasswordGeneratorWidget::dicewareSliderMoved()
{
m_ui->spinBoxWordCount->setValue(m_ui->sliderWordCount->value());
updateGenerator();
}
void PasswordGeneratorWidget::dicewareSpinBoxChanged()
{
m_ui->sliderWordCount->setValue(m_ui->spinBoxWordCount->value());
updateGenerator(); updateGenerator();
} }
@ -332,49 +309,46 @@ void PasswordGeneratorWidget::dicewareSpinBoxChanged()
void PasswordGeneratorWidget::setPasswordVisible(bool visible) void PasswordGeneratorWidget::setPasswordVisible(bool visible)
{ {
m_ui->editNewPassword->setShowPassword(visible); m_ui->editNewPassword->setShowPassword(visible);
bool blockSignals = m_ui->togglePasswordButton->blockSignals(true);
m_ui->togglePasswordButton->setChecked(visible);
m_ui->togglePasswordButton->blockSignals(blockSignals);
} }
bool PasswordGeneratorWidget::isPasswordVisible() const bool PasswordGeneratorWidget::isPasswordVisible() const
{ {
return m_ui->togglePasswordButton->isChecked(); return m_ui->editNewPassword->isPasswordVisible();
} }
void PasswordGeneratorWidget::selectSimpleMode() void PasswordGeneratorWidget::setAdvancedMode(bool state)
{ {
m_ui->advancedBar->hide(); if (state) {
m_ui->excludedChars->hide(); m_ui->simpleBar->hide();
m_ui->checkBoxExcludeAlike->hide(); m_ui->checkBoxUpperAdv->setChecked(m_ui->checkBoxUpper->isChecked());
m_ui->checkBoxEnsureEvery->hide(); m_ui->checkBoxLowerAdv->setChecked(m_ui->checkBoxLower->isChecked());
m_ui->checkBoxUpper->setChecked(m_ui->checkBoxUpperAdv->isChecked()); m_ui->checkBoxNumbersAdv->setChecked(m_ui->checkBoxNumbers->isChecked());
m_ui->checkBoxLower->setChecked(m_ui->checkBoxLowerAdv->isChecked()); m_ui->checkBoxBraces->setChecked(m_ui->checkBoxSpecialChars->isChecked());
m_ui->checkBoxNumbers->setChecked(m_ui->checkBoxNumbersAdv->isChecked()); m_ui->checkBoxPunctuation->setChecked(m_ui->checkBoxSpecialChars->isChecked());
m_ui->checkBoxSpecialChars->setChecked(m_ui->checkBoxBraces->isChecked() | m_ui->checkBoxPunctuation->isChecked() m_ui->checkBoxQuotes->setChecked(m_ui->checkBoxSpecialChars->isChecked());
| m_ui->checkBoxQuotes->isChecked() | m_ui->checkBoxMath->isChecked() m_ui->checkBoxMath->setChecked(m_ui->checkBoxSpecialChars->isChecked());
| m_ui->checkBoxDashes->isChecked() | m_ui->checkBoxLogograms->isChecked()); m_ui->checkBoxDashes->setChecked(m_ui->checkBoxSpecialChars->isChecked());
m_ui->checkBoxExtASCII->setChecked(m_ui->checkBoxExtASCIIAdv->isChecked()); m_ui->checkBoxLogograms->setChecked(m_ui->checkBoxSpecialChars->isChecked());
m_ui->simpleBar->show(); m_ui->checkBoxExtASCIIAdv->setChecked(m_ui->checkBoxExtASCII->isChecked());
} m_ui->advancedBar->show();
m_ui->excludedChars->show();
void PasswordGeneratorWidget::selectAdvancedMode() m_ui->checkBoxExcludeAlike->show();
{ m_ui->checkBoxEnsureEvery->show();
m_ui->simpleBar->hide(); } else {
m_ui->checkBoxUpperAdv->setChecked(m_ui->checkBoxUpper->isChecked()); m_ui->advancedBar->hide();
m_ui->checkBoxLowerAdv->setChecked(m_ui->checkBoxLower->isChecked()); m_ui->excludedChars->hide();
m_ui->checkBoxNumbersAdv->setChecked(m_ui->checkBoxNumbers->isChecked()); m_ui->checkBoxExcludeAlike->hide();
m_ui->checkBoxBraces->setChecked(m_ui->checkBoxSpecialChars->isChecked()); m_ui->checkBoxEnsureEvery->hide();
m_ui->checkBoxPunctuation->setChecked(m_ui->checkBoxSpecialChars->isChecked()); m_ui->checkBoxUpper->setChecked(m_ui->checkBoxUpperAdv->isChecked());
m_ui->checkBoxQuotes->setChecked(m_ui->checkBoxSpecialChars->isChecked()); m_ui->checkBoxLower->setChecked(m_ui->checkBoxLowerAdv->isChecked());
m_ui->checkBoxMath->setChecked(m_ui->checkBoxSpecialChars->isChecked()); m_ui->checkBoxNumbers->setChecked(m_ui->checkBoxNumbersAdv->isChecked());
m_ui->checkBoxDashes->setChecked(m_ui->checkBoxSpecialChars->isChecked()); m_ui->checkBoxSpecialChars->setChecked(
m_ui->checkBoxLogograms->setChecked(m_ui->checkBoxSpecialChars->isChecked()); m_ui->checkBoxBraces->isChecked() | m_ui->checkBoxPunctuation->isChecked()
m_ui->checkBoxExtASCIIAdv->setChecked(m_ui->checkBoxExtASCII->isChecked()); | m_ui->checkBoxQuotes->isChecked() | m_ui->checkBoxMath->isChecked() | m_ui->checkBoxDashes->isChecked()
m_ui->advancedBar->show(); | m_ui->checkBoxLogograms->isChecked());
m_ui->excludedChars->show(); m_ui->checkBoxExtASCII->setChecked(m_ui->checkBoxExtASCIIAdv->isChecked());
m_ui->checkBoxExcludeAlike->show(); m_ui->simpleBar->show();
m_ui->checkBoxEnsureEvery->show(); }
} }
void PasswordGeneratorWidget::excludeHexChars() void PasswordGeneratorWidget::excludeHexChars()
@ -392,7 +366,7 @@ void PasswordGeneratorWidget::colorStrengthIndicator(const PasswordHealth& healt
// Set the color and background based on entropy // Set the color and background based on entropy
QList<QString> qualityColors; QList<QString> qualityColors;
if (osUtils->isDarkMode()) { if (kpxcApp->isDarkTheme()) {
qualityColors << QStringLiteral("#C43F31") << QStringLiteral("#DB9837") << QStringLiteral("#608A22") qualityColors << QStringLiteral("#C43F31") << QStringLiteral("#DB9837") << QStringLiteral("#608A22")
<< QStringLiteral("#1F8023"); << QStringLiteral("#1F8023");
} else { } else {
@ -496,12 +470,14 @@ PasswordGenerator::GeneratorFlags PasswordGeneratorWidget::generatorFlags()
{ {
PasswordGenerator::GeneratorFlags flags; PasswordGenerator::GeneratorFlags flags;
if (m_ui->checkBoxExcludeAlike->isChecked()) { if (m_ui->buttonAdvancedMode->isChecked()) {
flags |= PasswordGenerator::ExcludeLookAlike; if (m_ui->checkBoxExcludeAlike->isChecked()) {
} flags |= PasswordGenerator::ExcludeLookAlike;
}
if (m_ui->checkBoxEnsureEvery->isChecked()) { if (m_ui->checkBoxEnsureEvery->isChecked()) {
flags |= PasswordGenerator::CharFromEveryGroup; flags |= PasswordGenerator::CharFromEveryGroup;
}
} }
return flags; return flags;
@ -510,62 +486,52 @@ PasswordGenerator::GeneratorFlags PasswordGeneratorWidget::generatorFlags()
void PasswordGeneratorWidget::updateGenerator() void PasswordGeneratorWidget::updateGenerator()
{ {
if (m_ui->tabWidget->currentIndex() == Password) { if (m_ui->tabWidget->currentIndex() == Password) {
PasswordGenerator::CharClasses classes = charClasses(); auto classes = charClasses();
PasswordGenerator::GeneratorFlags flags = generatorFlags(); auto flags = generatorFlags();
int minLength = 0; int length = 0;
if (flags.testFlag(PasswordGenerator::CharFromEveryGroup)) { if (flags.testFlag(PasswordGenerator::CharFromEveryGroup)) {
if (classes.testFlag(PasswordGenerator::LowerLetters)) { if (classes.testFlag(PasswordGenerator::LowerLetters)) {
minLength++; ++length;
} }
if (classes.testFlag(PasswordGenerator::UpperLetters)) { if (classes.testFlag(PasswordGenerator::UpperLetters)) {
minLength++; ++length;
} }
if (classes.testFlag(PasswordGenerator::Numbers)) { if (classes.testFlag(PasswordGenerator::Numbers)) {
minLength++; ++length;
} }
if (classes.testFlag(PasswordGenerator::Braces)) { if (classes.testFlag(PasswordGenerator::Braces)) {
minLength++; ++length;
} }
if (classes.testFlag(PasswordGenerator::Punctuation)) { if (classes.testFlag(PasswordGenerator::Punctuation)) {
minLength++; ++length;
} }
if (classes.testFlag(PasswordGenerator::Quotes)) { if (classes.testFlag(PasswordGenerator::Quotes)) {
minLength++; ++length;
} }
if (classes.testFlag(PasswordGenerator::Dashes)) { if (classes.testFlag(PasswordGenerator::Dashes)) {
minLength++; ++length;
} }
if (classes.testFlag(PasswordGenerator::Math)) { if (classes.testFlag(PasswordGenerator::Math)) {
minLength++; ++length;
} }
if (classes.testFlag(PasswordGenerator::Logograms)) { if (classes.testFlag(PasswordGenerator::Logograms)) {
minLength++; ++length;
} }
if (classes.testFlag(PasswordGenerator::EASCII)) { if (classes.testFlag(PasswordGenerator::EASCII)) {
minLength++; ++length;
} }
} }
minLength = qMax(minLength, 1);
if (m_ui->spinBoxLength->value() < minLength) { length = qMax(length, m_ui->spinBoxLength->value());
m_updatingSpinBox = true; m_passwordGenerator->setLength(length);
m_ui->spinBoxLength->setValue(minLength);
m_ui->sliderLength->setValue(minLength);
m_updatingSpinBox = false;
}
m_ui->spinBoxLength->setMinimum(minLength);
m_ui->sliderLength->setMinimum(minLength);
m_passwordGenerator->setLength(m_ui->spinBoxLength->value());
m_passwordGenerator->setCharClasses(classes); m_passwordGenerator->setCharClasses(classes);
if (m_ui->simpleBar->isVisible()) {
m_passwordGenerator->setExcludedChars("");
} else {
m_passwordGenerator->setExcludedChars(m_ui->editExcludedChars->text());
}
m_passwordGenerator->setFlags(flags); m_passwordGenerator->setFlags(flags);
if (m_ui->buttonAdvancedMode->isChecked()) {
m_passwordGenerator->setExcludedChars(m_ui->editExcludedChars->text());
} else {
m_passwordGenerator->setExcludedChars("");
}
if (m_passwordGenerator->isValid()) { if (m_passwordGenerator->isValid()) {
m_ui->buttonGenerate->setEnabled(true); m_ui->buttonGenerate->setEnabled(true);
@ -573,21 +539,9 @@ void PasswordGeneratorWidget::updateGenerator()
m_ui->buttonGenerate->setEnabled(false); m_ui->buttonGenerate->setEnabled(false);
} }
} else { } else {
int minWordCount = 1;
if (m_ui->spinBoxWordCount->value() < minWordCount) {
m_updatingSpinBox = true;
m_ui->spinBoxWordCount->setValue(minWordCount);
m_ui->sliderWordCount->setValue(minWordCount);
m_updatingSpinBox = false;
}
m_dicewareGenerator->setWordCase( m_dicewareGenerator->setWordCase(
static_cast<PassphraseGenerator::PassphraseWordCase>(m_ui->wordCaseComboBox->currentData().toInt())); static_cast<PassphraseGenerator::PassphraseWordCase>(m_ui->wordCaseComboBox->currentData().toInt()));
m_ui->spinBoxWordCount->setMinimum(minWordCount);
m_ui->sliderWordCount->setMinimum(minWordCount);
m_dicewareGenerator->setWordCount(m_ui->spinBoxWordCount->value()); m_dicewareGenerator->setWordCount(m_ui->spinBoxWordCount->value());
if (!m_ui->comboBoxWordList->currentText().isEmpty()) { if (!m_ui->comboBoxWordList->currentText().isEmpty()) {
QString path = filePath()->wordlistPath(m_ui->comboBoxWordList->currentText()); QString path = filePath()->wordlistPath(m_ui->comboBoxWordList->currentText());

View File

@ -54,9 +54,6 @@ public:
QString getGeneratedPassword(); QString getGeneratedPassword();
bool isPasswordVisible() const; bool isPasswordVisible() const;
protected:
void showEvent(QShowEvent* event) override;
public slots: public slots:
void regeneratePassword(); void regeneratePassword();
void applyPassword(); void applyPassword();
@ -65,25 +62,21 @@ public slots:
signals: signals:
void appliedPassword(const QString& password); void appliedPassword(const QString& password);
void dialogTerminated(); void closePasswordGenerator();
private slots: private slots:
void updateButtonsEnabled(const QString& password); void updateButtonsEnabled(const QString& password);
void updatePasswordStrength(const QString& password); void updatePasswordStrength(const QString& password);
void selectSimpleMode(); void setAdvancedMode(bool state);
void selectAdvancedMode();
void excludeHexChars(); void excludeHexChars();
void passwordSliderMoved(); void passwordLengthChanged(int length);
void passwordSpinBoxChanged(); void passphraseLengthChanged(int length);
void dicewareSliderMoved();
void dicewareSpinBoxChanged();
void colorStrengthIndicator(const PasswordHealth& health); void colorStrengthIndicator(const PasswordHealth& health);
void updateGenerator(); void updateGenerator();
private: private:
bool m_updatingSpinBox;
bool m_standalone = false; bool m_standalone = false;
PasswordGenerator::CharClasses charClasses(); PasswordGenerator::CharClasses charClasses();

File diff suppressed because it is too large Load Diff

View File

@ -148,8 +148,6 @@ void EditEntryWidget::setupMain()
m_usernameCompleter->setModel(m_usernameCompleterModel); m_usernameCompleter->setModel(m_usernameCompleterModel);
m_mainUi->usernameComboBox->setCompleter(m_usernameCompleter); m_mainUi->usernameComboBox->setCompleter(m_usernameCompleter);
m_mainUi->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show"));
m_mainUi->togglePasswordGeneratorButton->setIcon(filePath()->icon("actions", "password-generator"));
#ifdef WITH_XC_NETWORKING #ifdef WITH_XC_NETWORKING
m_mainUi->fetchFaviconButton->setIcon(filePath()->icon("actions", "favicon-download")); m_mainUi->fetchFaviconButton->setIcon(filePath()->icon("actions", "favicon-download"));
m_mainUi->fetchFaviconButton->setDisabled(true); m_mainUi->fetchFaviconButton->setDisabled(true);
@ -157,8 +155,6 @@ void EditEntryWidget::setupMain()
m_mainUi->fetchFaviconButton->setVisible(false); m_mainUi->fetchFaviconButton->setVisible(false);
#endif #endif
connect(m_mainUi->togglePasswordButton, SIGNAL(toggled(bool)), m_mainUi->passwordEdit, SLOT(setShowPassword(bool)));
connect(m_mainUi->togglePasswordGeneratorButton, SIGNAL(toggled(bool)), SLOT(togglePasswordGeneratorButton(bool)));
#ifdef WITH_XC_NETWORKING #ifdef WITH_XC_NETWORKING
connect(m_mainUi->fetchFaviconButton, SIGNAL(clicked()), m_iconsWidget, SLOT(downloadFavicon())); connect(m_mainUi->fetchFaviconButton, SIGNAL(clicked()), m_iconsWidget, SLOT(downloadFavicon()));
connect(m_mainUi->urlEdit, SIGNAL(textChanged(QString)), m_iconsWidget, SLOT(setUrl(QString))); connect(m_mainUi->urlEdit, SIGNAL(textChanged(QString)), m_iconsWidget, SLOT(setUrl(QString)));
@ -166,8 +162,9 @@ void EditEntryWidget::setupMain()
#endif #endif
connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool))); connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool)));
connect(m_mainUi->notesEnabled, SIGNAL(toggled(bool)), this, SLOT(toggleHideNotes(bool))); connect(m_mainUi->notesEnabled, SIGNAL(toggled(bool)), this, SLOT(toggleHideNotes(bool)));
m_mainUi->passwordRepeatEdit->enableVerifyMode(m_mainUi->passwordEdit);
connect(m_mainUi->passwordGenerator, SIGNAL(appliedPassword(QString)), SLOT(setGeneratedPassword(QString))); connect(m_mainUi->passwordGenerator, SIGNAL(appliedPassword(QString)), SLOT(setGeneratedPassword(QString)));
connect(m_mainUi->passwordGenerator, SIGNAL(closePasswordGenerator()), SLOT(togglePasswordGenerator()));
m_mainUi->expirePresets->setMenu(createPresetsMenu()); m_mainUi->expirePresets->setMenu(createPresetsMenu());
connect(m_mainUi->expirePresets->menu(), SIGNAL(triggered(QAction*)), this, SLOT(useExpiryPreset(QAction*))); connect(m_mainUi->expirePresets->menu(), SIGNAL(triggered(QAction*)), this, SLOT(useExpiryPreset(QAction*)));
@ -417,7 +414,6 @@ void EditEntryWidget::setupEntryUpdate()
connect(m_mainUi->titleEdit, SIGNAL(textChanged(QString)), this, SLOT(setModified())); connect(m_mainUi->titleEdit, SIGNAL(textChanged(QString)), this, SLOT(setModified()));
connect(m_mainUi->usernameComboBox->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(setModified())); connect(m_mainUi->usernameComboBox->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(setModified()));
connect(m_mainUi->passwordEdit, SIGNAL(textChanged(QString)), this, SLOT(setModified())); connect(m_mainUi->passwordEdit, SIGNAL(textChanged(QString)), this, SLOT(setModified()));
connect(m_mainUi->passwordRepeatEdit, SIGNAL(textChanged(QString)), this, SLOT(setModified()));
connect(m_mainUi->urlEdit, SIGNAL(textChanged(QString)), this, SLOT(setModified())); connect(m_mainUi->urlEdit, SIGNAL(textChanged(QString)), this, SLOT(setModified()));
#ifdef WITH_XC_NETWORKING #ifdef WITH_XC_NETWORKING
connect(m_mainUi->urlEdit, SIGNAL(textChanged(QString)), this, SLOT(updateFaviconButtonEnable(QString))); connect(m_mainUi->urlEdit, SIGNAL(textChanged(QString)), this, SLOT(updateFaviconButtonEnable(QString)));
@ -809,7 +805,6 @@ void EditEntryWidget::setForms(Entry* entry, bool restore)
m_mainUi->usernameComboBox->lineEdit()->setReadOnly(m_history); m_mainUi->usernameComboBox->lineEdit()->setReadOnly(m_history);
m_mainUi->urlEdit->setReadOnly(m_history); m_mainUi->urlEdit->setReadOnly(m_history);
m_mainUi->passwordEdit->setReadOnly(m_history); m_mainUi->passwordEdit->setReadOnly(m_history);
m_mainUi->passwordRepeatEdit->setReadOnly(m_history);
m_mainUi->expireCheck->setEnabled(!m_history); m_mainUi->expireCheck->setEnabled(!m_history);
m_mainUi->expireDatePicker->setReadOnly(m_history); m_mainUi->expireDatePicker->setReadOnly(m_history);
m_mainUi->notesEnabled->setChecked(!config()->get("security/hidenotes").toBool()); m_mainUi->notesEnabled->setChecked(!config()->get("security/hidenotes").toBool());
@ -821,8 +816,7 @@ void EditEntryWidget::setForms(Entry* entry, bool restore)
} else { } else {
m_mainUi->notesEdit->setFont(Font::defaultFont()); m_mainUi->notesEdit->setFont(Font::defaultFont());
} }
m_mainUi->togglePasswordGeneratorButton->setChecked(false); m_mainUi->passwordGenerator->setVisible(false);
m_mainUi->togglePasswordGeneratorButton->setDisabled(m_history);
m_mainUi->passwordGenerator->reset(entry->password().length()); m_mainUi->passwordGenerator->reset(entry->password().length());
m_advancedUi->attachmentsWidget->setReadOnly(m_history); m_advancedUi->attachmentsWidget->setReadOnly(m_history);
@ -849,11 +843,14 @@ void EditEntryWidget::setForms(Entry* entry, bool restore)
m_mainUi->usernameComboBox->lineEdit()->setText(entry->username()); m_mainUi->usernameComboBox->lineEdit()->setText(entry->username());
m_mainUi->urlEdit->setText(entry->url()); m_mainUi->urlEdit->setText(entry->url());
m_mainUi->passwordEdit->setText(entry->password()); m_mainUi->passwordEdit->setText(entry->password());
m_mainUi->passwordRepeatEdit->setText(entry->password()); m_mainUi->passwordEdit->setShowPassword(config()->get("security/passwordscleartext").toBool());
if (!m_history) {
m_mainUi->passwordEdit->enablePasswordGenerator(true);
}
m_mainUi->expireCheck->setChecked(entry->timeInfo().expires()); m_mainUi->expireCheck->setChecked(entry->timeInfo().expires());
m_mainUi->expireDatePicker->setDateTime(entry->timeInfo().expiryTime().toLocalTime()); m_mainUi->expireDatePicker->setDateTime(entry->timeInfo().expiryTime().toLocalTime());
m_mainUi->expirePresets->setEnabled(!m_history); m_mainUi->expirePresets->setEnabled(!m_history);
m_mainUi->togglePasswordButton->setChecked(config()->get("security/passwordscleartext").toBool());
QList<QString> commonUsernames = m_db->commonUsernames(); QList<QString> commonUsernames = m_db->commonUsernames();
m_usernameCompleterModel->setStringList(commonUsernames); m_usernameCompleterModel->setStringList(commonUsernames);
@ -973,13 +970,8 @@ bool EditEntryWidget::commitEntry()
return true; return true;
} }
if (!passwordsEqual()) {
showMessage(tr("Different passwords supplied."), MessageWidget::Error);
return false;
}
// Ask the user to apply the generator password, if open // Ask the user to apply the generator password, if open
if (m_mainUi->togglePasswordGeneratorButton->isChecked() if (m_mainUi->passwordGenerator->isVisible()
&& m_mainUi->passwordGenerator->getGeneratedPassword() != m_mainUi->passwordEdit->text()) { && m_mainUi->passwordGenerator->getGeneratedPassword() != m_mainUi->passwordEdit->text()) {
auto answer = MessageBox::question(this, auto answer = MessageBox::question(this,
tr("Apply generated password?"), tr("Apply generated password?"),
@ -992,7 +984,7 @@ bool EditEntryWidget::commitEntry()
} }
// Hide the password generator // Hide the password generator
m_mainUi->togglePasswordGeneratorButton->setChecked(false); m_mainUi->passwordGenerator->setVisible(false);
if (m_advancedUi->attributesView->currentIndex().isValid() && m_advancedUi->attributesEdit->isEnabled()) { if (m_advancedUi->attributesView->currentIndex().isValid() && m_advancedUi->attributesEdit->isEnabled()) {
QString key = m_attributesModel->keyByIndex(m_advancedUi->attributesView->currentIndex()); QString key = m_attributesModel->keyByIndex(m_advancedUi->attributesView->currentIndex());
@ -1139,7 +1131,6 @@ void EditEntryWidget::clear()
m_mainUi->titleEdit->setText(""); m_mainUi->titleEdit->setText("");
m_mainUi->passwordEdit->setText(""); m_mainUi->passwordEdit->setText("");
m_mainUi->passwordRepeatEdit->setText("");
m_mainUi->urlEdit->setText(""); m_mainUi->urlEdit->setText("");
m_mainUi->notesEdit->clear(); m_mainUi->notesEdit->clear();
@ -1151,25 +1142,20 @@ void EditEntryWidget::clear()
hideMessage(); hideMessage();
} }
void EditEntryWidget::togglePasswordGeneratorButton(bool checked) void EditEntryWidget::togglePasswordGenerator()
{ {
if (checked) { bool visible = m_mainUi->passwordGenerator->isVisible();
if (!visible) {
m_mainUi->passwordGenerator->regeneratePassword(); m_mainUi->passwordGenerator->regeneratePassword();
m_mainUi->passwordGenerator->setPasswordVisible(m_mainUi->passwordEdit->isPasswordVisible());
} }
m_mainUi->passwordGenerator->setVisible(checked); m_mainUi->passwordGenerator->setVisible(!visible);
}
bool EditEntryWidget::passwordsEqual()
{
return m_mainUi->passwordEdit->text() == m_mainUi->passwordRepeatEdit->text();
} }
void EditEntryWidget::setGeneratedPassword(const QString& password) void EditEntryWidget::setGeneratedPassword(const QString& password)
{ {
m_mainUi->passwordEdit->setText(password); m_mainUi->passwordEdit->setText(password);
m_mainUi->passwordRepeatEdit->setText(password); m_mainUi->passwordGenerator->setVisible(false);
m_mainUi->togglePasswordGeneratorButton->setChecked(false);
} }
#ifdef WITH_XC_NETWORKING #ifdef WITH_XC_NETWORKING

View File

@ -83,7 +83,7 @@ private slots:
void acceptEntry(); void acceptEntry();
bool commitEntry(); bool commitEntry();
void cancel(); void cancel();
void togglePasswordGeneratorButton(bool checked); void togglePasswordGenerator();
void setGeneratedPassword(const QString& password); void setGeneratedPassword(const QString& password);
#ifdef WITH_XC_NETWORKING #ifdef WITH_XC_NETWORKING
void updateFaviconButtonEnable(const QString& url); void updateFaviconButtonEnable(const QString& url);

View File

@ -20,122 +20,16 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item row="5" column="0" alignment="Qt::AlignRight"> <item row="7" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="urlLabel"> <widget class="QCheckBox" name="expireCheck">
<property name="text">
<string>URL:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="URLEdit" name="urlEdit">
<property name="accessibleName">
<string>Url field</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="fetchFaviconButton">
<property name="toolTip">
<string>Download favicon for URL</string>
</property>
<property name="accessibleName">
<string>Download favicon for URL</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="1">
<widget class="PasswordGeneratorWidget" name="passwordGenerator" native="true"/>
</item>
<item row="2" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="passwordLabel">
<property name="text">
<string>Password:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="PasswordEdit" name="passwordRepeatEdit">
<property name="accessibleName">
<string>Repeat password field</string>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="togglePasswordGeneratorButton">
<property name="toolTip">
<string>Toggle password generator</string>
</property>
<property name="accessibleName">
<string>Toggle password generator</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="PasswordEdit" name="passwordEdit">
<property name="accessibleName">
<string>Password field</string>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="togglePasswordButton">
<property name="toolTip">
<string>Toggle password visibility</string>
</property>
<property name="accessibleName">
<string>Toggle password visibility</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="passwordRepeatLabel">
<property name="text">
<string>Repeat:</string>
</property>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="titleLabel">
<property name="text">
<string>Title:</string>
</property>
</widget>
</item>
<item row="9" column="0" alignment="Qt::AlignLeft|Qt::AlignTop">
<widget class="QCheckBox" name="notesEnabled">
<property name="toolTip"> <property name="toolTip">
<string>Toggle notes visible</string> <string>Toggle expiration</string>
</property> </property>
<property name="accessibleName"> <property name="accessibleName">
<string>Toggle notes visible</string> <string>Toggle expiration</string>
</property> </property>
<property name="text"> <property name="text">
<string>Notes</string> <string>Expires</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -194,10 +88,48 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QComboBox" name="usernameComboBox">
<property name="accessibleName">
<string>Username field</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="PasswordGeneratorWidget" name="passwordGenerator" native="true"/>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="titleEdit">
<property name="accessibleName">
<string>Title field</string>
</property>
</widget>
</item>
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="URLEdit" name="urlEdit">
<property name="accessibleName">
<string>Url field</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="fetchFaviconButton">
<property name="toolTip">
<string>Download favicon for URL</string>
</property>
<property name="accessibleName">
<string>Download favicon for URL</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="9" column="1"> <item row="9" column="1">
<widget class="QLabel" name="notesHint"> <widget class="QLabel" name="notesHint">
<property name="visible"> <property name="visible">
<bool>false</bool> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Toggle the checkbox to reveal the notes section.</string> <string>Toggle the checkbox to reveal the notes section.</string>
@ -207,6 +139,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="urlLabel">
<property name="text">
<string>URL:</string>
</property>
</widget>
</item>
<item row="1" column="0" alignment="Qt::AlignRight"> <item row="1" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="usernameLabel"> <widget class="QLabel" name="usernameLabel">
<property name="text"> <property name="text">
@ -214,34 +153,50 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="9" column="0" alignment="Qt::AlignLeft|Qt::AlignTop">
<widget class="QLineEdit" name="titleEdit"> <widget class="QCheckBox" name="notesEnabled">
<property name="accessibleName">
<string>Title field</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="usernameComboBox">
<property name="accessibleName">
<string>Username field</string>
</property>
</widget>
</item>
<item row="7" column="0" alignment="Qt::AlignRight">
<widget class="QCheckBox" name="expireCheck">
<property name="toolTip"> <property name="toolTip">
<string>Toggle expiration</string> <string>Toggle notes visible</string>
</property> </property>
<property name="accessibleName"> <property name="accessibleName">
<string>Toggle expiration</string> <string>Toggle notes visible</string>
</property> </property>
<property name="text"> <property name="text">
<string>Expires</string> <string>Notes</string>
</property>
</widget>
</item>
<item row="2" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="passwordLabel">
<property name="text">
<string>Password:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="PasswordEdit" name="passwordEdit">
<property name="accessibleName">
<string>Password field</string>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
<widget class="QLabel" name="titleLabel">
<property name="geometry">
<rect>
<x>35</x>
<y>0</y>
<width>23</width>
<height>19</height>
</rect>
</property>
<property name="text">
<string>Title:</string>
</property>
</widget>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>
@ -267,9 +222,6 @@
<tabstop>titleEdit</tabstop> <tabstop>titleEdit</tabstop>
<tabstop>usernameComboBox</tabstop> <tabstop>usernameComboBox</tabstop>
<tabstop>passwordEdit</tabstop> <tabstop>passwordEdit</tabstop>
<tabstop>togglePasswordButton</tabstop>
<tabstop>passwordRepeatEdit</tabstop>
<tabstop>togglePasswordGeneratorButton</tabstop>
<tabstop>urlEdit</tabstop> <tabstop>urlEdit</tabstop>
<tabstop>fetchFaviconButton</tabstop> <tabstop>fetchFaviconButton</tabstop>
<tabstop>expireCheck</tabstop> <tabstop>expireCheck</tabstop>

View File

@ -53,7 +53,7 @@ bool PasswordEditWidget::addToCompositeKey(QSharedPointer<CompositeKey> key)
*/ */
void PasswordEditWidget::setPasswordVisible(bool visible) void PasswordEditWidget::setPasswordVisible(bool visible)
{ {
m_compUi->togglePasswordButton->setChecked(visible); m_compUi->enterPasswordEdit->setShowPassword(visible);
} }
/** /**
@ -61,7 +61,7 @@ void PasswordEditWidget::setPasswordVisible(bool visible)
*/ */
bool PasswordEditWidget::isPasswordVisible() const bool PasswordEditWidget::isPasswordVisible() const
{ {
return m_compUi->togglePasswordButton->isChecked(); return m_compUi->enterPasswordEdit->isPasswordVisible();
} }
bool PasswordEditWidget::isEmpty() const bool PasswordEditWidget::isEmpty() const
@ -73,16 +73,8 @@ QWidget* PasswordEditWidget::componentEditWidget()
{ {
m_compEditWidget = new QWidget(); m_compEditWidget = new QWidget();
m_compUi->setupUi(m_compEditWidget); m_compUi->setupUi(m_compEditWidget);
m_compUi->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show")); m_compUi->enterPasswordEdit->enablePasswordGenerator();
m_compUi->passwordGeneratorButton->setIcon(filePath()->icon("actions", "password-generator")); m_compUi->enterPasswordEdit->setRepeatPartner(m_compUi->repeatPasswordEdit);
m_compUi->repeatPasswordEdit->enableVerifyMode(m_compUi->enterPasswordEdit);
connect(m_compUi->togglePasswordButton,
SIGNAL(toggled(bool)),
m_compUi->enterPasswordEdit,
SLOT(setShowPassword(bool)));
connect(m_compUi->passwordGeneratorButton, SIGNAL(clicked(bool)), SLOT(showPasswordGenerator()));
return m_compEditWidget; return m_compEditWidget;
} }
@ -113,26 +105,6 @@ bool PasswordEditWidget::validate(QString& errorMessage) const
return true; return true;
} }
void PasswordEditWidget::showPasswordGenerator()
{
QDialog pwDialog;
pwDialog.setWindowTitle(tr("Generate master password"));
auto layout = new QVBoxLayout();
pwDialog.setLayout(layout);
auto pwGenerator = new PasswordGeneratorWidget(&pwDialog);
layout->addWidget(pwGenerator);
pwGenerator->setStandaloneMode(false);
connect(pwGenerator, SIGNAL(appliedPassword(QString)), SLOT(setPassword(QString)));
connect(pwGenerator, SIGNAL(dialogTerminated()), &pwDialog, SLOT(close()));
pwGenerator->setPasswordVisible(isPasswordVisible());
pwDialog.exec();
}
void PasswordEditWidget::setPassword(const QString& password) void PasswordEditWidget::setPassword(const QString& password)
{ {
Q_ASSERT(m_compEditWidget); Q_ASSERT(m_compEditWidget);

View File

@ -47,7 +47,6 @@ protected:
void hideEvent(QHideEvent* event) override; void hideEvent(QHideEvent* event) override;
private slots: private slots:
void showPasswordGenerator();
void setPassword(const QString& password); void setPassword(const QString& password);
private: private:

View File

@ -31,49 +31,26 @@
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout"> <widget class="PasswordEdit" name="enterPasswordEdit">
<item> <property name="sizePolicy">
<widget class="PasswordEdit" name="enterPasswordEdit"> <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<property name="accessibleName"> <horstretch>0</horstretch>
<string>Password field</string> <verstretch>0</verstretch>
</property> </sizepolicy>
<property name="echoMode"> </property>
<enum>QLineEdit::Password</enum> <property name="minimumSize">
</property> <size>
</widget> <width>300</width>
</item> <height>0</height>
<item> </size>
<widget class="QToolButton" name="togglePasswordButton"> </property>
<property name="accessibleName"> <property name="accessibleName">
<string>Toggle password visibility</string> <string>Password field</string>
</property> </property>
<property name="checkable"> <property name="echoMode">
<bool>true</bool> <enum>QLineEdit::Password</enum>
</property> </property>
</widget> </widget>
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="PasswordEdit" name="repeatPasswordEdit">
<property name="accessibleName">
<string>Repeat password field</string>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="passwordGeneratorButton">
<property name="accessibleName">
<string>Toggle password generator</string>
</property>
</widget>
</item>
</layout>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="repeatPasswordLabel"> <widget class="QLabel" name="repeatPasswordLabel">
@ -82,6 +59,28 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="PasswordEdit" name="repeatPasswordEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="accessibleName">
<string>Repeat password field</string>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
@ -95,8 +94,6 @@
<tabstops> <tabstops>
<tabstop>enterPasswordEdit</tabstop> <tabstop>enterPasswordEdit</tabstop>
<tabstop>repeatPasswordEdit</tabstop> <tabstop>repeatPasswordEdit</tabstop>
<tabstop>togglePasswordButton</tabstop>
<tabstop>passwordGeneratorButton</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -37,5 +37,5 @@ NewDatabaseWizardPageMasterKey::~NewDatabaseWizardPageMasterKey()
void NewDatabaseWizardPageMasterKey::updateWindowSize() void NewDatabaseWizardPageMasterKey::updateWindowSize()
{ {
// ugly workaround for QWizard not managing to react to size changes automatically // ugly workaround for QWizard not managing to react to size changes automatically
QApplication::activeWindow()->adjustSize(); window()->adjustSize();
} }

View File

@ -471,17 +471,6 @@ void TestGui::testEditEntry()
QCOMPARE(attrTextEdit->toPlainText(), attrText); QCOMPARE(attrTextEdit->toPlainText(), attrText);
editEntryWidget->setCurrentPage(0); editEntryWidget->setCurrentPage(0);
// Test mismatch passwords
auto* passwordEdit = editEntryWidget->findChild<QLineEdit*>("passwordEdit");
QString originalPassword = passwordEdit->text();
passwordEdit->setText("newpass");
QTest::mouseClick(okButton, Qt::LeftButton);
auto* messageWiget = editEntryWidget->findChild<MessageWidget*>("messageWidget");
QTRY_VERIFY(messageWiget->isVisible());
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
QCOMPARE(passwordEdit->text(), QString("newpass"));
passwordEdit->setText(originalPassword);
// Save the edit (press OK) // Save the edit (press OK)
QTest::mouseClick(okButton, Qt::LeftButton); QTest::mouseClick(okButton, Qt::LeftButton);
QApplication::processEvents(); QApplication::processEvents();
@ -506,7 +495,6 @@ void TestGui::testEditEntry()
titleEdit->setText("multiline\ntitle"); titleEdit->setText("multiline\ntitle");
editEntryWidget->findChild<QComboBox*>("usernameComboBox")->lineEdit()->setText("multiline\nusername"); editEntryWidget->findChild<QComboBox*>("usernameComboBox")->lineEdit()->setText("multiline\nusername");
editEntryWidget->findChild<QLineEdit*>("passwordEdit")->setText("multiline\npassword"); editEntryWidget->findChild<QLineEdit*>("passwordEdit")->setText("multiline\npassword");
editEntryWidget->findChild<QLineEdit*>("passwordRepeatEdit")->setText("multiline\npassword");
editEntryWidget->findChild<QLineEdit*>("urlEdit")->setText("multiline\nurl"); editEntryWidget->findChild<QLineEdit*>("urlEdit")->setText("multiline\nurl");
QTest::mouseClick(okButton, Qt::LeftButton); QTest::mouseClick(okButton, Qt::LeftButton);
@ -615,9 +603,7 @@ void TestGui::testAddEntry()
QTest::keyClicks(usernameComboBox, "Auto"); QTest::keyClicks(usernameComboBox, "Auto");
QTest::keyPress(usernameComboBox, Qt::Key_Right); QTest::keyPress(usernameComboBox, Qt::Key_Right);
auto* passwordEdit = editEntryWidget->findChild<QLineEdit*>("passwordEdit"); auto* passwordEdit = editEntryWidget->findChild<QLineEdit*>("passwordEdit");
auto* passwordRepeatEdit = editEntryWidget->findChild<QLineEdit*>("passwordRepeatEdit");
QTest::keyClicks(passwordEdit, "something 2"); QTest::keyClicks(passwordEdit, "something 2");
QTest::keyClicks(passwordRepeatEdit, "something 2");
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::ViewMode); QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::ViewMode);
@ -663,8 +649,10 @@ void TestGui::testPasswordEntryEntropy()
QTest::keyClicks(titleEdit, "test"); QTest::keyClicks(titleEdit, "test");
// Open the password generator // Open the password generator
auto* generatorButton = editEntryWidget->findChild<QToolButton*>("togglePasswordGeneratorButton"); auto* passwordEdit = editEntryWidget->findChild<PasswordEdit*>();
QTest::mouseClick(generatorButton, Qt::LeftButton); QVERIFY(passwordEdit);
QTest::mouseClick(passwordEdit, Qt::LeftButton);
QTest::keyClick(passwordEdit, Qt::Key_G, Qt::ControlModifier);
// Type in some password // Type in some password
auto* editNewPassword = editEntryWidget->findChild<QLineEdit*>("editNewPassword"); auto* editNewPassword = editEntryWidget->findChild<QLineEdit*>("editNewPassword");
@ -735,8 +723,10 @@ void TestGui::testDicewareEntryEntropy()
QTest::keyClicks(titleEdit, "test"); QTest::keyClicks(titleEdit, "test");
// Open the password generator // Open the password generator
auto* generatorButton = editEntryWidget->findChild<QToolButton*>("togglePasswordGeneratorButton"); auto* passwordEdit = editEntryWidget->findChild<PasswordEdit*>();
QTest::mouseClick(generatorButton, Qt::LeftButton); QVERIFY(passwordEdit);
QTest::mouseClick(passwordEdit, Qt::LeftButton);
QTest::keyClick(passwordEdit, Qt::Key_G, Qt::ControlModifier);
// Select Diceware // Select Diceware
auto* tabWidget = editEntryWidget->findChild<QTabWidget*>("tabWidget"); auto* tabWidget = editEntryWidget->findChild<QTabWidget*>("tabWidget");
@ -1440,7 +1430,6 @@ int TestGui::addCannedEntries()
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget"); auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
auto* titleEdit = editEntryWidget->findChild<QLineEdit*>("titleEdit"); auto* titleEdit = editEntryWidget->findChild<QLineEdit*>("titleEdit");
auto* passwordEdit = editEntryWidget->findChild<QLineEdit*>("passwordEdit"); auto* passwordEdit = editEntryWidget->findChild<QLineEdit*>("passwordEdit");
auto* passwordRepeatEdit = editEntryWidget->findChild<QLineEdit*>("passwordRepeatEdit");
// Add entry "test" and confirm added // Add entry "test" and confirm added
QTest::mouseClick(entryNewWidget, Qt::LeftButton); QTest::mouseClick(entryNewWidget, Qt::LeftButton);
@ -1453,7 +1442,6 @@ int TestGui::addCannedEntries()
QTest::mouseClick(entryNewWidget, Qt::LeftButton); QTest::mouseClick(entryNewWidget, Qt::LeftButton);
QTest::keyClicks(titleEdit, "something 2"); QTest::keyClicks(titleEdit, "something 2");
QTest::keyClicks(passwordEdit, "something 2"); QTest::keyClicks(passwordEdit, "something 2");
QTest::keyClicks(passwordRepeatEdit, "something 2");
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
++entries_added; ++entries_added;