Fix minor UX issues with DB Open Widget

* Only clear password field when switching tabs or minimizing. This prevents the setting "Remember Key Files and Hardware Keys" from being useless with multiple databases.
* Convert key file field to Line Edit, simplifies usage. Fix clear field button as well.
* Removed need for clearForms to check if the database is being opened (was a solution to tab switching while unlocking, no longer a problem).
This commit is contained in:
Jonathan White 2020-06-06 09:54:57 -04:00
parent 6c9125402a
commit 1ad0184473
4 changed files with 51 additions and 68 deletions

View file

@ -38,6 +38,11 @@
#include <QFont> #include <QFont>
#include <QSharedPointer> #include <QSharedPointer>
namespace
{
constexpr int clearFormsDelay = 30000;
}
DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
: DialogyWidget(parent) : DialogyWidget(parent)
, m_ui(new Ui::DatabaseOpenWidget()) , m_ui(new Ui::DatabaseOpenWidget())
@ -47,14 +52,20 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
m_ui->messageWidget->setHidden(true); m_ui->messageWidget->setHidden(true);
m_hideTimer.setInterval(clearFormsDelay);
m_hideTimer.setSingleShot(true);
connect(&m_hideTimer, &QTimer::timeout, this, [this] {
// Reset the password field after being hidden for a set time
m_ui->editPassword->setText("");
m_ui->editPassword->setShowPassword(false);
});
QFont font; QFont font;
font.setPointSize(font.pointSize() + 4); font.setPointSize(font.pointSize() + 4);
font.setBold(true); font.setBold(true);
m_ui->labelHeadline->setFont(font); m_ui->labelHeadline->setFont(font);
m_ui->labelHeadline->setText(tr("Unlock KeePassXC Database")); m_ui->labelHeadline->setText(tr("Unlock KeePassXC Database"));
m_ui->comboKeyFile->lineEdit()->addAction(m_ui->keyFileClearIcon, QLineEdit::TrailingPosition);
connect(m_ui->buttonBrowseFile, SIGNAL(clicked()), SLOT(browseKeyFile())); connect(m_ui->buttonBrowseFile, SIGNAL(clicked()), SLOT(browseKeyFile()));
connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase())); connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase()));
@ -65,11 +76,11 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
m_ui->keyFileLabelHelp->setIcon(resources()->icon("system-help").pixmap(QSize(12, 12))); m_ui->keyFileLabelHelp->setIcon(resources()->icon("system-help").pixmap(QSize(12, 12)));
connect(m_ui->keyFileLabelHelp, SIGNAL(clicked(bool)), SLOT(openKeyFileHelp())); connect(m_ui->keyFileLabelHelp, SIGNAL(clicked(bool)), SLOT(openKeyFileHelp()));
connect(m_ui->comboKeyFile->lineEdit(), SIGNAL(textChanged(QString)), SLOT(handleKeyFileComboEdited())); connect(m_ui->keyFileLineEdit, SIGNAL(textChanged(QString)), SLOT(keyFileTextChanged()));
connect(m_ui->comboKeyFile, SIGNAL(currentIndexChanged(int)), SLOT(handleKeyFileComboChanged())); m_ui->keyFileLineEdit->addAction(m_ui->keyFileClearIcon, QLineEdit::TrailingPosition);
m_ui->keyFileClearIcon->setIcon(resources()->icon("edit-clear-locationbar-rtl")); m_ui->keyFileClearIcon->setIcon(resources()->icon("edit-clear-locationbar-rtl"));
m_ui->keyFileClearIcon->setVisible(false); m_ui->keyFileClearIcon->setVisible(false);
connect(m_ui->keyFileClearIcon, SIGNAL(triggered(bool)), SLOT(clearKeyFileEdit())); connect(m_ui->keyFileClearIcon, SIGNAL(triggered(bool)), SLOT(clearKeyFileText()));
#ifdef WITH_XC_YUBIKEY #ifdef WITH_XC_YUBIKEY
m_ui->hardwareKeyProgress->setVisible(false); m_ui->hardwareKeyProgress->setVisible(false);
@ -114,33 +125,32 @@ void DatabaseOpenWidget::showEvent(QShowEvent* event)
{ {
DialogyWidget::showEvent(event); DialogyWidget::showEvent(event);
m_ui->editPassword->setFocus(); m_ui->editPassword->setFocus();
m_hideTimer.stop();
} }
void DatabaseOpenWidget::hideEvent(QHideEvent* event) void DatabaseOpenWidget::hideEvent(QHideEvent* event)
{ {
DialogyWidget::hideEvent(event); DialogyWidget::hideEvent(event);
// Clear the forms if we are minimized // Schedule form clearing if we are hidden
if (!isVisible()) { if (!isVisible()) {
clearForms(); m_hideTimer.start();
} }
} }
void DatabaseOpenWidget::load(const QString& filename) void DatabaseOpenWidget::load(const QString& filename)
{ {
clearForms();
m_filename = filename; m_filename = filename;
m_ui->fileNameLabel->setRawText(m_filename); m_ui->fileNameLabel->setRawText(m_filename);
m_ui->comboKeyFile->addItem(tr("Select key file..."), -1);
m_ui->comboKeyFile->setCurrentIndex(0);
m_ui->keyFileClearIcon->setVisible(false); m_ui->keyFileClearIcon->setVisible(false);
m_keyFileComboEdited = false;
if (config()->get(Config::RememberLastKeyFiles).toBool()) { if (config()->get(Config::RememberLastKeyFiles).toBool()) {
auto lastKeyFiles = config()->get(Config::LastKeyFiles).toHash(); auto lastKeyFiles = config()->get(Config::LastKeyFiles).toHash();
if (lastKeyFiles.contains(m_filename)) { if (lastKeyFiles.contains(m_filename)) {
m_ui->comboKeyFile->addItem(lastKeyFiles[m_filename].toString()); m_ui->keyFileLineEdit->setText(lastKeyFiles[m_filename].toString());
m_ui->comboKeyFile->setCurrentIndex(1);
} }
} }
@ -160,14 +170,12 @@ void DatabaseOpenWidget::load(const QString& filename)
void DatabaseOpenWidget::clearForms() void DatabaseOpenWidget::clearForms()
{ {
if (!m_isOpeningDatabase) {
m_ui->editPassword->setText(""); m_ui->editPassword->setText("");
m_ui->editPassword->setShowPassword(false); m_ui->editPassword->setShowPassword(false);
m_ui->comboKeyFile->clear(); m_ui->keyFileLineEdit->clear();
m_ui->comboKeyFile->setEditText("");
m_ui->checkTouchID->setChecked(false); m_ui->checkTouchID->setChecked(false);
m_ui->challengeResponseCombo->clear();
m_db.reset(); m_db.reset();
}
} }
QSharedPointer<Database> DatabaseOpenWidget::database() QSharedPointer<Database> DatabaseOpenWidget::database()
@ -183,8 +191,7 @@ QString DatabaseOpenWidget::filename()
void DatabaseOpenWidget::enterKey(const QString& pw, const QString& keyFile) void DatabaseOpenWidget::enterKey(const QString& pw, const QString& keyFile)
{ {
m_ui->editPassword->setText(pw); m_ui->editPassword->setText(pw);
m_ui->comboKeyFile->setCurrentIndex(-1); m_ui->keyFileLineEdit->setText(keyFile);
m_ui->comboKeyFile->setEditText(keyFile);
openDatabase(); openDatabase();
} }
@ -200,7 +207,6 @@ void DatabaseOpenWidget::openDatabase()
m_ui->editPassword->setShowPassword(false); m_ui->editPassword->setShowPassword(false);
QCoreApplication::processEvents(); QCoreApplication::processEvents();
m_isOpeningDatabase = true;
m_db.reset(new Database()); m_db.reset(new Database());
QString error; QString error;
@ -230,10 +236,8 @@ void DatabaseOpenWidget::openDatabase()
config()->set(Config::UseTouchID, useTouchID); config()->set(Config::UseTouchID, useTouchID);
#endif #endif
emit dialogFinished(true); emit dialogFinished(true);
m_isOpeningDatabase = false;
clearForms(); clearForms();
} else { } else {
m_isOpeningDatabase = false;
if (m_ui->editPassword->text().isEmpty() && !m_retryUnlockWithEmptyPassword) { if (m_ui->editPassword->text().isEmpty() && !m_retryUnlockWithEmptyPassword) {
QScopedPointer<QMessageBox> msgBox(new QMessageBox(this)); QScopedPointer<QMessageBox> msgBox(new QMessageBox(this));
msgBox->setIcon(QMessageBox::Critical); msgBox->setIcon(QMessageBox::Critical);
@ -298,8 +302,8 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey()
lastKeyFiles.remove(m_filename); lastKeyFiles.remove(m_filename);
auto key = QSharedPointer<FileKey>::create(); auto key = QSharedPointer<FileKey>::create();
QString keyFilename = m_ui->comboKeyFile->currentText(); QString keyFilename = m_ui->keyFileLineEdit->text();
if (!m_ui->comboKeyFile->currentText().isEmpty() && m_keyFileComboEdited) { if (!keyFilename.isEmpty()) {
QString errorMsg; QString errorMsg;
if (!key->load(keyFilename, &errorMsg)) { if (!key->load(keyFilename, &errorMsg)) {
m_ui->messageWidget->showMessage(tr("Failed to open key file: %1").arg(errorMsg), MessageWidget::Error); m_ui->messageWidget->showMessage(tr("Failed to open key file: %1").arg(errorMsg), MessageWidget::Error);
@ -375,28 +379,18 @@ void DatabaseOpenWidget::browseKeyFile()
} }
if (!filename.isEmpty()) { if (!filename.isEmpty()) {
m_ui->comboKeyFile->setCurrentIndex(-1); m_ui->keyFileLineEdit->setText(filename);
m_ui->comboKeyFile->setEditText(filename);
} }
} }
void DatabaseOpenWidget::clearKeyFileEdit() void DatabaseOpenWidget::clearKeyFileText()
{ {
m_ui->comboKeyFile->setCurrentIndex(0); m_ui->keyFileLineEdit->clear();
// make sure that handler is called even if 0 was the current index already
handleKeyFileComboChanged();
} }
void DatabaseOpenWidget::handleKeyFileComboEdited() void DatabaseOpenWidget::keyFileTextChanged()
{ {
m_keyFileComboEdited = true; m_ui->keyFileClearIcon->setVisible(!m_ui->keyFileLineEdit->text().isEmpty());
m_ui->keyFileClearIcon->setVisible(true);
}
void DatabaseOpenWidget::handleKeyFileComboChanged()
{
m_keyFileComboEdited = m_ui->comboKeyFile->currentIndex() != 0;
m_ui->keyFileClearIcon->setVisible(m_keyFileComboEdited);
} }
void DatabaseOpenWidget::pollHardwareKey() void DatabaseOpenWidget::pollHardwareKey()

View file

@ -20,6 +20,7 @@
#define KEEPASSX_DATABASEOPENWIDGET_H #define KEEPASSX_DATABASEOPENWIDGET_H
#include <QScopedPointer> #include <QScopedPointer>
#include <QTimer>
#include "gui/DialogyWidget.h" #include "gui/DialogyWidget.h"
#include "keys/CompositeKey.h" #include "keys/CompositeKey.h"
@ -53,30 +54,28 @@ protected:
void hideEvent(QHideEvent* event) override; void hideEvent(QHideEvent* event) override;
QSharedPointer<CompositeKey> databaseKey(); QSharedPointer<CompositeKey> databaseKey();
const QScopedPointer<Ui::DatabaseOpenWidget> m_ui;
QSharedPointer<Database> m_db;
QString m_filename;
bool m_retryUnlockWithEmptyPassword = false;
protected slots: protected slots:
virtual void openDatabase(); virtual void openDatabase();
void reject(); void reject();
private slots: private slots:
void browseKeyFile(); void browseKeyFile();
void clearKeyFileEdit(); void clearKeyFileText();
void handleKeyFileComboEdited(); void keyFileTextChanged();
void handleKeyFileComboChanged();
void pollHardwareKey(); void pollHardwareKey();
void hardwareKeyResponse(bool found); void hardwareKeyResponse(bool found);
void openHardwareKeyHelp(); void openHardwareKeyHelp();
void openKeyFileHelp(); void openKeyFileHelp();
protected:
const QScopedPointer<Ui::DatabaseOpenWidget> m_ui;
QSharedPointer<Database> m_db;
QString m_filename;
bool m_retryUnlockWithEmptyPassword = false;
private: private:
bool m_pollingHardwareKey = false; bool m_pollingHardwareKey = false;
bool m_keyFileComboEdited = false; QTimer m_hideTimer;
bool m_isOpeningDatabase = false;
Q_DISABLE_COPY(DatabaseOpenWidget) Q_DISABLE_COPY(DatabaseOpenWidget)
}; };

View file

@ -237,7 +237,7 @@
<string>Key File:</string> <string>Key File:</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>comboKeyFile</cstring> <cstring>keyFileLineEdit</cstring>
</property> </property>
</widget> </widget>
</item> </item>
@ -406,10 +406,7 @@
<number>0</number> <number>0</number>
</property> </property>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="comboKeyFile"> <widget class="QLineEdit" name="keyFileLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -417,10 +414,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="accessibleName"> <property name="accessibleName">
<string>Key file selection</string> <string>Key file to unlock the database</string>
</property>
<property name="editable">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
@ -610,7 +604,7 @@
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>editPassword</tabstop> <tabstop>editPassword</tabstop>
<tabstop>comboKeyFile</tabstop> <tabstop>keyFileLineEdit</tabstop>
<tabstop>buttonBrowseFile</tabstop> <tabstop>buttonBrowseFile</tabstop>
<tabstop>challengeResponseCombo</tabstop> <tabstop>challengeResponseCombo</tabstop>
<tabstop>buttonRedetectYubikey</tabstop> <tabstop>buttonRedetectYubikey</tabstop>

View file

@ -37,16 +37,12 @@ void KeePass1OpenWidget::openDatabase()
KeePass1Reader reader; KeePass1Reader reader;
QString password; QString password;
QString keyFileName; QString keyFileName = m_ui->keyFileLineEdit->text();
if (!m_ui->editPassword->text().isEmpty() || m_retryUnlockWithEmptyPassword) { if (!m_ui->editPassword->text().isEmpty() || m_retryUnlockWithEmptyPassword) {
password = m_ui->editPassword->text(); password = m_ui->editPassword->text();
} }
if (!m_ui->comboKeyFile->currentText().isEmpty() && m_ui->comboKeyFile->currentData() != -1) {
keyFileName = m_ui->comboKeyFile->currentText();
}
QFile file(m_filename); QFile file(m_filename);
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly)) {
m_ui->messageWidget->showMessage(tr("Unable to open the database.").append("\n").append(file.errorString()), m_ui->messageWidget->showMessage(tr("Unable to open the database.").append("\n").append(file.errorString()),