Remove inline password generator when editing entries

* Always use a pop-up generator to avoid cluttering the user interface and making it clear that a password is being created
This commit is contained in:
Jonathan White 2020-02-25 18:02:46 -05:00
parent fe1189ea79
commit fb5173cebd
12 changed files with 237 additions and 298 deletions

View File

@ -94,14 +94,10 @@ void PasswordEdit::setParentPasswordEdit(PasswordEdit* parent)
m_passwordGeneratorAction->setVisible(false); m_passwordGeneratorAction->setVisible(false);
} }
void PasswordEdit::enablePasswordGenerator(bool signalOnly) void PasswordEdit::enablePasswordGenerator()
{ {
disconnect(m_passwordGeneratorAction); if (!m_passwordGeneratorAction->isVisible()) {
m_passwordGeneratorAction->setVisible(true); m_passwordGeneratorAction->setVisible(true);
if (signalOnly) {
connect(m_passwordGeneratorAction, &QAction::triggered, this, &PasswordEdit::togglePasswordGenerator);
} else {
connect(m_passwordGeneratorAction, &QAction::triggered, this, &PasswordEdit::popupPasswordGenerator); connect(m_passwordGeneratorAction, &QAction::triggered, this, &PasswordEdit::popupPasswordGenerator);
} }
} }
@ -139,6 +135,7 @@ void PasswordEdit::popupPasswordGenerator()
pwGenerator->setStandaloneMode(false); pwGenerator->setStandaloneMode(false);
pwGenerator->setPasswordVisible(isPasswordVisible()); pwGenerator->setPasswordVisible(isPasswordVisible());
pwGenerator->setPasswordLength(text().length());
connect(pwGenerator, SIGNAL(closePasswordGenerator()), &pwDialog, SLOT(close())); connect(pwGenerator, SIGNAL(closePasswordGenerator()), &pwDialog, SLOT(close()));
connect(pwGenerator, SIGNAL(appliedPassword(QString)), SLOT(setText(QString))); connect(pwGenerator, SIGNAL(appliedPassword(QString)), SLOT(setText(QString)));

View File

@ -23,13 +23,15 @@
#include <QLineEdit> #include <QLineEdit>
#include <QPointer> #include <QPointer>
class QDialog;
class PasswordEdit : public QLineEdit class PasswordEdit : public QLineEdit
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit PasswordEdit(QWidget* parent = nullptr); explicit PasswordEdit(QWidget* parent = nullptr);
void enablePasswordGenerator(bool signalOnly = false); void enablePasswordGenerator();
void setRepeatPartner(PasswordEdit* repeatEdit); void setRepeatPartner(PasswordEdit* repeatEdit);
bool isPasswordVisible() const; bool isPasswordVisible() const;
@ -37,9 +39,6 @@ public slots:
void setShowPassword(bool show); void setShowPassword(bool show);
void updateRepeatStatus(); void updateRepeatStatus();
signals:
void togglePasswordGenerator();
private slots: private slots:
void autocompletePassword(const QString& password); void autocompletePassword(const QString& password);
void popupPasswordGenerator(); void popupPasswordGenerator();

View File

@ -187,18 +187,13 @@ void PasswordGeneratorWidget::saveSettings()
config()->set("generator/Type", m_ui->tabWidget->currentIndex()); config()->set("generator/Type", m_ui->tabWidget->currentIndex());
} }
void PasswordGeneratorWidget::reset(int length) void PasswordGeneratorWidget::setPasswordLength(int length)
{ {
m_ui->editNewPassword->setText("");
if (length > 0) { if (length > 0) {
m_ui->spinBoxLength->setValue(length); m_ui->spinBoxLength->setValue(length);
} else { } else {
m_ui->spinBoxLength->setValue(config()->get("generator/Length", PasswordGenerator::DefaultLength).toInt()); m_ui->spinBoxLength->setValue(config()->get("generator/Length", PasswordGenerator::DefaultLength).toInt());
} }
setStandaloneMode(false);
setPasswordVisible(config()->get("security/passwordscleartext").toBool());
updateGenerator();
} }
void PasswordGeneratorWidget::setStandaloneMode(bool standalone) void PasswordGeneratorWidget::setStandaloneMode(bool standalone)

View File

@ -49,7 +49,7 @@ public:
~PasswordGeneratorWidget(); ~PasswordGeneratorWidget();
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
void reset(int length = 0); void setPasswordLength(int length);
void setStandaloneMode(bool standalone); void setStandaloneMode(bool standalone);
QString getGeneratedPassword(); QString getGeneratedPassword();
bool isPasswordVisible() const; bool isPasswordVisible() const;

View File

@ -128,8 +128,6 @@ EditEntryWidget::EditEntryWidget(QWidget* parent)
connect(m_iconsWidget, SIGNAL(messageEditEntryDismiss()), SLOT(hideMessage())); connect(m_iconsWidget, SIGNAL(messageEditEntryDismiss()), SLOT(hideMessage()));
m_mainUi->passwordGenerator->layout()->setContentsMargins(0, 0, 0, 0);
m_editWidgetProperties->setCustomData(m_customData.data()); m_editWidgetProperties->setCustomData(m_customData.data());
} }
@ -163,14 +161,8 @@ void EditEntryWidget::setupMain()
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)));
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*)));
m_mainUi->passwordGenerator->hide();
m_mainUi->passwordGenerator->reset();
} }
void EditEntryWidget::setupAdvanced() void EditEntryWidget::setupAdvanced()
@ -816,8 +808,6 @@ void EditEntryWidget::setForms(Entry* entry, bool restore)
} else { } else {
m_mainUi->notesEdit->setFont(Font::defaultFont()); m_mainUi->notesEdit->setFont(Font::defaultFont());
} }
m_mainUi->passwordGenerator->setVisible(false);
m_mainUi->passwordGenerator->reset(entry->password().length());
m_advancedUi->attachmentsWidget->setReadOnly(m_history); m_advancedUi->attachmentsWidget->setReadOnly(m_history);
m_advancedUi->addAttributeButton->setEnabled(!m_history); m_advancedUi->addAttributeButton->setEnabled(!m_history);
@ -845,13 +835,12 @@ void EditEntryWidget::setForms(Entry* entry, bool restore)
m_mainUi->passwordEdit->setText(entry->password()); m_mainUi->passwordEdit->setText(entry->password());
m_mainUi->passwordEdit->setShowPassword(config()->get("security/passwordscleartext").toBool()); m_mainUi->passwordEdit->setShowPassword(config()->get("security/passwordscleartext").toBool());
if (!m_history) { if (!m_history) {
m_mainUi->passwordEdit->enablePasswordGenerator(true); m_mainUi->passwordEdit->enablePasswordGenerator();
} }
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);
QList<QString> commonUsernames = m_db->commonUsernames(); QList<QString> commonUsernames = m_db->commonUsernames();
m_usernameCompleterModel->setStringList(commonUsernames); m_usernameCompleterModel->setStringList(commonUsernames);
QString usernameToRestore = m_mainUi->usernameComboBox->lineEdit()->text(); QString usernameToRestore = m_mainUi->usernameComboBox->lineEdit()->text();
@ -970,22 +959,6 @@ bool EditEntryWidget::commitEntry()
return true; return true;
} }
// Ask the user to apply the generator password, if open
if (m_mainUi->passwordGenerator->isVisible()
&& m_mainUi->passwordGenerator->getGeneratedPassword() != m_mainUi->passwordEdit->text()) {
auto answer = MessageBox::question(this,
tr("Apply generated password?"),
tr("Do you want to apply the generated password to this entry?"),
MessageBox::Yes | MessageBox::No,
MessageBox::Yes);
if (answer == MessageBox::Yes) {
m_mainUi->passwordGenerator->applyPassword();
}
}
// Hide the password generator
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());
m_entryAttributes->set(key, m_advancedUi->attributesEdit->toPlainText(), m_entryAttributes->isProtected(key)); m_entryAttributes->set(key, m_advancedUi->attributesEdit->toPlainText(), m_entryAttributes->isProtected(key));
@ -1142,22 +1115,6 @@ void EditEntryWidget::clear()
hideMessage(); hideMessage();
} }
void EditEntryWidget::togglePasswordGenerator()
{
bool visible = m_mainUi->passwordGenerator->isVisible();
if (!visible) {
m_mainUi->passwordGenerator->regeneratePassword();
m_mainUi->passwordGenerator->setPasswordVisible(m_mainUi->passwordEdit->isPasswordVisible());
}
m_mainUi->passwordGenerator->setVisible(!visible);
}
void EditEntryWidget::setGeneratedPassword(const QString& password)
{
m_mainUi->passwordEdit->setText(password);
m_mainUi->passwordGenerator->setVisible(false);
}
#ifdef WITH_XC_NETWORKING #ifdef WITH_XC_NETWORKING
void EditEntryWidget::updateFaviconButtonEnable(const QString& url) void EditEntryWidget::updateFaviconButtonEnable(const QString& url)
{ {

View File

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

View File

@ -20,7 +20,65 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item row="7" column="0" alignment="Qt::AlignRight"> <item row="8" column="1">
<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>
<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">
<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="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="urlLabel">
<property name="text">
<string>URL:</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>
</widget>
</item>
<item row="6" column="0" alignment="Qt::AlignRight">
<widget class="QCheckBox" name="expireCheck"> <widget class="QCheckBox" name="expireCheck">
<property name="toolTip"> <property name="toolTip">
<string>Toggle expiration</string> <string>Toggle expiration</string>
@ -33,7 +91,53 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1"> <item row="8" column="1">
<widget class="QPlainTextEdit" name="notesEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="accessibleName">
<string>Notes field</string>
</property>
</widget>
</item>
<item row="8" column="0" alignment="Qt::AlignLeft|Qt::AlignTop">
<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 row="0" column="1">
<widget class="QLineEdit" name="titleEdit">
<property name="accessibleName">
<string>Title field</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="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<widget class="QDateTimeEdit" name="expireDatePicker"> <widget class="QDateTimeEdit" name="expireDatePicker">
@ -69,83 +173,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="9" column="1">
<widget class="QPlainTextEdit" name="notesEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="accessibleName">
<string>Notes 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="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">
<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>
<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">
@ -153,36 +180,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0" alignment="Qt::AlignLeft|Qt::AlignTop">
<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 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>
</widget>
</item>
</layout> </layout>
<widget class="QLabel" name="titleLabel"> <widget class="QLabel" name="titleLabel">
<property name="geometry"> <property name="geometry">
@ -199,12 +196,6 @@
</widget> </widget>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>PasswordGeneratorWidget</class>
<extends>QWidget</extends>
<header>gui/PasswordGeneratorWidget.h</header>
<container>1</container>
</customwidget>
<customwidget> <customwidget>
<class>PasswordEdit</class> <class>PasswordEdit</class>
<extends>QLineEdit</extends> <extends>QLineEdit</extends>

View File

@ -36,21 +36,13 @@ EditGroupWidgetKeeShare::EditGroupWidgetKeeShare(QWidget* parent)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show"));
m_ui->togglePasswordGeneratorButton->setIcon(filePath()->icon("actions", "password-generator"));
m_ui->passwordGenerator->layout()->setContentsMargins(0, 0, 0, 0);
m_ui->passwordGenerator->hide();
m_ui->passwordGenerator->reset();
m_ui->messageWidget->hide(); m_ui->messageWidget->hide();
m_ui->messageWidget->setCloseButtonVisible(false); m_ui->messageWidget->setCloseButtonVisible(false);
m_ui->messageWidget->setAutoHideTimeout(-1); m_ui->messageWidget->setAutoHideTimeout(-1);
connect(m_ui->togglePasswordButton, SIGNAL(toggled(bool)), m_ui->passwordEdit, SLOT(setShowPassword(bool))); m_ui->passwordEdit->enablePasswordGenerator();
connect(m_ui->togglePasswordGeneratorButton, SIGNAL(toggled(bool)), SLOT(togglePasswordGeneratorButton(bool)));
connect(m_ui->passwordEdit, SIGNAL(textChanged(QString)), SLOT(selectPassword())); connect(m_ui->passwordEdit, SIGNAL(textChanged(QString)), SLOT(selectPassword()));
connect(m_ui->passwordGenerator, SIGNAL(appliedPassword(QString)), SLOT(setGeneratedPassword(QString)));
connect(m_ui->pathEdit, SIGNAL(editingFinished()), SLOT(selectPath())); connect(m_ui->pathEdit, SIGNAL(editingFinished()), SLOT(selectPath()));
connect(m_ui->pathSelectionButton, SIGNAL(pressed()), SLOT(launchPathSelectionDialog())); connect(m_ui->pathSelectionButton, SIGNAL(pressed()), SLOT(launchPathSelectionDialog()));
connect(m_ui->typeComboBox, SIGNAL(currentIndexChanged(int)), SLOT(selectType())); connect(m_ui->typeComboBox, SIGNAL(currentIndexChanged(int)), SLOT(selectType()));
@ -201,10 +193,6 @@ void EditGroupWidgetKeeShare::update()
showSharingState(); showSharingState();
} }
m_ui->passwordGenerator->hide();
m_ui->togglePasswordGeneratorButton->setChecked(false);
m_ui->togglePasswordButton->setChecked(false);
} }
void EditGroupWidgetKeeShare::clearInputs() void EditGroupWidgetKeeShare::clearInputs()
@ -215,24 +203,6 @@ void EditGroupWidgetKeeShare::clearInputs()
m_ui->passwordEdit->clear(); m_ui->passwordEdit->clear();
m_ui->pathEdit->clear(); m_ui->pathEdit->clear();
m_ui->typeComboBox->setCurrentIndex(KeeShareSettings::Inactive); m_ui->typeComboBox->setCurrentIndex(KeeShareSettings::Inactive);
m_ui->passwordGenerator->setVisible(false);
}
void EditGroupWidgetKeeShare::togglePasswordGeneratorButton(bool checked)
{
m_ui->passwordGenerator->regeneratePassword();
m_ui->passwordGenerator->setVisible(checked);
}
void EditGroupWidgetKeeShare::setGeneratedPassword(const QString& password)
{
if (!m_temporaryGroup) {
return;
}
auto reference = KeeShare::referenceOf(m_temporaryGroup);
reference.password = password;
KeeShare::setReferenceTo(m_temporaryGroup, reference);
m_ui->togglePasswordGeneratorButton->setChecked(false);
} }
void EditGroupWidgetKeeShare::selectPath() void EditGroupWidgetKeeShare::selectPath()

View File

@ -49,8 +49,6 @@ private slots:
void selectPassword(); void selectPassword();
void launchPathSelectionDialog(); void launchPathSelectionDialog();
void selectPath(); void selectPath();
void setGeneratedPassword(const QString& password);
void togglePasswordGeneratorButton(bool checked);
private: private:
QScopedPointer<Ui::EditGroupWidgetKeeShare> m_ui; QScopedPointer<Ui::EditGroupWidgetKeeShare> m_ui;

View File

@ -6,56 +6,62 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>342</width> <width>344</width>
<height>378</height> <height>143</height>
</rect> </rect>
</property> </property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property> </property>
<item> <item>
<widget class="MessageWidget" name="messageWidget" native="true"/> <widget class="MessageWidget" name="messageWidget" native="true"/>
</item> </item>
<item> <item>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
<item row="2" column="0"> <item row="0" column="0">
<widget class="QLabel" name="typeLabel"> <widget class="QLabel" name="typeLabel">
<property name="text"> <property name="text">
<string>Type:</string> <string>Type:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="typeComboBox"> <widget class="QComboBox" name="typeComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="accessibleName"> <property name="accessibleName">
<string>Sharing mode field</string> <string>Sharing mode field</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="1" column="0">
<widget class="QLabel" name="pathLabel"> <widget class="QLabel" name="pathLabel">
<property name="text"> <property name="text">
<string>Path:</string> <string>Path:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="1" column="1">
<layout class="QHBoxLayout" name="pathLayout"> <layout class="QHBoxLayout" name="pathLayout">
<item> <item>
<widget class="QLineEdit" name="pathEdit"> <widget class="QLineEdit" name="pathEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="accessibleName"> <property name="accessibleName">
<string>Path to share file field</string> <string>Path to share file field</string>
</property> </property>
@ -73,60 +79,68 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="4" column="0"> <item row="2" column="0">
<widget class="QLabel" name="passwordLabel"> <widget class="QLabel" name="passwordLabel">
<property name="text"> <property name="text">
<string>Password:</string> <string>Password:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="2" column="1">
<layout class="QHBoxLayout" name="passwordLayout"> <widget class="PasswordEdit" name="passwordEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="accessibleName">
<string>Password field</string>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="PasswordEdit" name="passwordEdit"> <spacer name="horizontalSpacer">
<property name="accessibleName"> <property name="orientation">
<string>Password field</string> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="echoMode"> <property name="sizeHint" stdset="0">
<enum>QLineEdit::Password</enum> <size>
<width>40</width>
<height>20</height>
</size>
</property> </property>
</widget> </spacer>
</item> </item>
<item> <item>
<widget class="QToolButton" name="togglePasswordButton"> <widget class="QPushButton" name="clearButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="accessibleName"> <property name="accessibleName">
<string>Toggle password visibility</string> <string>Clear fields</string>
</property> </property>
<property name="checkable"> <property name="text">
<bool>true</bool> <string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="togglePasswordGeneratorButton">
<property name="accessibleName">
<string>Toggle password generator</string>
</property>
<property name="checkable">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
<item row="5" column="1">
<widget class="PasswordGeneratorWidget" name="passwordGenerator" native="true"/>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="clearButton">
<property name="accessibleName">
<string>Clear fields</string>
</property>
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -145,12 +159,6 @@
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>PasswordGeneratorWidget</class>
<extends>QWidget</extends>
<header>gui/PasswordGeneratorWidget.h</header>
<container>1</container>
</customwidget>
<customwidget> <customwidget>
<class>PasswordEdit</class> <class>PasswordEdit</class>
<extends>QLineEdit</extends> <extends>QLineEdit</extends>

View File

@ -58,6 +58,7 @@
#include "gui/FileDialog.h" #include "gui/FileDialog.h"
#include "gui/MessageBox.h" #include "gui/MessageBox.h"
#include "gui/PasswordEdit.h" #include "gui/PasswordEdit.h"
#include "gui/PasswordGeneratorWidget.h"
#include "gui/SearchWidget.h" #include "gui/SearchWidget.h"
#include "gui/TotpDialog.h" #include "gui/TotpDialog.h"
#include "gui/TotpSetupDialog.h" #include "gui/TotpSetupDialog.h"
@ -652,52 +653,63 @@ void TestGui::testPasswordEntryEntropy()
auto* passwordEdit = editEntryWidget->findChild<PasswordEdit*>(); auto* passwordEdit = editEntryWidget->findChild<PasswordEdit*>();
QVERIFY(passwordEdit); QVERIFY(passwordEdit);
QTest::mouseClick(passwordEdit, Qt::LeftButton); QTest::mouseClick(passwordEdit, Qt::LeftButton);
QTimer::singleShot(50, this, SLOT(passwordGeneratorCallback()));
QTest::keyClick(passwordEdit, Qt::Key_G, Qt::ControlModifier); QTest::keyClick(passwordEdit, Qt::Key_G, Qt::ControlModifier);
}
void TestGui::passwordGeneratorCallback()
{
auto* pwGeneratorWidget = m_dbWidget->findChild<PasswordGeneratorWidget*>();
QVERIFY(pwGeneratorWidget);
// Type in some password // Type in some password
auto* editNewPassword = editEntryWidget->findChild<QLineEdit*>("editNewPassword"); auto* generatedPassword = pwGeneratorWidget->findChild<QLineEdit*>("editNewPassword");
auto* entropyLabel = editEntryWidget->findChild<QLabel*>("entropyLabel"); auto* entropyLabel = pwGeneratorWidget->findChild<QLabel*>("entropyLabel");
auto* strengthLabel = editEntryWidget->findChild<QLabel*>("strengthLabel"); auto* strengthLabel = pwGeneratorWidget->findChild<QLabel*>("strengthLabel");
editNewPassword->setText(""); generatedPassword->setText("");
QTest::keyClicks(editNewPassword, "hello"); QTest::keyClicks(generatedPassword, "hello");
QCOMPARE(entropyLabel->text(), QString("Entropy: 6.38 bit")); QCOMPARE(entropyLabel->text(), QString("Entropy: 6.38 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor"));
editNewPassword->setText(""); generatedPassword->setText("");
QTest::keyClicks(editNewPassword, "helloworld"); QTest::keyClicks(generatedPassword, "helloworld");
QCOMPARE(entropyLabel->text(), QString("Entropy: 13.10 bit")); QCOMPARE(entropyLabel->text(), QString("Entropy: 13.10 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor"));
editNewPassword->setText(""); generatedPassword->setText("");
QTest::keyClicks(editNewPassword, "password1"); QTest::keyClicks(generatedPassword, "password1");
QCOMPARE(entropyLabel->text(), QString("Entropy: 4.00 bit")); QCOMPARE(entropyLabel->text(), QString("Entropy: 4.00 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor"));
editNewPassword->setText(""); generatedPassword->setText("");
QTest::keyClicks(editNewPassword, "D0g.................."); QTest::keyClicks(generatedPassword, "D0g..................");
QCOMPARE(entropyLabel->text(), QString("Entropy: 19.02 bit")); QCOMPARE(entropyLabel->text(), QString("Entropy: 19.02 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor"));
editNewPassword->setText(""); generatedPassword->setText("");
QTest::keyClicks(editNewPassword, "Tr0ub4dour&3"); QTest::keyClicks(generatedPassword, "Tr0ub4dour&3");
QCOMPARE(entropyLabel->text(), QString("Entropy: 30.87 bit")); QCOMPARE(entropyLabel->text(), QString("Entropy: 30.87 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Poor"));
editNewPassword->setText(""); generatedPassword->setText("");
QTest::keyClicks(editNewPassword, "correcthorsebatterystaple"); QTest::keyClicks(generatedPassword, "correcthorsebatterystaple");
QCOMPARE(entropyLabel->text(), QString("Entropy: 47.98 bit")); QCOMPARE(entropyLabel->text(), QString("Entropy: 47.98 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Weak")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Weak"));
editNewPassword->setText(""); generatedPassword->setText("");
QTest::keyClicks(editNewPassword, "YQC3kbXbjC652dTDH"); QTest::keyClicks(generatedPassword, "YQC3kbXbjC652dTDH");
QCOMPARE(entropyLabel->text(), QString("Entropy: 95.83 bit")); QCOMPARE(entropyLabel->text(), QString("Entropy: 95.83 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Good")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Good"));
editNewPassword->setText(""); generatedPassword->setText("");
QTest::keyClicks(editNewPassword, "Bs5ZFfthWzR8DGFEjaCM6bGqhmCT4km"); QTest::keyClicks(generatedPassword, "Bs5ZFfthWzR8DGFEjaCM6bGqhmCT4km");
QCOMPARE(entropyLabel->text(), QString("Entropy: 174.59 bit")); QCOMPARE(entropyLabel->text(), QString("Entropy: 174.59 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Excellent")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Excellent"));
QTest::mouseClick(generatedPassword, Qt::LeftButton);
QTest::keyClick(generatedPassword, Qt::Key_Escape);
} }
void TestGui::testDicewareEntryEntropy() void TestGui::testDicewareEntryEntropy()
@ -726,11 +738,20 @@ void TestGui::testDicewareEntryEntropy()
auto* passwordEdit = editEntryWidget->findChild<PasswordEdit*>(); auto* passwordEdit = editEntryWidget->findChild<PasswordEdit*>();
QVERIFY(passwordEdit); QVERIFY(passwordEdit);
QTest::mouseClick(passwordEdit, Qt::LeftButton); QTest::mouseClick(passwordEdit, Qt::LeftButton);
QTimer::singleShot(50, this, SLOT(passwordGeneratorCallback()));
QTest::keyClick(passwordEdit, Qt::Key_G, Qt::ControlModifier); QTest::keyClick(passwordEdit, Qt::Key_G, Qt::ControlModifier);
}
void TestGui::passphraseGeneratorCallback()
{
auto* pwGeneratorWidget = m_dbWidget->findChild<PasswordGeneratorWidget*>();
QVERIFY(pwGeneratorWidget);
// Select Diceware // Select Diceware
auto* tabWidget = editEntryWidget->findChild<QTabWidget*>("tabWidget"); auto* generatedPassword = pwGeneratorWidget->findChild<QLineEdit*>("editNewPassword");
auto* dicewareWidget = editEntryWidget->findChild<QWidget*>("dicewareWidget"); auto* tabWidget = pwGeneratorWidget->findChild<QTabWidget*>("tabWidget");
auto* dicewareWidget = pwGeneratorWidget->findChild<QWidget*>("dicewareWidget");
tabWidget->setCurrentWidget(dicewareWidget); tabWidget->setCurrentWidget(dicewareWidget);
auto* comboBoxWordList = dicewareWidget->findChild<QComboBox*>("comboBoxWordList"); auto* comboBoxWordList = dicewareWidget->findChild<QComboBox*>("comboBoxWordList");
@ -738,12 +759,15 @@ void TestGui::testDicewareEntryEntropy()
auto* spinBoxWordCount = dicewareWidget->findChild<QSpinBox*>("spinBoxWordCount"); auto* spinBoxWordCount = dicewareWidget->findChild<QSpinBox*>("spinBoxWordCount");
spinBoxWordCount->setValue(6); spinBoxWordCount->setValue(6);
// Type in some password // Verify entropy and strength
auto* entropyLabel = editEntryWidget->findChild<QLabel*>("entropyLabel"); auto* entropyLabel = pwGeneratorWidget->findChild<QLabel*>("entropyLabel");
auto* strengthLabel = editEntryWidget->findChild<QLabel*>("strengthLabel"); auto* strengthLabel = pwGeneratorWidget->findChild<QLabel*>("strengthLabel");
QCOMPARE(entropyLabel->text(), QString("Entropy: 77.55 bit")); QCOMPARE(entropyLabel->text(), QString("Entropy: 77.55 bit"));
QCOMPARE(strengthLabel->text(), QString("Password Quality: Good")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Good"));
QTest::mouseClick(generatedPassword, Qt::LeftButton);
QTest::keyClick(generatedPassword, Qt::Key_Escape);
} }
void TestGui::testTotp() void TestGui::testTotp()

View File

@ -39,6 +39,8 @@ class TestGui : public QObject
protected slots: protected slots:
void createDatabaseCallback(); void createDatabaseCallback();
void passwordGeneratorCallback();
void passphraseGeneratorCallback();
private slots: private slots:
void initTestCase(); void initTestCase();