diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3052df47e..c10a19d93 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,12 +44,14 @@ set(keepassx_SOURCES format/KeePass2Writer.cpp format/KeePass2XmlReader.cpp format/KeePass2XmlWriter.cpp + gui/DatabaseManager.cpp gui/DatabaseWidget.cpp gui/EditEntryWidget.cpp gui/EntryModel.cpp gui/EntryView.cpp gui/GroupModel.cpp gui/GroupView.cpp + gui/KeyOpenDialog.cpp gui/MainWindow.cpp keys/CompositeKey.cpp keys/Key.h @@ -65,12 +67,14 @@ set(keepassx_MOC core/Entry.h core/Group.h core/Metadata.h + gui/DatabaseManager.h gui/DatabaseWidget.h gui/EditEntryWidget.h gui/EntryModel.h gui/EntryView.h gui/GroupModel.h gui/GroupView.h + gui/KeyOpenDialog.h gui/MainWindow.h streams/HashedBlockStream.h streams/LayeredStream.h @@ -82,6 +86,7 @@ set(keepassx_FORMS gui/EditEntryWidget.ui gui/EditEntryWidgetMain.ui gui/EditEntryWidgetNotes.ui + gui/KeyOpenDialog.ui gui/MainWindow.ui ) diff --git a/src/gui/DatabaseManager.cpp b/src/gui/DatabaseManager.cpp new file mode 100644 index 000000000..aac637bdd --- /dev/null +++ b/src/gui/DatabaseManager.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2011 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 "DatabaseManager.h" + +#include +#include +#include + +#include "core/Database.h" +#include "core/Metadata.h" +#include "format/KeePass2XmlReader.h" +#include "gui/DatabaseWidget.h" +#include "gui/KeyOpenDialog.h" + +DatabaseManagerStruct::DatabaseManagerStruct() + : file(0) + , dbWidget(0) + , modified(false) + , readOnly(false) +{ +} + +DatabaseManager::DatabaseManager(QTabWidget* tabWidget) + : m_tabWidget(tabWidget) + , m_window(tabWidget->window()) +{ + connect(m_tabWidget, SIGNAL(tabCloseRequested(int)), SLOT(closeDatabase(int))); +} + +void DatabaseManager::openDatabase() +{ + QString fileName = QFileDialog::getOpenFileName(m_window, tr("Open database"), QString(), + tr("KeePass 2 Database").append(" (*.kdbx)")); + if (!fileName.isEmpty()) { + openDatabase(fileName); + } +} + +void DatabaseManager::openDatabase(const QString& fileName) +{ + DatabaseManagerStruct dbStruct; + + QScopedPointer file(new QFile(fileName)); + if (!file->open(QIODevice::ReadWrite)) { + if (!file->open(QIODevice::ReadOnly)) { + // can only open read-only + dbStruct.readOnly = true; + } + else { + // can't open + return; + } + } + + Database* db; + + do { + QScopedPointer keyDialog(new KeyOpenDialog(m_window)); + if (keyDialog->exec() == QDialog::Rejected) { + return; + } + + file->reset(); + db = m_reader.readDatabase(file.data(), keyDialog->key()); + } while (!db); + + dbStruct.file = file.take(); + dbStruct.dbWidget = new DatabaseWidget(db, m_tabWidget); + + m_dbList.insert(db, dbStruct); + + m_tabWidget->addTab(dbStruct.dbWidget, ""); + updateTabName(db); + + connect(db->metadata(), SIGNAL(nameTextChanged(Database*)), SLOT(updateTabName(Database*))); +} + +void DatabaseManager::closeDatabase(Database* db) +{ + Q_ASSERT(db); + + const DatabaseManagerStruct& dbStruct = m_dbList.value(db); + + if (dbStruct.modified) { + // TODO message box + } + + int index = databaseIndex(db); + Q_ASSERT(index != -1); + + m_tabWidget->removeTab(index); + delete dbStruct.dbWidget; + delete db; +} + +void DatabaseManager::closeDatabase(int index) +{ + closeDatabase(indexDatabase(index)); +} + +void DatabaseManager::updateTabName(Database* db) +{ + int index = databaseIndex(db); + Q_ASSERT(index != -1); + + const DatabaseManagerStruct& dbStruct = m_dbList.value(db); + + QString filename = QFileInfo(*dbStruct.file).completeBaseName(); + + QString tabName; + if (db->metadata()->name().isEmpty()) { + tabName = filename; + } + else { + tabName = QString("%1 [%2]").arg(db->metadata()->name().arg(filename)); + } + + m_tabWidget->setTabText(index, tabName); +} + +int DatabaseManager::databaseIndex(Database* db) +{ + QWidget* dbWidget = m_dbList.value(db).dbWidget; + return m_tabWidget->indexOf(dbWidget); +} + +Database* DatabaseManager::indexDatabase(int index) +{ + QWidget* dbWidget = m_tabWidget->widget(index); + + QHashIterator i(m_dbList); + while (i.hasNext()) { + i.next(); + if (i.value().dbWidget == dbWidget) { + return i.key(); + } + } + + return 0; +} diff --git a/src/gui/DatabaseManager.h b/src/gui/DatabaseManager.h new file mode 100644 index 000000000..6a583f05a --- /dev/null +++ b/src/gui/DatabaseManager.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011 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_DATABASEMANAGER_H +#define KEEPASSX_DATABASEMANAGER_H + +#include +#include + +#include "format/KeePass2Reader.h" +#include "format/KeePass2Writer.h" + +class QFile; +class QTabWidget; + +struct DatabaseManagerStruct +{ + DatabaseManagerStruct(); + + QFile* file; + QWidget* dbWidget; + bool modified; + bool readOnly; +}; + +class DatabaseManager : public QObject +{ + Q_OBJECT + +public: + DatabaseManager(QTabWidget* tabWidget); + void openDatabase(const QString& fileName); + void closeDatabase(Database* db); + +public Q_SLOTS: + void openDatabase(); + void closeDatabase(int index); + +private Q_SLOTS: + void updateTabName(Database* db); + +private: + int databaseIndex(Database* db); + Database* indexDatabase(int index); + + QTabWidget* m_tabWidget; + QWidget* m_window; + KeePass2Reader m_reader; + KeePass2Writer m_writer; + QHash m_dbList; +}; + +#endif // KEEPASSX_DATABASEMANAGER_H diff --git a/src/gui/KeyOpenDialog.cpp b/src/gui/KeyOpenDialog.cpp new file mode 100644 index 000000000..34fd2beab --- /dev/null +++ b/src/gui/KeyOpenDialog.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011 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 "KeyOpenDialog.h" +#include "ui_KeyOpenDialog.h" + +#include "keys/PasswordKey.h" + +KeyOpenDialog::KeyOpenDialog(QWidget* parent) + : QDialog(parent) + , m_ui(new Ui::KeyOpenDialog()) +{ + m_ui->setupUi(this); + + connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(createKey())); +} + +KeyOpenDialog::~KeyOpenDialog() +{ +} + +CompositeKey KeyOpenDialog::key() +{ + return m_key; +} + +void KeyOpenDialog::createKey() +{ + if (m_ui->checkPassword->isChecked()) { + m_key.addKey(PasswordKey(m_ui->editPassword->text())); + } + + if (m_ui->checkKeyFile->isChecked()) { + // TODO read key file + } +} diff --git a/src/gui/KeyOpenDialog.h b/src/gui/KeyOpenDialog.h new file mode 100644 index 000000000..7ae2c7faa --- /dev/null +++ b/src/gui/KeyOpenDialog.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011 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_KEYOPENDIALOG_H +#define KEEPASSX_KEYOPENDIALOG_H + +#include +#include + +#include "keys/CompositeKey.h" + +namespace Ui { + class KeyOpenDialog; +} + +class KeyOpenDialog : public QDialog +{ + Q_OBJECT + +public: + explicit KeyOpenDialog(QWidget* parent = 0); + ~KeyOpenDialog(); + CompositeKey key(); + +private Q_SLOTS: + void createKey(); + +private: + QScopedPointer m_ui; + CompositeKey m_key; + + Q_DISABLE_COPY(KeyOpenDialog) +}; + +#endif // KEEPASSX_KEYOPENDIALOG_H diff --git a/src/gui/KeyOpenDialog.ui b/src/gui/KeyOpenDialog.ui new file mode 100644 index 000000000..da0236042 --- /dev/null +++ b/src/gui/KeyOpenDialog.ui @@ -0,0 +1,113 @@ + + + KeyOpenDialog + + + + 0 + 0 + 353 + 172 + + + + Dialog + + + + + + Password: + + + + + + + + + + + + ... + + + + + + + + + Key File: + + + + + + + + + + 0 + 0 + + + + + + + + Browse + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + KeyOpenDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + KeyOpenDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 17ab64018..65c45119b 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -19,16 +19,15 @@ #include "core/Database.h" #include "core/Metadata.h" +#include "gui/DatabaseManager.h" #include "gui/DatabaseWidget.h" MainWindow::MainWindow() { setupUi(this); + + m_dbManager = new DatabaseManager(tabWidget); + + connect(actionOpenDatabase, SIGNAL(triggered()), m_dbManager, SLOT(openDatabase())); connect(actionQuit, SIGNAL(triggered()), SLOT(close())); } - -void MainWindow::addDatabase(Database* db) -{ - QWidget* databaseWidget = new DatabaseWidget(db, tabWidget); - tabWidget->addTab(databaseWidget, db->metadata()->name()); -} diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 4d57ba7ae..eb2a3f857 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -21,6 +21,7 @@ #include "ui_MainWindow.h" class Database; +class DatabaseManager; class MainWindow : public QMainWindow, private Ui::MainWindow { @@ -28,7 +29,9 @@ class MainWindow : public QMainWindow, private Ui::MainWindow public: MainWindow(); - void addDatabase(Database* db); + +private: + DatabaseManager* m_dbManager; }; #endif // KEEPASSX_MAINWINDOW_H diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index 0919ee58f..b00924ffe 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -20,6 +20,12 @@ -1 + + true + + + true + @@ -37,6 +43,8 @@ File + + @@ -59,6 +67,11 @@ About + + + Open database + + diff --git a/src/main.cpp b/src/main.cpp index d659cfed0..07d7f8e8a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,15 +39,14 @@ int main(int argc, char **argv) password.setPassword("a"); key.addKey(password); - KeePass2Reader* xreader = new KeePass2Reader(); - Database* db = xreader->readDatabase(QString(KEEPASSX_TEST_DIR).append("/NewDatabase.kdbx"), key); + //KeePass2Reader* xreader = new KeePass2Reader(); + //Database* db = xreader->readDatabase(QString(KEEPASSX_TEST_DIR).append("/NewDatabase.kdbx"), key); //KeePass2XmlReader* reader = new KeePass2XmlReader(); //Database* db = reader->readDatabase(QString(KEEPASSX_TEST_DIR).append("/NewDatabase.xml")); MainWindow mainWindow; mainWindow.show(); - mainWindow.addDatabase(db); return app.exec(); }