From 3cf14971f2f00e37c1c548b55b7a93f3af20ce04 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 24 Jun 2023 12:25:18 -0400 Subject: [PATCH] Improve database encryption settings UX Fixes #6190 Remove the advanced settings checkbox and replace with a dedicated tab widget interface to toggle between basic and advanced encryption settings. --- share/translations/keepassxc_en.ts | 37 +- src/core/Config.cpp | 6 +- src/core/Config.h | 1 - src/gui/dbsettings/DatabaseSettingsDialog.cpp | 32 +- src/gui/dbsettings/DatabaseSettingsDialog.h | 1 - src/gui/dbsettings/DatabaseSettingsDialog.ui | 21 +- .../DatabaseSettingsWidgetBrowser.h | 4 - .../DatabaseSettingsWidgetDatabaseKey.h | 5 - .../DatabaseSettingsWidgetEncryption.cpp | 110 +-- .../DatabaseSettingsWidgetEncryption.h | 13 +- .../DatabaseSettingsWidgetEncryption.ui | 850 ++++++++++-------- .../DatabaseSettingsWidgetGeneral.h | 5 - .../DatabaseSettingsWidgetMaintenance.h | 5 - .../DatabaseSettingsWidgetMetaDataSimple.h | 5 - src/gui/settings/SettingsWidget.cpp | 24 +- src/gui/settings/SettingsWidget.h | 10 +- src/gui/wizard/NewDatabaseWizardPage.cpp | 21 - src/gui/wizard/NewDatabaseWizardPage.h | 3 - src/gui/wizard/NewDatabaseWizardPage.ui | 41 +- tests/gui/TestGui.cpp | 27 +- tests/gui/TestGuiBrowser.cpp | 2 - 21 files changed, 574 insertions(+), 649 deletions(-) diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index 9553a10f1..5234515b5 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -1581,10 +1581,6 @@ If you do not have a key file, please leave the field empty. DatabaseSettingsDialog - - Advanced Settings - - General @@ -1778,14 +1774,6 @@ Are you sure you want to continue without a password? Decryption Time: - - Change existing decryption time - - - - Change - - Decryption time in seconds @@ -1866,11 +1854,6 @@ Are you sure you want to continue without a password? KDBX 3 - - unchanged - Database decryption time is unchanged - - Number of rounds too high Key transformation rounds @@ -1925,6 +1908,18 @@ If you keep this number, your database will not be protected from brute force at + + Encryption Settings: + + + + Basic + + + + Advanced + + DatabaseSettingsWidgetFdoSecrets @@ -5592,14 +5587,6 @@ We recommend you use the AppImage available on our downloads page. Here you can adjust the database encryption settings. Don't worry, you can change them later in the database settings. - - Advanced Settings - - - - Simple Settings - - NewDatabaseWizardPageDatabaseKey diff --git a/src/core/Config.cpp b/src/core/Config.cpp index bb80f012b..25048513e 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -104,7 +104,6 @@ static const QHash configStrings = { {Config::GUI_MinimizeOnClose, {QS("GUI/MinimizeOnClose"), Roaming, false}}, {Config::GUI_HideUsernames, {QS("GUI/HideUsernames"), Roaming, false}}, {Config::GUI_HidePasswords, {QS("GUI/HidePasswords"), Roaming, true}}, - {Config::GUI_AdvancedSettings, {QS("GUI/AdvancedSettings"), Roaming, false}}, {Config::GUI_ColorPasswords, {QS("GUI/ColorPasswords"), Roaming, false}}, {Config::GUI_MonospaceNotes, {QS("GUI/MonospaceNotes"), Roaming, false}}, {Config::GUI_ApplicationTheme, {QS("GUI/ApplicationTheme"), Roaming, QS("auto")}}, @@ -371,7 +370,10 @@ static const QHash deprecationMap = { {QS("UseTouchID"), Config::Deleted}, {QS("Security/ResetTouchId"), Config::Deleted}, {QS("Security/ResetTouchIdTimeout"), Config::Deleted}, - {QS("Security/ResetTouchIdScreenlock"), Config::Deleted}}; + {QS("Security/ResetTouchIdScreenlock"), Config::Deleted}, + + // 2.8.0 + {QS("GUI/AdvancedSettings"), Config::Deleted}}; /** * Migrate settings from previous versions. diff --git a/src/core/Config.h b/src/core/Config.h index d47362d9e..59014f04d 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -85,7 +85,6 @@ public: GUI_MinimizeOnClose, GUI_HideUsernames, GUI_HidePasswords, - GUI_AdvancedSettings, GUI_ColorPasswords, GUI_MonospaceNotes, GUI_ApplicationTheme, diff --git a/src/gui/dbsettings/DatabaseSettingsDialog.cpp b/src/gui/dbsettings/DatabaseSettingsDialog.cpp index 8bbf7fd6d..ed6b2c090 100644 --- a/src/gui/dbsettings/DatabaseSettingsDialog.cpp +++ b/src/gui/dbsettings/DatabaseSettingsDialog.cpp @@ -33,7 +33,6 @@ #include "fdosecrets/DatabaseSettingsPageFdoSecrets.h" #endif -#include "core/Config.h" #include "core/Database.h" #include "core/Global.h" #include "gui/Icons.h" @@ -109,7 +108,6 @@ DatabaseSettingsDialog::DatabaseSettingsDialog(QWidget* parent) connect(m_securityTabWidget, SIGNAL(currentChanged(int)), SLOT(pageChanged())); connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int))); - connect(m_ui->advancedSettingsToggle, SIGNAL(toggled(bool)), SLOT(toggleAdvancedMode(bool))); #ifdef WITH_XC_BROWSER m_ui->categoryList->addCategory(tr("Browser Integration"), icons()->icon("internet-web-browser")); @@ -137,7 +135,6 @@ void DatabaseSettingsDialog::load(const QSharedPointer& db) for (const ExtraPage& page : asConst(m_extraPages)) { page.loadSettings(db); } - m_ui->advancedSettingsToggle->setChecked(config()->get(Config::GUI_AdvancedSettings).toBool()); m_db = db; } @@ -189,32 +186,5 @@ void DatabaseSettingsDialog::reject() void DatabaseSettingsDialog::pageChanged() { - int pageIndex = m_ui->stackedWidget->currentIndex(); - - bool enabled = (pageIndex == Page::General && m_generalWidget->hasAdvancedMode()); - - if (Page::Security == pageIndex) { - int tabIndex = m_securityTabWidget->currentIndex(); - enabled = (tabIndex == 0 && m_databaseKeyWidget->hasAdvancedMode()); - enabled |= (tabIndex == 1 && m_encryptionWidget->hasAdvancedMode()); - } - - m_ui->advancedSettingsToggle->setEnabled(enabled); -} - -void DatabaseSettingsDialog::toggleAdvancedMode(bool advanced) -{ - if (m_generalWidget->hasAdvancedMode()) { - m_generalWidget->setAdvancedMode(advanced); - } - - if (m_databaseKeyWidget->hasAdvancedMode()) { - m_databaseKeyWidget->setAdvancedMode(advanced); - } - - if (m_encryptionWidget->hasAdvancedMode()) { - m_encryptionWidget->setAdvancedMode(advanced); - } - - config()->set(Config::GUI_AdvancedSettings, advanced); + m_ui->stackedWidget->currentIndex(); } diff --git a/src/gui/dbsettings/DatabaseSettingsDialog.h b/src/gui/dbsettings/DatabaseSettingsDialog.h index 7607f9f78..05b2e837b 100644 --- a/src/gui/dbsettings/DatabaseSettingsDialog.h +++ b/src/gui/dbsettings/DatabaseSettingsDialog.h @@ -69,7 +69,6 @@ private slots: void save(); void reject(); void pageChanged(); - void toggleAdvancedMode(bool advanced); private: enum Page diff --git a/src/gui/dbsettings/DatabaseSettingsDialog.ui b/src/gui/dbsettings/DatabaseSettingsDialog.ui index 1e10e4f1d..16d46646d 100644 --- a/src/gui/dbsettings/DatabaseSettingsDialog.ui +++ b/src/gui/dbsettings/DatabaseSettingsDialog.ui @@ -18,22 +18,11 @@ - - - - - Advanced Settings - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.h b/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.h index 149cd3a6a..18f00b1e2 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.h +++ b/src/gui/dbsettings/DatabaseSettingsWidgetBrowser.h @@ -43,10 +43,6 @@ public: ~DatabaseSettingsWidgetBrowser() override; CustomData* customData() const; - inline bool hasAdvancedMode() const override - { - return false; - } public slots: void initialize() override; diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.h b/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.h index a7d90e43e..258f33e36 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.h +++ b/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.h @@ -44,11 +44,6 @@ public: void load(QSharedPointer db) override; - inline bool hasAdvancedMode() const override - { - return false; - } - public slots: void initialize() override; void uninitialize() override; diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp index 16db94d9f..aeee1554b 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp +++ b/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp @@ -27,8 +27,24 @@ #include "format/KeePass2Writer.h" #include "gui/MessageBox.h" +#include + const char* DatabaseSettingsWidgetEncryption::CD_DECRYPTION_TIME_PREFERENCE_KEY = "KPXC_DECRYPTION_TIME_PREFERENCE"; +#define IS_ARGON2(uuid) (uuid == KeePass2::KDF_ARGON2D || uuid == KeePass2::KDF_ARGON2ID) +#define IS_AES_KDF(uuid) (uuid == KeePass2::KDF_AES_KDBX3 || uuid == KeePass2::KDF_AES_KDBX4) + +namespace +{ + QString getTextualEncryptionTime(int millisecs) + { + if (millisecs < 1000) { + return QObject::tr("%1 ms", "milliseconds", millisecs).arg(millisecs); + } + return QObject::tr("%1 s", "seconds", millisecs / 1000).arg(millisecs / 1000.0, 0, 'f', 1); + } +} // namespace + DatabaseSettingsWidgetEncryption::DatabaseSettingsWidgetEncryption(QWidget* parent) : DatabaseSettingsWidget(parent) , m_ui(new Ui::DatabaseSettingsWidgetEncryption()) @@ -50,19 +66,16 @@ DatabaseSettingsWidgetEncryption::DatabaseSettingsWidgetEncryption(QWidget* pare updateDecryptionTime(m_ui->decryptionTimeSlider->value()); m_ui->transformBenchmarkButton->setText( - QObject::tr("Benchmark %1 delay") - .arg(DatabaseSettingsWidgetEncryption::getTextualEncryptionTime(Kdf::DEFAULT_ENCRYPTION_TIME))); - m_ui->minTimeLabel->setText(DatabaseSettingsWidgetEncryption::getTextualEncryptionTime(Kdf::MIN_ENCRYPTION_TIME)); - m_ui->maxTimeLabel->setText(DatabaseSettingsWidgetEncryption::getTextualEncryptionTime(Kdf::MAX_ENCRYPTION_TIME)); + QObject::tr("Benchmark %1 delay").arg(getTextualEncryptionTime(Kdf::DEFAULT_ENCRYPTION_TIME))); + m_ui->minTimeLabel->setText(getTextualEncryptionTime(Kdf::MIN_ENCRYPTION_TIME)); + m_ui->maxTimeLabel->setText(getTextualEncryptionTime(Kdf::MAX_ENCRYPTION_TIME)); - connect(m_ui->activateChangeDecryptionTimeButton, SIGNAL(clicked()), SLOT(activateChangeDecryptionTime())); connect(m_ui->decryptionTimeSlider, SIGNAL(valueChanged(int)), SLOT(updateDecryptionTime(int))); connect(m_ui->compatibilitySelection, SIGNAL(currentIndexChanged(int)), SLOT(updateFormatCompatibility(int))); // conditions under which a key re-transformation is needed connect(m_ui->decryptionTimeSlider, SIGNAL(valueChanged(int)), SLOT(markDirty())); connect(m_ui->compatibilitySelection, SIGNAL(currentIndexChanged(int)), SLOT(markDirty())); - connect(m_ui->activateChangeDecryptionTimeButton, SIGNAL(clicked()), SLOT(markDirty())); connect(m_ui->algorithmComboBox, SIGNAL(currentIndexChanged(int)), SLOT(markDirty())); connect(m_ui->kdfComboBox, SIGNAL(currentIndexChanged(int)), SLOT(markDirty())); connect(m_ui->transformRoundsSpinBox, SIGNAL(valueChanged(int)), SLOT(markDirty())); @@ -72,8 +85,13 @@ DatabaseSettingsWidgetEncryption::DatabaseSettingsWidgetEncryption(QWidget* pare DatabaseSettingsWidgetEncryption::~DatabaseSettingsWidgetEncryption() = default; -#define IS_ARGON2(uuid) (uuid == KeePass2::KDF_ARGON2D || uuid == KeePass2::KDF_ARGON2ID) -#define IS_AES_KDF(uuid) (uuid == KeePass2::KDF_AES_KDBX3 || uuid == KeePass2::KDF_AES_KDBX4) +void DatabaseSettingsWidgetEncryption::showBasicEncryption(int decryptionMillisecs) +{ + // Show the basic encryption settings tab and set the slider to the stored values + m_ui->decryptionTimeSlider->setValue(decryptionMillisecs / 100); + m_ui->encryptionSettingsTabWidget->setCurrentWidget(m_ui->basicTab); + m_initWithAdvanced = false; +} void DatabaseSettingsWidgetEncryption::initialize() { @@ -82,39 +100,44 @@ void DatabaseSettingsWidgetEncryption::initialize() return; } - bool isDirty = false; + auto version = KDBX4; + if (m_db->kdf()) { + version = (m_db->kdf()->uuid() == KeePass2::KDF_AES_KDBX3) ? KDBX3 : KDBX4; + } + m_ui->compatibilitySelection->setCurrentIndex(version); + + bool isNewDatabase = false; if (!m_db->kdf()) { m_db->setKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2D)); - isDirty = true; + isNewDatabase = true; } if (!m_db->key()) { m_db->setKey(QSharedPointer::create(), true, false, false); m_db->setCipher(KeePass2::CIPHER_AES256); - isDirty = true; + isNewDatabase = true; } bool kdbx3Enabled = KeePass2Writer::kdbxVersionRequired(m_db.data(), true, true) <= KeePass2::FILE_VERSION_3_1; // check if the DB's custom data has a decryption time setting stored // and set the slider to it, otherwise just state that the time is unchanged // (we cannot infer the time from the raw KDF settings) + auto* cd = m_db->metadata()->customData(); if (cd->hasKey(CD_DECRYPTION_TIME_PREFERENCE_KEY)) { int decryptionTime = qMax(100, cd->value(CD_DECRYPTION_TIME_PREFERENCE_KEY).toInt()); - bool block = m_ui->decryptionTimeSlider->blockSignals(true); - m_ui->decryptionTimeSlider->setValue(decryptionTime / 100); - updateDecryptionTime(decryptionTime / 100); - m_ui->decryptionTimeSlider->blockSignals(block); - m_ui->activateChangeDecryptionTimeButton->setVisible(false); + showBasicEncryption(decryptionTime); + } else if (isNewDatabase) { + showBasicEncryption(); } else { - m_ui->decryptionTimeSettings->setVisible(isDirty); - m_ui->activateChangeDecryptionTimeButton->setVisible(!isDirty); - if (!isDirty) { - m_ui->decryptionTimeValueLabel->setText(tr("unchanged", "Database decryption time is unchanged")); - } + // Set default basic decryption time + m_ui->decryptionTimeSlider->setValue(Kdf::DEFAULT_ENCRYPTION_TIME / 100); + // Show the advanced encryption settings tab + m_ui->encryptionSettingsTabWidget->setCurrentWidget(m_ui->advancedTab); + m_initWithAdvanced = true; } - updateFormatCompatibility(m_db->kdf()->uuid() == KeePass2::KDF_AES_KDBX3 ? KDBX3 : KDBX4, isDirty); + updateFormatCompatibility(m_db->kdf()->uuid() == KeePass2::KDF_AES_KDBX3 ? KDBX3 : KDBX4, isNewDatabase); setupAlgorithmComboBox(); setupKdfComboBox(kdbx3Enabled); loadKdfParameters(); @@ -124,7 +147,7 @@ void DatabaseSettingsWidgetEncryption::initialize() m_ui->formatCannotBeChanged->setVisible(true); } - m_isDirty = isDirty; + m_isDirty = isNewDatabase; } void DatabaseSettingsWidgetEncryption::uninitialize() @@ -170,7 +193,6 @@ void DatabaseSettingsWidgetEncryption::loadKdfParameters() } auto kdf = m_db->kdf(); - Q_ASSERT(kdf); if (!kdf) { return; } @@ -202,13 +224,6 @@ void DatabaseSettingsWidgetEncryption::updateKdfFields() m_ui->parallelismSpinBox->setVisible(IS_ARGON2(id)); } -void DatabaseSettingsWidgetEncryption::activateChangeDecryptionTime() -{ - m_ui->decryptionTimeSettings->setVisible(true); - m_ui->activateChangeDecryptionTimeButton->setVisible(false); - updateDecryptionTime(m_ui->decryptionTimeSlider->value()); -} - void DatabaseSettingsWidgetEncryption::markDirty() { m_isDirty = true; @@ -221,6 +236,11 @@ bool DatabaseSettingsWidgetEncryption::save() return false; } + if (m_initWithAdvanced != isAdvancedMode()) { + // Switched from basic <-> advanced mode, need to recalculate everything + m_isDirty = true; + } + if (m_db->key() && !m_db->key()->keys().isEmpty() && !m_isDirty) { // nothing has changed, don't re-transform return true; @@ -229,7 +249,7 @@ bool DatabaseSettingsWidgetEncryption::save() auto kdf = m_db->kdf(); Q_ASSERT(kdf); - if (!advancedMode()) { + if (!isAdvancedMode()) { if (kdf && !m_isDirty && !m_ui->decryptionTimeSettings->isVisible()) { return true; } @@ -352,7 +372,6 @@ void DatabaseSettingsWidgetEncryption::changeKdf(int index) QUuid id(m_ui->kdfComboBox->itemData(index).toByteArray()); m_db->setKdf(KeePass2::uuidToKdf(id)); updateKdfFields(); - activateChangeDecryptionTime(); benchmarkTransformRounds(); } @@ -372,22 +391,14 @@ void DatabaseSettingsWidgetEncryption::parallelismChanged(int value) m_ui->parallelismSpinBox->setSuffix(tr(" thread(s)", "Threads for parallel execution (KDF settings)", value)); } -void DatabaseSettingsWidgetEncryption::setAdvancedMode(bool advanced) +bool DatabaseSettingsWidgetEncryption::isAdvancedMode() { - DatabaseSettingsWidget::setAdvancedMode(advanced); - - if (advanced) { - loadKdfParameters(); - m_ui->stackedWidget->setCurrentIndex(1); - } else { - m_ui->compatibilitySelection->setCurrentIndex(m_db->kdf()->uuid() == KeePass2::KDF_AES_KDBX3 ? KDBX3 : KDBX4); - m_ui->stackedWidget->setCurrentIndex(0); - } + return m_ui->encryptionSettingsTabWidget->currentWidget() == m_ui->advancedTab; } void DatabaseSettingsWidgetEncryption::updateDecryptionTime(int value) { - m_ui->decryptionTimeValueLabel->setText(DatabaseSettingsWidgetEncryption::getTextualEncryptionTime(value * 100)); + m_ui->decryptionTimeValueLabel->setText(getTextualEncryptionTime(value * 100)); } void DatabaseSettingsWidgetEncryption::updateFormatCompatibility(int index, bool retransform) @@ -415,16 +426,5 @@ void DatabaseSettingsWidgetEncryption::updateFormatCompatibility(int index, bool argon2Kdf->setMemory(1 << 16); argon2Kdf->setParallelism(2); } - - activateChangeDecryptionTime(); - } -} - -QString DatabaseSettingsWidgetEncryption::getTextualEncryptionTime(int millisecs) -{ - if (millisecs < 1000) { - return QObject::tr("%1 ms", "milliseconds", millisecs).arg(millisecs); - } else { - return QObject::tr("%1 s", "seconds", millisecs / 1000).arg(millisecs / 1000.0, 0, 'f', 1); } } diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.h b/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.h index c3d7ccf74..874868d07 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.h +++ b/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.h @@ -37,19 +37,11 @@ public: Q_DISABLE_COPY(DatabaseSettingsWidgetEncryption); ~DatabaseSettingsWidgetEncryption() override; - inline bool hasAdvancedMode() const override - { - return true; - } - void setAdvancedMode(bool advanced) override; - public slots: void initialize() override; void uninitialize() override; bool save() override; - static QString getTextualEncryptionTime(int millisecs); - protected: void showEvent(QShowEvent* event) override; @@ -64,10 +56,12 @@ private slots: void setupKdfComboBox(bool enableKdbx3); void loadKdfParameters(); void updateKdfFields(); - void activateChangeDecryptionTime(); void markDirty(); private: + bool isAdvancedMode(); + void showBasicEncryption(int decryptionMillisecs = Kdf::DEFAULT_ENCRYPTION_TIME); + enum FormatSelection { KDBX4, @@ -76,6 +70,7 @@ private: static const char* CD_DECRYPTION_TIME_PREFERENCE_KEY; bool m_isDirty = false; + bool m_initWithAdvanced = false; bool m_formatCompatibilityDirty = false; const QScopedPointer m_ui; }; diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.ui b/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.ui index f43bf9ddb..581bc6ca2 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.ui +++ b/src/gui/dbsettings/DatabaseSettingsWidgetEncryption.ui @@ -6,23 +6,40 @@ 0 0 - 585 - 339 + 451 + 329 - + - - - 0 + + + QFrame::NoFrame - - + + QFrame::Plain + + + true + + + + + 0 + 0 + 433 + 311 + + + + + 6 + 0 - 0 + 10 0 @@ -30,6 +47,60 @@ 0 + + + + QFormLayout::DontWrapRows + + + 2 + + + + + + 75 + true + + + + Database format: + + + + + + + + 0 + 0 + + + + Unless you need to open your database with other programs, always use the latest format. + + + Database format + + + + + + + + true + + + + Format cannot be changed: Your database uses KDBX 4 features + + + true + + + + + @@ -46,399 +117,420 @@ - - - - - - Decryption Time: - - - - - - - ?? s - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Change existing decryption time - - - Change - - - - - - - - - - - - Decryption time in seconds - - - 1 - - - 10 - - - 10 - - - Qt::Horizontal - - - QSlider::TicksBelow - - - 5 - - - - - - - - - ?? ms - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - ? s - - - - - - - - - - 0 - 0 - - - - Higher values offer more protection, but opening the database will take longer. - - - true - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - - - - 2 - - - - - Database format: - - - - - - - - 0 - 0 - - - - Database format - - - - - - - - true - - - - Format cannot be changed: Your database uses KDBX 4 features - - - - - + + + 75 + true + + - Unless you need to open your database with other programs, always use the latest format. + Encryption Settings: - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Encryption Algorithm: + + + + QTabWidget::North + + QTabWidget::Rounded + + + 0 + + + + Basic + + + + 6 + + + 9 + + + 6 + + + 9 + + + 6 + + + + + + + + 75 + true + + + + Decryption Time: + + + + + + + + 50 + false + + + + ?? s + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 6 + + + 0 + + + 6 + + + 9 + + + + + Decryption time in seconds + + + 1 + + + 10 + + + 10 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 5 + + + + + + + + + ?? ms + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + ? s + + + + + + + + + + 0 + 0 + + + + Higher values offer more protection, but opening the database will take longer. + + + true + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + + + + + Advanced + + + + 6 + + + 6 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 150 + 0 + + + + + 150 + 16777215 + + + + Parallelism + + + 1 + + + 128 + + + + + + + Parallelism: + + + + + + + + 150 + 0 + + + + + 150 + 16777215 + + + + Memory usage + + + 1 + + + 1048576 + + + + + + + Memory Usage: + + + + + + + + + + 150 + 0 + + + + + 150 + 16777215 + + + + Transform rounds + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 1 + + + 1000000000 + + + + + + + Qt::WheelFocus + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Transform rounds: + + + + + + + + 0 + 0 + + + + Key derivation function + + + + + + + Key Derivation Function: + + + + + + + + 0 + 0 + + + + Encryption algorithm + + + + AES: 256 Bit (default) + + + + + Twofish: 256 Bit + + + + + + + + Encryption Algorithm: + + + + + - - - - - 0 - 0 - + + + + Qt::Vertical - - Encryption algorithm - - - - AES: 256 Bit (default) - - - - - Twofish: 256 Bit - - - - - - - - Key Derivation Function: - - - - - - - - 0 - 0 - - - - Key derivation function - - - - - - - Transform rounds: - - - - - - - - - - 150 - 0 - - - - - 150 - 16777215 - - - - Transform rounds - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - 1 - - - 1000000000 - - - - - - - Qt::WheelFocus - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Memory Usage: - - - - - - + - 150 + 20 0 - - - 150 - 16777215 - - - - Memory usage - - - 1 - - - 1048576 - - - - - - - Parallelism: - - - - - - - - 150 - 0 - - - - - 150 - 16777215 - - - - Parallelism - - - 1 - - - 128 - - + - - - - Qt::Vertical - - - - 20 - 40 - - - - - activateChangeDecryptionTimeButton decryptionTimeSlider - compatibilitySelection algorithmComboBox kdfComboBox transformRoundsSpinBox diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.h b/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.h index 9e18d4277..a26e1ef7a 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.h +++ b/src/gui/dbsettings/DatabaseSettingsWidgetGeneral.h @@ -35,11 +35,6 @@ public: Q_DISABLE_COPY(DatabaseSettingsWidgetGeneral); ~DatabaseSettingsWidgetGeneral() override; - inline bool hasAdvancedMode() const override - { - return false; - } - public slots: void initialize() override; void uninitialize() override; diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.h b/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.h index 5ee6d55fb..e17689f9e 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.h +++ b/src/gui/dbsettings/DatabaseSettingsWidgetMaintenance.h @@ -37,11 +37,6 @@ public: Q_DISABLE_COPY(DatabaseSettingsWidgetMaintenance); ~DatabaseSettingsWidgetMaintenance() override; - inline bool hasAdvancedMode() const override - { - return false; - } - public slots: void initialize() override; void uninitialize() override{}; diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.h b/src/gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.h index d2b739474..8a32e0670 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.h +++ b/src/gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.h @@ -35,11 +35,6 @@ public: Q_DISABLE_COPY(DatabaseSettingWidgetMetaData); ~DatabaseSettingWidgetMetaData() override; - inline bool hasAdvancedMode() const override - { - return false; - } - public slots: void initialize() override; void uninitialize() override; diff --git a/src/gui/settings/SettingsWidget.cpp b/src/gui/settings/SettingsWidget.cpp index 779d076c0..7b8d04519 100644 --- a/src/gui/settings/SettingsWidget.cpp +++ b/src/gui/settings/SettingsWidget.cpp @@ -24,28 +24,6 @@ SettingsWidget::SettingsWidget(QWidget* parent) SettingsWidget::~SettingsWidget() = default; -/** - * Switch between simple mode (the default) and advanced mode. - * Subclasses which implement an advanced mode, need to override this method, - * \link advancedMode() and \link hasAdvancedMode. - * - * When overriding this method, make sure to also emit the - * \link advancedModeChanged() signal. - * - * @param advanced whether advanced mode is enabled - */ -void SettingsWidget::setAdvancedMode(bool advanced) +void SettingsWidget::discard() { - if (hasAdvancedMode() && advanced != advancedMode()) { - m_advancedMode = advanced; - emit advancedModeChanged(advanced); - } -} - -/** - * @return true if advanced mode is on (default: false) - */ -bool SettingsWidget::advancedMode() const -{ - return m_advancedMode; } diff --git a/src/gui/settings/SettingsWidget.h b/src/gui/settings/SettingsWidget.h index 8c55c5221..90d8161df 100644 --- a/src/gui/settings/SettingsWidget.h +++ b/src/gui/settings/SettingsWidget.h @@ -34,13 +34,6 @@ public: Q_DISABLE_COPY(SettingsWidget); ~SettingsWidget() override; - /** - * @return true if widget has an advanced mode - */ - virtual bool hasAdvancedMode() const = 0; - virtual void setAdvancedMode(bool advanced); - virtual bool advancedMode() const; - public slots: /** * Initialize settings widget. @@ -62,11 +55,10 @@ public slots: /** * Discard settings. */ - virtual void discard(){}; + virtual void discard(); signals: void editFinished(bool saved); - void advancedModeChanged(bool advanced); private: bool m_advancedMode = false; diff --git a/src/gui/wizard/NewDatabaseWizardPage.cpp b/src/gui/wizard/NewDatabaseWizardPage.cpp index f1acd943c..4b169ce49 100644 --- a/src/gui/wizard/NewDatabaseWizardPage.cpp +++ b/src/gui/wizard/NewDatabaseWizardPage.cpp @@ -27,8 +27,6 @@ NewDatabaseWizardPage::NewDatabaseWizardPage(QWidget* parent) , m_ui(new Ui::NewDatabaseWizardPage()) { m_ui->setupUi(this); - - connect(m_ui->advancedSettingsButton, SIGNAL(clicked()), SLOT(toggleAdvancedSettings())); } NewDatabaseWizardPage::~NewDatabaseWizardPage() = default; @@ -43,7 +41,6 @@ void NewDatabaseWizardPage::setPageWidget(DatabaseSettingsWidget* page) { m_pageWidget = page; m_ui->pageContent->setWidget(m_pageWidget); - m_ui->advancedSettingsButton->setVisible(m_pageWidget->hasAdvancedMode()); } /** @@ -86,21 +83,3 @@ bool NewDatabaseWizardPage::validatePage() m_pageWidget->uninitialize(); return valid; } - -/** - * Toggle settings page widget between simple and advanced mode. - */ -void NewDatabaseWizardPage::toggleAdvancedSettings() -{ - if (!m_pageWidget || !m_pageWidget->hasAdvancedMode()) { - return; - } - - if (m_pageWidget->advancedMode()) { - m_pageWidget->setAdvancedMode(false); - m_ui->advancedSettingsButton->setText(tr("Advanced Settings")); - } else { - m_pageWidget->setAdvancedMode(true); - m_ui->advancedSettingsButton->setText(tr("Simple Settings")); - } -} diff --git a/src/gui/wizard/NewDatabaseWizardPage.h b/src/gui/wizard/NewDatabaseWizardPage.h index 185e6f8ca..2e26cfd10 100644 --- a/src/gui/wizard/NewDatabaseWizardPage.h +++ b/src/gui/wizard/NewDatabaseWizardPage.h @@ -47,9 +47,6 @@ public: void initializePage() override; bool validatePage() override; -public slots: - void toggleAdvancedSettings(); - protected: QPointer m_pageWidget; QSharedPointer m_db; diff --git a/src/gui/wizard/NewDatabaseWizardPage.ui b/src/gui/wizard/NewDatabaseWizardPage.ui index a91b653d0..1f347d059 100644 --- a/src/gui/wizard/NewDatabaseWizardPage.ui +++ b/src/gui/wizard/NewDatabaseWizardPage.ui @@ -25,7 +25,7 @@ Here you can adjust the database encryption settings. Don't worry, you can change them later in the database settings. - + @@ -66,49 +66,12 @@ QScrollArea > QWidget > QScrollBar { background: 1; } 0 0 560 - 349 + 392 - - - - Qt::Vertical - - - - 20 - 6 - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Advanced Settings - - - - - diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index a1dc7c967..170bf3a17 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -189,7 +189,7 @@ void TestGui::testSettingsDefaultTabOrder() QVERIFY(dbSettingsWidget->isVisible()); QCOMPARE(dbSettingsWidget->findChild("categoryList")->currentCategory(), 0); for (auto* w : dbSettingsWidget->findChildren()) { - if (w->currentIndex() != 0) { + if (w->currentIndex() != 0 && w->objectName() != "encryptionSettingsTabWidget") { QFAIL("Database settings contain QTabWidgets whose default index is not 0"); } } @@ -208,12 +208,16 @@ void TestGui::testCreateDatabase() QTest::keyClick(wizard, Qt::Key_Enter); QCOMPARE(wizard->currentId(), 1); + // Check that basic encryption settings are visible auto decryptionTimeSlider = wizard->currentPage()->findChild("decryptionTimeSlider"); auto algorithmComboBox = wizard->currentPage()->findChild("algorithmComboBox"); QTRY_VERIFY(decryptionTimeSlider->isVisible()); QVERIFY(!algorithmComboBox->isVisible()); - auto advancedToggle = wizard->currentPage()->findChild("advancedSettingsButton"); - QTest::mouseClick(advancedToggle, Qt::MouseButton::LeftButton); + + // Set the encryption settings to the advanced view + auto encryptionSettings = wizard->currentPage()->findChild("encryptionSettingsTabWidget"); + auto advancedTab = encryptionSettings->findChild("advancedTab"); + encryptionSettings->setCurrentWidget(advancedTab); QTRY_VERIFY(!decryptionTimeSlider->isVisible()); QVERIFY(algorithmComboBox->isVisible()); @@ -1468,19 +1472,24 @@ void TestGui::testDatabaseSettings() auto* dbSettingsDialog = m_dbWidget->findChild("databaseSettingsDialog"); auto* dbSettingsCategoryList = dbSettingsDialog->findChild("categoryList"); auto* dbSettingsStackedWidget = dbSettingsDialog->findChild("stackedWidget"); - auto* transformRoundsSpinBox = dbSettingsDialog->findChild("transformRoundsSpinBox"); - auto advancedToggle = dbSettingsDialog->findChild("advancedSettingsToggle"); auto* autosaveDelayCheckBox = dbSettingsDialog->findChild("autosaveDelayCheckBox"); auto* autosaveDelaySpinBox = dbSettingsDialog->findChild("autosaveDelaySpinBox"); auto* dbSettingsButtonBox = dbSettingsDialog->findChild("buttonBox"); int autosaveDelayTestValue = 2; - advancedToggle->setChecked(true); - QApplication::processEvents(); - dbSettingsCategoryList->setCurrentCategory(1); // go into security category dbSettingsStackedWidget->findChild()->setCurrentIndex(1); // go into encryption tab - QVERIFY(transformRoundsSpinBox != nullptr); + + auto encryptionSettings = dbSettingsDialog->findChild("encryptionSettingsTabWidget"); + auto advancedTab = encryptionSettings->findChild("advancedTab"); + encryptionSettings->setCurrentWidget(advancedTab); + + QApplication::processEvents(); + + auto transformRoundsSpinBox = advancedTab->findChild("transformRoundsSpinBox"); + QVERIFY(transformRoundsSpinBox); + QVERIFY(transformRoundsSpinBox->isVisible()); + transformRoundsSpinBox->setValue(123456); QTest::keyClick(transformRoundsSpinBox, Qt::Key_Enter); QTRY_COMPARE(m_db->kdf()->rounds(), 123456); diff --git a/tests/gui/TestGuiBrowser.cpp b/tests/gui/TestGuiBrowser.cpp index 075d49dc9..bdbfda8c7 100644 --- a/tests/gui/TestGuiBrowser.cpp +++ b/tests/gui/TestGuiBrowser.cpp @@ -66,8 +66,6 @@ void TestGuiBrowser::initTestCase() config()->set(Config::AutoSaveOnExit, false); // Enable the tray icon so we can test hiding/restoring the windowQByteArray config()->set(Config::GUI_ShowTrayIcon, true); - // Disable advanced settings mode (activate within individual tests to test advanced settings) - config()->set(Config::GUI_AdvancedSettings, false); // Disable the update check first time alert config()->set(Config::UpdateCheckMessageShown, true);