2
* Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
3
* Copyright (C) 2022 KeePassXC Team <team@keepassxc.org>
5
* This program is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation, either version 2 or (at your option)
8
* version 3 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19
#include "PasswordGeneratorWidget.h"
20
#include "ui_PasswordGeneratorWidget.h"
27
#include "core/Config.h"
28
#include "core/PasswordHealth.h"
29
#include "core/Resources.h"
30
#include "gui/Clipboard.h"
31
#include "gui/FileDialog.h"
33
#include "gui/MessageBox.h"
34
#include "gui/styles/StateColorPalette.h"
36
PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent)
38
, m_passwordGenerator(new PasswordGenerator())
39
, m_dicewareGenerator(new PassphraseGenerator())
40
, m_ui(new Ui::PasswordGeneratorWidget())
44
m_ui->buttonGenerate->setIcon(icons()->icon("refresh"));
45
m_ui->buttonGenerate->setToolTip(
46
tr("Regenerate password (%1)").arg(m_ui->buttonGenerate->shortcut().toString(QKeySequence::NativeText)));
47
m_ui->buttonCopy->setIcon(icons()->icon("clipboard-text"));
48
m_ui->buttonDeleteWordList->setIcon(icons()->icon("trash"));
49
m_ui->buttonAddWordList->setIcon(icons()->icon("document-new"));
50
m_ui->buttonClose->setShortcut(Qt::Key_Escape);
52
// Add two shortcuts to save the form CTRL+Enter and CTRL+S
53
auto shortcut = new QShortcut(Qt::CTRL + Qt::Key_Return, this);
54
connect(shortcut, &QShortcut::activated, this, [this] { applyPassword(); });
55
shortcut = new QShortcut(Qt::CTRL + Qt::Key_S, this);
56
connect(shortcut, &QShortcut::activated, this, [this] { applyPassword(); });
58
connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updateButtonsEnabled(QString)));
59
connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updatePasswordStrength()));
60
connect(m_ui->buttonAdvancedMode, SIGNAL(toggled(bool)), SLOT(setAdvancedMode(bool)));
61
connect(m_ui->buttonAddHex, SIGNAL(clicked()), SLOT(excludeHexChars()));
62
connect(m_ui->editAdditionalChars, SIGNAL(textChanged(QString)), SLOT(updateGenerator()));
63
connect(m_ui->editExcludedChars, SIGNAL(textChanged(QString)), SLOT(updateGenerator()));
64
connect(m_ui->buttonApply, SIGNAL(clicked()), SLOT(applyPassword()));
65
connect(m_ui->buttonCopy, SIGNAL(clicked()), SLOT(copyPassword()));
66
connect(m_ui->buttonGenerate, SIGNAL(clicked()), SLOT(regeneratePassword()));
67
connect(m_ui->buttonDeleteWordList, SIGNAL(clicked()), SLOT(deleteWordList()));
68
connect(m_ui->buttonAddWordList, SIGNAL(clicked()), SLOT(addWordList()));
69
connect(m_ui->buttonClose, SIGNAL(clicked()), SIGNAL(closed()));
71
connect(m_ui->sliderLength, SIGNAL(valueChanged(int)), SLOT(passwordLengthChanged(int)));
72
connect(m_ui->spinBoxLength, SIGNAL(valueChanged(int)), SLOT(passwordLengthChanged(int)));
74
connect(m_ui->sliderWordCount, SIGNAL(valueChanged(int)), SLOT(passphraseLengthChanged(int)));
75
connect(m_ui->spinBoxWordCount, SIGNAL(valueChanged(int)), SLOT(passphraseLengthChanged(int)));
77
connect(m_ui->editWordSeparator, SIGNAL(textChanged(QString)), SLOT(updateGenerator()));
78
connect(m_ui->comboBoxWordList, SIGNAL(currentIndexChanged(int)), SLOT(updateGenerator()));
79
connect(m_ui->optionButtons, SIGNAL(buttonClicked(int)), SLOT(updateGenerator()));
80
connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(updateGenerator()));
81
connect(m_ui->wordCaseComboBox, SIGNAL(currentIndexChanged(int)), SLOT(updateGenerator()));
83
// set font size of password quality and entropy labels dynamically to 80% of
84
// the default font size, but make it no smaller than 8pt
86
auto smallerSize = static_cast<int>(defaultFont.pointSize() * 0.8f);
87
if (smallerSize >= 8) {
88
defaultFont.setPointSize(smallerSize);
89
m_ui->entropyLabel->setFont(defaultFont);
90
m_ui->strengthLabel->setFont(defaultFont);
93
// set default separator to Space
94
m_ui->editWordSeparator->setText(PassphraseGenerator::DefaultSeparator);
96
// add passphrase generator case options
97
m_ui->wordCaseComboBox->addItem(tr("lower case"), PassphraseGenerator::LOWERCASE);
98
m_ui->wordCaseComboBox->addItem(tr("UPPER CASE"), PassphraseGenerator::UPPERCASE);
99
m_ui->wordCaseComboBox->addItem(tr("Title Case"), PassphraseGenerator::TITLECASE);
101
// load system-wide wordlists
102
QDir path(resources()->wordlistPath(""));
103
for (const auto& fileName : path.entryList(QDir::Files)) {
104
m_ui->comboBoxWordList->addItem(tr("(SYSTEM)") + " " + fileName, fileName);
107
m_firstCustomWordlistIndex = m_ui->comboBoxWordList->count();
109
// load user-provided wordlists
110
path = QDir(resources()->userWordlistPath(""));
111
for (const auto& fileName : path.entryList(QDir::Files)) {
112
m_ui->comboBoxWordList->addItem(fileName, path.absolutePath() + QDir::separator() + fileName);
118
PasswordGeneratorWidget::~PasswordGeneratorWidget() = default;
120
void PasswordGeneratorWidget::closeEvent(QCloseEvent* event)
122
// Emits closed signal when clicking X from title bar
124
QWidget::closeEvent(event);
127
PasswordGeneratorWidget* PasswordGeneratorWidget::popupGenerator(QWidget* parent)
129
auto pwGenerator = new PasswordGeneratorWidget(parent);
130
pwGenerator->setWindowModality(Qt::ApplicationModal);
131
pwGenerator->setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
132
pwGenerator->setStandaloneMode(false);
134
connect(pwGenerator, SIGNAL(closed()), pwGenerator, SLOT(deleteLater()));
137
pwGenerator->raise();
138
pwGenerator->activateWindow();
139
pwGenerator->adjustSize();
144
void PasswordGeneratorWidget::loadSettings()
147
m_ui->checkBoxLower->setChecked(config()->get(Config::PasswordGenerator_LowerCase).toBool());
148
m_ui->checkBoxUpper->setChecked(config()->get(Config::PasswordGenerator_UpperCase).toBool());
149
m_ui->checkBoxNumbers->setChecked(config()->get(Config::PasswordGenerator_Numbers).toBool());
150
m_ui->editAdditionalChars->setText(config()->get(Config::PasswordGenerator_AdditionalChars).toString());
151
m_ui->editExcludedChars->setText(config()->get(Config::PasswordGenerator_ExcludedChars).toString());
153
bool advanced = config()->get(Config::PasswordGenerator_AdvancedMode).toBool();
155
m_ui->checkBoxSpecialChars->setChecked(config()->get(Config::PasswordGenerator_Logograms).toBool());
157
m_ui->checkBoxSpecialChars->setChecked(config()->get(Config::PasswordGenerator_SpecialChars).toBool());
160
m_ui->checkBoxBraces->setChecked(config()->get(Config::PasswordGenerator_Braces).toBool());
161
m_ui->checkBoxQuotes->setChecked(config()->get(Config::PasswordGenerator_Quotes).toBool());
162
m_ui->checkBoxPunctuation->setChecked(config()->get(Config::PasswordGenerator_Punctuation).toBool());
163
m_ui->checkBoxDashes->setChecked(config()->get(Config::PasswordGenerator_Dashes).toBool());
164
m_ui->checkBoxMath->setChecked(config()->get(Config::PasswordGenerator_Math).toBool());
166
m_ui->checkBoxExtASCII->setChecked(config()->get(Config::PasswordGenerator_EASCII).toBool());
167
m_ui->checkBoxExcludeAlike->setChecked(config()->get(Config::PasswordGenerator_ExcludeAlike).toBool());
168
m_ui->checkBoxEnsureEvery->setChecked(config()->get(Config::PasswordGenerator_EnsureEvery).toBool());
169
m_ui->spinBoxLength->setValue(config()->get(Config::PasswordGenerator_Length).toInt());
172
m_ui->spinBoxWordCount->setValue(config()->get(Config::PasswordGenerator_WordCount).toInt());
173
m_ui->editWordSeparator->setText(config()->get(Config::PasswordGenerator_WordSeparator).toString());
174
int i = m_ui->comboBoxWordList->findData(config()->get(Config::PasswordGenerator_WordList).toString());
176
m_ui->comboBoxWordList->setCurrentIndex(i);
178
m_ui->wordCaseComboBox->setCurrentIndex(config()->get(Config::PasswordGenerator_WordCase).toInt());
180
// Password or diceware?
181
m_ui->tabWidget->setCurrentIndex(config()->get(Config::PasswordGenerator_Type).toInt());
184
m_ui->buttonAdvancedMode->setChecked(advanced);
185
setAdvancedMode(advanced);
189
void PasswordGeneratorWidget::saveSettings()
192
config()->set(Config::PasswordGenerator_LowerCase, m_ui->checkBoxLower->isChecked());
193
config()->set(Config::PasswordGenerator_UpperCase, m_ui->checkBoxUpper->isChecked());
194
config()->set(Config::PasswordGenerator_Numbers, m_ui->checkBoxNumbers->isChecked());
195
config()->set(Config::PasswordGenerator_EASCII, m_ui->checkBoxExtASCII->isChecked());
197
config()->set(Config::PasswordGenerator_AdvancedMode, m_ui->buttonAdvancedMode->isChecked());
198
if (m_ui->buttonAdvancedMode->isChecked()) {
199
config()->set(Config::PasswordGenerator_Logograms, m_ui->checkBoxSpecialChars->isChecked());
201
config()->set(Config::PasswordGenerator_SpecialChars, m_ui->checkBoxSpecialChars->isChecked());
203
config()->set(Config::PasswordGenerator_Braces, m_ui->checkBoxBraces->isChecked());
204
config()->set(Config::PasswordGenerator_Punctuation, m_ui->checkBoxPunctuation->isChecked());
205
config()->set(Config::PasswordGenerator_Quotes, m_ui->checkBoxQuotes->isChecked());
206
config()->set(Config::PasswordGenerator_Dashes, m_ui->checkBoxDashes->isChecked());
207
config()->set(Config::PasswordGenerator_Math, m_ui->checkBoxMath->isChecked());
209
config()->set(Config::PasswordGenerator_AdditionalChars, m_ui->editAdditionalChars->text());
210
config()->set(Config::PasswordGenerator_ExcludedChars, m_ui->editExcludedChars->text());
211
config()->set(Config::PasswordGenerator_ExcludeAlike, m_ui->checkBoxExcludeAlike->isChecked());
212
config()->set(Config::PasswordGenerator_EnsureEvery, m_ui->checkBoxEnsureEvery->isChecked());
213
config()->set(Config::PasswordGenerator_Length, m_ui->spinBoxLength->value());
216
config()->set(Config::PasswordGenerator_WordCount, m_ui->spinBoxWordCount->value());
217
config()->set(Config::PasswordGenerator_WordSeparator, m_ui->editWordSeparator->text());
218
config()->set(Config::PasswordGenerator_WordList, m_ui->comboBoxWordList->currentData());
219
config()->set(Config::PasswordGenerator_WordCase, m_ui->wordCaseComboBox->currentIndex());
221
// Password or diceware?
222
config()->set(Config::PasswordGenerator_Type, m_ui->tabWidget->currentIndex());
225
void PasswordGeneratorWidget::setPasswordLength(int length)
228
m_ui->spinBoxLength->setValue(length);
230
m_ui->spinBoxLength->setValue(config()->get(Config::PasswordGenerator_Length).toInt());
234
void PasswordGeneratorWidget::setStandaloneMode(bool standalone)
236
m_standalone = standalone;
238
m_ui->buttonApply->setVisible(false);
239
setPasswordVisible(true);
241
m_ui->buttonApply->setVisible(true);
245
QString PasswordGeneratorWidget::getGeneratedPassword()
247
return m_ui->editNewPassword->text();
250
void PasswordGeneratorWidget::regeneratePassword()
252
if (m_ui->tabWidget->currentIndex() == Password) {
253
if (m_passwordGenerator->isValid()) {
254
m_ui->editNewPassword->setText(m_passwordGenerator->generatePassword());
257
if (m_dicewareGenerator->isValid()) {
258
m_ui->editNewPassword->setText(m_dicewareGenerator->generatePassphrase());
263
void PasswordGeneratorWidget::updateButtonsEnabled(const QString& password)
266
m_ui->buttonApply->setEnabled(!password.isEmpty());
268
m_ui->buttonCopy->setEnabled(!password.isEmpty());
271
void PasswordGeneratorWidget::updatePasswordStrength()
273
// Calculate the password / passphrase health
274
PasswordHealth passwordHealth(0);
275
if (m_ui->tabWidget->currentIndex() == Diceware) {
276
passwordHealth.init(m_dicewareGenerator->estimateEntropy());
277
m_ui->charactersInPassphraseLabel->setText(QString::number(m_ui->editNewPassword->text().length()));
279
passwordHealth = PasswordHealth(m_ui->editNewPassword->text());
282
// Update the entropy text labels
283
m_ui->entropyLabel->setText(tr("Entropy: %1 bit").arg(QString::number(passwordHealth.entropy(), 'f', 2)));
284
m_ui->entropyProgressBar->setValue(std::min(int(passwordHealth.entropy()), m_ui->entropyProgressBar->maximum()));
286
// Update the visual strength meter
287
QString style = m_ui->entropyProgressBar->styleSheet();
288
QRegularExpression re("(QProgressBar::chunk\\s*\\{.*?background-color:)[^;]+;",
289
QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
290
style.replace(re, "\\1 %1;");
292
StateColorPalette statePalette;
293
switch (passwordHealth.quality()) {
294
case PasswordHealth::Quality::Bad:
295
case PasswordHealth::Quality::Poor:
296
m_ui->entropyProgressBar->setStyleSheet(
297
style.arg(statePalette.color(StateColorPalette::HealthCritical).name()));
298
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Poor", "Password quality")));
301
case PasswordHealth::Quality::Weak:
302
m_ui->entropyProgressBar->setStyleSheet(style.arg(statePalette.color(StateColorPalette::HealthBad).name()));
303
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Weak", "Password quality")));
306
case PasswordHealth::Quality::Good:
307
m_ui->entropyProgressBar->setStyleSheet(style.arg(statePalette.color(StateColorPalette::HealthOk).name()));
308
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Good", "Password quality")));
311
case PasswordHealth::Quality::Excellent:
312
m_ui->entropyProgressBar->setStyleSheet(
313
style.arg(statePalette.color(StateColorPalette::HealthExcellent).name()));
314
m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Excellent", "Password quality")));
319
void PasswordGeneratorWidget::applyPassword()
322
m_passwordGenerated = true;
323
emit appliedPassword(m_ui->editNewPassword->text());
327
void PasswordGeneratorWidget::copyPassword()
329
clipboard()->setText(m_ui->editNewPassword->text());
332
void PasswordGeneratorWidget::passwordLengthChanged(int length)
334
m_ui->spinBoxLength->blockSignals(true);
335
m_ui->sliderLength->blockSignals(true);
337
m_ui->spinBoxLength->setValue(length);
338
m_ui->sliderLength->setValue(length);
340
m_ui->spinBoxLength->blockSignals(false);
341
m_ui->sliderLength->blockSignals(false);
346
void PasswordGeneratorWidget::passphraseLengthChanged(int length)
348
m_ui->spinBoxWordCount->blockSignals(true);
349
m_ui->sliderWordCount->blockSignals(true);
351
m_ui->spinBoxWordCount->setValue(length);
352
m_ui->sliderWordCount->setValue(length);
354
m_ui->spinBoxWordCount->blockSignals(false);
355
m_ui->sliderWordCount->blockSignals(false);
360
void PasswordGeneratorWidget::setPasswordVisible(bool visible)
362
m_ui->editNewPassword->setShowPassword(visible);
365
bool PasswordGeneratorWidget::isPasswordVisible() const
367
return m_ui->editNewPassword->isPasswordVisible();
370
bool PasswordGeneratorWidget::isPasswordGenerated() const
372
return m_passwordGenerated;
375
void PasswordGeneratorWidget::deleteWordList()
377
if (m_ui->comboBoxWordList->currentIndex() < m_firstCustomWordlistIndex) {
381
QFile file(m_ui->comboBoxWordList->currentData().toString());
382
if (!file.exists()) {
386
auto result = MessageBox::question(this,
387
tr("Confirm Delete Wordlist"),
388
tr("Do you really want to delete the wordlist \"%1\"?").arg(file.fileName()),
389
MessageBox::Delete | MessageBox::Cancel,
391
if (result != MessageBox::Delete) {
395
if (!file.remove()) {
396
MessageBox::critical(this, tr("Failed to delete wordlist"), file.errorString());
400
m_ui->comboBoxWordList->removeItem(m_ui->comboBoxWordList->currentIndex());
404
void PasswordGeneratorWidget::addWordList()
406
auto filter = QString("%1 (*.txt *.asc *.wordlist);;%2 (*)").arg(tr("Wordlists"), tr("All files"));
407
auto filePath = fileDialog()->getOpenFileName(this, tr("Select Custom Wordlist"), "", filter);
408
if (filePath.isEmpty()) {
412
// create directory for user-specified wordlists, if necessary
413
QDir destDir(resources()->userWordlistPath(""));
416
// check if destination wordlist already exists
417
QString fileName = QFileInfo(filePath).fileName();
418
QString destPath = destDir.absolutePath() + QDir::separator() + fileName;
419
QFile dest(destPath);
421
auto response = MessageBox::warning(this,
422
tr("Overwrite Wordlist?"),
423
tr("Wordlist \"%1\" already exists as a custom wordlist.\n"
424
"Do you want to overwrite it?")
426
MessageBox::Overwrite | MessageBox::Cancel,
428
if (response != MessageBox::Overwrite) {
431
if (!dest.remove()) {
432
MessageBox::critical(this, tr("Failed to delete wordlist"), dest.errorString());
437
// copy wordlist to destination path and add corresponding item to the combo box
438
QFile file(filePath);
439
if (!file.copy(destPath)) {
440
MessageBox::critical(this, tr("Failed to add wordlist"), file.errorString());
444
auto index = m_ui->comboBoxWordList->findData(destPath);
446
m_ui->comboBoxWordList->addItem(fileName, destPath);
447
index = m_ui->comboBoxWordList->count() - 1;
449
m_ui->comboBoxWordList->setCurrentIndex(index);
451
// update the password generator
455
void PasswordGeneratorWidget::setAdvancedMode(bool advanced)
460
m_ui->checkBoxSpecialChars->setText("# $ % && @ ^ ` ~");
461
m_ui->checkBoxSpecialChars->setToolTip(tr("Logograms"));
462
m_ui->checkBoxSpecialChars->setChecked(config()->get(Config::PasswordGenerator_Logograms).toBool());
464
m_ui->checkBoxSpecialChars->setText("/ * + && …");
465
m_ui->checkBoxSpecialChars->setToolTip(tr("Special Characters"));
466
m_ui->checkBoxSpecialChars->setChecked(config()->get(Config::PasswordGenerator_SpecialChars).toBool());
469
m_ui->advancedContainer->setVisible(advanced);
470
m_ui->checkBoxBraces->setVisible(advanced);
471
m_ui->checkBoxPunctuation->setVisible(advanced);
472
m_ui->checkBoxQuotes->setVisible(advanced);
473
m_ui->checkBoxMath->setVisible(advanced);
474
m_ui->checkBoxDashes->setVisible(advanced);
477
QTimer::singleShot(50, this, [this] { adjustSize(); });
481
void PasswordGeneratorWidget::excludeHexChars()
483
m_ui->editExcludedChars->setText("GHIJKLMNOPQRSTUVWXYZ");
484
m_ui->checkBoxNumbers->setChecked(true);
485
m_ui->checkBoxUpper->setChecked(true);
487
m_ui->checkBoxLower->setChecked(false);
488
m_ui->checkBoxSpecialChars->setChecked(false);
489
m_ui->checkBoxExtASCII->setChecked(false);
490
m_ui->checkBoxPunctuation->setChecked(false);
491
m_ui->checkBoxQuotes->setChecked(false);
492
m_ui->checkBoxDashes->setChecked(false);
493
m_ui->checkBoxMath->setChecked(false);
494
m_ui->checkBoxBraces->setChecked(false);
499
PasswordGenerator::CharClasses PasswordGeneratorWidget::charClasses()
501
PasswordGenerator::CharClasses classes;
503
if (m_ui->checkBoxLower->isChecked()) {
504
classes |= PasswordGenerator::LowerLetters;
507
if (m_ui->checkBoxUpper->isChecked()) {
508
classes |= PasswordGenerator::UpperLetters;
511
if (m_ui->checkBoxNumbers->isChecked()) {
512
classes |= PasswordGenerator::Numbers;
515
if (m_ui->checkBoxExtASCII->isChecked()) {
516
classes |= PasswordGenerator::EASCII;
519
if (!m_ui->buttonAdvancedMode->isChecked()) {
520
if (m_ui->checkBoxSpecialChars->isChecked()) {
521
classes |= PasswordGenerator::SpecialCharacters;
524
if (m_ui->checkBoxBraces->isChecked()) {
525
classes |= PasswordGenerator::Braces;
528
if (m_ui->checkBoxPunctuation->isChecked()) {
529
classes |= PasswordGenerator::Punctuation;
532
if (m_ui->checkBoxQuotes->isChecked()) {
533
classes |= PasswordGenerator::Quotes;
536
if (m_ui->checkBoxDashes->isChecked()) {
537
classes |= PasswordGenerator::Dashes;
540
if (m_ui->checkBoxMath->isChecked()) {
541
classes |= PasswordGenerator::Math;
544
if (m_ui->checkBoxSpecialChars->isChecked()) {
545
classes |= PasswordGenerator::Logograms;
552
PasswordGenerator::GeneratorFlags PasswordGeneratorWidget::generatorFlags()
554
PasswordGenerator::GeneratorFlags flags;
556
if (m_ui->buttonAdvancedMode->isChecked()) {
557
if (m_ui->checkBoxExcludeAlike->isChecked()) {
558
flags |= PasswordGenerator::ExcludeLookAlike;
561
if (m_ui->checkBoxEnsureEvery->isChecked()) {
562
flags |= PasswordGenerator::CharFromEveryGroup;
569
void PasswordGeneratorWidget::updateGenerator()
571
if (m_ui->tabWidget->currentIndex() == Password) {
572
auto classes = charClasses();
573
auto flags = generatorFlags();
575
m_passwordGenerator->setLength(m_ui->spinBoxLength->value());
576
if (m_ui->buttonAdvancedMode->isChecked()) {
577
m_passwordGenerator->setCharClasses(classes);
578
m_passwordGenerator->setCustomCharacterSet(m_ui->editAdditionalChars->text());
579
m_passwordGenerator->setExcludedCharacterSet(m_ui->editExcludedChars->text());
581
m_passwordGenerator->setCharClasses(classes);
583
m_passwordGenerator->setFlags(flags);
585
if (m_passwordGenerator->isValid()) {
586
m_ui->buttonGenerate->setEnabled(true);
588
m_ui->buttonGenerate->setEnabled(false);
591
m_dicewareGenerator->setWordCase(
592
static_cast<PassphraseGenerator::PassphraseWordCase>(m_ui->wordCaseComboBox->currentData().toInt()));
594
m_dicewareGenerator->setWordCount(m_ui->spinBoxWordCount->value());
595
auto path = m_ui->comboBoxWordList->currentData().toString();
596
if (m_ui->comboBoxWordList->currentIndex() < m_firstCustomWordlistIndex) {
597
path = resources()->wordlistPath(path);
598
m_ui->buttonDeleteWordList->setEnabled(false);
600
m_ui->buttonDeleteWordList->setEnabled(true);
602
m_dicewareGenerator->setWordList(path);
604
m_dicewareGenerator->setWordSeparator(m_ui->editWordSeparator->text());
606
if (m_dicewareGenerator->isValid()) {
607
m_ui->buttonGenerate->setEnabled(true);
609
m_ui->buttonGenerate->setEnabled(false);
613
regeneratePassword();