diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f68afc8f6..f8e7b2269 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -123,8 +123,7 @@ set(keepassx_SOURCES gui/TotpSetupDialog.cpp gui/TotpDialog.cpp gui/TotpExportSettingsDialog.cpp - gui/UnlockDatabaseWidget.cpp - gui/UnlockDatabaseDialog.cpp + gui/DatabaseOpenDialog.cpp gui/WelcomeWidget.cpp gui/csvImport/CsvImportWidget.cpp gui/csvImport/CsvImportWizard.cpp diff --git a/src/gui/DatabaseOpenDialog.cpp b/src/gui/DatabaseOpenDialog.cpp new file mode 100644 index 000000000..1b8b018e2 --- /dev/null +++ b/src/gui/DatabaseOpenDialog.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2018 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "DatabaseOpenDialog.h" +#include "DatabaseOpenWidget.h" +#include "DatabaseWidget.h" +#include "core/Database.h" + +DatabaseOpenDialog::DatabaseOpenDialog(QWidget* parent) + : QDialog(parent) + , m_view(new DatabaseOpenWidget(this)) +{ + setWindowTitle(tr("Unlock Database - KeePassXC")); + setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint | Qt::ForeignWindow); + connect(m_view, SIGNAL(dialogFinished(bool)), this, SLOT(complete(bool))); +} + +void DatabaseOpenDialog::setFilePath(const QString& filePath) +{ + m_view->load(filePath); +} + +/** + * Set target DatabaseWidget to which signals are connected. + * + * @param dbWidget database widget + */ +void DatabaseOpenDialog::setTargetDatabaseWidget(DatabaseWidget* dbWidget) +{ + if (m_dbWidget) { + disconnect(this, nullptr, m_dbWidget, nullptr); + } + m_dbWidget = dbWidget; + connect(this, SIGNAL(dialogFinished(bool)), dbWidget, SLOT(unlockDatabase(bool))); +} + +void DatabaseOpenDialog::setIntent(DatabaseOpenDialog::Intent intent) +{ + m_intent = intent; +} + +DatabaseOpenDialog::Intent DatabaseOpenDialog::intent() const +{ + return m_intent; +} + +void DatabaseOpenDialog::clearForms() +{ + m_view->clearForms(); + m_db.reset(); + m_intent = Intent::None; + if (m_dbWidget) { + disconnect(this, nullptr, m_dbWidget, nullptr); + m_dbWidget = nullptr; + } +} + +QSharedPointer DatabaseOpenDialog::database() +{ + return m_db; +} + +void DatabaseOpenDialog::complete(bool accepted) +{ + // save DB, since DatabaseOpenWidget will reset its data after accept() is called + m_db = m_view->database(); + + if (accepted) { + accept(); + } else { + reject(); + } + emit dialogFinished(accepted); + clearForms(); +} diff --git a/src/gui/UnlockDatabaseDialog.h b/src/gui/DatabaseOpenDialog.h similarity index 60% rename from src/gui/UnlockDatabaseDialog.h rename to src/gui/DatabaseOpenDialog.h index 7f06029c8..236d2e0c2 100644 --- a/src/gui/UnlockDatabaseDialog.h +++ b/src/gui/DatabaseOpenDialog.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 KeePassXC Team + * Copyright (C) 2018 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,32 +18,47 @@ #ifndef KEEPASSX_AUTOTYPEUNLOCKDIALOG_H #define KEEPASSX_AUTOTYPEUNLOCKDIALOG_H -#include - -//#include - #include "core/Global.h" -class UnlockDatabaseWidget; -class Database; +#include +#include +#include -class UnlockDatabaseDialog : public QDialog +class Database; +class DatabaseWidget; +class DatabaseOpenWidget; + +class DatabaseOpenDialog : public QDialog { Q_OBJECT + public: - explicit UnlockDatabaseDialog(QWidget* parent = nullptr); + enum class Intent + { + None, + AutoType, + Merge + }; + + explicit DatabaseOpenDialog(QWidget* parent = nullptr); void setFilePath(const QString& filePath); - void clearForms(); + void setTargetDatabaseWidget(DatabaseWidget* dbWidget); + void setIntent(Intent intent); + Intent intent() const; QSharedPointer database(); + void clearForms(); signals: - void unlockDone(bool); + void dialogFinished(bool); public slots: - void complete(bool r); + void complete(bool accepted); private: - UnlockDatabaseWidget* const m_view; + QPointer m_view; + QSharedPointer m_db; + QPointer m_dbWidget; + Intent m_intent = Intent::None; }; #endif // KEEPASSX_AUTOTYPEUNLOCKDIALOG_H diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 7f1f9942e..c7d752bd2 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -28,6 +28,7 @@ #include "core/Global.h" #include "core/Group.h" #include "core/Metadata.h" +#include "core/Tools.h" #include "format/CsvExporter.h" #include "gui/Clipboard.h" #include "gui/DatabaseWidget.h" @@ -35,7 +36,7 @@ #include "gui/DragTabBar.h" #include "gui/FileDialog.h" #include "gui/MessageBox.h" -#include "gui/UnlockDatabaseDialog.h" +#include "gui/DatabaseOpenDialog.h" #include "gui/entry/EntryView.h" #include "gui/group/GroupView.h" #include "gui/wizard/NewDatabaseWizard.h" @@ -43,7 +44,8 @@ DatabaseTabWidget::DatabaseTabWidget(QWidget* parent) : QTabWidget(parent) , m_dbWidgetStateSync(new DatabaseWidgetStateSync(this)) - , m_dbPendingLock(nullptr) + , m_dbWidgetPendingLock(nullptr) + , m_databaseOpenDialog(new DatabaseOpenDialog()) { auto* tabBar = new DragTabBar(this); setTabBar(tabBar); @@ -54,6 +56,7 @@ DatabaseTabWidget::DatabaseTabWidget(QWidget* parent) connect(this, SIGNAL(activateDatabaseChanged(DatabaseWidget*)), m_dbWidgetStateSync, SLOT(setActive(DatabaseWidget*))); connect(autoType(), SIGNAL(globalShortcutTriggered()), SLOT(performGlobalAutoType())); connect(autoType(), SIGNAL(autotypePerformed()), SLOT(relockPendingDatabase())); + connect(autoType(), SIGNAL(autotypeRejected()), SLOT(relockPendingDatabase())); } DatabaseTabWidget::~DatabaseTabWidget() @@ -220,9 +223,9 @@ void DatabaseTabWidget::mergeDatabase() } } -void DatabaseTabWidget::mergeDatabase(const QString& fileName) +void DatabaseTabWidget::mergeDatabase(const QString& filePath) { - currentDatabaseWidget()->switchToOpenMergeDatabase(fileName); + unlockDatabaseInDialog(currentDatabaseWidget(), DatabaseOpenDialog::Intent::Merge, filePath); } void DatabaseTabWidget::importKeePass1Database() @@ -513,23 +516,60 @@ void DatabaseTabWidget::lockDatabases() } } +/** + * Unlock a database with an unlock popup dialog. + * + * @param dbWidget DatabaseWidget which to connect signals to + * @param intent intent for unlocking + */ +void DatabaseTabWidget::unlockDatabaseInDialog(DatabaseWidget* dbWidget, DatabaseOpenDialog::Intent intent) +{ + unlockDatabaseInDialog(dbWidget, intent, dbWidget->database()->filePath()); +} + +/** + * Unlock a database with an unlock popup dialog. + * + * @param dbWidget DatabaseWidget which to connect signals to + * @param intent intent for unlocking + * @param file path of the database to be unlocked + */ +void DatabaseTabWidget::unlockDatabaseInDialog(DatabaseWidget* dbWidget, DatabaseOpenDialog::Intent intent, + const QString& filePath) +{ + m_databaseOpenDialog->setTargetDatabaseWidget(dbWidget); + m_databaseOpenDialog->setIntent(intent); + m_databaseOpenDialog->setFilePath(filePath); + +#ifdef Q_OS_MACOS + if (intent == DatabaseOpenDialog::Intent::AutoType) { + autoType()->raiseWindow(); + Tools::wait(500); + } +#endif + + m_databaseOpenDialog->show(); + m_databaseOpenDialog->raise(); + m_databaseOpenDialog->activateWindow(); +} + /** * This function relock the pending database when autotype has been performed successfully * A database is marked as pending when it's unlocked after a global Auto-Type invocation */ void DatabaseTabWidget::relockPendingDatabase() { - if (!m_dbPendingLock || !config()->get("security/relockautotype").toBool()) { + if (!m_dbWidgetPendingLock || !config()->get("security/relockautotype").toBool()) { return; } - if (m_dbPendingLock->isLocked() || !m_dbPendingLock->database()->hasKey()) { - m_dbPendingLock = nullptr; + if (m_dbWidgetPendingLock->isLocked() || !m_dbWidgetPendingLock->database()->hasKey()) { + m_dbWidgetPendingLock = nullptr; return; } - m_dbPendingLock->lock(); - m_dbPendingLock = nullptr; + m_dbWidgetPendingLock->lock(); + m_dbWidgetPendingLock = nullptr; } void DatabaseTabWidget::updateLastDatabases(const QString& filename) @@ -579,11 +619,13 @@ void DatabaseTabWidget::performGlobalAutoType() } } + // TODO: allow for database selection during Auto-Type instead of using the current tab if (!unlockedDatabases.isEmpty()) { autoType()->performGlobalAutoType(unlockedDatabases); } else if (count() > 0) { - // TODO: allow for database selection during Auto-Type instead of using the first tab - m_dbPendingLock = databaseWidgetFromIndex(0); - m_dbPendingLock->prepareUnlock(); + if (config()->get("security/relockautotype").toBool()) { + m_dbWidgetPendingLock = currentDatabaseWidget(); + } + unlockDatabaseInDialog(currentDatabaseWidget(), DatabaseOpenDialog::Intent::AutoType); } } diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index f9d4bdf15..a659e4fe6 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -19,6 +19,7 @@ #define KEEPASSX_DATABASETABWIDGET_H #include "gui/MessageWidget.h" +#include "DatabaseOpenDialog.h" #include #include @@ -27,7 +28,6 @@ class Database; class DatabaseWidget; class DatabaseWidgetStateSync; class DatabaseOpenWidget; -class QFile; class DatabaseTabWidget : public QTabWidget { @@ -68,6 +68,8 @@ public slots: void lockDatabases(); void closeDatabaseFromSender(); + void unlockDatabaseInDialog(DatabaseWidget* dbWidget, DatabaseOpenDialog::Intent intent); + void unlockDatabaseInDialog(DatabaseWidget* dbWidget, DatabaseOpenDialog::Intent intent, const QString& filePath); void relockPendingDatabase(); void changeMasterKey(); @@ -93,7 +95,8 @@ private: void updateLastDatabases(const QString& filename); QPointer m_dbWidgetStateSync; - QPointer m_dbPendingLock; + QPointer m_dbWidgetPendingLock; + QScopedPointer m_databaseOpenDialog; }; #endif // KEEPASSX_DATABASETABWIDGET_H diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 782c9b83f..35beb5368 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -45,6 +45,7 @@ #include "gui/Clipboard.h" #include "gui/CloneDialog.h" #include "gui/DatabaseOpenWidget.h" +#include "gui/DatabaseOpenDialog.h" #include "gui/dbsettings/DatabaseSettingsDialog.h" #include "gui/EntryPreviewWidget.h" #include "gui/KeePass1OpenWidget.h" @@ -52,8 +53,6 @@ #include "gui/TotpSetupDialog.h" #include "gui/TotpDialog.h" #include "gui/TotpExportSettingsDialog.h" -#include "gui/UnlockDatabaseDialog.h" -#include "gui/UnlockDatabaseWidget.h" #include "gui/entry/EditEntryWidget.h" #include "gui/entry/EntryView.h" #include "gui/group/EditGroupWidget.h" @@ -86,16 +85,8 @@ DatabaseWidget::DatabaseWidget(QSharedPointer db, QWidget* parent) , m_historyEditEntryWidget(new EditEntryWidget(this)) , m_databaseSettingDialog(new DatabaseSettingsDialog(this)) , m_databaseOpenWidget(new DatabaseOpenWidget(this)) - , m_databaseOpenMergeWidget(new DatabaseOpenWidget(this)) , m_keepass1OpenWidget(new KeePass1OpenWidget(this)) - , m_unlockDatabaseWidget(new UnlockDatabaseWidget(this)) - , m_unlockDatabaseDialog(new UnlockDatabaseDialog(this)) , m_groupView(new GroupView(m_db.data(), m_mainSplitter)) - , m_entryView(nullptr) - - , m_newGroup() - , m_newEntry() - , m_newParent() { m_messageWidget->setHidden(true); @@ -153,10 +144,7 @@ DatabaseWidget::DatabaseWidget(QSharedPointer db, QWidget* parent) m_csvImportWizard->setObjectName("csvImportWizard"); m_databaseSettingDialog->setObjectName("databaseSettingsDialog"); m_databaseOpenWidget->setObjectName("databaseOpenWidget"); - m_databaseOpenMergeWidget->setObjectName("databaseOpenMergeWidget"); m_keepass1OpenWidget->setObjectName("keepass1OpenWidget"); - m_unlockDatabaseWidget->setObjectName("unlockDatabaseWidget"); - m_unlockDatabaseDialog->setObjectName("unlockDatabaseDialog"); addChildWidget(m_mainWidget); addChildWidget(m_editEntryWidget); @@ -165,9 +153,7 @@ DatabaseWidget::DatabaseWidget(QSharedPointer db, QWidget* parent) addChildWidget(m_historyEditEntryWidget); addChildWidget(m_databaseOpenWidget); addChildWidget(m_csvImportWizard); - addChildWidget(m_databaseOpenMergeWidget); addChildWidget(m_keepass1OpenWidget); - addChildWidget(m_unlockDatabaseWidget); connect(m_mainSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(mainSplitterSizesChanged())); connect(m_previewSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(previewSplitterSizesChanged())); @@ -181,17 +167,14 @@ DatabaseWidget::DatabaseWidget(QSharedPointer db, QWidget* parent) connect(m_entryView, SIGNAL(entryActivated(Entry*,EntryModel::ModelColumn)), SLOT(entryActivationSignalReceived(Entry*,EntryModel::ModelColumn))); connect(m_entryView, SIGNAL(entrySelectionChanged()), SIGNAL(entrySelectionChanged())); - connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool))); + connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchToMainView(bool))); connect(m_editEntryWidget, SIGNAL(historyEntryActivated(Entry*)), SLOT(switchToHistoryView(Entry*))); connect(m_historyEditEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchBackToEntryEdit())); - connect(m_editGroupWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool))); - connect(m_databaseSettingDialog, SIGNAL(editFinished(bool)), SLOT(switchToView(bool))); + connect(m_editGroupWidget, SIGNAL(editFinished(bool)), SLOT(switchToMainView(bool))); + connect(m_databaseSettingDialog, SIGNAL(editFinished(bool)), SLOT(switchToMainView(bool))); connect(m_databaseOpenWidget, SIGNAL(dialogFinished(bool)), SLOT(loadDatabase(bool))); - connect(m_databaseOpenMergeWidget, SIGNAL(dialogFinished(bool)), SLOT(mergeDatabase(bool))); connect(m_keepass1OpenWidget, SIGNAL(dialogFinished(bool)), SLOT(loadDatabase(bool))); connect(m_csvImportWizard, SIGNAL(importFinished(bool)), SLOT(csvImportFinished(bool))); - connect(m_unlockDatabaseWidget, SIGNAL(dialogFinished(bool)), SLOT(unlockDatabase(bool))); - connect(m_unlockDatabaseDialog, SIGNAL(unlockDone(bool)), SLOT(unlockDatabase(bool))); connect(&m_fileWatcher, SIGNAL(fileChanged(QString)), this, SLOT(onWatchedFileChanged())); connect(&m_fileWatchTimer, SIGNAL(timeout()), this, SLOT(reloadDatabaseFile())); connect(&m_fileWatchUnblockTimer, SIGNAL(timeout()), this, SLOT(unblockAutoReload())); @@ -217,7 +200,7 @@ DatabaseWidget::DatabaseWidget(QSharedPointer db, QWidget* parent) } #endif - setCurrentWidget(m_mainWidget); + switchToMainView(); } DatabaseWidget::DatabaseWidget(const QString& filePath, QWidget* parent) @@ -239,12 +222,12 @@ DatabaseWidget::Mode DatabaseWidget::currentMode() const { if (currentWidget() == nullptr) { return DatabaseWidget::Mode::None; - } else if (currentWidget() == m_csvImportWizard) { - return DatabaseWidget::Mode::ImportMode; } else if (currentWidget() == m_mainWidget) { return DatabaseWidget::Mode::ViewMode; - } else if (currentWidget() == m_unlockDatabaseWidget || currentWidget() == m_databaseOpenWidget) { + } else if (currentWidget() == m_databaseOpenWidget || currentWidget() == m_keepass1OpenWidget) { return DatabaseWidget::Mode::LockedMode; + } else if (currentWidget() == m_csvImportWizard) { + return DatabaseWidget::Mode::ImportMode; } else { return DatabaseWidget::Mode::EditMode; } @@ -358,7 +341,7 @@ void DatabaseWidget::createEntry() return; } - m_newEntry = new Entry(); + m_newEntry.reset(new Entry()); if (isSearchActive()) { m_newEntry->setTitle(getCurrentSearch()); @@ -368,7 +351,7 @@ void DatabaseWidget::createEntry() m_newEntry->setUsername(m_db->metadata()->defaultUserName()); m_newParent = m_groupView->currentGroup(); setIconFromParent(); - switchToEntryEdit(m_newEntry, true); + switchToEntryEdit(m_newEntry.data(), true); } void DatabaseWidget::setIconFromParent() @@ -652,10 +635,10 @@ void DatabaseWidget::createGroup() return; } - m_newGroup = new Group(); + m_newGroup.reset(new Group()); m_newGroup->setUuid(QUuid::createUuid()); m_newParent = m_groupView->currentGroup(); - switchToGroupEdit(m_newGroup, true); + switchToGroupEdit(m_newGroup.data(), true); } void DatabaseWidget::deleteGroup() @@ -692,38 +675,27 @@ int DatabaseWidget::addChildWidget(QWidget* w) return index; } -void DatabaseWidget::csvImportFinished(bool accepted) -{ - if (!accepted) { - emit closeRequest(); - } else { - setCurrentWidget(m_mainWidget); - } -} - -void DatabaseWidget::switchToView(bool accepted) +void DatabaseWidget::switchToMainView(bool previousDialogAccepted) { if (m_newGroup) { - if (accepted) { + if (previousDialogAccepted) { m_newGroup->setParent(m_newParent); - m_groupView->setCurrentGroup(m_newGroup); + m_groupView->setCurrentGroup(m_newGroup.take()); m_groupView->expandGroup(m_newParent); } else { - delete m_newGroup; + m_newGroup.reset(); } - m_newGroup = nullptr; m_newParent = nullptr; } else if (m_newEntry) { - if (accepted) { + if (previousDialogAccepted) { m_newEntry->setGroup(m_newParent); m_entryView->setFocus(); - m_entryView->setCurrentEntry(m_newEntry); + m_entryView->setCurrentEntry(m_newEntry.take()); } else { - delete m_newEntry; + m_newEntry.reset(); } - m_newEntry = nullptr; m_newParent = nullptr; } @@ -789,7 +761,7 @@ void DatabaseWidget::loadDatabase(bool accepted) if (accepted) { replaceDatabase(openWidget->database()); - setCurrentWidget(m_mainWidget); + switchToMainView(); m_fileWatcher.addPath(m_db->filePath()); emit databaseUnlocked(); } else { @@ -809,7 +781,13 @@ void DatabaseWidget::mergeDatabase(bool accepted) return; } - auto srcDb = qobject_cast(sender())->database(); + auto* senderDialog = qobject_cast(sender()); + + Q_ASSERT(senderDialog); + if (!senderDialog) { + return; + } + auto srcDb = senderDialog->database(); if (!srcDb) { showMessage(tr("No source database, nothing to do."), MessageWidget::Error); @@ -820,25 +798,37 @@ void DatabaseWidget::mergeDatabase(bool accepted) merger.merge(); } - m_databaseOpenMergeWidget->clearForms(); - setCurrentWidget(m_mainWidget); + switchToMainView(); emit databaseMerged(m_db); } +/** + * Unlock the database. + * + * @param accepted true if the unlock dialog or widget was confirmed with OK + */ void DatabaseWidget::unlockDatabase(bool accepted) { + auto* senderDialog = qobject_cast(sender()); + if (!accepted) { - emit closeRequest(); + if (!senderDialog && (!m_db || !m_db->isInitialized())) { + emit closeRequest(); + } return; } - auto db = QSharedPointer::create(); - if (sender() == m_unlockDatabaseDialog) { - db = m_unlockDatabaseDialog->database(); - } else if (sender() == m_unlockDatabaseWidget) { - db = m_unlockDatabaseWidget->database(); + if (senderDialog && senderDialog->intent() == DatabaseOpenDialog::Intent::Merge) { + mergeDatabase(accepted); + return; } + QSharedPointer db; + if (senderDialog) { + db = senderDialog->database(); + } else { + db = m_databaseOpenWidget->database(); + } replaceDatabase(db); if (db->isReadOnly()) { showMessage(tr("File opened in read only mode."), MessageWidget::Warning, false, -1); @@ -848,11 +838,10 @@ void DatabaseWidget::unlockDatabase(bool accepted) m_groupBeforeLock = QUuid(); m_entryBeforeLock = QUuid(); - setCurrentWidget(m_mainWidget); - m_unlockDatabaseWidget->clearForms(); + switchToMainView(); emit databaseUnlocked(); - if (sender() == m_unlockDatabaseDialog) { + if (senderDialog && senderDialog->intent() == DatabaseOpenDialog::Intent::AutoType) { QList> dbList; dbList.append(m_db); autoType()->performGlobalAutoType(dbList); @@ -905,6 +894,52 @@ void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::Mod } } +void DatabaseWidget::switchToDatabaseSettings() +{ + m_databaseSettingDialog->load(m_db); + setCurrentWidget(m_databaseSettingDialog); +} + +void DatabaseWidget::switchToOpenDatabase() +{ + switchToOpenDatabase(m_db->filePath()); +} + +void DatabaseWidget::switchToOpenDatabase(const QString& filePath) +{ + updateFilePath(filePath); + m_databaseOpenWidget->load(filePath); + setCurrentWidget(m_databaseOpenWidget); +} + +void DatabaseWidget::switchToOpenDatabase(const QString& filePath, const QString& password, const QString& keyFile) +{ + switchToOpenDatabase(filePath); + m_databaseOpenWidget->enterKey(password, keyFile); +} + +void DatabaseWidget::switchToCsvImport(const QString& filePath) +{ + setCurrentWidget(m_csvImportWizard); + m_csvImportWizard->load(filePath, m_db.data()); +} + +void DatabaseWidget::csvImportFinished(bool accepted) +{ + if (!accepted) { + emit closeRequest(); + } else { + switchToMainView(); + } +} + +void DatabaseWidget::switchToImportKeepass1(const QString& filePath) +{ + updateFilePath(filePath); + m_keepass1OpenWidget->load(filePath); + setCurrentWidget(m_keepass1OpenWidget); +} + void DatabaseWidget::switchToEntryEdit() { Entry* entry = m_entryView->currentEntry(); @@ -933,55 +968,6 @@ void DatabaseWidget::switchToMasterKeyChange() m_databaseSettingDialog->showMasterKeySettings(); } -void DatabaseWidget::switchToDatabaseSettings() -{ - m_databaseSettingDialog->load(m_db); - setCurrentWidget(m_databaseSettingDialog); -} - -void DatabaseWidget::switchToOpenDatabase() -{ - switchToOpenDatabase(m_db->filePath()); -} - -void DatabaseWidget::switchToOpenDatabase(const QString& filePath) -{ - updateFilePath(filePath); - if (m_databaseOpenWidget) { - m_databaseOpenWidget->load(filePath); - setCurrentWidget(m_databaseOpenWidget); - } else if (m_unlockDatabaseWidget) { - m_unlockDatabaseWidget->load(filePath); - setCurrentWidget(m_unlockDatabaseWidget); - } -} - -void DatabaseWidget::switchToCsvImport(const QString& filePath) -{ - setCurrentWidget(m_csvImportWizard); - m_csvImportWizard->load(filePath, m_db.data()); -} - -void DatabaseWidget::switchToOpenMergeDatabase(const QString& filePath) -{ - m_databaseOpenMergeWidget->clearForms(); - m_databaseOpenMergeWidget->load(filePath); - setCurrentWidget(m_databaseOpenMergeWidget); -} - -void DatabaseWidget::switchToOpenMergeDatabase(const QString& filePath, const QString& password, const QString& keyFile) -{ - switchToOpenMergeDatabase(filePath); - m_databaseOpenMergeWidget->enterKey(password, keyFile); -} - -void DatabaseWidget::switchToImportKeepass1(const QString& filePath) -{ - updateFilePath(filePath); - m_keepass1OpenWidget->load(filePath); - setCurrentWidget(m_keepass1OpenWidget); -} - void DatabaseWidget::performUnlockDatabase(const QString& password, const QString& keyfile) { if (password.isEmpty() && keyfile.isEmpty()) { @@ -1187,8 +1173,7 @@ bool DatabaseWidget::lock() endSearch(); clearAllWidgets(); - m_unlockDatabaseWidget->load(m_db->filePath()); - setCurrentWidget(m_unlockDatabaseWidget); + switchToOpenDatabase(m_db->filePath()); auto newDb = QSharedPointer::create(m_db->filePath()); replaceDatabase(newDb); @@ -1427,20 +1412,6 @@ EntryView* DatabaseWidget::entryView() return m_entryView; } -void DatabaseWidget::prepareUnlock() -{ - m_unlockDatabaseDialog->clearForms(); - m_unlockDatabaseDialog->setFilePath(m_db->filePath()); - -#if defined(Q_OS_MACOS) - autoType()->raiseWindow(); - Tools::wait(500); -#endif - - m_unlockDatabaseDialog->show(); - m_unlockDatabaseDialog->activateWindow(); -} - /** * Save the database to disk. * diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index addabe060..078ae9d23 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -24,12 +24,14 @@ #include #include +#include "DatabaseOpenDialog.h" #include "gui/entry/EntryModel.h" #include "gui/MessageWidget.h" #include "gui/csvImport/CsvImportWizard.h" #include "gui/entry/EntryModel.h" class DatabaseOpenWidget; +class KeePass1OpenWidget; class DatabaseSettingsDialog; class Database; class EditEntryWidget; @@ -39,15 +41,12 @@ class EntryView; class EntrySearcher; class Group; class GroupView; -class KeePass1OpenWidget; class QFile; class QMenu; class QSplitter; class QLabel; -class UnlockDatabaseWidget; class MessageWidget; class EntryPreviewWidget; -class UnlockDatabaseDialog; class QFileSystemWatcher; namespace Ui @@ -60,6 +59,8 @@ class DatabaseWidget : public QStackedWidget Q_OBJECT public: + friend class DatabaseOpenDialog; + enum class Mode { None, @@ -75,11 +76,6 @@ public: QSharedPointer database() const; - bool lock(); - void prepareUnlock(); - bool save(int attempt = 0); - bool saveAs(); - DatabaseWidget::Mode currentMode() const; bool isLocked() const; bool isSearchActive() const; @@ -148,6 +144,10 @@ signals: void clearSearch(); public slots: + bool lock(); + bool save(int attempt = 0); + bool saveAs(); + void replaceDatabase(QSharedPointer db); void createEntry(); void cloneEntry(); @@ -169,19 +169,18 @@ public slots: void createGroup(); void deleteGroup(); void onGroupChanged(Group* group); - void switchToView(bool accepted); + void switchToMainView(bool previousDialogAccepted = false); void switchToEntryEdit(); void switchToGroupEdit(); void switchToMasterKeyChange(); void switchToDatabaseSettings(); void switchToOpenDatabase(); void switchToOpenDatabase(const QString& filePath); + void switchToOpenDatabase(const QString& filePath, const QString& password, const QString& keyFile); void switchToCsvImport(const QString& filePath); - void csvImportFinished(bool accepted); - void switchToOpenMergeDatabase(const QString& filePath); - void switchToOpenMergeDatabase(const QString& filePath, const QString& password, const QString& keyFile); - void switchToImportKeepass1(const QString& filePath); void performUnlockDatabase(const QString& password, const QString& keyfile = {}); + void csvImportFinished(bool accepted); + void switchToImportKeepass1(const QString& filePath); void emptyRecycleBin(); // Search related slots @@ -215,8 +214,8 @@ private slots: void emitEntrySelectionChanged(); void connectDatabaseSignals(); void loadDatabase(bool accepted); - void mergeDatabase(bool accepted); void unlockDatabase(bool accepted); + void mergeDatabase(bool accepted); void emitCurrentModeChanged(); // Database autoreload slots void onWatchedFileChanged(); @@ -244,23 +243,17 @@ private: QPointer m_historyEditEntryWidget; QPointer m_databaseSettingDialog; QPointer m_databaseOpenWidget; - QPointer m_databaseOpenMergeWidget; QPointer m_keepass1OpenWidget; - QPointer m_unlockDatabaseWidget; - QPointer m_unlockDatabaseDialog; QPointer m_groupView; QPointer m_entryView; - QPointer m_newGroup; - QPointer m_newEntry; + QScopedPointer m_newGroup; + QScopedPointer m_newEntry; QPointer m_newParent; QUuid m_groupBeforeLock; QUuid m_entryBeforeLock; - QString m_databaseName; - QString m_databaseFileName; - // Search state EntrySearcher* m_EntrySearcher; QString m_lastSearchText; diff --git a/src/gui/KeePass1OpenWidget.cpp b/src/gui/KeePass1OpenWidget.cpp index 6b4c04a66..d033979b8 100644 --- a/src/gui/KeePass1OpenWidget.cpp +++ b/src/gui/KeePass1OpenWidget.cpp @@ -61,10 +61,9 @@ void KeePass1OpenWidget::openDatabase() if (m_db) { m_db->metadata()->setName(QFileInfo(m_filename).completeBaseName()); emit dialogFinished(true); + clearForms(); } else { m_ui->messageWidget->showMessage(tr("Unable to open the database.").append("\n").append(reader.errorString()), MessageWidget::Error); - - m_ui->editPassword->clear(); } } diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 649990416..1cd700b43 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -468,7 +468,7 @@ void MainWindow::openDatabase(const QString& filePath, const QString& pw, const if (db->open(filePath, key, nullptr, false)) { auto* dbWidget = new DatabaseWidget(db, this); m_ui->tabWidget->addDatabaseTab(dbWidget); - dbWidget->switchToView(true); + dbWidget->switchToMainView(true); } } diff --git a/src/gui/UnlockDatabaseDialog.cpp b/src/gui/UnlockDatabaseDialog.cpp deleted file mode 100644 index 8e2066ef4..000000000 --- a/src/gui/UnlockDatabaseDialog.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2016 KeePassXC Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "UnlockDatabaseDialog.h" -#include "UnlockDatabaseWidget.h" - -#include "autotype/AutoType.h" -#include "core/Database.h" -#include "gui/DragTabBar.h" - -UnlockDatabaseDialog::UnlockDatabaseDialog(QWidget* parent) - : QDialog(parent) - , m_view(new UnlockDatabaseWidget(this)) -{ - setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); - connect(m_view, SIGNAL(dialogFinished(bool)), this, SLOT(complete(bool))); -} - -void UnlockDatabaseDialog::setFilePath(const QString& filePath) -{ - m_view->load(filePath); -} - -void UnlockDatabaseDialog::clearForms() -{ - m_view->clearForms(); -} - -QSharedPointer UnlockDatabaseDialog::database() -{ - return m_view->database(); -} - -void UnlockDatabaseDialog::complete(bool r) -{ - if (r) { - accept(); - emit unlockDone(true); - } else { - reject(); - } -} diff --git a/src/gui/UnlockDatabaseWidget.cpp b/src/gui/UnlockDatabaseWidget.cpp deleted file mode 100644 index ffd2bf225..000000000 --- a/src/gui/UnlockDatabaseWidget.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "UnlockDatabaseWidget.h" - -#include "core/Database.h" -#include "gui/MessageBox.h" -#include "ui_DatabaseOpenWidget.h" - -UnlockDatabaseWidget::UnlockDatabaseWidget(QWidget* parent) - : DatabaseOpenWidget(parent) -{ - m_ui->labelHeadline->setText(tr("Unlock database")); -} diff --git a/src/gui/UnlockDatabaseWidget.h b/src/gui/UnlockDatabaseWidget.h deleted file mode 100644 index c10fcf0a8..000000000 --- a/src/gui/UnlockDatabaseWidget.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef KEEPASSX_UNLOCKDATABASEWIDGET_H -#define KEEPASSX_UNLOCKDATABASEWIDGET_H - -#include "gui/DatabaseOpenWidget.h" - -class UnlockDatabaseWidget : public DatabaseOpenWidget -{ - Q_OBJECT - -public: - explicit UnlockDatabaseWidget(QWidget* parent = nullptr); -}; - -#endif // KEEPASSX_UNLOCKDATABASEWIDGET_H diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 41499d16e..1964b0e0f 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -307,12 +307,10 @@ void TestGui::testMergeDatabase() fileDialog()->setNextFileName(QString(KEEPASSX_TEST_DATA_DIR).append("/MergeDatabase.kdbx")); triggerAction("actionDatabaseMerge"); - auto* databaseOpenMergeWidget = m_tabWidget->currentDatabaseWidget()->findChild("databaseOpenMergeWidget"); - auto* editPasswordMerge = databaseOpenMergeWidget->findChild("editPassword"); + QTRY_COMPARE(QApplication::focusWidget()->objectName(), QString("editPassword")); + auto* editPasswordMerge = QApplication::focusWidget(); QVERIFY(editPasswordMerge->isVisible()); - m_tabWidget->currentDatabaseWidget()->setCurrentWidget(databaseOpenMergeWidget); - QTest::keyClicks(editPasswordMerge, "a"); QTest::keyClick(editPasswordMerge, Qt::Key_Enter); @@ -1191,14 +1189,16 @@ void TestGui::testDatabaseLocking() auto* actionDatabaseSave = m_mainWindow->findChild("actionDatabaseSave", Qt::FindChildrenRecursively); QCOMPARE(actionDatabaseSave->isEnabled(), false); - QWidget* dbWidget = m_tabWidget->currentDatabaseWidget(); - auto* unlockDatabaseWidget = dbWidget->findChild("unlockDatabaseWidget"); + DatabaseWidget* dbWidget = m_tabWidget->currentDatabaseWidget(); + QVERIFY(dbWidget->isLocked()); + auto* unlockDatabaseWidget = dbWidget->findChild("databaseOpenWidget"); QWidget* editPassword = unlockDatabaseWidget->findChild("editPassword"); QVERIFY(editPassword); QTest::keyClicks(editPassword, "a"); QTest::keyClick(editPassword, Qt::Key_Enter); + QVERIFY(!dbWidget->isLocked()); QCOMPARE(m_tabWidget->tabName(0), origDbName); actionDatabaseMerge = m_mainWindow->findChild("actionDatabaseMerge", Qt::FindChildrenRecursively);