Improve auto save handling.

This commit is contained in:
Florian Geyer 2012-06-24 17:53:01 +02:00
parent b0ad864fe0
commit 204822b66f
11 changed files with 52 additions and 54 deletions

View File

@ -18,6 +18,7 @@
#include "Database.h" #include "Database.h"
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QTimer>
#include <QtCore/QXmlStreamReader> #include <QtCore/QXmlStreamReader>
#include "core/Group.h" #include "core/Group.h"
@ -30,19 +31,24 @@ QHash<Uuid, Database*> Database::m_uuidMap;
Database::Database() Database::Database()
: m_metadata(new Metadata(this)) : m_metadata(new Metadata(this))
, m_timer(new QTimer(this))
, m_cipher(KeePass2::CIPHER_AES) , m_cipher(KeePass2::CIPHER_AES)
, m_compressionAlgo(CompressionGZip) , m_compressionAlgo(CompressionGZip)
, m_transformRounds(50000) , m_transformRounds(50000)
, m_hasKey(false) , m_hasKey(false)
, m_emitModified(false)
, m_uuid(Uuid::random()) , m_uuid(Uuid::random())
{ {
setRootGroup(new Group()); setRootGroup(new Group());
rootGroup()->setUuid(Uuid::random()); rootGroup()->setUuid(Uuid::random());
m_timer->setSingleShot(true);
m_uuidMap.insert(m_uuid, this); m_uuidMap.insert(m_uuid, this);
connect(m_metadata, SIGNAL(modified()), this, SIGNAL(modified())); connect(m_metadata, SIGNAL(modified()), this, SIGNAL(modifiedImmediate()));
connect(m_metadata, SIGNAL(nameTextChanged()), this, SIGNAL(nameTextChanged())); connect(m_metadata, SIGNAL(nameTextChanged()), this, SIGNAL(nameTextChanged()));
connect(this, SIGNAL(modifiedImmediate()), this, SLOT(startModifiedTimer()));
connect(m_timer, SIGNAL(timeout()), SIGNAL(modified()));
} }
Database::~Database() Database::~Database()
@ -195,7 +201,7 @@ void Database::setKey(const CompositeKey& key, const QByteArray& transformSeed,
if (updateChangedTime) { if (updateChangedTime) {
m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc()); m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc());
} }
Q_EMIT modified(); Q_EMIT modifiedImmediate();
} }
void Database::setKey(const CompositeKey& key) void Database::setKey(const CompositeKey& key)
@ -209,7 +215,7 @@ void Database::updateKey(quint64 rounds)
m_transformRounds = rounds; m_transformRounds = rounds;
m_transformedMasterKey = m_key.transform(m_transformSeed, transformRounds()); m_transformedMasterKey = m_key.transform(m_transformSeed, transformRounds());
m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc()); m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc());
Q_EMIT modified(); Q_EMIT modifiedImmediate();
} }
} }
@ -256,6 +262,15 @@ void Database::recycleGroup(Group* group)
} }
} }
void Database::setEmitModified(bool value)
{
if (m_emitModified && !value) {
m_timer->stop();
}
m_emitModified = value;
}
Uuid Database::uuid() Uuid Database::uuid()
{ {
return m_uuid; return m_uuid;
@ -265,3 +280,15 @@ Database* Database::databaseByUuid(const Uuid& uuid)
{ {
return m_uuidMap.value(uuid, 0); return m_uuidMap.value(uuid, 0);
} }
void Database::startModifiedTimer()
{
if (!m_emitModified) {
return;
}
if (m_timer->isActive()) {
m_timer->stop();
}
m_timer->start(150);
}

View File

@ -27,6 +27,7 @@
class Entry; class Entry;
class Group; class Group;
class Metadata; class Metadata;
class QTimer;
struct DeletedObject struct DeletedObject
{ {
@ -89,6 +90,7 @@ public:
bool hasKey(); bool hasKey();
void recycleEntry(Entry* entry); void recycleEntry(Entry* entry);
void recycleGroup(Group* group); void recycleGroup(Group* group);
void setEmitModified(bool value);
/** /**
* Returns a unique id that is only valid as long as the Database exists. * Returns a unique id that is only valid as long as the Database exists.
@ -107,6 +109,10 @@ Q_SIGNALS:
void groupMoved(); void groupMoved();
void nameTextChanged(); void nameTextChanged();
void modified(); void modified();
void modifiedImmediate();
private Q_SLOTS:
void startModifiedTimer();
private: private:
Entry* recFindEntry(const Uuid& uuid, Group* group); Entry* recFindEntry(const Uuid& uuid, Group* group);
@ -117,6 +123,7 @@ private:
Metadata* const m_metadata; Metadata* const m_metadata;
Group* m_rootGroup; Group* m_rootGroup;
QList<DeletedObject> m_deletedObjects; QList<DeletedObject> m_deletedObjects;
QTimer* m_timer;
Uuid m_cipher; Uuid m_cipher;
CompressionAlgorithm m_compressionAlgo; CompressionAlgorithm m_compressionAlgo;
@ -126,6 +133,7 @@ private:
CompositeKey m_key; CompositeKey m_key;
bool m_hasKey; bool m_hasKey;
bool m_emitModified;
Uuid m_uuid; Uuid m_uuid;
static QHash<Uuid, Database*> m_uuidMap; static QHash<Uuid, Database*> m_uuidMap;

View File

@ -434,7 +434,7 @@ void Group::addEntry(Entry* entry)
m_entries << entry; m_entries << entry;
connect(entry, SIGNAL(dataChanged(Entry*)), SIGNAL(entryDataChanged(Entry*))); connect(entry, SIGNAL(dataChanged(Entry*)), SIGNAL(entryDataChanged(Entry*)));
if (m_db) { if (m_db) {
connect(entry, SIGNAL(modified()), m_db, SIGNAL(modified())); connect(entry, SIGNAL(modified()), m_db, SIGNAL(modifiedImmediate()));
} }
Q_EMIT modified(); Q_EMIT modified();
@ -474,7 +474,7 @@ void Group::recSetDatabase(Database* db)
entry->disconnect(m_db); entry->disconnect(m_db);
} }
if (db) { if (db) {
connect(entry, SIGNAL(modified()), db, SIGNAL(modified())); connect(entry, SIGNAL(modified()), db, SIGNAL(modifiedImmediate()));
} }
} }
@ -486,7 +486,7 @@ void Group::recSetDatabase(Database* db)
connect(this, SIGNAL(added()), db, SIGNAL(groupAdded())); connect(this, SIGNAL(added()), db, SIGNAL(groupAdded()));
connect(this, SIGNAL(aboutToMove(Group*,Group*,int)), db, SIGNAL(groupAboutToMove(Group*,Group*,int))); connect(this, SIGNAL(aboutToMove(Group*,Group*,int)), db, SIGNAL(groupAboutToMove(Group*,Group*,int)));
connect(this, SIGNAL(moved()), db, SIGNAL(groupMoved())); connect(this, SIGNAL(moved()), db, SIGNAL(groupMoved()));
connect(this, SIGNAL(modified()), db, SIGNAL(modified())); connect(this, SIGNAL(modified()), db, SIGNAL(modifiedImmediate()));
} }
m_db = db; m_db = db;

View File

@ -503,7 +503,6 @@ 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())); connect(db, SIGNAL(nameTextChanged()), SLOT(updateTabNameFromSender()));
connect(dbStruct.dbWidget->entryView(), SIGNAL(entrySelectionChanged()), connect(dbStruct.dbWidget->entryView(), SIGNAL(entrySelectionChanged()),
SLOT(emitEntrySelectionChanged())); SLOT(emitEntrySelectionChanged()));
@ -511,7 +510,7 @@ void DatabaseTabWidget::insertDatabase(Database* db, const DatabaseManagerStruct
connect(db, SIGNAL(modified()), SLOT(modified())); 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)));
connect(dbStruct.dbWidget, SIGNAL(editFinished()), SLOT(autoSave())); db->setEmitModified(true);
} }
DatabaseWidget* DatabaseTabWidget::currentDatabaseWidget() DatabaseWidget* DatabaseTabWidget::currentDatabaseWidget()
@ -532,25 +531,17 @@ void DatabaseTabWidget::modified()
Database* db = static_cast<Database*>(sender()); Database* db = static_cast<Database*>(sender());
DatabaseManagerStruct& dbStruct = m_dbList[db]; DatabaseManagerStruct& dbStruct = m_dbList[db];
if (config()->get("AutoSaveAfterEveryChange").toBool() && dbStruct.file) {
saveDatabase(db);
return;
}
if (!dbStruct.modified) { if (!dbStruct.modified) {
dbStruct.modified = true; dbStruct.modified = true;
updateTabName(db); updateTabName(db);
} }
} }
void DatabaseTabWidget::autoSave()
{
Q_ASSERT(qobject_cast<DatabaseWidget*>(sender()));
DatabaseWidget* dbWidget = static_cast<DatabaseWidget*>(sender());
Database* db = databaseFromDatabaseWidget(dbWidget);
DatabaseManagerStruct& dbStruct = m_dbList[db];
if (dbStruct.modified && config()->get("AutoSaveAfterEveryChange").toBool() && dbStruct.file) {
saveDatabase(db);
}
}
void DatabaseTabWidget::updateLastDatabases(const QString& filename) void DatabaseTabWidget::updateLastDatabases(const QString& filename)
{ {
if (!config()->get("RememberLastDatabases").toBool()) { if (!config()->get("RememberLastDatabases").toBool()) {

View File

@ -82,7 +82,6 @@ Q_SIGNALS:
void tabNameChanged(); void tabNameChanged();
private Q_SLOTS: private Q_SLOTS:
void autoSave();
void updateTabName(Database* db); void updateTabName(Database* db);
void updateTabNameFromSender(); void updateTabNameFromSender();
void openDatabaseDialog(const QString& pw = QString(), const QString& keyFile = QString()); void openDatabaseDialog(const QString& pw = QString(), const QString& keyFile = QString());

View File

@ -147,7 +147,6 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
connect(m_groupView, SIGNAL(groupChanged(Group*)), this, SLOT(clearLastGroup(Group*))); connect(m_groupView, SIGNAL(groupChanged(Group*)), this, SLOT(clearLastGroup(Group*)));
connect(m_groupView, SIGNAL(groupChanged(Group*)), SLOT(updateGroupActions(Group*))); connect(m_groupView, SIGNAL(groupChanged(Group*)), SLOT(updateGroupActions(Group*)));
connect(m_groupView, SIGNAL(groupChanged(Group*)), m_entryView, SLOT(setGroup(Group*))); connect(m_groupView, SIGNAL(groupChanged(Group*)), m_entryView, SLOT(setGroup(Group*)));
connect(m_groupView, SIGNAL(editFinished()), this, SIGNAL(editFinished()));
connect(m_entryView, SIGNAL(entryActivated(Entry*)), SLOT(switchToEntryEdit(Entry*))); connect(m_entryView, SIGNAL(entryActivated(Entry*)), SLOT(switchToEntryEdit(Entry*)));
connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool))); connect(m_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool)));
connect(m_editEntryWidget, SIGNAL(historyEntryActivated(Entry*)), SLOT(switchToHistoryView(Entry*))); connect(m_editEntryWidget, SIGNAL(historyEntryActivated(Entry*)), SLOT(switchToHistoryView(Entry*)));
@ -259,8 +258,6 @@ void DatabaseWidget::cloneEntry()
entry->setGroup(currentEntry->group()); entry->setGroup(currentEntry->group());
m_entryView->setFocus(); m_entryView->setFocus();
m_entryView->setCurrentEntry(entry); m_entryView->setCurrentEntry(entry);
Q_EMIT editFinished();
} }
void DatabaseWidget::deleteEntry() void DatabaseWidget::deleteEntry()
@ -285,8 +282,6 @@ void DatabaseWidget::deleteEntry()
else { else {
m_db->recycleEntry(currentEntry); m_db->recycleEntry(currentEntry);
} }
Q_EMIT editFinished();
} }
void DatabaseWidget::copyUsername() void DatabaseWidget::copyUsername()
@ -346,8 +341,6 @@ void DatabaseWidget::deleteGroup()
else { else {
m_db->recycleGroup(currentGroup); m_db->recycleGroup(currentGroup);
} }
Q_EMIT editFinished();
} }
int DatabaseWidget::addWidget(QWidget* w) int DatabaseWidget::addWidget(QWidget* w)
@ -405,8 +398,6 @@ void DatabaseWidget::switchToView(bool accepted)
m_newParent = 0; m_newParent = 0;
} }
Q_EMIT editFinished();
setCurrentIndex(0); setCurrentIndex(0);
} }
@ -455,8 +446,6 @@ void DatabaseWidget::updateMasterKey(bool accepted)
return; return;
} }
Q_EMIT editFinished();
setCurrentIndex(0); setCurrentIndex(0);
} }

View File

@ -74,7 +74,6 @@ public:
Q_SIGNALS: Q_SIGNALS:
void closeRequest(); void closeRequest();
void currentModeChanged(DatabaseWidget::Mode mode); void currentModeChanged(DatabaseWidget::Mode mode);
void editFinished();
public Q_SLOTS: public Q_SLOTS:
void createEntry(); void createEntry();

View File

@ -29,7 +29,6 @@ GroupView::GroupView(Database* db, QWidget* parent)
, m_model(new GroupModel(db, this)) , m_model(new GroupModel(db, this))
{ {
QTreeView::setModel(m_model); QTreeView::setModel(m_model);
m_emitEditFinished = false;
setHeaderHidden(true); setHeaderHidden(true);
setUniformRowHeights(true); setUniformRowHeights(true);
@ -48,7 +47,6 @@ GroupView::GroupView(Database* db, QWidget* parent)
setDragEnabled(true); setDragEnabled(true);
viewport()->setAcceptDrops(true); viewport()->setAcceptDrops(true);
setDropIndicatorShown(true); setDropIndicatorShown(true);
m_emitEditFinished = true;
} }
void GroupView::dragMoveEvent(QDragMoveEvent* event) void GroupView::dragMoveEvent(QDragMoveEvent* event)
@ -76,7 +74,6 @@ void GroupView::expandedChanged(const QModelIndex& index)
{ {
Group* group = m_model->groupFromIndex(index); Group* group = m_model->groupFromIndex(index);
group->setExpanded(isExpanded(index)); group->setExpanded(isExpanded(index));
emitEditFinished();
} }
void GroupView::recInitExpanded(Group* group) void GroupView::recInitExpanded(Group* group)
@ -88,13 +85,6 @@ void GroupView::recInitExpanded(Group* group)
} }
} }
void GroupView::emitEditFinished()
{
if (m_emitEditFinished) {
Q_EMIT editFinished();
}
}
void GroupView::expandGroup(Group* group, bool expand) void GroupView::expandGroup(Group* group, bool expand)
{ {
QModelIndex index = m_model->index(group); QModelIndex index = m_model->index(group);
@ -119,13 +109,10 @@ void GroupView::emitGroupChanged()
void GroupView::syncExpandedState(const QModelIndex& parent, int start, int end) void GroupView::syncExpandedState(const QModelIndex& parent, int start, int end)
{ {
m_emitEditFinished = false;
for (int row = start; row <= end; row++) { for (int row = start; row <= end; row++) {
Group* group = m_model->groupFromIndex(m_model->index(row, 0, parent)); Group* group = m_model->groupFromIndex(m_model->index(row, 0, parent));
recInitExpanded(group); recInitExpanded(group);
} }
m_emitEditFinished = true;
emitEditFinished();
} }
void GroupView::setCurrentGroup(Group* group) void GroupView::setCurrentGroup(Group* group)

View File

@ -37,7 +37,6 @@ public:
Q_SIGNALS: Q_SIGNALS:
void groupChanged(Group* group); void groupChanged(Group* group);
void editFinished();
private Q_SLOTS: private Q_SLOTS:
void expandedChanged(const QModelIndex& index); void expandedChanged(const QModelIndex& index);
@ -50,10 +49,8 @@ protected:
private: private:
void recInitExpanded(Group* group); void recInitExpanded(Group* group);
void emitEditFinished();
GroupModel* const m_model; GroupModel* const m_model;
bool m_emitEditFinished;
}; };
#endif // KEEPASSX_GROUPVIEW_H #endif // KEEPASSX_GROUPVIEW_H

View File

@ -41,7 +41,7 @@ void TestModified::testSignals()
Database* db = new Database(); Database* db = new Database();
Group* root = db->rootGroup(); Group* root = db->rootGroup();
QSignalSpy spyModified(db, SIGNAL(modified())); QSignalSpy spyModified(db, SIGNAL(modifiedImmediate()));
db->setKey(compositeKey); db->setKey(compositeKey);
QCOMPARE(spyModified.count(), ++spyCount); QCOMPARE(spyModified.count(), ++spyCount);
@ -63,7 +63,7 @@ void TestModified::testSignals()
Database* db2 = new Database(); Database* db2 = new Database();
Group* root2 = db2->rootGroup(); Group* root2 = db2->rootGroup();
QSignalSpy spyModified2(db2, SIGNAL(modified())); QSignalSpy spyModified2(db2, SIGNAL(modifiedImmediate()));
g1->setParent(root2); g1->setParent(root2);
QCOMPARE(spyModified.count(), ++spyCount); QCOMPARE(spyModified.count(), ++spyCount);
@ -116,7 +116,7 @@ void TestModified::testGroupSets()
Group* g = new Group(); Group* g = new Group();
g->setParent(root); g->setParent(root);
QSignalSpy spyModified(db, SIGNAL(modified())); QSignalSpy spyModified(db, SIGNAL(modifiedImmediate()));
root->setUuid(Uuid::random()); root->setUuid(Uuid::random());
QCOMPARE(spyModified.count(), ++spyCount); QCOMPARE(spyModified.count(), ++spyCount);
@ -183,7 +183,7 @@ void TestModified::testEntrySets()
Entry* entry = new Entry(); Entry* entry = new Entry();
entry->setGroup(g); entry->setGroup(g);
QSignalSpy spyModified(db, SIGNAL(modified())); QSignalSpy spyModified(db, SIGNAL(modifiedImmediate()));
entry->setUuid(Uuid::random()); entry->setUuid(Uuid::random());
QCOMPARE(spyModified.count(), ++spyCount); QCOMPARE(spyModified.count(), ++spyCount);

View File

@ -134,6 +134,7 @@ void TestGui::testAddEntry()
QCOMPARE(entry->title(), QString("test")); QCOMPARE(entry->title(), QString("test"));
QCOMPARE(entry->historyItems().size(), 0); QCOMPARE(entry->historyItems().size(), 0);
QTest::qWait(200);
QCOMPARE(tabWidget->tabText(tabWidget->currentIndex()), QString("NewDatabase.kdbx*")); QCOMPARE(tabWidget->tabText(tabWidget->currentIndex()), QString("NewDatabase.kdbx*"));
QAction* entryEditAction = m_mainWindow->findChild<QAction*>("actionEntryEdit"); QAction* entryEditAction = m_mainWindow->findChild<QAction*>("actionEntryEdit");