From af263fd80df2f5434b691b19f5a180435a9f20b6 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Tue, 22 Oct 2019 22:47:45 -0400 Subject: [PATCH] Prevent new entry loss on database file reload * Fix #3651 * Correct data loss when the database reloads due to a file change while creating a new entry. The issue occurred due to the "new parent group" pointer being invalid after the database is reloaded following merge. * Also fix re-selecting entries following database file reload. If the entry was moved out of the current group it would result in an assert hit. This fix prevents recursively looking for the entry. --- src/core/Group.cpp | 9 +++++++-- src/core/Group.h | 2 +- src/gui/DatabaseWidget.cpp | 17 ++++++++++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 7fd403ab1..2c0d67091 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -585,13 +585,18 @@ QList Group::referencesRecursive(const Entry* entry) const [entry](const Entry* e) { return e->hasReferencesTo(entry->uuid()); }); } -Entry* Group::findEntryByUuid(const QUuid& uuid) const +Entry* Group::findEntryByUuid(const QUuid& uuid, bool recursive) const { if (uuid.isNull()) { return nullptr; } - for (Entry* entry : entriesRecursive(false)) { + auto entries = m_entries; + if (recursive) { + entries = entriesRecursive(false); + } + + for (auto entry : entries) { if (entry->uuid() == uuid) { return entry; } diff --git a/src/core/Group.h b/src/core/Group.h index 2e6da887e..cfeb9feee 100644 --- a/src/core/Group.h +++ b/src/core/Group.h @@ -114,7 +114,7 @@ public: static const QString RootAutoTypeSequence; Group* findChildByName(const QString& name); - Entry* findEntryByUuid(const QUuid& uuid) const; + Entry* findEntryByUuid(const QUuid& uuid, bool recursive = true) const; Entry* findEntryByPath(const QString& entryPath); Entry* findEntryBySearchTerm(const QString& term, EntryReferenceType referenceType); Group* findGroupByUuid(const QUuid& uuid); diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 5e3c101c1..45645fa55 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -381,6 +381,12 @@ void DatabaseWidget::createEntry() void DatabaseWidget::replaceDatabase(QSharedPointer db) { + // Save off new parent UUID which will be valid when creating a new entry + QUuid newParentUuid; + if (m_newParent) { + newParentUuid = m_newParent->uuid(); + } + // TODO: instead of increasing the ref count temporarily, there should be a clean // break from the old database. Without this crashes occur due to the change // signals triggering dangling pointers. @@ -390,6 +396,15 @@ void DatabaseWidget::replaceDatabase(QSharedPointer db) m_groupView->changeDatabase(m_db); processAutoOpen(); + // Restore the new parent group pointer, if not found default to the root group + // this prevents data loss when merging a database while creating a new entry + if (!newParentUuid.isNull()) { + m_newParent = m_db->rootGroup()->findGroupByUuid(newParentUuid); + if (!m_newParent) { + m_newParent = m_db->rootGroup(); + } + } + emit databaseReplaced(oldDb, m_db); #if defined(WITH_XC_KEESHARE) @@ -1480,7 +1495,7 @@ void DatabaseWidget::restoreGroupEntryFocus(const QUuid& groupUuid, const QUuid& auto group = m_db->rootGroup()->findGroupByUuid(groupUuid); if (group) { m_groupView->setCurrentGroup(group); - auto entry = group->findEntryByUuid(entryUuid); + auto entry = group->findEntryByUuid(entryUuid, false); if (entry) { m_entryView->setCurrentEntry(entry); }