Convert DatabaseOpenDialog into a widget on DatabaseWidget.

This commit is contained in:
Felix Geyer 2012-06-28 09:21:15 +02:00
parent 900beae046
commit 92af92ccbe
15 changed files with 250 additions and 135 deletions

View File

@ -55,7 +55,7 @@ set(keepassx_SOURCES
gui/Application.cpp gui/Application.cpp
gui/ChangeMasterKeyWidget.cpp gui/ChangeMasterKeyWidget.cpp
gui/Clipboard.cpp gui/Clipboard.cpp
gui/DatabaseOpenDialog.cpp gui/DatabaseOpenWidget.cpp
gui/DatabaseSettingsWidget.cpp gui/DatabaseSettingsWidget.cpp
gui/DatabaseTabWidget.cpp gui/DatabaseTabWidget.cpp
gui/DatabaseWidget.cpp gui/DatabaseWidget.cpp
@ -65,7 +65,7 @@ set(keepassx_SOURCES
gui/EditWidgetIcons.cpp gui/EditWidgetIcons.cpp
gui/FileDialog.cpp gui/FileDialog.cpp
gui/IconModels.cpp gui/IconModels.cpp
gui/KeePass1OpenDialog.cpp gui/KeePass1OpenWidget.cpp
gui/LineEdit.cpp gui/LineEdit.cpp
gui/MainWindow.cpp gui/MainWindow.cpp
gui/SettingsWidget.cpp gui/SettingsWidget.cpp
@ -101,7 +101,7 @@ set(keepassx_MOC
gui/Application.h gui/Application.h
gui/ChangeMasterKeyWidget.h gui/ChangeMasterKeyWidget.h
gui/Clipboard.h gui/Clipboard.h
gui/DatabaseOpenDialog.h gui/DatabaseOpenWidget.h
gui/DatabaseSettingsWidget.h gui/DatabaseSettingsWidget.h
gui/DatabaseTabWidget.h gui/DatabaseTabWidget.h
gui/DatabaseWidget.h gui/DatabaseWidget.h
@ -110,7 +110,7 @@ set(keepassx_MOC
gui/EditWidget.h gui/EditWidget.h
gui/EditWidgetIcons.h gui/EditWidgetIcons.h
gui/IconModels.h gui/IconModels.h
gui/KeePass1OpenDialog.h gui/KeePass1OpenWidget.h
gui/LineEdit.h gui/LineEdit.h
gui/MainWindow.h gui/MainWindow.h
gui/SettingsWidget.h gui/SettingsWidget.h
@ -134,7 +134,7 @@ set(keepassx_MOC
set(keepassx_FORMS set(keepassx_FORMS
gui/AboutDialog.ui gui/AboutDialog.ui
gui/ChangeMasterKeyWidget.ui gui/ChangeMasterKeyWidget.ui
gui/DatabaseOpenDialog.ui gui/DatabaseOpenWidget.ui
gui/DatabaseSettingsWidget.ui gui/DatabaseSettingsWidget.ui
gui/EditWidget.ui gui/EditWidget.ui
gui/EditWidgetIcons.ui gui/EditWidgetIcons.ui

View File

@ -15,23 +15,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "DatabaseOpenDialog.h" #include "DatabaseOpenWidget.h"
#include "ui_DatabaseOpenDialog.h" #include "ui_DatabaseOpenWidget.h"
#include <QtGui/QMessageBox> #include <QtGui/QMessageBox>
#include "core/Config.h" #include "core/Config.h"
#include "core/Database.h"
#include "gui/FileDialog.h" #include "gui/FileDialog.h"
#include "format/KeePass2Reader.h" #include "format/KeePass2Reader.h"
#include "keys/FileKey.h" #include "keys/FileKey.h"
#include "keys/PasswordKey.h" #include "keys/PasswordKey.h"
DatabaseOpenDialog::DatabaseOpenDialog(QFile* file, const QString& filename, QWidget* parent) DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent)
: QDialog(parent) : DialogyWidget(parent)
, m_ui(new Ui::DatabaseOpenDialog()) , m_ui(new Ui::DatabaseOpenWidget())
, m_db(0) , m_db(0)
, m_file(file) , m_file(0)
, m_filename(filename)
{ {
m_ui->setupUi(this); 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(accepted()), SLOT(openDatabase()));
connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject())); 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<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)) {
@ -59,16 +69,12 @@ DatabaseOpenDialog::DatabaseOpenDialog(QFile* file, const QString& filename, QWi
m_ui->editPassword->setFocus(); m_ui->editPassword->setFocus();
} }
DatabaseOpenDialog::~DatabaseOpenDialog() Database* DatabaseOpenWidget::database()
{
}
Database* DatabaseOpenDialog::database()
{ {
return m_db; return m_db;
} }
void DatabaseOpenDialog::enterKey(const QString& pw, const QString& keyFile) void DatabaseOpenWidget::enterKey(const QString& pw, const QString& keyFile)
{ {
if (!pw.isNull()) { if (!pw.isNull()) {
m_ui->editPassword->setText(pw); m_ui->editPassword->setText(pw);
@ -80,7 +86,7 @@ void DatabaseOpenDialog::enterKey(const QString& pw, const QString& keyFile)
openDatabase(); openDatabase();
} }
void DatabaseOpenDialog::openDatabase() void DatabaseOpenWidget::openDatabase()
{ {
KeePass2Reader reader; KeePass2Reader reader;
CompositeKey masterKey; CompositeKey masterKey;
@ -109,10 +115,13 @@ void DatabaseOpenDialog::openDatabase()
config()->set("LastKeyFiles", lastKeyFiles); config()->set("LastKeyFiles", lastKeyFiles);
m_file->reset(); m_file->reset();
if (m_db) {
delete m_db;
}
m_db = reader.readDatabase(m_file, masterKey); m_db = reader.readDatabase(m_file, masterKey);
if (m_db) { if (m_db) {
accept(); Q_EMIT editFinished(true);
} }
else { else {
QMessageBox::warning(this, tr("Error"), tr("Unable to open the database.\n%1") 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); m_ui->editPassword->setEchoMode(checked ? QLineEdit::Password : QLineEdit::Normal);
} }
void DatabaseOpenDialog::activatePassword() void DatabaseOpenWidget::activatePassword()
{ {
m_ui->checkPassword->setChecked(true); m_ui->checkPassword->setChecked(true);
} }
void DatabaseOpenDialog::activateKeyFile() void DatabaseOpenWidget::activateKeyFile()
{ {
m_ui->checkKeyFile->setChecked(true); m_ui->checkKeyFile->setChecked(true);
} }
void DatabaseOpenDialog::setOkButtonEnabled() void DatabaseOpenWidget::setOkButtonEnabled()
{ {
bool enable = m_ui->checkPassword->isChecked() bool enable = m_ui->checkPassword->isChecked()
|| (m_ui->checkKeyFile->isChecked() && !m_ui->comboKeyFile->currentText().isEmpty()); || (m_ui->checkKeyFile->isChecked() && !m_ui->comboKeyFile->currentText().isEmpty());
@ -144,7 +158,7 @@ void DatabaseOpenDialog::setOkButtonEnabled()
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enable); 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 filters = QString("%1 (*);;%2 (*.key)").arg(tr("All files"), tr("Key files"));
QString filename = fileDialog()->getOpenFileName(this, tr("Select key file"), QString(), filters); QString filename = fileDialog()->getOpenFileName(this, tr("Select key file"), QString(), filters);

View File

@ -15,31 +15,37 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KEEPASSX_DATABASEOPENDIALOG_H #ifndef KEEPASSX_DATABASEOPENWIDGET_H
#define KEEPASSX_DATABASEOPENDIALOG_H #define KEEPASSX_DATABASEOPENWIDGET_H
#include <QtCore/QScopedPointer> #include <QtCore/QScopedPointer>
#include <QtGui/QDialog>
#include "gui/DialogyWidget.h"
class Database; class Database;
class QFile; class QFile;
namespace Ui { namespace Ui {
class DatabaseOpenDialog; class DatabaseOpenWidget;
} }
class DatabaseOpenDialog : public QDialog class DatabaseOpenWidget : public DialogyWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
DatabaseOpenDialog(QFile* file, const QString& filename, QWidget* parent = 0); DatabaseOpenWidget(QWidget* parent = 0);
~DatabaseOpenDialog(); ~DatabaseOpenWidget();
Database* database(); void load(QFile* file, const QString& filename);
void enterKey(const QString& pw, const QString& keyFile); void enterKey(const QString& pw, const QString& keyFile);
Database* database();
Q_SIGNALS:
void editFinished(bool accepted);
protected Q_SLOTS: protected Q_SLOTS:
virtual void openDatabase(); virtual void openDatabase();
void reject();
private Q_SLOTS: private Q_SLOTS:
void togglePassword(bool checked); void togglePassword(bool checked);
@ -49,13 +55,13 @@ private Q_SLOTS:
void browseKeyFile(); void browseKeyFile();
protected: protected:
const QScopedPointer<Ui::DatabaseOpenDialog> m_ui; const QScopedPointer<Ui::DatabaseOpenWidget> m_ui;
Database* m_db; Database* m_db;
QFile* const m_file; QFile* m_file;
const QString m_filename; QString m_filename;
private: private:
Q_DISABLE_COPY(DatabaseOpenDialog) Q_DISABLE_COPY(DatabaseOpenWidget)
}; };
#endif // KEEPASSX_DATABASEOPENDIALOG_H #endif // KEEPASSX_DATABASEOPENWIDGET_H

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>DatabaseOpenDialog</class> <class>DatabaseOpenWidget</class>
<widget class="QDialog" name="DatabaseOpenDialog"> <widget class="QWidget" name="DatabaseOpenWidget">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@ -25,11 +25,9 @@
#include "core/Database.h" #include "core/Database.h"
#include "core/Group.h" #include "core/Group.h"
#include "core/Metadata.h" #include "core/Metadata.h"
#include "gui/DatabaseOpenDialog.h"
#include "gui/DatabaseWidget.h" #include "gui/DatabaseWidget.h"
#include "gui/DragTabBar.h" #include "gui/DragTabBar.h"
#include "gui/FileDialog.h" #include "gui/FileDialog.h"
#include "gui/KeePass1OpenDialog.h"
#include "gui/entry/EntryView.h" #include "gui/entry/EntryView.h"
#include "gui/group/GroupView.h" #include "gui/group/GroupView.h"
@ -93,6 +91,8 @@ void DatabaseTabWidget::openDatabase()
void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw,
const QString& keyFile) const QString& keyFile)
{ {
DatabaseManagerStruct dbStruct;
QScopedPointer<QFile> file(new QFile(fileName)); QScopedPointer<QFile> file(new QFile(fileName));
// TODO: error handling // TODO: error handling
if (!file->open(QIODevice::ReadWrite)) { if (!file->open(QIODevice::ReadWrite)) {
@ -102,26 +102,22 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw,
} }
else { else {
// can only open read-only // can only open read-only
m_curDbStruct.readOnly = true; dbStruct.readOnly = true;
} }
} }
m_curDbStruct.file = file.take(); Database* db = new Database();
m_curDbStruct.fileName = QFileInfo(fileName).absoluteFilePath(); dbStruct.dbWidget = new DatabaseWidget(db, this);
dbStruct.file = file.take();
dbStruct.fileName = QFileInfo(fileName).absoluteFilePath();
openDatabaseDialog(pw, keyFile); insertDatabase(db, dbStruct);
}
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();
if (!pw.isNull() || !keyFile.isEmpty()) { 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; 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); insertDatabase(db, dbStruct);
connect(m_curKeyDialog, SIGNAL(accepted()), SLOT(openDatabaseRead()));
connect(m_curKeyDialog, SIGNAL(rejected()), SLOT(openDatabaseCleanup()));
m_curKeyDialog->setModal(true);
m_curKeyDialog->show();
}
void DatabaseTabWidget::openDatabaseRead() dbStruct.dbWidget->switchToImportKeepass1(file.take(), fileName);
{
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();
} }
void DatabaseTabWidget::emitEntrySelectionChanged() void DatabaseTabWidget::emitEntrySelectionChanged()
@ -503,14 +474,13 @@ void DatabaseTabWidget::insertDatabase(Database* db, const DatabaseManagerStruct
updateTabName(db); updateTabName(db);
int index = databaseIndex(db); int index = databaseIndex(db);
setCurrentIndex(index); setCurrentIndex(index);
connect(db, SIGNAL(nameTextChanged()), SLOT(updateTabNameFromSender())); connectDatabase(db);
connect(dbStruct.dbWidget->entryView(), SIGNAL(entrySelectionChanged()), connect(dbStruct.dbWidget->entryView(), SIGNAL(entrySelectionChanged()),
SLOT(emitEntrySelectionChanged())); SLOT(emitEntrySelectionChanged()));
connect(dbStruct.dbWidget, SIGNAL(closeRequest()), SLOT(closeDatabaseFromSender())); connect(dbStruct.dbWidget, SIGNAL(closeRequest()), SLOT(closeDatabaseFromSender()));
connect(db, SIGNAL(modified()), SLOT(modified()));
connect(dbStruct.dbWidget, SIGNAL(currentModeChanged(DatabaseWidget::Mode)), connect(dbStruct.dbWidget, SIGNAL(currentModeChanged(DatabaseWidget::Mode)),
SIGNAL(currentWidgetModeChanged(DatabaseWidget::Mode))); SIGNAL(currentWidgetModeChanged(DatabaseWidget::Mode)));
db->setEmitModified(true); connect(dbStruct.dbWidget, SIGNAL(databaseChanged(Database*)), SLOT(changeDatabase(Database*)));
} }
DatabaseWidget* DatabaseTabWidget::currentDatabaseWidget() DatabaseWidget* DatabaseTabWidget::currentDatabaseWidget()
@ -558,3 +528,29 @@ void DatabaseTabWidget::updateLastDatabases(const QString& filename)
config()->set("LastDatabases", lastDatabases); config()->set("LastDatabases", lastDatabases);
} }
} }
void DatabaseTabWidget::changeDatabase(Database* newDb)
{
Q_ASSERT(sender());
Q_ASSERT(!m_dbList.contains(newDb));
DatabaseWidget* dbWidget = static_cast<DatabaseWidget*>(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);
}

View File

@ -25,7 +25,7 @@
#include "gui/DatabaseWidget.h" #include "gui/DatabaseWidget.h"
class DatabaseWidget; class DatabaseWidget;
class DatabaseOpenDialog; class DatabaseOpenWidget;
class QFile; class QFile;
struct DatabaseManagerStruct struct DatabaseManagerStruct
@ -84,12 +84,10 @@ Q_SIGNALS:
private Q_SLOTS: private Q_SLOTS:
void updateTabName(Database* db); void updateTabName(Database* db);
void updateTabNameFromSender(); void updateTabNameFromSender();
void openDatabaseDialog(const QString& pw = QString(), const QString& keyFile = QString());
void openDatabaseRead();
void openDatabaseCleanup();
void emitEntrySelectionChanged(); void emitEntrySelectionChanged();
void modified(); void modified();
void toggleTabbar(); void toggleTabbar();
void changeDatabase(Database* newDb);
private: private:
void saveDatabase(Database* db); void saveDatabase(Database* db);
@ -98,16 +96,14 @@ private:
int databaseIndex(Database* db); int databaseIndex(Database* db);
Database* indexDatabase(int index); Database* indexDatabase(int index);
DatabaseManagerStruct indexDatabaseManagerStruct(int index); DatabaseManagerStruct indexDatabaseManagerStruct(int index);
Database* databaseFromDatabaseWidget(DatabaseWidget* dbWidget); Database* databaseFromDatabaseWidget(DatabaseWidget* dbWidget);
void insertDatabase(Database* db, const DatabaseManagerStruct& dbStruct); void insertDatabase(Database* db, const DatabaseManagerStruct& dbStruct);
void updateLastDatabases(const QString& filename); void updateLastDatabases(const QString& filename);
void connectDatabase(Database* newDb, Database* oldDb = 0);
QWidget* const m_window; QWidget* const m_window;
KeePass2Writer m_writer; KeePass2Writer m_writer;
QHash<Database*, DatabaseManagerStruct> m_dbList; QHash<Database*, DatabaseManagerStruct> m_dbList;
DatabaseManagerStruct m_curDbStruct;
DatabaseOpenDialog* m_curKeyDialog;
}; };
#endif // KEEPASSX_DATABASETABWIDGET_H #endif // KEEPASSX_DATABASETABWIDGET_H

View File

@ -32,7 +32,9 @@
#include "core/Tools.h" #include "core/Tools.h"
#include "gui/ChangeMasterKeyWidget.h" #include "gui/ChangeMasterKeyWidget.h"
#include "gui/Clipboard.h" #include "gui/Clipboard.h"
#include "gui/DatabaseOpenWidget.h"
#include "gui/DatabaseSettingsWidget.h" #include "gui/DatabaseSettingsWidget.h"
#include "gui/KeePass1OpenWidget.h"
#include "gui/entry/EditEntryWidget.h" #include "gui/entry/EditEntryWidget.h"
#include "gui/entry/EntryView.h" #include "gui/entry/EntryView.h"
#include "gui/group/EditGroupWidget.h" #include "gui/group/EditGroupWidget.h"
@ -69,6 +71,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
m_entryView = new EntryView(rightHandSideWidget); m_entryView = new EntryView(rightHandSideWidget);
m_entryView->setObjectName("entryView"); m_entryView->setObjectName("entryView");
m_entryView->setContextMenuPolicy(Qt::CustomContextMenu); m_entryView->setContextMenuPolicy(Qt::CustomContextMenu);
m_entryView->setGroup(db->rootGroup());
connect(m_entryView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showEntryContextMenu(QPoint))); connect(m_entryView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showEntryContextMenu(QPoint)));
QSizePolicy policy; QSizePolicy policy;
@ -111,12 +114,18 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
headlineLabelFont.setPointSize(headlineLabelFont.pointSize() + 2); headlineLabelFont.setPointSize(headlineLabelFont.pointSize() + 2);
m_changeMasterKeyWidget->headlineLabel()->setFont(headlineLabelFont); m_changeMasterKeyWidget->headlineLabel()->setFont(headlineLabelFont);
m_databaseSettingsWidget = new DatabaseSettingsWidget(); 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_mainWidget);
addWidget(m_editEntryWidget); addWidget(m_editEntryWidget);
addWidget(m_editGroupWidget); addWidget(m_editGroupWidget);
addWidget(m_changeMasterKeyWidget); addWidget(m_changeMasterKeyWidget);
addWidget(m_databaseSettingsWidget); addWidget(m_databaseSettingsWidget);
addWidget(m_historyEditEntryWidget); addWidget(m_historyEditEntryWidget);
addWidget(m_databaseOpenWidget);
addWidget(m_keepass1OpenWidget);
m_actionEntryNew = m_menuEntry->addAction(tr("Add new entry"), this, SLOT(createEntry())); m_actionEntryNew = m_menuEntry->addAction(tr("Add new entry"), this, SLOT(createEntry()));
m_actionEntryNew->setIcon(dataPath()->icon("actions", "entry-new", false)); 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_editGroupWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool)));
connect(m_changeMasterKeyWidget, SIGNAL(editFinished(bool)), SLOT(updateMasterKey(bool))); connect(m_changeMasterKeyWidget, SIGNAL(editFinished(bool)), SLOT(updateMasterKey(bool)));
connect(m_databaseSettingsWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(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(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged()));
connect(m_searchUi->searchEdit, SIGNAL(textChanged(QString)), this, SLOT(startSearchTimer())); connect(m_searchUi->searchEdit, SIGNAL(textChanged(QString)), this, SLOT(startSearchTimer()));
connect(m_searchUi->caseSensitiveCheckBox, SIGNAL(toggled(bool)), this, SLOT(startSearch())); connect(m_searchUi->caseSensitiveCheckBox, SIGNAL(toggled(bool)), this, SLOT(startSearch()));
@ -182,6 +193,8 @@ DatabaseWidget::Mode DatabaseWidget::currentMode()
case 3: // change master key case 3: // change master key
case 4: // database settings case 4: // database settings
case 5: // entry history case 5: // entry history
case 6: // open database
case 7: // keepass 1 import
return DatabaseWidget::EditMode; return DatabaseWidget::EditMode;
default: default:
Q_ASSERT(false); Q_ASSERT(false);
@ -449,6 +462,31 @@ void DatabaseWidget::updateMasterKey(bool accepted)
setCurrentIndex(0); setCurrentIndex(0);
} }
void DatabaseWidget::openDatabase(bool accepted)
{
if (accepted) {
Database* oldDb = m_db;
m_db = static_cast<DatabaseOpenWidget*>(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() void DatabaseWidget::switchToEntryEdit()
{ {
switchToEntryEdit(m_entryView->currentEntry(), false); switchToEntryEdit(m_entryView->currentEntry(), false);
@ -471,6 +509,25 @@ void DatabaseWidget::switchToDatabaseSettings()
setCurrentIndex(4); 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() void DatabaseWidget::toggleSearch()
{ {
if (m_entryView->inSearch()) { if (m_entryView->inSearch()) {

View File

@ -22,6 +22,7 @@
#include <QtGui/QStackedWidget> #include <QtGui/QStackedWidget>
class ChangeMasterKeyWidget; class ChangeMasterKeyWidget;
class DatabaseOpenWidget;
class DatabaseSettingsWidget; class DatabaseSettingsWidget;
class Database; class Database;
class EditEntryWidget; class EditEntryWidget;
@ -30,6 +31,8 @@ class Entry;
class EntryView; class EntryView;
class Group; class Group;
class GroupView; class GroupView;
class KeePass1OpenWidget;
class QFile;
class QMenu; class QMenu;
namespace Ui { namespace Ui {
@ -74,6 +77,7 @@ public:
Q_SIGNALS: Q_SIGNALS:
void closeRequest(); void closeRequest();
void currentModeChanged(DatabaseWidget::Mode mode); void currentModeChanged(DatabaseWidget::Mode mode);
void databaseChanged(Database* newDb);
public Q_SLOTS: public Q_SLOTS:
void createEntry(); void createEntry();
@ -87,6 +91,9 @@ public Q_SLOTS:
void switchToGroupEdit(); void switchToGroupEdit();
void switchToMasterKeyChange(); void switchToMasterKeyChange();
void switchToDatabaseSettings(); 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(); void toggleSearch();
private Q_SLOTS: private Q_SLOTS:
@ -97,6 +104,7 @@ private Q_SLOTS:
void switchToEntryEdit(Entry* entry, bool create); void switchToEntryEdit(Entry* entry, bool create);
void switchToGroupEdit(Group* entry, bool create); void switchToGroupEdit(Group* entry, bool create);
void updateMasterKey(bool accepted); void updateMasterKey(bool accepted);
void openDatabase(bool accepted);
void emitCurrentModeChanged(); void emitCurrentModeChanged();
void clearLastGroup(Group* group); void clearLastGroup(Group* group);
void search(); void search();
@ -110,7 +118,7 @@ private Q_SLOTS:
void showEntryContextMenu(const QPoint& pos); void showEntryContextMenu(const QPoint& pos);
private: private:
Database* const m_db; Database* m_db;
const QScopedPointer<Ui::SearchWidget> m_searchUi; const QScopedPointer<Ui::SearchWidget> m_searchUi;
QWidget* const m_searchWidget; QWidget* const m_searchWidget;
QWidget* m_mainWidget; QWidget* m_mainWidget;
@ -119,6 +127,8 @@ private:
EditGroupWidget* m_editGroupWidget; EditGroupWidget* m_editGroupWidget;
ChangeMasterKeyWidget* m_changeMasterKeyWidget; ChangeMasterKeyWidget* m_changeMasterKeyWidget;
DatabaseSettingsWidget* m_databaseSettingsWidget; DatabaseSettingsWidget* m_databaseSettingsWidget;
DatabaseOpenWidget* m_databaseOpenWidget;
KeePass1OpenWidget* m_keepass1OpenWidget;
GroupView* m_groupView; GroupView* m_groupView;
EntryView* m_entryView; EntryView* m_entryView;
Group* m_newGroup; Group* m_newGroup;

View File

@ -15,29 +15,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "KeePass1OpenDialog.h" #include "KeePass1OpenWidget.h"
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtGui/QMessageBox> #include <QtGui/QMessageBox>
#include "ui_DatabaseOpenDialog.h" #include "ui_DatabaseOpenWidget.h"
#include "core/Database.h" #include "core/Database.h"
#include "core/Metadata.h" #include "core/Metadata.h"
#include "format/KeePass1Reader.h" #include "format/KeePass1Reader.h"
KeePass1OpenDialog::KeePass1OpenDialog(QFile* file, const QString& filename, QWidget* parent) KeePass1OpenWidget::KeePass1OpenWidget(QWidget* parent)
: DatabaseOpenDialog(file, filename, parent) : DatabaseOpenWidget(parent)
{ {
setWindowTitle(tr("Import KeePass1 database")); setWindowTitle(tr("Import KeePass1 database"));
} }
KeePass1OpenDialog::~KeePass1OpenDialog() KeePass1OpenWidget::~KeePass1OpenWidget()
{ {
delete m_file; delete m_file;
} }
void KeePass1OpenDialog::openDatabase() void KeePass1OpenWidget::openDatabase()
{ {
KeePass1Reader reader; KeePass1Reader reader;
@ -53,11 +53,14 @@ void KeePass1OpenDialog::openDatabase()
} }
m_file->reset(); m_file->reset();
if (m_db) {
delete m_db;
}
m_db = reader.readDatabase(m_file, password, keyFileName); m_db = reader.readDatabase(m_file, password, keyFileName);
if (m_db) { if (m_db) {
m_db->metadata()->setName(QFileInfo(m_filename).completeBaseName()); m_db->metadata()->setName(QFileInfo(m_filename).completeBaseName());
accept(); Q_EMIT editFinished(true);
} }
else { else {
QMessageBox::warning(this, tr("Error"), tr("Unable to open the database.\n%1") QMessageBox::warning(this, tr("Error"), tr("Unable to open the database.\n%1")

View File

@ -15,21 +15,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KEEPASSX_KEEPASS1OPENDIALOG_H #ifndef KEEPASSX_KEEPASS1OPENWIDGET_H
#define KEEPASSX_KEEPASS1OPENDIALOG_H #define KEEPASSX_KEEPASS1OPENWIDGET_H
#include "gui/DatabaseOpenDialog.h" #include "gui/DatabaseOpenWidget.h"
class KeePass1OpenDialog : public DatabaseOpenDialog class KeePass1OpenWidget : public DatabaseOpenWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit KeePass1OpenDialog(QFile* file, const QString& filename, QWidget* parent = 0); explicit KeePass1OpenWidget(QWidget* parent = 0);
~KeePass1OpenDialog(); ~KeePass1OpenWidget();
protected: protected:
void openDatabase(); void openDatabase();
}; };
#endif // KEEPASSX_KEEPASS1OPENDIALOG_H #endif // KEEPASSX_KEEPASS1OPENWIDGET_H

View File

@ -27,15 +27,30 @@
GroupModel::GroupModel(Database* db, QObject* parent) GroupModel::GroupModel(Database* db, QObject* parent)
: QAbstractItemModel(parent) : QAbstractItemModel(parent)
, m_db(0)
{ {
m_root = db->rootGroup(); changeDatabase(db);
connect(db, SIGNAL(groupDataChanged(Group*)), SLOT(groupDataChanged(Group*))); }
connect(db, SIGNAL(groupAboutToAdd(Group*,int)), SLOT(groupAboutToAdd(Group*,int)));
connect(db, SIGNAL(groupAdded()), SLOT(groupAdded())); void GroupModel::changeDatabase(Database* newDb)
connect(db, SIGNAL(groupAboutToRemove(Group*)), SLOT(groupAboutToRemove(Group*))); {
connect(db, SIGNAL(groupRemoved()), SLOT(groupRemoved())); beginResetModel();
connect(db, SIGNAL(groupAboutToMove(Group*,Group*,int)), SLOT(groupAboutToMove(Group*,Group*,int)));
connect(db, SIGNAL(groupMoved()), SLOT(groupMoved())); 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 int GroupModel::rowCount(const QModelIndex& parent) const
@ -66,7 +81,7 @@ QModelIndex GroupModel::index(int row, int column, const QModelIndex& parent) co
Group* group; Group* group;
if (!parent.isValid()) { if (!parent.isValid()) {
group = m_root; group = m_db->rootGroup();
} }
else { else {
group = groupFromIndex(parent)->children().at(row); group = groupFromIndex(parent)->children().at(row);
@ -269,7 +284,7 @@ QMimeData* GroupModel::mimeData(const QModelIndexList& indexes) const
if (!indexes[i].isValid()) { if (!indexes[i].isValid()) {
continue; continue;
} }
stream << m_root->database()->uuid() << groupFromIndex(indexes[i])->uuid(); stream << m_db->uuid() << groupFromIndex(indexes[i])->uuid();
} }
data->setData(mimeTypes().first(), encoded); data->setData(mimeTypes().first(), encoded);

View File

@ -29,6 +29,7 @@ class GroupModel : public QAbstractItemModel
public: public:
explicit GroupModel(Database* db, QObject* parent = 0); explicit GroupModel(Database* db, QObject* parent = 0);
void changeDatabase(Database* newDb);
QModelIndex index(Group* group) const; QModelIndex index(Group* group) const;
Group* groupFromIndex(const QModelIndex& index) const; Group* groupFromIndex(const QModelIndex& index) const;
@ -58,7 +59,7 @@ private Q_SLOTS:
void groupMoved(); void groupMoved();
private: private:
Group* m_root; Database* m_db;
}; };
#endif // KEEPASSX_GROUPMODEL_H #endif // KEEPASSX_GROUPMODEL_H

View File

@ -27,28 +27,31 @@
GroupView::GroupView(Database* db, QWidget* parent) GroupView::GroupView(Database* db, QWidget* parent)
: QTreeView(parent) : QTreeView(parent)
, m_model(new GroupModel(db, this)) , m_model(new GroupModel(db, this))
, m_updatingExpanded(false)
{ {
QTreeView::setModel(m_model); QTreeView::setModel(m_model);
setHeaderHidden(true); setHeaderHidden(true);
setUniformRowHeights(true); setUniformRowHeights(true);
recInitExpanded(db->rootGroup());
connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(expandedChanged(QModelIndex))); connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(expandedChanged(QModelIndex)));
connect(this, SIGNAL(collapsed(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(rowsInserted(QModelIndex,int,int)), SLOT(syncExpandedState(QModelIndex,int,int)));
connect(m_model, SIGNAL(modelReset()), SLOT(modelReset()));
connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(emitGroupChanged())); connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(emitGroupChanged()));
setCurrentIndex(m_model->index(0, 0)); modelReset();
// invoke later so the EntryView is connected
QMetaObject::invokeMethod(this, "emitGroupChanged", Qt::QueuedConnection,
Q_ARG(QModelIndex, m_model->index(0, 0)));
setDragEnabled(true); setDragEnabled(true);
viewport()->setAcceptDrops(true); viewport()->setAcceptDrops(true);
setDropIndicatorShown(true); setDropIndicatorShown(true);
} }
void GroupView::changeDatabase(Database* newDb)
{
m_model->changeDatabase(newDb);
}
void GroupView::dragMoveEvent(QDragMoveEvent* event) void GroupView::dragMoveEvent(QDragMoveEvent* event)
{ {
QTreeView::dragMoveEvent(event); QTreeView::dragMoveEvent(event);
@ -72,13 +75,19 @@ Group* GroupView::currentGroup()
void GroupView::expandedChanged(const QModelIndex& index) void GroupView::expandedChanged(const QModelIndex& index)
{ {
if (m_updatingExpanded) {
return;
}
Group* group = m_model->groupFromIndex(index); Group* group = m_model->groupFromIndex(index);
group->setExpanded(isExpanded(index)); group->setExpanded(isExpanded(index));
} }
void GroupView::recInitExpanded(Group* group) void GroupView::recInitExpanded(Group* group)
{ {
m_updatingExpanded = true;
expandGroup(group, group->isExpanded()); expandGroup(group, group->isExpanded());
m_updatingExpanded = false;
Q_FOREACH (Group* child, group->children()) { Q_FOREACH (Group* child, group->children()) {
recInitExpanded(child); recInitExpanded(child);
@ -119,3 +128,9 @@ void GroupView::setCurrentGroup(Group* group)
{ {
setCurrentIndex(m_model->index(group)); setCurrentIndex(m_model->index(group));
} }
void GroupView::modelReset()
{
recInitExpanded(m_model->groupFromIndex(m_model->index(0, 0)));
setCurrentIndex(m_model->index(0, 0));
}

View File

@ -30,6 +30,7 @@ class GroupView : public QTreeView
public: public:
explicit GroupView(Database* db, QWidget* parent = 0); explicit GroupView(Database* db, QWidget* parent = 0);
void changeDatabase(Database* newDb);
void setModel(QAbstractItemModel* model); void setModel(QAbstractItemModel* model);
Group* currentGroup(); Group* currentGroup();
void setCurrentGroup(Group* group); void setCurrentGroup(Group* group);
@ -43,6 +44,7 @@ private Q_SLOTS:
void emitGroupChanged(const QModelIndex& index); void emitGroupChanged(const QModelIndex& index);
void emitGroupChanged(); void emitGroupChanged();
void syncExpandedState(const QModelIndex& parent, int start, int end); void syncExpandedState(const QModelIndex& parent, int start, int end);
void modelReset();
protected: protected:
void dragMoveEvent(QDragMoveEvent* event); void dragMoveEvent(QDragMoveEvent* event);
@ -51,6 +53,7 @@ private:
void recInitExpanded(Group* group); void recInitExpanded(Group* group);
GroupModel* const m_model; GroupModel* const m_model;
bool m_updatingExpanded;
}; };
#endif // KEEPASSX_GROUPVIEW_H #endif // KEEPASSX_GROUPVIEW_H

View File

@ -52,16 +52,15 @@ void TestGui::testOpenDatabase()
QAction* actionDatabaseOpen = m_mainWindow->findChild<QAction*>("actionDatabaseOpen"); QAction* actionDatabaseOpen = m_mainWindow->findChild<QAction*>("actionDatabaseOpen");
fileDialog()->setNextFileName(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.kdbx")); fileDialog()->setNextFileName(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.kdbx"));
actionDatabaseOpen->trigger(); actionDatabaseOpen->trigger();
QWidget* keyDialog = m_mainWindow->findChild<QWidget*>("DatabaseOpenDialog"); QTest::qWait(20);
QVERIFY(keyDialog);
QTest::qWaitForWindowShown(keyDialog);
QLineEdit* editPassword = keyDialog->findChild<QLineEdit*>("editPassword"); QWidget* databaseOpenWidget = m_mainWindow->findChild<QWidget*>("databaseOpenWidget");
QLineEdit* editPassword = databaseOpenWidget->findChild<QLineEdit*>("editPassword");
QVERIFY(editPassword); QVERIFY(editPassword);
QTest::keyClicks(editPassword, "a");
QDialogButtonBox* buttonBox = keyDialog->findChild<QDialogButtonBox*>("buttonBox"); QTest::keyClicks(editPassword, "a");
QTest::mouseClick(buttonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); QTest::keyClick(editPassword, Qt::Key_Enter);
QTest::qWait(20); QTest::qWait(20);
} }