From 92af92ccbef0bf12951c52957efce8b2641fef92 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Thu, 28 Jun 2012 09:21:15 +0200 Subject: [PATCH] Convert DatabaseOpenDialog into a widget on DatabaseWidget. --- src/CMakeLists.txt | 10 +- ...eOpenDialog.cpp => DatabaseOpenWidget.cpp} | 54 +++++++---- ...abaseOpenDialog.h => DatabaseOpenWidget.h} | 32 ++++--- ...aseOpenDialog.ui => DatabaseOpenWidget.ui} | 4 +- src/gui/DatabaseTabWidget.cpp | 96 +++++++++---------- src/gui/DatabaseTabWidget.h | 10 +- src/gui/DatabaseWidget.cpp | 57 +++++++++++ src/gui/DatabaseWidget.h | 12 ++- ...1OpenDialog.cpp => KeePass1OpenWidget.cpp} | 17 ++-- ...Pass1OpenDialog.h => KeePass1OpenWidget.h} | 14 +-- src/gui/group/GroupModel.cpp | 35 +++++-- src/gui/group/GroupModel.h | 3 +- src/gui/group/GroupView.cpp | 25 ++++- src/gui/group/GroupView.h | 3 + tests/gui/TestGui.cpp | 13 ++- 15 files changed, 250 insertions(+), 135 deletions(-) rename src/gui/{DatabaseOpenDialog.cpp => DatabaseOpenWidget.cpp} (81%) rename src/gui/{DatabaseOpenDialog.h => DatabaseOpenWidget.h} (67%) rename src/gui/{DatabaseOpenDialog.ui => DatabaseOpenWidget.ui} (96%) rename src/gui/{KeePass1OpenDialog.cpp => KeePass1OpenWidget.cpp} (83%) rename src/gui/{KeePass1OpenDialog.h => KeePass1OpenWidget.h} (70%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cac9244d..667c2a51 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,7 +55,7 @@ set(keepassx_SOURCES gui/Application.cpp gui/ChangeMasterKeyWidget.cpp gui/Clipboard.cpp - gui/DatabaseOpenDialog.cpp + gui/DatabaseOpenWidget.cpp gui/DatabaseSettingsWidget.cpp gui/DatabaseTabWidget.cpp gui/DatabaseWidget.cpp @@ -65,7 +65,7 @@ set(keepassx_SOURCES gui/EditWidgetIcons.cpp gui/FileDialog.cpp gui/IconModels.cpp - gui/KeePass1OpenDialog.cpp + gui/KeePass1OpenWidget.cpp gui/LineEdit.cpp gui/MainWindow.cpp gui/SettingsWidget.cpp @@ -101,7 +101,7 @@ set(keepassx_MOC gui/Application.h gui/ChangeMasterKeyWidget.h gui/Clipboard.h - gui/DatabaseOpenDialog.h + gui/DatabaseOpenWidget.h gui/DatabaseSettingsWidget.h gui/DatabaseTabWidget.h gui/DatabaseWidget.h @@ -110,7 +110,7 @@ set(keepassx_MOC gui/EditWidget.h gui/EditWidgetIcons.h gui/IconModels.h - gui/KeePass1OpenDialog.h + gui/KeePass1OpenWidget.h gui/LineEdit.h gui/MainWindow.h gui/SettingsWidget.h @@ -134,7 +134,7 @@ set(keepassx_MOC set(keepassx_FORMS gui/AboutDialog.ui gui/ChangeMasterKeyWidget.ui - gui/DatabaseOpenDialog.ui + gui/DatabaseOpenWidget.ui gui/DatabaseSettingsWidget.ui gui/EditWidget.ui gui/EditWidgetIcons.ui diff --git a/src/gui/DatabaseOpenDialog.cpp b/src/gui/DatabaseOpenWidget.cpp similarity index 81% rename from src/gui/DatabaseOpenDialog.cpp rename to src/gui/DatabaseOpenWidget.cpp index cd6950fc..61f601b5 100644 --- a/src/gui/DatabaseOpenDialog.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -15,23 +15,23 @@ * along with this program. If not, see . */ -#include "DatabaseOpenDialog.h" -#include "ui_DatabaseOpenDialog.h" +#include "DatabaseOpenWidget.h" +#include "ui_DatabaseOpenWidget.h" #include #include "core/Config.h" +#include "core/Database.h" #include "gui/FileDialog.h" #include "format/KeePass2Reader.h" #include "keys/FileKey.h" #include "keys/PasswordKey.h" -DatabaseOpenDialog::DatabaseOpenDialog(QFile* file, const QString& filename, QWidget* parent) - : QDialog(parent) - , m_ui(new Ui::DatabaseOpenDialog()) +DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) + : DialogyWidget(parent) + , m_ui(new Ui::DatabaseOpenWidget()) , m_db(0) - , m_file(file) - , m_filename(filename) + , m_file(0) { m_ui->setupUi(this); @@ -49,6 +49,16 @@ DatabaseOpenDialog::DatabaseOpenDialog(QFile* file, const QString& filename, QWi connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase())); connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject())); +} + +DatabaseOpenWidget::~DatabaseOpenWidget() +{ +} + +void DatabaseOpenWidget::load(QFile* file, const QString& filename) +{ + m_file = file; + m_filename = filename; QHash lastKeyFiles = config()->get("LastKeyFiles").toHash(); if (lastKeyFiles.contains(m_filename)) { @@ -59,16 +69,12 @@ DatabaseOpenDialog::DatabaseOpenDialog(QFile* file, const QString& filename, QWi m_ui->editPassword->setFocus(); } -DatabaseOpenDialog::~DatabaseOpenDialog() -{ -} - -Database* DatabaseOpenDialog::database() +Database* DatabaseOpenWidget::database() { return m_db; } -void DatabaseOpenDialog::enterKey(const QString& pw, const QString& keyFile) +void DatabaseOpenWidget::enterKey(const QString& pw, const QString& keyFile) { if (!pw.isNull()) { m_ui->editPassword->setText(pw); @@ -80,7 +86,7 @@ void DatabaseOpenDialog::enterKey(const QString& pw, const QString& keyFile) openDatabase(); } -void DatabaseOpenDialog::openDatabase() +void DatabaseOpenWidget::openDatabase() { KeePass2Reader reader; CompositeKey masterKey; @@ -109,10 +115,13 @@ void DatabaseOpenDialog::openDatabase() config()->set("LastKeyFiles", lastKeyFiles); m_file->reset(); + if (m_db) { + delete m_db; + } m_db = reader.readDatabase(m_file, masterKey); if (m_db) { - accept(); + Q_EMIT editFinished(true); } else { QMessageBox::warning(this, tr("Error"), tr("Unable to open the database.\n%1") @@ -121,22 +130,27 @@ void DatabaseOpenDialog::openDatabase() } } -void DatabaseOpenDialog::togglePassword(bool checked) +void DatabaseOpenWidget::reject() +{ + Q_EMIT editFinished(false); +} + +void DatabaseOpenWidget::togglePassword(bool checked) { m_ui->editPassword->setEchoMode(checked ? QLineEdit::Password : QLineEdit::Normal); } -void DatabaseOpenDialog::activatePassword() +void DatabaseOpenWidget::activatePassword() { m_ui->checkPassword->setChecked(true); } -void DatabaseOpenDialog::activateKeyFile() +void DatabaseOpenWidget::activateKeyFile() { m_ui->checkKeyFile->setChecked(true); } -void DatabaseOpenDialog::setOkButtonEnabled() +void DatabaseOpenWidget::setOkButtonEnabled() { bool enable = m_ui->checkPassword->isChecked() || (m_ui->checkKeyFile->isChecked() && !m_ui->comboKeyFile->currentText().isEmpty()); @@ -144,7 +158,7 @@ void DatabaseOpenDialog::setOkButtonEnabled() m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enable); } -void DatabaseOpenDialog::browseKeyFile() +void DatabaseOpenWidget::browseKeyFile() { QString filters = QString("%1 (*);;%2 (*.key)").arg(tr("All files"), tr("Key files")); QString filename = fileDialog()->getOpenFileName(this, tr("Select key file"), QString(), filters); diff --git a/src/gui/DatabaseOpenDialog.h b/src/gui/DatabaseOpenWidget.h similarity index 67% rename from src/gui/DatabaseOpenDialog.h rename to src/gui/DatabaseOpenWidget.h index a87fc8c6..5a6ea22f 100644 --- a/src/gui/DatabaseOpenDialog.h +++ b/src/gui/DatabaseOpenWidget.h @@ -15,31 +15,37 @@ * along with this program. If not, see . */ -#ifndef KEEPASSX_DATABASEOPENDIALOG_H -#define KEEPASSX_DATABASEOPENDIALOG_H +#ifndef KEEPASSX_DATABASEOPENWIDGET_H +#define KEEPASSX_DATABASEOPENWIDGET_H #include -#include + +#include "gui/DialogyWidget.h" class Database; class QFile; namespace Ui { - class DatabaseOpenDialog; + class DatabaseOpenWidget; } -class DatabaseOpenDialog : public QDialog +class DatabaseOpenWidget : public DialogyWidget { Q_OBJECT public: - DatabaseOpenDialog(QFile* file, const QString& filename, QWidget* parent = 0); - ~DatabaseOpenDialog(); - Database* database(); + DatabaseOpenWidget(QWidget* parent = 0); + ~DatabaseOpenWidget(); + void load(QFile* file, const QString& filename); void enterKey(const QString& pw, const QString& keyFile); + Database* database(); + +Q_SIGNALS: + void editFinished(bool accepted); protected Q_SLOTS: virtual void openDatabase(); + void reject(); private Q_SLOTS: void togglePassword(bool checked); @@ -49,13 +55,13 @@ private Q_SLOTS: void browseKeyFile(); protected: - const QScopedPointer m_ui; + const QScopedPointer m_ui; Database* m_db; - QFile* const m_file; - const QString m_filename; + QFile* m_file; + QString m_filename; private: - Q_DISABLE_COPY(DatabaseOpenDialog) + Q_DISABLE_COPY(DatabaseOpenWidget) }; -#endif // KEEPASSX_DATABASEOPENDIALOG_H +#endif // KEEPASSX_DATABASEOPENWIDGET_H diff --git a/src/gui/DatabaseOpenDialog.ui b/src/gui/DatabaseOpenWidget.ui similarity index 96% rename from src/gui/DatabaseOpenDialog.ui rename to src/gui/DatabaseOpenWidget.ui index 3c65a5cc..672f025e 100644 --- a/src/gui/DatabaseOpenDialog.ui +++ b/src/gui/DatabaseOpenWidget.ui @@ -1,7 +1,7 @@ - DatabaseOpenDialog - + DatabaseOpenWidget + 0 diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index c943644a..c8b54e06 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -25,11 +25,9 @@ #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" -#include "gui/DatabaseOpenDialog.h" #include "gui/DatabaseWidget.h" #include "gui/DragTabBar.h" #include "gui/FileDialog.h" -#include "gui/KeePass1OpenDialog.h" #include "gui/entry/EntryView.h" #include "gui/group/GroupView.h" @@ -93,6 +91,8 @@ void DatabaseTabWidget::openDatabase() void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, const QString& keyFile) { + DatabaseManagerStruct dbStruct; + QScopedPointer file(new QFile(fileName)); // TODO: error handling if (!file->open(QIODevice::ReadWrite)) { @@ -102,26 +102,22 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, } else { // can only open read-only - m_curDbStruct.readOnly = true; + dbStruct.readOnly = true; } } - m_curDbStruct.file = file.take(); - m_curDbStruct.fileName = QFileInfo(fileName).absoluteFilePath(); + Database* db = new Database(); + dbStruct.dbWidget = new DatabaseWidget(db, this); + dbStruct.file = file.take(); + dbStruct.fileName = QFileInfo(fileName).absoluteFilePath(); - openDatabaseDialog(pw, keyFile); -} - -void DatabaseTabWidget::openDatabaseDialog(const QString& pw, const QString& keyFile) -{ - m_curKeyDialog = new DatabaseOpenDialog(m_curDbStruct.file, m_curDbStruct.fileName, m_window); - connect(m_curKeyDialog, SIGNAL(accepted()), SLOT(openDatabaseRead())); - connect(m_curKeyDialog, SIGNAL(rejected()), SLOT(openDatabaseCleanup())); - m_curKeyDialog->setModal(true); - m_curKeyDialog->show(); + insertDatabase(db, dbStruct); if (!pw.isNull() || !keyFile.isEmpty()) { - m_curKeyDialog->enterKey(pw, keyFile); + dbStruct.dbWidget->switchToOpenDatabase(dbStruct.file, dbStruct.fileName, pw, keyFile); + } + else { + dbStruct.dbWidget->switchToOpenDatabase(dbStruct.file, dbStruct.fileName); } } @@ -140,39 +136,14 @@ void DatabaseTabWidget::importKeePass1Database() return; } - m_curDbStruct.modified = true; + Database* db = new Database(); + DatabaseManagerStruct dbStruct; + dbStruct.dbWidget = new DatabaseWidget(db, this); + dbStruct.modified = true; - m_curKeyDialog = new KeePass1OpenDialog(file.take(), fileName, m_window); - connect(m_curKeyDialog, SIGNAL(accepted()), SLOT(openDatabaseRead())); - connect(m_curKeyDialog, SIGNAL(rejected()), SLOT(openDatabaseCleanup())); - m_curKeyDialog->setModal(true); - m_curKeyDialog->show(); -} + insertDatabase(db, dbStruct); -void DatabaseTabWidget::openDatabaseRead() -{ - Database* db = m_curKeyDialog->database(); - - delete m_curKeyDialog; - m_curKeyDialog = 0; - - m_curDbStruct.dbWidget = new DatabaseWidget(db, this); - QString filename = m_curDbStruct.fileName; - insertDatabase(db, m_curDbStruct); - m_curDbStruct = DatabaseManagerStruct(); - - updateLastDatabases(filename); -} - -void DatabaseTabWidget::openDatabaseCleanup() -{ - delete m_curKeyDialog; - m_curKeyDialog = 0; - - if (m_curDbStruct.file) { - delete m_curDbStruct.file; - } - m_curDbStruct = DatabaseManagerStruct(); + dbStruct.dbWidget->switchToImportKeepass1(file.take(), fileName); } void DatabaseTabWidget::emitEntrySelectionChanged() @@ -503,14 +474,13 @@ void DatabaseTabWidget::insertDatabase(Database* db, const DatabaseManagerStruct updateTabName(db); int index = databaseIndex(db); setCurrentIndex(index); - connect(db, SIGNAL(nameTextChanged()), SLOT(updateTabNameFromSender())); + connectDatabase(db); connect(dbStruct.dbWidget->entryView(), SIGNAL(entrySelectionChanged()), SLOT(emitEntrySelectionChanged())); connect(dbStruct.dbWidget, SIGNAL(closeRequest()), SLOT(closeDatabaseFromSender())); - connect(db, SIGNAL(modified()), SLOT(modified())); connect(dbStruct.dbWidget, SIGNAL(currentModeChanged(DatabaseWidget::Mode)), SIGNAL(currentWidgetModeChanged(DatabaseWidget::Mode))); - db->setEmitModified(true); + connect(dbStruct.dbWidget, SIGNAL(databaseChanged(Database*)), SLOT(changeDatabase(Database*))); } DatabaseWidget* DatabaseTabWidget::currentDatabaseWidget() @@ -558,3 +528,29 @@ void DatabaseTabWidget::updateLastDatabases(const QString& filename) config()->set("LastDatabases", lastDatabases); } } + +void DatabaseTabWidget::changeDatabase(Database* newDb) +{ + Q_ASSERT(sender()); + Q_ASSERT(!m_dbList.contains(newDb)); + + DatabaseWidget* dbWidget = static_cast(sender()); + Database* oldDb = databaseFromDatabaseWidget(dbWidget); + DatabaseManagerStruct dbStruct = m_dbList[oldDb]; + m_dbList.remove(oldDb); + m_dbList.insert(newDb, dbStruct); + + updateTabName(newDb); + connectDatabase(newDb, oldDb); +} + +void DatabaseTabWidget::connectDatabase(Database* newDb, Database* oldDb) +{ + if (oldDb) { + oldDb->disconnect(this); + } + + connect(newDb, SIGNAL(nameTextChanged()), SLOT(updateTabNameFromSender())); + connect(newDb, SIGNAL(modified()), SLOT(modified())); + newDb->setEmitModified(true); +} diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index a06c7524..da0d65a2 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -25,7 +25,7 @@ #include "gui/DatabaseWidget.h" class DatabaseWidget; -class DatabaseOpenDialog; +class DatabaseOpenWidget; class QFile; struct DatabaseManagerStruct @@ -84,12 +84,10 @@ Q_SIGNALS: private Q_SLOTS: void updateTabName(Database* db); void updateTabNameFromSender(); - void openDatabaseDialog(const QString& pw = QString(), const QString& keyFile = QString()); - void openDatabaseRead(); - void openDatabaseCleanup(); void emitEntrySelectionChanged(); void modified(); void toggleTabbar(); + void changeDatabase(Database* newDb); private: void saveDatabase(Database* db); @@ -98,16 +96,14 @@ private: int databaseIndex(Database* db); Database* indexDatabase(int index); DatabaseManagerStruct indexDatabaseManagerStruct(int index); - Database* databaseFromDatabaseWidget(DatabaseWidget* dbWidget); void insertDatabase(Database* db, const DatabaseManagerStruct& dbStruct); void updateLastDatabases(const QString& filename); + void connectDatabase(Database* newDb, Database* oldDb = 0); QWidget* const m_window; KeePass2Writer m_writer; QHash m_dbList; - DatabaseManagerStruct m_curDbStruct; - DatabaseOpenDialog* m_curKeyDialog; }; #endif // KEEPASSX_DATABASETABWIDGET_H diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index d1327cd5..21a06187 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -32,7 +32,9 @@ #include "core/Tools.h" #include "gui/ChangeMasterKeyWidget.h" #include "gui/Clipboard.h" +#include "gui/DatabaseOpenWidget.h" #include "gui/DatabaseSettingsWidget.h" +#include "gui/KeePass1OpenWidget.h" #include "gui/entry/EditEntryWidget.h" #include "gui/entry/EntryView.h" #include "gui/group/EditGroupWidget.h" @@ -69,6 +71,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) m_entryView = new EntryView(rightHandSideWidget); m_entryView->setObjectName("entryView"); m_entryView->setContextMenuPolicy(Qt::CustomContextMenu); + m_entryView->setGroup(db->rootGroup()); connect(m_entryView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showEntryContextMenu(QPoint))); QSizePolicy policy; @@ -111,12 +114,18 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) headlineLabelFont.setPointSize(headlineLabelFont.pointSize() + 2); m_changeMasterKeyWidget->headlineLabel()->setFont(headlineLabelFont); m_databaseSettingsWidget = new DatabaseSettingsWidget(); + m_databaseOpenWidget = new DatabaseOpenWidget(); + m_databaseOpenWidget->setObjectName("databaseOpenWidget"); + m_keepass1OpenWidget = new KeePass1OpenWidget(); + m_keepass1OpenWidget->setObjectName("keepass1OpenWidget"); addWidget(m_mainWidget); addWidget(m_editEntryWidget); addWidget(m_editGroupWidget); addWidget(m_changeMasterKeyWidget); addWidget(m_databaseSettingsWidget); addWidget(m_historyEditEntryWidget); + addWidget(m_databaseOpenWidget); + addWidget(m_keepass1OpenWidget); m_actionEntryNew = m_menuEntry->addAction(tr("Add new entry"), this, SLOT(createEntry())); m_actionEntryNew->setIcon(dataPath()->icon("actions", "entry-new", false)); @@ -154,6 +163,8 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) connect(m_editGroupWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool))); connect(m_changeMasterKeyWidget, SIGNAL(editFinished(bool)), SLOT(updateMasterKey(bool))); connect(m_databaseSettingsWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool))); + connect(m_databaseOpenWidget, SIGNAL(editFinished(bool)), SLOT(openDatabase(bool))); + connect(m_keepass1OpenWidget, SIGNAL(editFinished(bool)), SLOT(openDatabase(bool))); connect(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged())); connect(m_searchUi->searchEdit, SIGNAL(textChanged(QString)), this, SLOT(startSearchTimer())); connect(m_searchUi->caseSensitiveCheckBox, SIGNAL(toggled(bool)), this, SLOT(startSearch())); @@ -182,6 +193,8 @@ DatabaseWidget::Mode DatabaseWidget::currentMode() case 3: // change master key case 4: // database settings case 5: // entry history + case 6: // open database + case 7: // keepass 1 import return DatabaseWidget::EditMode; default: Q_ASSERT(false); @@ -449,6 +462,31 @@ void DatabaseWidget::updateMasterKey(bool accepted) setCurrentIndex(0); } +void DatabaseWidget::openDatabase(bool accepted) +{ + if (accepted) { + Database* oldDb = m_db; + m_db = static_cast(sender())->database(); + m_groupView->changeDatabase(m_db); + Q_EMIT databaseChanged(m_db); + delete oldDb; + setCurrentIndex(0); + + // We won't need those anymore and KeePass1OpenWidget closes + // the file in its dtor. + delete m_databaseOpenWidget; + m_databaseOpenWidget = 0; + delete m_keepass1OpenWidget; + m_keepass1OpenWidget = 0; + } + else { + if (m_databaseOpenWidget->database()) { + delete m_databaseOpenWidget->database(); + } + Q_EMIT closeRequest(); + } +} + void DatabaseWidget::switchToEntryEdit() { switchToEntryEdit(m_entryView->currentEntry(), false); @@ -471,6 +509,25 @@ void DatabaseWidget::switchToDatabaseSettings() setCurrentIndex(4); } +void DatabaseWidget::switchToOpenDatabase(QFile* file, const QString& fileName) +{ + m_databaseOpenWidget->load(file, fileName); + setCurrentIndex(6); +} + +void DatabaseWidget::switchToOpenDatabase(QFile* file, const QString& fileName, + const QString& password, const QString& keyFile) +{ + switchToOpenDatabase(file, fileName); + m_databaseOpenWidget->enterKey(password, keyFile); +} + +void DatabaseWidget::switchToImportKeepass1(QFile* file, const QString& fileName) +{ + m_keepass1OpenWidget->load(file, fileName); + setCurrentIndex(7); +} + void DatabaseWidget::toggleSearch() { if (m_entryView->inSearch()) { diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index c055db7c..b83b79a5 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -22,6 +22,7 @@ #include class ChangeMasterKeyWidget; +class DatabaseOpenWidget; class DatabaseSettingsWidget; class Database; class EditEntryWidget; @@ -30,6 +31,8 @@ class Entry; class EntryView; class Group; class GroupView; +class KeePass1OpenWidget; +class QFile; class QMenu; namespace Ui { @@ -74,6 +77,7 @@ public: Q_SIGNALS: void closeRequest(); void currentModeChanged(DatabaseWidget::Mode mode); + void databaseChanged(Database* newDb); public Q_SLOTS: void createEntry(); @@ -87,6 +91,9 @@ public Q_SLOTS: void switchToGroupEdit(); void switchToMasterKeyChange(); void switchToDatabaseSettings(); + void switchToOpenDatabase(QFile* file, const QString& fileName); + void switchToOpenDatabase(QFile* file, const QString& fileName, const QString& password, const QString& keyFile); + void switchToImportKeepass1(QFile* file, const QString& fileName); void toggleSearch(); private Q_SLOTS: @@ -97,6 +104,7 @@ private Q_SLOTS: void switchToEntryEdit(Entry* entry, bool create); void switchToGroupEdit(Group* entry, bool create); void updateMasterKey(bool accepted); + void openDatabase(bool accepted); void emitCurrentModeChanged(); void clearLastGroup(Group* group); void search(); @@ -110,7 +118,7 @@ private Q_SLOTS: void showEntryContextMenu(const QPoint& pos); private: - Database* const m_db; + Database* m_db; const QScopedPointer m_searchUi; QWidget* const m_searchWidget; QWidget* m_mainWidget; @@ -119,6 +127,8 @@ private: EditGroupWidget* m_editGroupWidget; ChangeMasterKeyWidget* m_changeMasterKeyWidget; DatabaseSettingsWidget* m_databaseSettingsWidget; + DatabaseOpenWidget* m_databaseOpenWidget; + KeePass1OpenWidget* m_keepass1OpenWidget; GroupView* m_groupView; EntryView* m_entryView; Group* m_newGroup; diff --git a/src/gui/KeePass1OpenDialog.cpp b/src/gui/KeePass1OpenWidget.cpp similarity index 83% rename from src/gui/KeePass1OpenDialog.cpp rename to src/gui/KeePass1OpenWidget.cpp index 6c9fee18..0f9b7da4 100644 --- a/src/gui/KeePass1OpenDialog.cpp +++ b/src/gui/KeePass1OpenWidget.cpp @@ -15,29 +15,29 @@ * along with this program. If not, see . */ -#include "KeePass1OpenDialog.h" +#include "KeePass1OpenWidget.h" #include #include #include -#include "ui_DatabaseOpenDialog.h" +#include "ui_DatabaseOpenWidget.h" #include "core/Database.h" #include "core/Metadata.h" #include "format/KeePass1Reader.h" -KeePass1OpenDialog::KeePass1OpenDialog(QFile* file, const QString& filename, QWidget* parent) - : DatabaseOpenDialog(file, filename, parent) +KeePass1OpenWidget::KeePass1OpenWidget(QWidget* parent) + : DatabaseOpenWidget(parent) { setWindowTitle(tr("Import KeePass1 database")); } -KeePass1OpenDialog::~KeePass1OpenDialog() +KeePass1OpenWidget::~KeePass1OpenWidget() { delete m_file; } -void KeePass1OpenDialog::openDatabase() +void KeePass1OpenWidget::openDatabase() { KeePass1Reader reader; @@ -53,11 +53,14 @@ void KeePass1OpenDialog::openDatabase() } m_file->reset(); + if (m_db) { + delete m_db; + } m_db = reader.readDatabase(m_file, password, keyFileName); if (m_db) { m_db->metadata()->setName(QFileInfo(m_filename).completeBaseName()); - accept(); + Q_EMIT editFinished(true); } else { QMessageBox::warning(this, tr("Error"), tr("Unable to open the database.\n%1") diff --git a/src/gui/KeePass1OpenDialog.h b/src/gui/KeePass1OpenWidget.h similarity index 70% rename from src/gui/KeePass1OpenDialog.h rename to src/gui/KeePass1OpenWidget.h index 2c343446..fc8a849e 100644 --- a/src/gui/KeePass1OpenDialog.h +++ b/src/gui/KeePass1OpenWidget.h @@ -15,21 +15,21 @@ * along with this program. If not, see . */ -#ifndef KEEPASSX_KEEPASS1OPENDIALOG_H -#define KEEPASSX_KEEPASS1OPENDIALOG_H +#ifndef KEEPASSX_KEEPASS1OPENWIDGET_H +#define KEEPASSX_KEEPASS1OPENWIDGET_H -#include "gui/DatabaseOpenDialog.h" +#include "gui/DatabaseOpenWidget.h" -class KeePass1OpenDialog : public DatabaseOpenDialog +class KeePass1OpenWidget : public DatabaseOpenWidget { Q_OBJECT public: - explicit KeePass1OpenDialog(QFile* file, const QString& filename, QWidget* parent = 0); - ~KeePass1OpenDialog(); + explicit KeePass1OpenWidget(QWidget* parent = 0); + ~KeePass1OpenWidget(); protected: void openDatabase(); }; -#endif // KEEPASSX_KEEPASS1OPENDIALOG_H +#endif // KEEPASSX_KEEPASS1OPENWIDGET_H diff --git a/src/gui/group/GroupModel.cpp b/src/gui/group/GroupModel.cpp index f79f9d00..0687d3a6 100644 --- a/src/gui/group/GroupModel.cpp +++ b/src/gui/group/GroupModel.cpp @@ -27,15 +27,30 @@ GroupModel::GroupModel(Database* db, QObject* parent) : QAbstractItemModel(parent) + , m_db(0) { - m_root = db->rootGroup(); - connect(db, SIGNAL(groupDataChanged(Group*)), SLOT(groupDataChanged(Group*))); - connect(db, SIGNAL(groupAboutToAdd(Group*,int)), SLOT(groupAboutToAdd(Group*,int))); - connect(db, SIGNAL(groupAdded()), SLOT(groupAdded())); - connect(db, SIGNAL(groupAboutToRemove(Group*)), SLOT(groupAboutToRemove(Group*))); - connect(db, SIGNAL(groupRemoved()), SLOT(groupRemoved())); - connect(db, SIGNAL(groupAboutToMove(Group*,Group*,int)), SLOT(groupAboutToMove(Group*,Group*,int))); - connect(db, SIGNAL(groupMoved()), SLOT(groupMoved())); + changeDatabase(db); +} + +void GroupModel::changeDatabase(Database* newDb) +{ + beginResetModel(); + + if (m_db) { + m_db->disconnect(this); + } + + m_db = newDb; + + connect(m_db, SIGNAL(groupDataChanged(Group*)), SLOT(groupDataChanged(Group*))); + connect(m_db, SIGNAL(groupAboutToAdd(Group*,int)), SLOT(groupAboutToAdd(Group*,int))); + connect(m_db, SIGNAL(groupAdded()), SLOT(groupAdded())); + connect(m_db, SIGNAL(groupAboutToRemove(Group*)), SLOT(groupAboutToRemove(Group*))); + connect(m_db, SIGNAL(groupRemoved()), SLOT(groupRemoved())); + connect(m_db, SIGNAL(groupAboutToMove(Group*,Group*,int)), SLOT(groupAboutToMove(Group*,Group*,int))); + connect(m_db, SIGNAL(groupMoved()), SLOT(groupMoved())); + + endResetModel(); } int GroupModel::rowCount(const QModelIndex& parent) const @@ -66,7 +81,7 @@ QModelIndex GroupModel::index(int row, int column, const QModelIndex& parent) co Group* group; if (!parent.isValid()) { - group = m_root; + group = m_db->rootGroup(); } else { group = groupFromIndex(parent)->children().at(row); @@ -269,7 +284,7 @@ QMimeData* GroupModel::mimeData(const QModelIndexList& indexes) const if (!indexes[i].isValid()) { continue; } - stream << m_root->database()->uuid() << groupFromIndex(indexes[i])->uuid(); + stream << m_db->uuid() << groupFromIndex(indexes[i])->uuid(); } data->setData(mimeTypes().first(), encoded); diff --git a/src/gui/group/GroupModel.h b/src/gui/group/GroupModel.h index 9ed577f1..e3565fec 100644 --- a/src/gui/group/GroupModel.h +++ b/src/gui/group/GroupModel.h @@ -29,6 +29,7 @@ class GroupModel : public QAbstractItemModel public: explicit GroupModel(Database* db, QObject* parent = 0); + void changeDatabase(Database* newDb); QModelIndex index(Group* group) const; Group* groupFromIndex(const QModelIndex& index) const; @@ -58,7 +59,7 @@ private Q_SLOTS: void groupMoved(); private: - Group* m_root; + Database* m_db; }; #endif // KEEPASSX_GROUPMODEL_H diff --git a/src/gui/group/GroupView.cpp b/src/gui/group/GroupView.cpp index 6d971577..ae34d8b0 100644 --- a/src/gui/group/GroupView.cpp +++ b/src/gui/group/GroupView.cpp @@ -27,28 +27,31 @@ GroupView::GroupView(Database* db, QWidget* parent) : QTreeView(parent) , m_model(new GroupModel(db, this)) + , m_updatingExpanded(false) { QTreeView::setModel(m_model); setHeaderHidden(true); setUniformRowHeights(true); - recInitExpanded(db->rootGroup()); connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(expandedChanged(QModelIndex))); connect(this, SIGNAL(collapsed(QModelIndex)), this, SLOT(expandedChanged(QModelIndex))); connect(m_model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(syncExpandedState(QModelIndex,int,int))); + connect(m_model, SIGNAL(modelReset()), SLOT(modelReset())); connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(emitGroupChanged())); - setCurrentIndex(m_model->index(0, 0)); - // invoke later so the EntryView is connected - QMetaObject::invokeMethod(this, "emitGroupChanged", Qt::QueuedConnection, - Q_ARG(QModelIndex, m_model->index(0, 0))); + modelReset(); setDragEnabled(true); viewport()->setAcceptDrops(true); setDropIndicatorShown(true); } +void GroupView::changeDatabase(Database* newDb) +{ + m_model->changeDatabase(newDb); +} + void GroupView::dragMoveEvent(QDragMoveEvent* event) { QTreeView::dragMoveEvent(event); @@ -72,13 +75,19 @@ Group* GroupView::currentGroup() void GroupView::expandedChanged(const QModelIndex& index) { + if (m_updatingExpanded) { + return; + } + Group* group = m_model->groupFromIndex(index); group->setExpanded(isExpanded(index)); } void GroupView::recInitExpanded(Group* group) { + m_updatingExpanded = true; expandGroup(group, group->isExpanded()); + m_updatingExpanded = false; Q_FOREACH (Group* child, group->children()) { recInitExpanded(child); @@ -119,3 +128,9 @@ void GroupView::setCurrentGroup(Group* group) { setCurrentIndex(m_model->index(group)); } + +void GroupView::modelReset() +{ + recInitExpanded(m_model->groupFromIndex(m_model->index(0, 0))); + setCurrentIndex(m_model->index(0, 0)); +} diff --git a/src/gui/group/GroupView.h b/src/gui/group/GroupView.h index af87dbe8..f9cb9beb 100644 --- a/src/gui/group/GroupView.h +++ b/src/gui/group/GroupView.h @@ -30,6 +30,7 @@ class GroupView : public QTreeView public: explicit GroupView(Database* db, QWidget* parent = 0); + void changeDatabase(Database* newDb); void setModel(QAbstractItemModel* model); Group* currentGroup(); void setCurrentGroup(Group* group); @@ -43,6 +44,7 @@ private Q_SLOTS: void emitGroupChanged(const QModelIndex& index); void emitGroupChanged(); void syncExpandedState(const QModelIndex& parent, int start, int end); + void modelReset(); protected: void dragMoveEvent(QDragMoveEvent* event); @@ -51,6 +53,7 @@ private: void recInitExpanded(Group* group); GroupModel* const m_model; + bool m_updatingExpanded; }; #endif // KEEPASSX_GROUPVIEW_H diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 740aee9f..b428b62c 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -52,16 +52,15 @@ void TestGui::testOpenDatabase() QAction* actionDatabaseOpen = m_mainWindow->findChild("actionDatabaseOpen"); fileDialog()->setNextFileName(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.kdbx")); actionDatabaseOpen->trigger(); - QWidget* keyDialog = m_mainWindow->findChild("DatabaseOpenDialog"); - QVERIFY(keyDialog); - QTest::qWaitForWindowShown(keyDialog); + QTest::qWait(20); - QLineEdit* editPassword = keyDialog->findChild("editPassword"); + QWidget* databaseOpenWidget = m_mainWindow->findChild("databaseOpenWidget"); + QLineEdit* editPassword = databaseOpenWidget->findChild("editPassword"); QVERIFY(editPassword); - QTest::keyClicks(editPassword, "a"); - QDialogButtonBox* buttonBox = keyDialog->findChild("buttonBox"); - QTest::mouseClick(buttonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + QTest::keyClicks(editPassword, "a"); + QTest::keyClick(editPassword, Qt::Key_Enter); + QTest::qWait(20); }