mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-07-26 08:15:32 -04:00
Redesign database unlock widget. (#3287)
With this change we get rid of the confusing key component checkboxes. Now a component is either there or not (if left empty). There is no redundant distinction between "unset" and "emtpy" anymore. For compatibility with older databases that have "empty" passwords, KeePassXC will ask if the user wants to retry with an empty password if unlocking failed and the password field was left blank. Besides these functional changes, the widget's layout has been rearranged to be more compact, less stretched out (e.g. input fields do not fill the full window width anymore), and more user-friendly by providing a help tooltip for the hardware key field and accessible descriptions for screen readers.
This commit is contained in:
parent
eb9371091a
commit
5492b5c4f6
7 changed files with 578 additions and 299 deletions
|
@ -36,6 +36,8 @@
|
||||||
|
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QtConcurrentRun>
|
#include <QtConcurrentRun>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QFont>
|
||||||
|
|
||||||
DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
|
DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
|
||||||
: DialogyWidget(parent)
|
: DialogyWidget(parent)
|
||||||
|
@ -46,21 +48,30 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
|
||||||
|
|
||||||
m_ui->messageWidget->setHidden(true);
|
m_ui->messageWidget->setHidden(true);
|
||||||
|
|
||||||
QFont font = m_ui->labelHeadline->font();
|
QFont font;
|
||||||
|
font.setPointSize(font.pointSize() + 4);
|
||||||
font.setBold(true);
|
font.setBold(true);
|
||||||
font.setPointSize(font.pointSize() + 2);
|
|
||||||
m_ui->labelHeadline->setFont(font);
|
m_ui->labelHeadline->setFont(font);
|
||||||
|
m_ui->labelHeadline->setText(tr("Unlock KeePassXC Database"));
|
||||||
|
|
||||||
|
m_ui->comboKeyFile->lineEdit()->addAction(m_ui->keyFileClearIcon, QLineEdit::TrailingPosition);
|
||||||
|
|
||||||
m_ui->buttonTogglePassword->setIcon(filePath()->onOffIcon("actions", "password-show"));
|
m_ui->buttonTogglePassword->setIcon(filePath()->onOffIcon("actions", "password-show"));
|
||||||
connect(m_ui->buttonTogglePassword, SIGNAL(toggled(bool)), m_ui->editPassword, SLOT(setShowPassword(bool)));
|
connect(m_ui->buttonTogglePassword, SIGNAL(toggled(bool)), m_ui->editPassword, SLOT(setShowPassword(bool)));
|
||||||
connect(m_ui->buttonBrowseFile, SIGNAL(clicked()), SLOT(browseKeyFile()));
|
connect(m_ui->buttonBrowseFile, SIGNAL(clicked()), SLOT(browseKeyFile()));
|
||||||
|
|
||||||
connect(m_ui->editPassword, SIGNAL(textChanged(QString)), SLOT(activatePassword()));
|
|
||||||
connect(m_ui->comboKeyFile, SIGNAL(editTextChanged(QString)), SLOT(activateKeyFile()));
|
|
||||||
|
|
||||||
connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase()));
|
connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase()));
|
||||||
connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject()));
|
connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject()));
|
||||||
|
|
||||||
|
m_ui->hardwareKeyLabelHelp->setIcon(filePath()->icon("actions", "system-help").pixmap(QSize(12, 12)));
|
||||||
|
connect(m_ui->hardwareKeyLabelHelp, SIGNAL(clicked(bool)), SLOT(openHardwareKeyHelp()));
|
||||||
|
|
||||||
|
connect(m_ui->comboKeyFile->lineEdit(), SIGNAL(textChanged(QString)), SLOT(handleKeyFileComboEdited()));
|
||||||
|
connect(m_ui->comboKeyFile, SIGNAL(currentIndexChanged(int)), SLOT(handleKeyFileComboChanged()));
|
||||||
|
m_ui->keyFileClearIcon->setIcon(filePath()->icon("actions", "edit-clear-locationbar-rtl"));
|
||||||
|
m_ui->keyFileClearIcon->setVisible(false);
|
||||||
|
connect(m_ui->keyFileClearIcon, SIGNAL(triggered(bool)), SLOT(clearKeyFileEdit()));
|
||||||
|
|
||||||
#ifdef WITH_XC_YUBIKEY
|
#ifdef WITH_XC_YUBIKEY
|
||||||
m_ui->yubikeyProgress->setVisible(false);
|
m_ui->yubikeyProgress->setVisible(false);
|
||||||
QSizePolicy sp = m_ui->yubikeyProgress->sizePolicy();
|
QSizePolicy sp = m_ui->yubikeyProgress->sizePolicy();
|
||||||
|
@ -68,7 +79,6 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
|
||||||
m_ui->yubikeyProgress->setSizePolicy(sp);
|
m_ui->yubikeyProgress->setSizePolicy(sp);
|
||||||
|
|
||||||
connect(m_ui->buttonRedetectYubikey, SIGNAL(clicked()), SLOT(pollYubikey()));
|
connect(m_ui->buttonRedetectYubikey, SIGNAL(clicked()), SLOT(pollYubikey()));
|
||||||
connect(m_ui->comboChallengeResponse, SIGNAL(activated(int)), SLOT(activateChallengeResponse()));
|
|
||||||
#else
|
#else
|
||||||
m_ui->checkChallengeResponse->setVisible(false);
|
m_ui->checkChallengeResponse->setVisible(false);
|
||||||
m_ui->buttonRedetectYubikey->setVisible(false);
|
m_ui->buttonRedetectYubikey->setVisible(false);
|
||||||
|
@ -80,11 +90,10 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
|
||||||
// add random padding to layouts to align widgets properly
|
// add random padding to layouts to align widgets properly
|
||||||
m_ui->dialogButtonsLayout->setContentsMargins(10, 0, 15, 0);
|
m_ui->dialogButtonsLayout->setContentsMargins(10, 0, 15, 0);
|
||||||
m_ui->gridLayout->setContentsMargins(10, 0, 0, 0);
|
m_ui->gridLayout->setContentsMargins(10, 0, 0, 0);
|
||||||
m_ui->labelLayout->setContentsMargins(10, 0, 10, 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WITH_XC_TOUCHID
|
#ifndef WITH_XC_TOUCHID
|
||||||
m_ui->checkTouchID->setVisible(false);
|
m_ui->touchIDContainer->setVisible(false);
|
||||||
#else
|
#else
|
||||||
if (!TouchID::getInstance().isAvailable()) {
|
if (!TouchID::getInstance().isAvailable()) {
|
||||||
m_ui->checkTouchID->setVisible(false);
|
m_ui->checkTouchID->setVisible(false);
|
||||||
|
@ -136,14 +145,18 @@ void DatabaseOpenWidget::hideEvent(QHideEvent* event)
|
||||||
void DatabaseOpenWidget::load(const QString& filename)
|
void DatabaseOpenWidget::load(const QString& filename)
|
||||||
{
|
{
|
||||||
m_filename = filename;
|
m_filename = filename;
|
||||||
|
m_ui->fileNameLabel->setRawText(m_filename);
|
||||||
|
|
||||||
m_ui->labelFilename->setText(filename);
|
m_ui->comboKeyFile->addItem(tr("Select file..."), -1);
|
||||||
|
m_ui->comboKeyFile->setCurrentIndex(0);
|
||||||
|
m_ui->keyFileClearIcon->setVisible(false);
|
||||||
|
m_keyFileComboEdited = false;
|
||||||
|
|
||||||
if (config()->get("RememberLastKeyFiles").toBool()) {
|
if (config()->get("RememberLastKeyFiles").toBool()) {
|
||||||
QHash<QString, QVariant> lastKeyFiles = config()->get("LastKeyFiles").toHash();
|
QHash<QString, QVariant> lastKeyFiles = config()->get("LastKeyFiles").toHash();
|
||||||
if (lastKeyFiles.contains(m_filename)) {
|
if (lastKeyFiles.contains(m_filename)) {
|
||||||
m_ui->checkKeyFile->setChecked(true);
|
|
||||||
m_ui->comboKeyFile->addItem(lastKeyFiles[m_filename].toString());
|
m_ui->comboKeyFile->addItem(lastKeyFiles[m_filename].toString());
|
||||||
|
m_ui->comboKeyFile->setCurrentIndex(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,9 +171,6 @@ void DatabaseOpenWidget::clearForms()
|
||||||
m_ui->editPassword->setText("");
|
m_ui->editPassword->setText("");
|
||||||
m_ui->comboKeyFile->clear();
|
m_ui->comboKeyFile->clear();
|
||||||
m_ui->comboKeyFile->setEditText("");
|
m_ui->comboKeyFile->setEditText("");
|
||||||
m_ui->checkPassword->setChecked(false);
|
|
||||||
m_ui->checkKeyFile->setChecked(false);
|
|
||||||
m_ui->checkChallengeResponse->setChecked(false);
|
|
||||||
m_ui->checkTouchID->setChecked(false);
|
m_ui->checkTouchID->setChecked(false);
|
||||||
m_ui->buttonTogglePassword->setChecked(false);
|
m_ui->buttonTogglePassword->setChecked(false);
|
||||||
m_db.reset();
|
m_db.reset();
|
||||||
|
@ -174,6 +184,7 @@ QSharedPointer<Database> DatabaseOpenWidget::database()
|
||||||
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->comboKeyFile->setEditText(keyFile);
|
m_ui->comboKeyFile->setEditText(keyFile);
|
||||||
openDatabase();
|
openDatabase();
|
||||||
}
|
}
|
||||||
|
@ -194,6 +205,26 @@ void DatabaseOpenWidget::openDatabase()
|
||||||
bool ok = m_db->open(m_filename, masterKey, &error, false);
|
bool ok = m_db->open(m_filename, masterKey, &error, false);
|
||||||
QApplication::restoreOverrideCursor();
|
QApplication::restoreOverrideCursor();
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
|
if (m_ui->editPassword->text().isEmpty() && !m_retryUnlockWithEmptyPassword) {
|
||||||
|
QScopedPointer<QMessageBox> msgBox(new QMessageBox(this));
|
||||||
|
msgBox->setIcon(QMessageBox::Critical);
|
||||||
|
msgBox->setWindowTitle(tr("Unlock failed and no password given"));
|
||||||
|
msgBox->setText(tr("Unlocking the database failed and you did not enter a password.\n"
|
||||||
|
"Do you want to retry with an \"empty\" password instead?\n\n"
|
||||||
|
"To prevent this error from appearing, you must go to "
|
||||||
|
"\"Database Settings / Security\" and reset your password."));
|
||||||
|
auto btn = msgBox->addButton(tr("Retry with empty password"), QMessageBox::ButtonRole::AcceptRole);
|
||||||
|
msgBox->setDefaultButton(btn);
|
||||||
|
msgBox->addButton(QMessageBox::Cancel);
|
||||||
|
msgBox->exec();
|
||||||
|
|
||||||
|
if (msgBox->clickedButton() == btn) {
|
||||||
|
m_retryUnlockWithEmptyPassword = true;
|
||||||
|
openDatabase();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_retryUnlockWithEmptyPassword = false;
|
||||||
m_ui->messageWidget->showMessage(error, MessageWidget::MessageType::Error);
|
m_ui->messageWidget->showMessage(error, MessageWidget::MessageType::Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +267,7 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey()
|
||||||
{
|
{
|
||||||
auto masterKey = QSharedPointer<CompositeKey>::create();
|
auto masterKey = QSharedPointer<CompositeKey>::create();
|
||||||
|
|
||||||
if (m_ui->checkPassword->isChecked()) {
|
if (!m_ui->editPassword->text().isEmpty() || m_retryUnlockWithEmptyPassword) {
|
||||||
masterKey->addKey(QSharedPointer<PasswordKey>::create(m_ui->editPassword->text()));
|
masterKey->addKey(QSharedPointer<PasswordKey>::create(m_ui->editPassword->text()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,11 +291,11 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QHash<QString, QVariant> lastKeyFiles = config()->get("LastKeyFiles").toHash();
|
QHash<QString, QVariant> lastKeyFiles = config()->get("LastKeyFiles").toHash();
|
||||||
QHash<QString, QVariant> lastChallengeResponse = config()->get("LastChallengeResponse").toHash();
|
lastKeyFiles.remove(m_filename);
|
||||||
|
|
||||||
if (m_ui->checkKeyFile->isChecked()) {
|
|
||||||
auto key = QSharedPointer<FileKey>::create();
|
auto key = QSharedPointer<FileKey>::create();
|
||||||
QString keyFilename = m_ui->comboKeyFile->currentText();
|
QString keyFilename = m_ui->comboKeyFile->currentText();
|
||||||
|
if (!m_ui->comboKeyFile->currentText().isEmpty() && m_keyFileComboEdited) {
|
||||||
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);
|
||||||
|
@ -281,7 +312,8 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey()
|
||||||
legacyWarning.setDefaultButton(QMessageBox::Ok);
|
legacyWarning.setDefaultButton(QMessageBox::Ok);
|
||||||
legacyWarning.setCheckBox(new QCheckBox(tr("Don't show this warning again")));
|
legacyWarning.setCheckBox(new QCheckBox(tr("Don't show this warning again")));
|
||||||
|
|
||||||
connect(legacyWarning.checkBox(), &QCheckBox::stateChanged, [](int state) {
|
connect(legacyWarning.checkBox(), &QCheckBox::stateChanged, [](int state)
|
||||||
|
{
|
||||||
config()->set("Messages/NoLegacyKeyFileWarning", state == Qt::CheckState::Checked);
|
config()->set("Messages/NoLegacyKeyFileWarning", state == Qt::CheckState::Checked);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -289,14 +321,6 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey()
|
||||||
}
|
}
|
||||||
masterKey->addKey(key);
|
masterKey->addKey(key);
|
||||||
lastKeyFiles[m_filename] = keyFilename;
|
lastKeyFiles[m_filename] = keyFilename;
|
||||||
} else {
|
|
||||||
lastKeyFiles.remove(m_filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ui->checkChallengeResponse->isChecked()) {
|
|
||||||
lastChallengeResponse[m_filename] = true;
|
|
||||||
} else {
|
|
||||||
lastChallengeResponse.remove(m_filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config()->get("RememberLastKeyFiles").toBool()) {
|
if (config()->get("RememberLastKeyFiles").toBool()) {
|
||||||
|
@ -304,19 +328,23 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_XC_YUBIKEY
|
#ifdef WITH_XC_YUBIKEY
|
||||||
if (config()->get("RememberLastKeyFiles").toBool()) {
|
QHash<QString, QVariant> lastChallengeResponse = config()->get("LastChallengeResponse").toHash();
|
||||||
config()->set("LastChallengeResponse", lastChallengeResponse);
|
lastChallengeResponse.remove(m_filename);
|
||||||
}
|
|
||||||
|
|
||||||
if (m_ui->checkChallengeResponse->isChecked()) {
|
|
||||||
int selectionIndex = m_ui->comboChallengeResponse->currentIndex();
|
int selectionIndex = m_ui->comboChallengeResponse->currentIndex();
|
||||||
|
if (selectionIndex > 0) {
|
||||||
int comboPayload = m_ui->comboChallengeResponse->itemData(selectionIndex).toInt();
|
int comboPayload = m_ui->comboChallengeResponse->itemData(selectionIndex).toInt();
|
||||||
|
|
||||||
// read blocking mode from LSB and slot index number from second LSB
|
// read blocking mode from LSB and slot index number from second LSB
|
||||||
bool blocking = comboPayload & 1;
|
bool blocking = comboPayload & 1;
|
||||||
int slot = comboPayload >> 1;
|
int slot = comboPayload >> 1;
|
||||||
auto key = QSharedPointer<YkChallengeResponseKey>(new YkChallengeResponseKey(slot, blocking));
|
auto crKey = QSharedPointer<YkChallengeResponseKey>(new YkChallengeResponseKey(slot, blocking));
|
||||||
masterKey->addChallengeResponseKey(key);
|
masterKey->addChallengeResponseKey(crKey);
|
||||||
|
lastChallengeResponse[m_filename] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config()->get("RememberLastKeyFiles").toBool()) {
|
||||||
|
config()->set("LastChallengeResponse", lastChallengeResponse);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -328,24 +356,6 @@ void DatabaseOpenWidget::reject()
|
||||||
emit dialogFinished(false);
|
emit dialogFinished(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseOpenWidget::activatePassword()
|
|
||||||
{
|
|
||||||
bool hasPassword = !m_ui->editPassword->text().isEmpty();
|
|
||||||
m_ui->checkPassword->setChecked(hasPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatabaseOpenWidget::activateKeyFile()
|
|
||||||
{
|
|
||||||
bool hasKeyFile = !m_ui->comboKeyFile->lineEdit()->text().isEmpty();
|
|
||||||
m_ui->checkKeyFile->setChecked(hasKeyFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatabaseOpenWidget::activateChallengeResponse()
|
|
||||||
{
|
|
||||||
bool hasCR = m_ui->comboChallengeResponse->currentData().toInt() != -1;
|
|
||||||
m_ui->checkChallengeResponse->setChecked(hasCR);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatabaseOpenWidget::browseKeyFile()
|
void DatabaseOpenWidget::browseKeyFile()
|
||||||
{
|
{
|
||||||
QString filters = QString("%1 (*);;%2 (*.key)").arg(tr("All files"), tr("Key files"));
|
QString filters = QString("%1 (*);;%2 (*.key)").arg(tr("All files"), tr("Key files"));
|
||||||
|
@ -355,15 +365,33 @@ void DatabaseOpenWidget::browseKeyFile()
|
||||||
QString filename = fileDialog()->getOpenFileName(this, tr("Select key file"), QString(), filters);
|
QString filename = fileDialog()->getOpenFileName(this, tr("Select key file"), QString(), filters);
|
||||||
|
|
||||||
if (!filename.isEmpty()) {
|
if (!filename.isEmpty()) {
|
||||||
m_ui->comboKeyFile->lineEdit()->setText(filename);
|
m_ui->comboKeyFile->setCurrentIndex(-1);
|
||||||
|
m_ui->comboKeyFile->setEditText(filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DatabaseOpenWidget::clearKeyFileEdit()
|
||||||
|
{
|
||||||
|
m_ui->comboKeyFile->setCurrentIndex(0);
|
||||||
|
// make sure that handler is called even if 0 was the current index already
|
||||||
|
handleKeyFileComboChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseOpenWidget::handleKeyFileComboEdited()
|
||||||
|
{
|
||||||
|
m_keyFileComboEdited = true;
|
||||||
|
m_ui->keyFileClearIcon->setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabaseOpenWidget::handleKeyFileComboChanged()
|
||||||
|
{
|
||||||
|
m_keyFileComboEdited = m_ui->comboKeyFile->currentIndex() != 0;
|
||||||
|
m_ui->keyFileClearIcon->setVisible(m_keyFileComboEdited);
|
||||||
|
}
|
||||||
|
|
||||||
void DatabaseOpenWidget::pollYubikey()
|
void DatabaseOpenWidget::pollYubikey()
|
||||||
{
|
{
|
||||||
m_ui->buttonRedetectYubikey->setEnabled(false);
|
m_ui->buttonRedetectYubikey->setEnabled(false);
|
||||||
m_ui->checkChallengeResponse->setEnabled(false);
|
|
||||||
m_ui->checkChallengeResponse->setChecked(false);
|
|
||||||
m_ui->comboChallengeResponse->setEnabled(false);
|
m_ui->comboChallengeResponse->setEnabled(false);
|
||||||
m_ui->comboChallengeResponse->clear();
|
m_ui->comboChallengeResponse->clear();
|
||||||
m_ui->comboChallengeResponse->addItem(tr("Select slot..."), -1);
|
m_ui->comboChallengeResponse->addItem(tr("Select slot..."), -1);
|
||||||
|
@ -382,7 +410,6 @@ void DatabaseOpenWidget::yubikeyDetected(int slot, bool blocking)
|
||||||
if (config()->get("RememberLastKeyFiles").toBool()) {
|
if (config()->get("RememberLastKeyFiles").toBool()) {
|
||||||
QHash<QString, QVariant> lastChallengeResponse = config()->get("LastChallengeResponse").toHash();
|
QHash<QString, QVariant> lastChallengeResponse = config()->get("LastChallengeResponse").toHash();
|
||||||
if (lastChallengeResponse.contains(m_filename)) {
|
if (lastChallengeResponse.contains(m_filename)) {
|
||||||
m_ui->checkChallengeResponse->setChecked(true);
|
|
||||||
m_ui->comboChallengeResponse->setCurrentIndex(1);
|
m_ui->comboChallengeResponse->setCurrentIndex(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -391,7 +418,6 @@ void DatabaseOpenWidget::yubikeyDetected(int slot, bool blocking)
|
||||||
void DatabaseOpenWidget::yubikeyDetectComplete()
|
void DatabaseOpenWidget::yubikeyDetectComplete()
|
||||||
{
|
{
|
||||||
m_ui->comboChallengeResponse->setEnabled(true);
|
m_ui->comboChallengeResponse->setEnabled(true);
|
||||||
m_ui->checkChallengeResponse->setEnabled(true);
|
|
||||||
m_ui->buttonRedetectYubikey->setEnabled(true);
|
m_ui->buttonRedetectYubikey->setEnabled(true);
|
||||||
m_ui->yubikeyProgress->setVisible(false);
|
m_ui->yubikeyProgress->setVisible(false);
|
||||||
m_yubiKeyBeingPolled = false;
|
m_yubiKeyBeingPolled = false;
|
||||||
|
@ -403,3 +429,8 @@ void DatabaseOpenWidget::noYubikeyFound()
|
||||||
m_ui->yubikeyProgress->setVisible(false);
|
m_ui->yubikeyProgress->setVisible(false);
|
||||||
m_yubiKeyBeingPolled = false;
|
m_yubiKeyBeingPolled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DatabaseOpenWidget::openHardwareKeyHelp()
|
||||||
|
{
|
||||||
|
QDesktopServices::openUrl(QUrl("https://keepassxc.org/docs#hwtoken"));
|
||||||
|
}
|
|
@ -60,21 +60,24 @@ protected slots:
|
||||||
void reject();
|
void reject();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void activatePassword();
|
|
||||||
void activateKeyFile();
|
|
||||||
void activateChallengeResponse();
|
|
||||||
void browseKeyFile();
|
void browseKeyFile();
|
||||||
|
void clearKeyFileEdit();
|
||||||
|
void handleKeyFileComboEdited();
|
||||||
|
void handleKeyFileComboChanged();
|
||||||
void yubikeyDetected(int slot, bool blocking);
|
void yubikeyDetected(int slot, bool blocking);
|
||||||
void yubikeyDetectComplete();
|
void yubikeyDetectComplete();
|
||||||
void noYubikeyFound();
|
void noYubikeyFound();
|
||||||
|
void openHardwareKeyHelp();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const QScopedPointer<Ui::DatabaseOpenWidget> m_ui;
|
const QScopedPointer<Ui::DatabaseOpenWidget> m_ui;
|
||||||
QSharedPointer<Database> m_db;
|
QSharedPointer<Database> m_db;
|
||||||
QString m_filename;
|
QString m_filename;
|
||||||
|
bool m_retryUnlockWithEmptyPassword = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_yubiKeyBeingPolled = false;
|
bool m_yubiKeyBeingPolled = false;
|
||||||
|
bool m_keyFileComboEdited = false;
|
||||||
Q_DISABLE_COPY(DatabaseOpenWidget)
|
Q_DISABLE_COPY(DatabaseOpenWidget)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>841</width>
|
<width>592</width>
|
||||||
<height>467</height>
|
<height>462</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<property name="accessibleName">
|
||||||
<property name="spacing">
|
<string>Unlock KePassXC Database</string>
|
||||||
<number>8</number>
|
|
||||||
</property>
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0,2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="MessageWidget" name="messageWidget" native="true"/>
|
<widget class="MessageWidget" name="messageWidget" native="true"/>
|
||||||
</item>
|
</item>
|
||||||
|
@ -22,36 +22,174 @@
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||||
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<width>20</width>
|
||||||
<height>40</height>
|
<height>5</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="labelLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,1,0">
|
||||||
<property name="leftMargin">
|
<property name="spacing">
|
||||||
<number>5</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="sizeConstraint">
|
||||||
<number>5</number>
|
<enum>QLayout::SetDefaultConstraint</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="formContainer" native="true">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>700</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="labelHeadline">
|
<widget class="QLabel" name="labelHeadline">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enter master key</string>
|
<string>Unlock KeePassXC Database</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="labelFilename"/>
|
<widget class="ElidedLabel" name="fileNameLabel">
|
||||||
</item>
|
<property name="text">
|
||||||
</layout>
|
<string>filename.kdbx</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_3">
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>439</width>
|
||||||
|
<height>13</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="horizontalFrame">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>550</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>20</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>15</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>20</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>15</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="verticalFrame">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>400</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>700</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Enter Password:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>editPassword</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="passwordLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="PasswordEdit" name="editPassword">
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Password field</string>
|
||||||
|
</property>
|
||||||
|
<property name="echoMode">
|
||||||
|
<enum>QLineEdit::Password</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="buttonTogglePassword">
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Toggle password visibility</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_4">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -61,42 +199,53 @@
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<width>20</width>
|
||||||
|
<height>5</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Enter Additional Credentials:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>15</width>
|
||||||
<height>20</height>
|
<height>20</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
<property name="leftMargin">
|
<property name="sizeConstraint">
|
||||||
<number>5</number>
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<property name="verticalSpacing">
|
<property name="verticalSpacing">
|
||||||
<number>8</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="1" column="0" alignment="Qt::AlignVCenter">
|
<item row="0" column="1">
|
||||||
<widget class="QCheckBox" name="checkKeyFile">
|
|
||||||
<property name="text">
|
|
||||||
<string>Key File:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0" alignment="Qt::AlignVCenter">
|
|
||||||
<widget class="QCheckBox" name="checkPassword">
|
|
||||||
<property name="text">
|
|
||||||
<string>Password:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<layout class="QHBoxLayout" name="keyFileLayout">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="comboKeyFile">
|
<widget class="QComboBox" name="comboKeyFile">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
@ -107,82 +256,22 @@
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Key file selection</string>
|
||||||
|
</property>
|
||||||
<property name="editable">
|
<property name="editable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="buttonBrowseFile">
|
|
||||||
<property name="text">
|
|
||||||
<string>Browse</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="1" column="3">
|
||||||
<layout class="QHBoxLayout" name="passwordLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<property name="leftMargin">
|
<property name="spacing">
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="PasswordEdit" name="editPassword">
|
|
||||||
<property name="echoMode">
|
|
||||||
<enum>QLineEdit::Password</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="buttonTogglePassword">
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="2">
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="verticalSpacing">
|
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="1">
|
<item row="1" column="2">
|
||||||
<widget class="QPushButton" name="buttonRedetectYubikey">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Refresh</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QComboBox" name="comboChallengeResponse">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="editable">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QProgressBar" name="yubikeyProgress">
|
<widget class="QProgressBar" name="yubikeyProgress">
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
|
@ -204,47 +293,158 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item row="0" column="2">
|
||||||
</item>
|
<widget class="QComboBox" name="comboChallengeResponse">
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QCheckBox" name="checkChallengeResponse">
|
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="sizePolicy">
|
||||||
<string>Challenge Response:</string>
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Hardware key slot selection</string>
|
||||||
|
</property>
|
||||||
|
<property name="editable">
|
||||||
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
</layout>
|
||||||
<widget class="QCheckBox" name="checkTouchID">
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QPushButton" name="buttonBrowseFile">
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Browse for key file</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>TouchID for quick unlock</string>
|
<string>Browse...</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2">
|
<item row="1" column="4">
|
||||||
<spacer name="verticalSpacer_4">
|
<widget class="QPushButton" name="buttonRedetectYubikey">
|
||||||
<property name="orientation">
|
<property name="enabled">
|
||||||
<enum>Qt::Vertical</enum>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="accessibleName">
|
||||||
|
<string>Refresh hardware tokens</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Refresh</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="hardwareKeyLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Hardware Key:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>comboChallengeResponse</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="hardwareKeyLabelHelp">
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>PointingHandCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><p>You can use a hardware security key such as a <strong>YubiKey</strong> or <strong>OnlyKey</strong> with slots configured for HMAC-SHA1.</p>
|
||||||
|
<p>Click for more information...</p></string>
|
||||||
|
</property>
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Hardware key help</string>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QToolButton {
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>?</string>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<width>12</width>
|
||||||
<height>40</height>
|
<height>12</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
<property name="popupMode">
|
||||||
|
<enum>QToolButton::InstantPopup</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="keyFileLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Key File:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>comboKeyFile</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="dialogButtonsLayout">
|
<widget class="QWidget" name="touchIDContainer" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="touchIDLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>5</number>
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>5</number>
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkTouchID">
|
||||||
|
<property name="text">
|
||||||
|
<string>TouchID for Quick Unlock</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="dialogButtonsLayout">
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>15</number>
|
||||||
</property>
|
</property>
|
||||||
<item alignment="Qt::AlignRight">
|
<item alignment="Qt::AlignRight">
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
@ -255,20 +455,58 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="horizontalSpacer_4">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<width>0</width>
|
||||||
<height>40</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>55</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
<action name="keyFileClearIcon">
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Clear Key File</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
@ -282,14 +520,21 @@
|
||||||
<header>gui/MessageWidget.h</header>
|
<header>gui/MessageWidget.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>ElidedLabel</class>
|
||||||
|
<extends>QLabel</extends>
|
||||||
|
<header>gui/widgets/ElidedLabel.h</header>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>checkPassword</tabstop>
|
|
||||||
<tabstop>editPassword</tabstop>
|
<tabstop>editPassword</tabstop>
|
||||||
<tabstop>buttonTogglePassword</tabstop>
|
<tabstop>buttonTogglePassword</tabstop>
|
||||||
<tabstop>checkKeyFile</tabstop>
|
|
||||||
<tabstop>comboKeyFile</tabstop>
|
<tabstop>comboKeyFile</tabstop>
|
||||||
<tabstop>buttonBrowseFile</tabstop>
|
<tabstop>buttonBrowseFile</tabstop>
|
||||||
|
<tabstop>hardwareKeyLabelHelp</tabstop>
|
||||||
|
<tabstop>comboChallengeResponse</tabstop>
|
||||||
|
<tabstop>buttonRedetectYubikey</tabstop>
|
||||||
|
<tabstop>checkTouchID</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
KeePass1OpenWidget::KeePass1OpenWidget(QWidget* parent)
|
KeePass1OpenWidget::KeePass1OpenWidget(QWidget* parent)
|
||||||
: DatabaseOpenWidget(parent)
|
: DatabaseOpenWidget(parent)
|
||||||
{
|
{
|
||||||
m_ui->labelHeadline->setText(tr("Import KeePass1 database"));
|
m_ui->labelHeadline->setText(tr("Import KeePass1 Database"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeePass1OpenWidget::openDatabase()
|
void KeePass1OpenWidget::openDatabase()
|
||||||
|
@ -39,11 +39,11 @@ void KeePass1OpenWidget::openDatabase()
|
||||||
QString password;
|
QString password;
|
||||||
QString keyFileName;
|
QString keyFileName;
|
||||||
|
|
||||||
if (m_ui->checkPassword->isChecked()) {
|
if (!m_ui->editPassword->text().isEmpty() || m_retryUnlockWithEmptyPassword) {
|
||||||
password = m_ui->editPassword->text();
|
password = m_ui->editPassword->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_ui->checkKeyFile->isChecked()) {
|
if (!m_ui->comboKeyFile->currentText().isEmpty() && m_ui->comboKeyFile->currentData() != -1) {
|
||||||
keyFileName = m_ui->comboKeyFile->currentText();
|
keyFileName = m_ui->comboKeyFile->currentText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
OpVaultOpenWidget::OpVaultOpenWidget(QWidget* parent)
|
OpVaultOpenWidget::OpVaultOpenWidget(QWidget* parent)
|
||||||
: DatabaseOpenWidget(parent)
|
: DatabaseOpenWidget(parent)
|
||||||
{
|
{
|
||||||
m_ui->labelHeadline->setText("Import 1Password database");
|
m_ui->labelHeadline->setText("Import 1Password Database");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpVaultOpenWidget::openDatabase()
|
void OpVaultOpenWidget::openDatabase()
|
||||||
|
@ -36,9 +36,7 @@ void OpVaultOpenWidget::openDatabase()
|
||||||
OpVaultReader reader;
|
OpVaultReader reader;
|
||||||
|
|
||||||
QString password;
|
QString password;
|
||||||
if (m_ui->checkPassword->isChecked()) {
|
|
||||||
password = m_ui->editPassword->text();
|
password = m_ui->editPassword->text();
|
||||||
}
|
|
||||||
|
|
||||||
QDir opVaultDir(m_filename);
|
QDir opVaultDir(m_filename);
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,21 @@ bool DatabaseSettingsWidgetMasterKey::save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!addToCompositeKey(m_passwordEditWidget, newKey, oldPasswordKey)) {
|
if (m_passwordEditWidget->visiblePage() == KeyComponentWidget::Page::AddNew || m_passwordEditWidget->isEmpty()) {
|
||||||
|
QScopedPointer<QMessageBox> msgBox(new QMessageBox(this));
|
||||||
|
msgBox->setIcon(QMessageBox::Warning);
|
||||||
|
msgBox->setWindowTitle(tr("No password set"));
|
||||||
|
msgBox->setText(tr("WARNING! You have not set a password. Using a database without "
|
||||||
|
"a password is strongly discouraged!\n\n"
|
||||||
|
"Are you sure you want to continue without a password?"));
|
||||||
|
auto btn = msgBox->addButton(tr("Continue without password"), QMessageBox::ButtonRole::AcceptRole);
|
||||||
|
msgBox->addButton(QMessageBox::Cancel);
|
||||||
|
msgBox->setDefaultButton(QMessageBox::Cancel);
|
||||||
|
msgBox->exec();
|
||||||
|
if (msgBox->clickedButton() != btn) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!addToCompositeKey(m_passwordEditWidget, newKey, oldPasswordKey)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,19 +192,6 @@ bool DatabaseSettingsWidgetMasterKey::save()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_passwordEditWidget->isEmpty()) {
|
|
||||||
auto answer = MessageBox::warning(this,
|
|
||||||
tr("No password set"),
|
|
||||||
tr("WARNING! You have not set a password. Using a database without "
|
|
||||||
"a password is strongly discouraged!\n\n"
|
|
||||||
"Are you sure you want to continue without a password?"),
|
|
||||||
MessageBox::Yes | MessageBox::Cancel,
|
|
||||||
MessageBox::Cancel);
|
|
||||||
if (answer != MessageBox::Yes) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_db->setKey(newKey, true, false, false);
|
m_db->setKey(newKey, true, false, false);
|
||||||
|
|
||||||
emit editFinished(true);
|
emit editFinished(true);
|
||||||
|
|
|
@ -43,8 +43,9 @@ bool PasswordEditWidget::addToCompositeKey(QSharedPointer<CompositeKey> key)
|
||||||
QString pw = m_compUi->enterPasswordEdit->text();
|
QString pw = m_compUi->enterPasswordEdit->text();
|
||||||
if (!pw.isEmpty()) {
|
if (!pw.isEmpty()) {
|
||||||
key->addKey(QSharedPointer<PasswordKey>::create(pw));
|
key->addKey(QSharedPointer<PasswordKey>::create(pw));
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue