diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 57b74b2bf..279243d5a 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -18,6 +18,7 @@ #include "Database.h" #include +#include #include #include "core/Group.h" @@ -30,19 +31,24 @@ QHash Database::m_uuidMap; Database::Database() : m_metadata(new Metadata(this)) + , m_timer(new QTimer(this)) , m_cipher(KeePass2::CIPHER_AES) , m_compressionAlgo(CompressionGZip) , m_transformRounds(50000) , m_hasKey(false) + , m_emitModified(false) , m_uuid(Uuid::random()) { setRootGroup(new Group()); rootGroup()->setUuid(Uuid::random()); + m_timer->setSingleShot(true); 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(this, SIGNAL(modifiedImmediate()), this, SLOT(startModifiedTimer())); + connect(m_timer, SIGNAL(timeout()), SIGNAL(modified())); } Database::~Database() @@ -195,7 +201,7 @@ void Database::setKey(const CompositeKey& key, const QByteArray& transformSeed, if (updateChangedTime) { m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc()); } - Q_EMIT modified(); + Q_EMIT modifiedImmediate(); } void Database::setKey(const CompositeKey& key) @@ -209,7 +215,7 @@ void Database::updateKey(quint64 rounds) m_transformRounds = rounds; m_transformedMasterKey = m_key.transform(m_transformSeed, transformRounds()); m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc()); - Q_EMIT modified(); + Q_EMIT modifiedImmediate(); } } @@ -253,7 +259,16 @@ void Database::recycleGroup(Group* group) } else { delete group; + } +} + +void Database::setEmitModified(bool value) +{ + if (m_emitModified && !value) { + m_timer->stop(); } + + m_emitModified = value; } Uuid Database::uuid() @@ -265,3 +280,15 @@ Database* Database::databaseByUuid(const Uuid& uuid) { return m_uuidMap.value(uuid, 0); } + +void Database::startModifiedTimer() +{ + if (!m_emitModified) { + return; + } + + if (m_timer->isActive()) { + m_timer->stop(); + } + m_timer->start(150); +} diff --git a/src/core/Database.h b/src/core/Database.h index 9600ba51a..de4f00c7f 100644 --- a/src/core/Database.h +++ b/src/core/Database.h @@ -27,6 +27,7 @@ class Entry; class Group; class Metadata; +class QTimer; struct DeletedObject { @@ -89,6 +90,7 @@ public: bool hasKey(); void recycleEntry(Entry* entry); void recycleGroup(Group* group); + void setEmitModified(bool value); /** * Returns a unique id that is only valid as long as the Database exists. @@ -107,6 +109,10 @@ Q_SIGNALS: void groupMoved(); void nameTextChanged(); void modified(); + void modifiedImmediate(); + +private Q_SLOTS: + void startModifiedTimer(); private: Entry* recFindEntry(const Uuid& uuid, Group* group); @@ -117,6 +123,7 @@ private: Metadata* const m_metadata; Group* m_rootGroup; QList m_deletedObjects; + QTimer* m_timer; Uuid m_cipher; CompressionAlgorithm m_compressionAlgo; @@ -126,6 +133,7 @@ private: CompositeKey m_key; bool m_hasKey; + bool m_emitModified; Uuid m_uuid; static QHash m_uuidMap; diff --git a/src/core/Group.cpp b/src/core/Group.cpp index ff19446e4..ff203f2cb 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -434,7 +434,7 @@ void Group::addEntry(Entry* entry) m_entries << entry; connect(entry, SIGNAL(dataChanged(Entry*)), SIGNAL(entryDataChanged(Entry*))); if (m_db) { - connect(entry, SIGNAL(modified()), m_db, SIGNAL(modified())); + connect(entry, SIGNAL(modified()), m_db, SIGNAL(modifiedImmediate())); } Q_EMIT modified(); @@ -474,7 +474,7 @@ void Group::recSetDatabase(Database* db) entry->disconnect(m_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(aboutToMove(Group*,Group*,int)), db, SIGNAL(groupAboutToMove(Group*,Group*,int))); connect(this, SIGNAL(moved()), db, SIGNAL(groupMoved())); - connect(this, SIGNAL(modified()), db, SIGNAL(modified())); + connect(this, SIGNAL(modified()), db, SIGNAL(modifiedImmediate())); } m_db = db; diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index f7e348a39..c943644a0 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -503,7 +503,6 @@ void DatabaseTabWidget::insertDatabase(Database* db, const DatabaseManagerStruct updateTabName(db); int index = databaseIndex(db); setCurrentIndex(index); - connect(db, SIGNAL(nameTextChanged()), SLOT(updateTabNameFromSender())); connect(dbStruct.dbWidget->entryView(), SIGNAL(entrySelectionChanged()), SLOT(emitEntrySelectionChanged())); @@ -511,7 +510,7 @@ void DatabaseTabWidget::insertDatabase(Database* db, const DatabaseManagerStruct connect(db, SIGNAL(modified()), SLOT(modified())); connect(dbStruct.dbWidget, SIGNAL(currentModeChanged(DatabaseWidget::Mode)), SIGNAL(currentWidgetModeChanged(DatabaseWidget::Mode))); - connect(dbStruct.dbWidget, SIGNAL(editFinished()), SLOT(autoSave())); + db->setEmitModified(true); } DatabaseWidget* DatabaseTabWidget::currentDatabaseWidget() @@ -532,25 +531,17 @@ void DatabaseTabWidget::modified() Database* db = static_cast(sender()); DatabaseManagerStruct& dbStruct = m_dbList[db]; + if (config()->get("AutoSaveAfterEveryChange").toBool() && dbStruct.file) { + saveDatabase(db); + return; + } + if (!dbStruct.modified) { dbStruct.modified = true; updateTabName(db); } } -void DatabaseTabWidget::autoSave() -{ - Q_ASSERT(qobject_cast(sender())); - - DatabaseWidget* dbWidget = static_cast(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) { if (!config()->get("RememberLastDatabases").toBool()) { diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index 1749bcee3..a06c7524f 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -82,7 +82,6 @@ Q_SIGNALS: void tabNameChanged(); private Q_SLOTS: - void autoSave(); void updateTabName(Database* db); void updateTabNameFromSender(); void openDatabaseDialog(const QString& pw = QString(), const QString& keyFile = QString()); diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index cb21c1328..d1327cd54 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -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*)), SLOT(updateGroupActions(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_editEntryWidget, SIGNAL(editFinished(bool)), SLOT(switchToView(bool))); connect(m_editEntryWidget, SIGNAL(historyEntryActivated(Entry*)), SLOT(switchToHistoryView(Entry*))); @@ -259,8 +258,6 @@ void DatabaseWidget::cloneEntry() entry->setGroup(currentEntry->group()); m_entryView->setFocus(); m_entryView->setCurrentEntry(entry); - - Q_EMIT editFinished(); } void DatabaseWidget::deleteEntry() @@ -285,8 +282,6 @@ void DatabaseWidget::deleteEntry() else { m_db->recycleEntry(currentEntry); } - - Q_EMIT editFinished(); } void DatabaseWidget::copyUsername() @@ -346,8 +341,6 @@ void DatabaseWidget::deleteGroup() else { m_db->recycleGroup(currentGroup); } - - Q_EMIT editFinished(); } int DatabaseWidget::addWidget(QWidget* w) @@ -405,8 +398,6 @@ void DatabaseWidget::switchToView(bool accepted) m_newParent = 0; } - Q_EMIT editFinished(); - setCurrentIndex(0); } @@ -455,8 +446,6 @@ void DatabaseWidget::updateMasterKey(bool accepted) return; } - Q_EMIT editFinished(); - setCurrentIndex(0); } diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 9c800eda3..c055db7c1 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -74,7 +74,6 @@ public: Q_SIGNALS: void closeRequest(); void currentModeChanged(DatabaseWidget::Mode mode); - void editFinished(); public Q_SLOTS: void createEntry(); diff --git a/src/gui/group/GroupView.cpp b/src/gui/group/GroupView.cpp index aa2e09d9f..6d9715771 100644 --- a/src/gui/group/GroupView.cpp +++ b/src/gui/group/GroupView.cpp @@ -29,7 +29,6 @@ GroupView::GroupView(Database* db, QWidget* parent) , m_model(new GroupModel(db, this)) { QTreeView::setModel(m_model); - m_emitEditFinished = false; setHeaderHidden(true); setUniformRowHeights(true); @@ -48,7 +47,6 @@ GroupView::GroupView(Database* db, QWidget* parent) setDragEnabled(true); viewport()->setAcceptDrops(true); setDropIndicatorShown(true); - m_emitEditFinished = true; } void GroupView::dragMoveEvent(QDragMoveEvent* event) @@ -76,7 +74,6 @@ void GroupView::expandedChanged(const QModelIndex& index) { Group* group = m_model->groupFromIndex(index); group->setExpanded(isExpanded(index)); - emitEditFinished(); } 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) { QModelIndex index = m_model->index(group); @@ -119,13 +109,10 @@ void GroupView::emitGroupChanged() void GroupView::syncExpandedState(const QModelIndex& parent, int start, int end) { - m_emitEditFinished = false; for (int row = start; row <= end; row++) { Group* group = m_model->groupFromIndex(m_model->index(row, 0, parent)); recInitExpanded(group); } - m_emitEditFinished = true; - emitEditFinished(); } void GroupView::setCurrentGroup(Group* group) diff --git a/src/gui/group/GroupView.h b/src/gui/group/GroupView.h index 94f52086d..af87dbe89 100644 --- a/src/gui/group/GroupView.h +++ b/src/gui/group/GroupView.h @@ -37,7 +37,6 @@ public: Q_SIGNALS: void groupChanged(Group* group); - void editFinished(); private Q_SLOTS: void expandedChanged(const QModelIndex& index); @@ -50,10 +49,8 @@ protected: private: void recInitExpanded(Group* group); - void emitEditFinished(); GroupModel* const m_model; - bool m_emitEditFinished; }; #endif // KEEPASSX_GROUPVIEW_H diff --git a/tests/TestModified.cpp b/tests/TestModified.cpp index d1563a196..6b96d09c0 100644 --- a/tests/TestModified.cpp +++ b/tests/TestModified.cpp @@ -41,7 +41,7 @@ void TestModified::testSignals() Database* db = new Database(); Group* root = db->rootGroup(); - QSignalSpy spyModified(db, SIGNAL(modified())); + QSignalSpy spyModified(db, SIGNAL(modifiedImmediate())); db->setKey(compositeKey); QCOMPARE(spyModified.count(), ++spyCount); @@ -63,7 +63,7 @@ void TestModified::testSignals() Database* db2 = new Database(); Group* root2 = db2->rootGroup(); - QSignalSpy spyModified2(db2, SIGNAL(modified())); + QSignalSpy spyModified2(db2, SIGNAL(modifiedImmediate())); g1->setParent(root2); QCOMPARE(spyModified.count(), ++spyCount); @@ -116,7 +116,7 @@ void TestModified::testGroupSets() Group* g = new Group(); g->setParent(root); - QSignalSpy spyModified(db, SIGNAL(modified())); + QSignalSpy spyModified(db, SIGNAL(modifiedImmediate())); root->setUuid(Uuid::random()); QCOMPARE(spyModified.count(), ++spyCount); @@ -183,7 +183,7 @@ void TestModified::testEntrySets() Entry* entry = new Entry(); entry->setGroup(g); - QSignalSpy spyModified(db, SIGNAL(modified())); + QSignalSpy spyModified(db, SIGNAL(modifiedImmediate())); entry->setUuid(Uuid::random()); QCOMPARE(spyModified.count(), ++spyCount); diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 04e770074..3777089e9 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -134,6 +134,7 @@ void TestGui::testAddEntry() QCOMPARE(entry->title(), QString("test")); QCOMPARE(entry->historyItems().size(), 0); + QTest::qWait(200); QCOMPARE(tabWidget->tabText(tabWidget->currentIndex()), QString("NewDatabase.kdbx*")); QAction* entryEditAction = m_mainWindow->findChild("actionEntryEdit");