mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Merge pull request #373 from keepassxreboot/feature/new-password-generator
New Diceware passphrase generator
This commit is contained in:
commit
5696178de4
@ -15,6 +15,9 @@
|
||||
|
||||
add_subdirectory(translations)
|
||||
|
||||
file(GLOB wordlists_files "wordlists/*.wordlist")
|
||||
install(FILES ${wordlists_files} DESTINATION ${DATA_INSTALL_DIR}/wordlists)
|
||||
|
||||
file(GLOB DATABASE_ICONS icons/database/*.png)
|
||||
|
||||
install(FILES ${DATABASE_ICONS} DESTINATION ${DATA_INSTALL_DIR}/icons/database)
|
||||
|
7776
share/wordlists/eff_large.wordlist
Normal file
7776
share/wordlists/eff_large.wordlist
Normal file
File diff suppressed because it is too large
Load Diff
@ -46,6 +46,7 @@ set(keepassx_SOURCES
|
||||
core/ListDeleter.h
|
||||
core/Metadata.cpp
|
||||
core/PasswordGenerator.cpp
|
||||
core/PassphraseGenerator.cpp
|
||||
core/SignalMultiplexer.cpp
|
||||
core/TimeDelta.cpp
|
||||
core/TimeInfo.cpp
|
||||
@ -96,7 +97,6 @@ set(keepassx_SOURCES
|
||||
gui/MessageWidget.cpp
|
||||
gui/PasswordEdit.cpp
|
||||
gui/PasswordGeneratorWidget.cpp
|
||||
gui/PasswordComboBox.cpp
|
||||
gui/SettingsWidget.cpp
|
||||
gui/SearchWidget.cpp
|
||||
gui/SortFilterHideProxyModel.cpp
|
||||
|
111
src/core/PassphraseGenerator.cpp
Normal file
111
src/core/PassphraseGenerator.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PassphraseGenerator.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "crypto/Random.h"
|
||||
#include "core/FilePath.h"
|
||||
|
||||
PassphraseGenerator::PassphraseGenerator()
|
||||
: m_wordCount(0)
|
||||
, m_separator(' ')
|
||||
{
|
||||
const QString path = filePath()->dataPath("wordlists/eff_large.wordlist");
|
||||
setWordList(path);
|
||||
}
|
||||
|
||||
double PassphraseGenerator::calculateEntropy(QString passphrase)
|
||||
{
|
||||
Q_UNUSED(passphrase);
|
||||
|
||||
if (m_wordlist.size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return log(m_wordlist.size()) / log(2.0) * m_wordCount;
|
||||
}
|
||||
|
||||
void PassphraseGenerator::setWordCount(int wordCount)
|
||||
{
|
||||
if (wordCount > 0) {
|
||||
m_wordCount = wordCount;
|
||||
} else {
|
||||
// safe default if something goes wrong
|
||||
m_wordCount = 7;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PassphraseGenerator::setWordList(QString path)
|
||||
{
|
||||
m_wordlist.clear();
|
||||
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qWarning("Couldn't load passphrase wordlist.");
|
||||
return;
|
||||
}
|
||||
|
||||
QTextStream in(&file);
|
||||
while (!in.atEnd()) {
|
||||
m_wordlist.append(in.readLine());
|
||||
}
|
||||
|
||||
if (m_wordlist.size() < 4000) {
|
||||
qWarning("Wordlist too short!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void PassphraseGenerator::setWordSeparator(QString separator) {
|
||||
m_separator = separator;
|
||||
}
|
||||
|
||||
QString PassphraseGenerator::generatePassphrase() const
|
||||
{
|
||||
Q_ASSERT(isValid());
|
||||
|
||||
// In case there was an error loading the wordlist
|
||||
if(m_wordlist.length() == 0) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
QStringList words;
|
||||
for (int i = 0; i < m_wordCount; i++) {
|
||||
int wordIndex = randomGen()->randomUInt(m_wordlist.length());
|
||||
words.append(m_wordlist.at(wordIndex));
|
||||
}
|
||||
|
||||
return words.join(m_separator);
|
||||
}
|
||||
|
||||
bool PassphraseGenerator::isValid() const
|
||||
{
|
||||
if (m_wordCount == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_wordlist.size() < 1000) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Michael Curtis <michael@moltenmercury.org>
|
||||
* Copyright (C) 2014 Felix Geyer <debfx@fobos.de>
|
||||
* Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -16,31 +15,32 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef KEEPASSX_PASSWORDCOMBOBOX_H
|
||||
#define KEEPASSX_PASSWORDCOMBOBOX_H
|
||||
#ifndef KEEPASSX_PASSPHRASEGENERATOR_H
|
||||
#define KEEPASSX_PASSPHRASEGENERATOR_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QFlags>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
class PasswordGenerator;
|
||||
|
||||
class PasswordComboBox : public QComboBox
|
||||
class PassphraseGenerator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PasswordComboBox(QWidget* parent = nullptr);
|
||||
~PasswordComboBox();
|
||||
PassphraseGenerator();
|
||||
|
||||
void setGenerator(PasswordGenerator* generator);
|
||||
void setNumberAlternatives(int alternatives);
|
||||
void showPopup();
|
||||
double calculateEntropy(QString passphrase);
|
||||
void setWordCount(int wordCount);
|
||||
void setWordList(QString path);
|
||||
void setWordSeparator(QString separator);
|
||||
bool isValid() const;
|
||||
|
||||
public slots:
|
||||
void setEcho(bool echo);
|
||||
QString generatePassphrase() const;
|
||||
|
||||
private:
|
||||
PasswordGenerator* m_generator;
|
||||
int m_alternatives;
|
||||
int m_wordCount;
|
||||
QString m_separator;
|
||||
QVector<QString> m_wordlist;
|
||||
|
||||
Q_DISABLE_COPY(PassphraseGenerator)
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_PASSWORDCOMBOBOX_H
|
||||
#endif // KEEPASSX_PASSPHRASEGENERATOR_H
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Michael Curtis <michael@moltenmercury.org>
|
||||
* Copyright (C) 2014 Felix Geyer <debfx@fobos.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 or (at your option)
|
||||
* version 3 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PasswordComboBox.h"
|
||||
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "core/PasswordGenerator.h"
|
||||
|
||||
PasswordComboBox::PasswordComboBox(QWidget* parent)
|
||||
: QComboBox(parent)
|
||||
, m_generator(nullptr)
|
||||
, m_alternatives(10)
|
||||
{
|
||||
setEditable(true);
|
||||
setEcho(false);
|
||||
}
|
||||
|
||||
PasswordComboBox::~PasswordComboBox()
|
||||
{
|
||||
}
|
||||
|
||||
void PasswordComboBox::setEcho(bool echo)
|
||||
{
|
||||
lineEdit()->setEchoMode(echo ? QLineEdit::Normal : QLineEdit::Password);
|
||||
|
||||
QString current = currentText();
|
||||
|
||||
if (echo) {
|
||||
// add fake item to show visual indication that a popup is available
|
||||
addItem("");
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// Qt on Mac OS doesn't seem to know the generic monospace family (tested with 4.8.6)
|
||||
setStyleSheet("QComboBox { font-family: monospace,Menlo,Monaco; }");
|
||||
#else
|
||||
setStyleSheet("QComboBox { font-family: monospace,Courier New; }");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
// clear items so the combobox indicates that no popup menu is available
|
||||
clear();
|
||||
|
||||
setStyleSheet("QComboBox { font-family: initial; }");
|
||||
}
|
||||
|
||||
setEditText(current);
|
||||
}
|
||||
|
||||
void PasswordComboBox::setGenerator(PasswordGenerator* generator)
|
||||
{
|
||||
m_generator = generator;
|
||||
}
|
||||
|
||||
void PasswordComboBox::setNumberAlternatives(int alternatives)
|
||||
{
|
||||
m_alternatives = alternatives;
|
||||
}
|
||||
|
||||
void PasswordComboBox::showPopup()
|
||||
{
|
||||
// no point in showing a bunch of hidden passwords
|
||||
if (lineEdit()->echoMode() == QLineEdit::Password) {
|
||||
hidePopup();
|
||||
return;
|
||||
}
|
||||
|
||||
// keep existing password as the first item in the popup
|
||||
QString current = currentText();
|
||||
clear();
|
||||
addItem(current);
|
||||
|
||||
if (m_generator && m_generator->isValid()) {
|
||||
for (int alternative = 0; alternative < m_alternatives; alternative++) {
|
||||
QString password = m_generator->generatePassword();
|
||||
|
||||
addItem(password);
|
||||
}
|
||||
}
|
||||
|
||||
QComboBox::showPopup();
|
||||
}
|
@ -19,6 +19,7 @@
|
||||
#include "ui_PasswordGeneratorWidget.h"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QDir>
|
||||
|
||||
#include "core/Config.h"
|
||||
#include "core/PasswordGenerator.h"
|
||||
@ -27,7 +28,8 @@
|
||||
PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_updatingSpinBox(false)
|
||||
, m_generator(new PasswordGenerator())
|
||||
, m_passwordGenerator(new PasswordGenerator())
|
||||
, m_dicewareGenerator(new PassphraseGenerator())
|
||||
, m_ui(new Ui::PasswordGeneratorWidget())
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
@ -38,12 +40,18 @@ PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent)
|
||||
connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updatePasswordStrength(QString)));
|
||||
connect(m_ui->togglePasswordButton, SIGNAL(toggled(bool)), SLOT(togglePasswordShown(bool)));
|
||||
connect(m_ui->buttonApply, SIGNAL(clicked()), SLOT(applyPassword()));
|
||||
connect(m_ui->buttonGenerate, SIGNAL(clicked()), SLOT(generatePassword()));
|
||||
connect(m_ui->buttonGenerate, SIGNAL(clicked()), SLOT(regeneratePassword()));
|
||||
|
||||
connect(m_ui->sliderLength, SIGNAL(valueChanged(int)), SLOT(sliderMoved()));
|
||||
connect(m_ui->spinBoxLength, SIGNAL(valueChanged(int)), SLOT(spinBoxChanged()));
|
||||
connect(m_ui->sliderLength, SIGNAL(valueChanged(int)), SLOT(passwordSliderMoved()));
|
||||
connect(m_ui->spinBoxLength, SIGNAL(valueChanged(int)), SLOT(passwordSpinBoxChanged()));
|
||||
|
||||
connect(m_ui->sliderWordCount, SIGNAL(valueChanged(int)), SLOT(dicewareSliderMoved()));
|
||||
connect(m_ui->spinBoxWordCount, SIGNAL(valueChanged(int)), SLOT(dicewareSpinBoxChanged()));
|
||||
|
||||
connect(m_ui->editWordSeparator, SIGNAL(textChanged(QString)), SLOT(updateGenerator()));
|
||||
connect(m_ui->comboBoxWordList, SIGNAL(currentIndexChanged(int)), SLOT(updateGenerator()));
|
||||
connect(m_ui->optionButtons, SIGNAL(buttonClicked(int)), SLOT(updateGenerator()));
|
||||
connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(updateGenerator()));
|
||||
|
||||
// set font size of password quality and entropy labels dynamically to 80% of
|
||||
// the default font size, but make it no smaller than 8pt
|
||||
@ -54,6 +62,20 @@ PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent)
|
||||
m_ui->entropyLabel->setFont(defaultFont);
|
||||
m_ui->strengthLabel->setFont(defaultFont);
|
||||
}
|
||||
|
||||
// set default separator to Space
|
||||
m_ui->editWordSeparator->setText(" ");
|
||||
|
||||
QDir path(filePath()->dataPath("wordlists/"));
|
||||
QStringList files = path.entryList(QDir::Files);
|
||||
m_ui->comboBoxWordList->addItems(files);
|
||||
if (files.size() > 1) {
|
||||
m_ui->comboBoxWordList->setVisible(true);
|
||||
m_ui->labelWordList->setVisible(true);
|
||||
} else {
|
||||
m_ui->comboBoxWordList->setVisible(false);
|
||||
m_ui->labelWordList->setVisible(false);
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
reset();
|
||||
@ -65,28 +87,42 @@ PasswordGeneratorWidget::~PasswordGeneratorWidget()
|
||||
|
||||
void PasswordGeneratorWidget::loadSettings()
|
||||
{
|
||||
// Password config
|
||||
m_ui->checkBoxLower->setChecked(config()->get("generator/LowerCase", true).toBool());
|
||||
m_ui->checkBoxUpper->setChecked(config()->get("generator/UpperCase", true).toBool());
|
||||
m_ui->checkBoxNumbers->setChecked(config()->get("generator/Numbers", true).toBool());
|
||||
m_ui->checkBoxSpecialChars->setChecked(config()->get("generator/SpecialChars", false).toBool());
|
||||
|
||||
m_ui->checkBoxExcludeAlike->setChecked(config()->get("generator/ExcludeAlike", true).toBool());
|
||||
m_ui->checkBoxEnsureEvery->setChecked(config()->get("generator/EnsureEvery", true).toBool());
|
||||
|
||||
m_ui->spinBoxLength->setValue(config()->get("generator/Length", 16).toInt());
|
||||
|
||||
// Diceware config
|
||||
m_ui->spinBoxWordCount->setValue(config()->get("generator/WordCount", 6).toInt());
|
||||
m_ui->editWordSeparator->setText(config()->get("generator/WordSeparator", " ").toString());
|
||||
m_ui->comboBoxWordList->setCurrentText(config()->get("generator/WordList", "eff_large.wordlist").toString());
|
||||
|
||||
// Password or diceware?
|
||||
m_ui->tabWidget->setCurrentIndex(config()->get("generator/Type", 0).toInt());
|
||||
}
|
||||
|
||||
void PasswordGeneratorWidget::saveSettings()
|
||||
{
|
||||
// Password config
|
||||
config()->set("generator/LowerCase", m_ui->checkBoxLower->isChecked());
|
||||
config()->set("generator/UpperCase", m_ui->checkBoxUpper->isChecked());
|
||||
config()->set("generator/Numbers", m_ui->checkBoxNumbers->isChecked());
|
||||
config()->set("generator/SpecialChars", m_ui->checkBoxSpecialChars->isChecked());
|
||||
|
||||
config()->set("generator/ExcludeAlike", m_ui->checkBoxExcludeAlike->isChecked());
|
||||
config()->set("generator/EnsureEvery", m_ui->checkBoxEnsureEvery->isChecked());
|
||||
|
||||
config()->set("generator/Length", m_ui->spinBoxLength->value());
|
||||
|
||||
// Diceware config
|
||||
config()->set("generator/WordCount", m_ui->spinBoxWordCount->value());
|
||||
config()->set("generator/WordSeparator", m_ui->editWordSeparator->text());
|
||||
config()->set("generator/WordList", m_ui->comboBoxWordList->currentText());
|
||||
|
||||
// Password or diceware?
|
||||
config()->set("generator/Type", m_ui->tabWidget->currentIndex());
|
||||
}
|
||||
|
||||
void PasswordGeneratorWidget::reset()
|
||||
@ -108,11 +144,19 @@ void PasswordGeneratorWidget::setStandaloneMode(bool standalone)
|
||||
}
|
||||
|
||||
void PasswordGeneratorWidget::regeneratePassword()
|
||||
{
|
||||
if (m_generator->isValid()) {
|
||||
QString password = m_generator->generatePassword();
|
||||
m_ui->editNewPassword->setText(password);
|
||||
updatePasswordStrength(password);
|
||||
{
|
||||
if (m_ui->tabWidget->currentIndex() == Password) {
|
||||
if (m_passwordGenerator->isValid()) {
|
||||
QString password = m_passwordGenerator->generatePassword();
|
||||
m_ui->editNewPassword->setText(password);
|
||||
updatePasswordStrength(password);
|
||||
}
|
||||
} else {
|
||||
if (m_dicewareGenerator->isValid()) {
|
||||
QString password = m_dicewareGenerator->generatePassphrase();
|
||||
m_ui->editNewPassword->setText(password);
|
||||
updatePasswordStrength(password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +167,13 @@ void PasswordGeneratorWidget::updateApplyEnabled(const QString& password)
|
||||
|
||||
void PasswordGeneratorWidget::updatePasswordStrength(const QString& password)
|
||||
{
|
||||
double entropy = m_generator->calculateEntropy(password);
|
||||
double entropy = 0.0;
|
||||
if (m_ui->tabWidget->currentIndex() == Password) {
|
||||
entropy = m_passwordGenerator->calculateEntropy(password);
|
||||
} else {
|
||||
entropy = m_dicewareGenerator->calculateEntropy(password);
|
||||
}
|
||||
|
||||
m_ui->entropyLabel->setText(tr("Entropy: %1 bit").arg(QString::number(entropy, 'f', 2)));
|
||||
|
||||
if (entropy > m_ui->entropyProgressBar->maximum()) {
|
||||
@ -134,14 +184,6 @@ void PasswordGeneratorWidget::updatePasswordStrength(const QString& password)
|
||||
colorStrengthIndicator(entropy);
|
||||
}
|
||||
|
||||
void PasswordGeneratorWidget::generatePassword()
|
||||
{
|
||||
if (m_generator->isValid()) {
|
||||
QString password = m_generator->generatePassword();
|
||||
m_ui->editNewPassword->setText(password);
|
||||
}
|
||||
}
|
||||
|
||||
void PasswordGeneratorWidget::applyPassword()
|
||||
{
|
||||
saveSettings();
|
||||
@ -149,7 +191,7 @@ void PasswordGeneratorWidget::applyPassword()
|
||||
emit dialogTerminated();
|
||||
}
|
||||
|
||||
void PasswordGeneratorWidget::sliderMoved()
|
||||
void PasswordGeneratorWidget::passwordSliderMoved()
|
||||
{
|
||||
if (m_updatingSpinBox) {
|
||||
return;
|
||||
@ -160,7 +202,7 @@ void PasswordGeneratorWidget::sliderMoved()
|
||||
updateGenerator();
|
||||
}
|
||||
|
||||
void PasswordGeneratorWidget::spinBoxChanged()
|
||||
void PasswordGeneratorWidget::passwordSpinBoxChanged()
|
||||
{
|
||||
if (m_updatingSpinBox) {
|
||||
return;
|
||||
@ -176,6 +218,20 @@ void PasswordGeneratorWidget::spinBoxChanged()
|
||||
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();
|
||||
}
|
||||
|
||||
void PasswordGeneratorWidget::togglePasswordShown(bool showing)
|
||||
{
|
||||
m_ui->editNewPassword->setShowPassword(showing);
|
||||
@ -196,13 +252,13 @@ void PasswordGeneratorWidget::colorStrengthIndicator(double entropy)
|
||||
// Set the color and background based on entropy
|
||||
// colors are taking from the KDE breeze palette
|
||||
// <https://community.kde.org/KDE_Visual_Design_Group/HIG/Color>
|
||||
if (entropy < 35) {
|
||||
if (entropy < 40) {
|
||||
m_ui->entropyProgressBar->setStyleSheet(style.arg("#c0392b"));
|
||||
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Poor")));
|
||||
} else if (entropy >= 35 && entropy < 55) {
|
||||
} else if (entropy >= 40 && entropy < 65) {
|
||||
m_ui->entropyProgressBar->setStyleSheet(style.arg("#f39c1f"));
|
||||
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Weak")));
|
||||
} else if (entropy >= 55 && entropy < 100) {
|
||||
} else if (entropy >= 65 && entropy < 100) {
|
||||
m_ui->entropyProgressBar->setStyleSheet(style.arg("#11d116"));
|
||||
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Good")));
|
||||
} else {
|
||||
@ -251,44 +307,71 @@ PasswordGenerator::GeneratorFlags PasswordGeneratorWidget::generatorFlags()
|
||||
|
||||
void PasswordGeneratorWidget::updateGenerator()
|
||||
{
|
||||
PasswordGenerator::CharClasses classes = charClasses();
|
||||
PasswordGenerator::GeneratorFlags flags = generatorFlags();
|
||||
if (m_ui->tabWidget->currentIndex() == Password) {
|
||||
PasswordGenerator::CharClasses classes = charClasses();
|
||||
PasswordGenerator::GeneratorFlags flags = generatorFlags();
|
||||
|
||||
int minLength = 0;
|
||||
if (flags.testFlag(PasswordGenerator::CharFromEveryGroup)) {
|
||||
if (classes.testFlag(PasswordGenerator::LowerLetters)) {
|
||||
minLength++;
|
||||
int minLength = 0;
|
||||
if (flags.testFlag(PasswordGenerator::CharFromEveryGroup)) {
|
||||
if (classes.testFlag(PasswordGenerator::LowerLetters)) {
|
||||
minLength++;
|
||||
}
|
||||
if (classes.testFlag(PasswordGenerator::UpperLetters)) {
|
||||
minLength++;
|
||||
}
|
||||
if (classes.testFlag(PasswordGenerator::Numbers)) {
|
||||
minLength++;
|
||||
}
|
||||
if (classes.testFlag(PasswordGenerator::SpecialCharacters)) {
|
||||
minLength++;
|
||||
}
|
||||
}
|
||||
if (classes.testFlag(PasswordGenerator::UpperLetters)) {
|
||||
minLength++;
|
||||
minLength = qMax(minLength, 1);
|
||||
|
||||
if (m_ui->spinBoxLength->value() < minLength) {
|
||||
m_updatingSpinBox = true;
|
||||
m_ui->spinBoxLength->setValue(minLength);
|
||||
m_ui->sliderLength->setValue(minLength);
|
||||
m_updatingSpinBox = false;
|
||||
}
|
||||
if (classes.testFlag(PasswordGenerator::Numbers)) {
|
||||
minLength++;
|
||||
|
||||
m_ui->spinBoxLength->setMinimum(minLength);
|
||||
m_ui->sliderLength->setMinimum(minLength);
|
||||
|
||||
m_passwordGenerator->setLength(m_ui->spinBoxLength->value());
|
||||
m_passwordGenerator->setCharClasses(classes);
|
||||
m_passwordGenerator->setFlags(flags);
|
||||
|
||||
if (m_passwordGenerator->isValid()) {
|
||||
m_ui->buttonGenerate->setEnabled(true);
|
||||
} else {
|
||||
m_ui->buttonGenerate->setEnabled(false);
|
||||
}
|
||||
if (classes.testFlag(PasswordGenerator::SpecialCharacters)) {
|
||||
minLength++;
|
||||
}
|
||||
}
|
||||
minLength = qMax(minLength, 1);
|
||||
|
||||
if (m_ui->spinBoxLength->value() < minLength) {
|
||||
m_updatingSpinBox = true;
|
||||
m_ui->spinBoxLength->setValue(minLength);
|
||||
m_ui->sliderLength->setValue(minLength);
|
||||
m_updatingSpinBox = false;
|
||||
}
|
||||
|
||||
m_ui->spinBoxLength->setMinimum(minLength);
|
||||
m_ui->sliderLength->setMinimum(minLength);
|
||||
|
||||
m_generator->setLength(m_ui->spinBoxLength->value());
|
||||
m_generator->setCharClasses(classes);
|
||||
m_generator->setFlags(flags);
|
||||
|
||||
if (m_generator->isValid()) {
|
||||
m_ui->buttonGenerate->setEnabled(true);
|
||||
} else {
|
||||
m_ui->buttonGenerate->setEnabled(false);
|
||||
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_ui->spinBoxWordCount->setMinimum(minWordCount);
|
||||
m_ui->sliderWordCount->setMinimum(minWordCount);
|
||||
|
||||
m_dicewareGenerator->setWordCount(m_ui->spinBoxWordCount->value());
|
||||
if (!m_ui->comboBoxWordList->currentText().isEmpty()) {
|
||||
QString path = filePath()->dataPath("wordlists/" + m_ui->comboBoxWordList->currentText());
|
||||
m_dicewareGenerator->setWordList(path);
|
||||
}
|
||||
m_dicewareGenerator->setWordSeparator(m_ui->editWordSeparator->text());
|
||||
|
||||
if (m_dicewareGenerator->isValid()) {
|
||||
m_ui->buttonGenerate->setEnabled(true);
|
||||
} else {
|
||||
m_ui->buttonGenerate->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
regeneratePassword();
|
||||
|
@ -23,24 +23,32 @@
|
||||
#include <QLabel>
|
||||
|
||||
#include "core/PasswordGenerator.h"
|
||||
#include "core/PassphraseGenerator.h"
|
||||
|
||||
namespace Ui {
|
||||
class PasswordGeneratorWidget;
|
||||
}
|
||||
|
||||
class PasswordGenerator;
|
||||
class PassphraseGenerator;
|
||||
|
||||
class PasswordGeneratorWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum GeneratorTypes
|
||||
{
|
||||
Password = 0,
|
||||
Diceware = 1
|
||||
};
|
||||
explicit PasswordGeneratorWidget(QWidget* parent = nullptr);
|
||||
~PasswordGeneratorWidget();
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
void reset();
|
||||
void setStandaloneMode(bool standalone);
|
||||
public Q_SLOTS:
|
||||
void regeneratePassword();
|
||||
|
||||
signals:
|
||||
@ -49,13 +57,14 @@ signals:
|
||||
|
||||
private slots:
|
||||
void applyPassword();
|
||||
void generatePassword();
|
||||
void updateApplyEnabled(const QString& password);
|
||||
void updatePasswordStrength(const QString& password);
|
||||
void togglePasswordShown(bool hidden);
|
||||
|
||||
void sliderMoved();
|
||||
void spinBoxChanged();
|
||||
void passwordSliderMoved();
|
||||
void passwordSpinBoxChanged();
|
||||
void dicewareSliderMoved();
|
||||
void dicewareSpinBoxChanged();
|
||||
void colorStrengthIndicator(double entropy);
|
||||
|
||||
void updateGenerator();
|
||||
@ -66,7 +75,8 @@ private:
|
||||
PasswordGenerator::CharClasses charClasses();
|
||||
PasswordGenerator::GeneratorFlags generatorFlags();
|
||||
|
||||
const QScopedPointer<PasswordGenerator> m_generator;
|
||||
const QScopedPointer<PasswordGenerator> m_passwordGenerator;
|
||||
const QScopedPointer<PassphraseGenerator> m_dicewareGenerator;
|
||||
const QScopedPointer<Ui::PasswordGeneratorWidget> m_ui;
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>575</width>
|
||||
<height>284</height>
|
||||
<height>305</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -31,14 +31,14 @@
|
||||
<property name="windowTitle">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="passwordFieldLayout">
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>0</number>
|
||||
@ -174,61 +174,6 @@ QProgressBar::chunk {
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelLength">
|
||||
<property name="text">
|
||||
<string>&Length:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>spinBoxLength</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<layout class="QHBoxLayout" name="passwordLengthSliderLayout">
|
||||
<property name="spacing">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSlider" name="sliderLength">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="sliderPosition">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignRight">
|
||||
<widget class="QSpinBox" name="spinBoxLength">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QToolButton" name="togglePasswordButton">
|
||||
<property name="checkable">
|
||||
@ -239,179 +184,390 @@ QProgressBar::chunk {
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="optionsLayout">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Character Types</string>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="alphabetLayout" stretch="0,0,0,0,1">
|
||||
<item>
|
||||
<widget class="QToolButton" name="checkBoxUpper">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Upper Case Letters</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">A-Z</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="checkBoxLower">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Lower Case Letters</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">a-z</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="checkBoxNumbers">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Numbers</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0-9</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="checkBoxSpecialChars">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Special Characters</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">/*_& ...</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxExcludeAlike">
|
||||
<property name="text">
|
||||
<string>Exclude look-alike characters</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxEnsureEvery">
|
||||
<property name="text">
|
||||
<string>Pick characters from every group</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="tabPosition">
|
||||
<enum>QTabWidget::North</enum>
|
||||
</property>
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="passwordWidget">
|
||||
<attribute name="title">
|
||||
<string>Password</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="optionsLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Character Types</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="alphabetLayout" stretch="0,0,0,0,1">
|
||||
<item>
|
||||
<widget class="QToolButton" name="checkBoxUpper">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Upper Case Letters</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">A-Z</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="checkBoxLower">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Lower Case Letters</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">a-z</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="checkBoxNumbers">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Numbers</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">0-9</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="checkBoxSpecialChars">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Special Characters</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">/*_& ...</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxExcludeAlike">
|
||||
<property name="text">
|
||||
<string>Exclude look-alike characters</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxEnsureEvery">
|
||||
<property name="text">
|
||||
<string>Pick characters from every group</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">optionButtons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="passwordLengthSliderLayout">
|
||||
<property name="spacing">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelLength">
|
||||
<property name="text">
|
||||
<string>&Length:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>spinBoxLength</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="sliderLength">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="sliderPosition">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignRight">
|
||||
<widget class="QSpinBox" name="spinBoxLength">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="dicewareWidget">
|
||||
<attribute name="title">
|
||||
<string>Passphrase</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0" alignment="Qt::AlignRight">
|
||||
<widget class="QLabel" name="labelWordList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Wordlist:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxWordList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" alignment="Qt::AlignRight">
|
||||
<widget class="QLabel" name="labelWordCount">
|
||||
<property name="text">
|
||||
<string>Word Count:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>spinBoxLength</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSlider" name="sliderWordCount">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>40</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="sliderPosition">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxWordCount">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>6</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0" alignment="Qt::AlignRight">
|
||||
<widget class="QLabel" name="labelWordSeparator">
|
||||
<property name="text">
|
||||
<string>Word Separator:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="editWordSeparator">
|
||||
<property name="text">
|
||||
<string> </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="globalButtonsLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<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>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonGenerate">
|
||||
<property name="text">
|
||||
@ -433,6 +589,9 @@ QProgressBar::chunk {
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
@ -440,6 +599,7 @@ QProgressBar::chunk {
|
||||
<class>PasswordEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>gui/PasswordEdit.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
@ -452,9 +612,6 @@ QProgressBar::chunk {
|
||||
<tabstop>checkBoxNumbers</tabstop>
|
||||
<tabstop>checkBoxSpecialChars</tabstop>
|
||||
<tabstop>checkBoxExcludeAlike</tabstop>
|
||||
<tabstop>checkBoxEnsureEvery</tabstop>
|
||||
<tabstop>buttonGenerate</tabstop>
|
||||
<tabstop>buttonApply</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@ -148,6 +148,12 @@
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" alignment="Qt::AlignRight">
|
||||
@ -186,6 +192,7 @@
|
||||
<class>PasswordEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>gui/PasswordEdit.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <QPushButton>
|
||||
#include <QSpinBox>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QComboBox>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTest>
|
||||
#include <QToolBar>
|
||||
@ -322,7 +323,7 @@ void TestGui::testAddEntry()
|
||||
QTRY_COMPARE(entryView->model()->rowCount(), 4);
|
||||
}
|
||||
|
||||
void TestGui::testEntryEntropy()
|
||||
void TestGui::testPasswordEntryEntropy()
|
||||
{
|
||||
QToolBar* toolBar = m_mainWindow->findChild<QToolBar*>("toolBar");
|
||||
|
||||
@ -396,6 +397,50 @@ void TestGui::testEntryEntropy()
|
||||
// We are done
|
||||
}
|
||||
|
||||
void TestGui::testDicewareEntryEntropy()
|
||||
{
|
||||
QToolBar* toolBar = m_mainWindow->findChild<QToolBar*>("toolBar");
|
||||
|
||||
// Find the new entry action
|
||||
QAction* entryNewAction = m_mainWindow->findChild<QAction*>("actionEntryNew");
|
||||
QVERIFY(entryNewAction->isEnabled());
|
||||
|
||||
// Find the button associated with the new entry action
|
||||
QWidget* entryNewWidget = toolBar->widgetForAction(entryNewAction);
|
||||
QVERIFY(entryNewWidget->isVisible());
|
||||
QVERIFY(entryNewWidget->isEnabled());
|
||||
|
||||
// Click the new entry button and check that we enter edit mode
|
||||
QTest::mouseClick(entryNewWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
|
||||
|
||||
// Add entry "test" and confirm added
|
||||
EditEntryWidget* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
QLineEdit* titleEdit = editEntryWidget->findChild<QLineEdit*>("titleEdit");
|
||||
QTest::keyClicks(titleEdit, "test");
|
||||
|
||||
// Open the password generator
|
||||
QToolButton* generatorButton = editEntryWidget->findChild<QToolButton*>("togglePasswordGeneratorButton");
|
||||
QTest::mouseClick(generatorButton, Qt::LeftButton);
|
||||
|
||||
// Select Diceware
|
||||
QTabWidget* tabWidget = editEntryWidget->findChild<QTabWidget*>("tabWidget");
|
||||
QWidget* dicewareWidget = editEntryWidget->findChild<QWidget*>("dicewareWidget");
|
||||
tabWidget->setCurrentWidget(dicewareWidget);
|
||||
|
||||
QComboBox* comboBoxWordList = dicewareWidget->findChild<QComboBox*>("comboBoxWordList");
|
||||
comboBoxWordList->setCurrentText("eff_large.wordlist");
|
||||
QSpinBox* spinBoxWordCount = dicewareWidget->findChild<QSpinBox*>("spinBoxWordCount");
|
||||
spinBoxWordCount->setValue(6);
|
||||
|
||||
// Type in some password
|
||||
QLabel* entropyLabel = editEntryWidget->findChild<QLabel*>("entropyLabel");
|
||||
QLabel* strengthLabel = editEntryWidget->findChild<QLabel*>("strengthLabel");
|
||||
|
||||
QCOMPARE(entropyLabel->text(), QString("Entropy: 77.55 bit"));
|
||||
QCOMPARE(strengthLabel->text(), QString("Password Quality: Good"));
|
||||
}
|
||||
|
||||
void TestGui::testSearch()
|
||||
{
|
||||
// Add canned entries for consistent testing
|
||||
|
@ -44,7 +44,8 @@ private slots:
|
||||
void testTabs();
|
||||
void testEditEntry();
|
||||
void testAddEntry();
|
||||
void testEntryEntropy();
|
||||
void testPasswordEntryEntropy();
|
||||
void testDicewareEntryEntropy();
|
||||
void testSearch();
|
||||
void testDeleteEntry();
|
||||
void testCloneEntry();
|
||||
|
Loading…
Reference in New Issue
Block a user