diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 82c9e7bc3..72b48283a 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -36,8 +36,6 @@ const int Entry::ResolveMaximumDepth = 10; const QString Entry::AutoTypeSequenceUsername = "{USERNAME}{ENTER}"; const QString Entry::AutoTypeSequencePassword = "{PASSWORD}{ENTER}"; -Entry::CloneFlags Entry::DefaultCloneFlags = Entry::CloneNewUuid | Entry::CloneResetTimeInfo; - Entry::Entry() : m_attributes(new EntryAttributes(this)) , m_attachments(new EntryAttachments(this)) diff --git a/src/core/Entry.h b/src/core/Entry.h index a0dbbf7d4..83c8eeb1d 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -160,6 +160,8 @@ public: CloneNewUuid = 1, // generate a random uuid for the clone CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time CloneIncludeHistory = 4, // clone the history items + CloneDefault = CloneNewUuid | CloneResetTimeInfo, + CloneCopy = CloneNewUuid | CloneResetTimeInfo | CloneIncludeHistory, CloneRenameTitle = 8, // add "-Clone" after the original title CloneUserAsRef = 16, // Add the user as a reference to the original entry ClonePassAsRef = 32, // Add the password as a reference to the original entry @@ -209,7 +211,6 @@ public: static const int ResolveMaximumDepth; static const QString AutoTypeSequenceUsername; static const QString AutoTypeSequencePassword; - static CloneFlags DefaultCloneFlags; /** * Creates a duplicate of this entry except that the returned entry isn't @@ -217,7 +218,7 @@ public: * Note that you need to copy the custom icons manually when inserting the * new entry into another database. */ - Entry* clone(CloneFlags flags = DefaultCloneFlags) const; + Entry* clone(CloneFlags flags = CloneDefault) const; void copyDataFrom(const Entry* other); QString maskPasswordPlaceholders(const QString& str) const; Entry* resolveReference(const QString& str) const; diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 56e545bf6..45e44bff0 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -36,9 +36,6 @@ const int Group::DefaultIconNumber = 48; const int Group::RecycleBinIconNumber = 43; const QString Group::RootAutoTypeSequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}"; -Group::CloneFlags Group::DefaultCloneFlags = - Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries; - Group::Group() : m_customData(new CustomData(this)) , m_updateTimeinfo(true) diff --git a/src/core/Group.h b/src/core/Group.h index 4bea8e4eb..2997abe17 100644 --- a/src/core/Group.h +++ b/src/core/Group.h @@ -56,6 +56,7 @@ public: CloneNewUuid = 1, // generate a random uuid for the clone CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time CloneIncludeEntries = 4, // clone the group entries + CloneDefault = CloneNewUuid | CloneResetTimeInfo | CloneIncludeEntries, }; Q_DECLARE_FLAGS(CloneFlags, CloneFlag) @@ -108,7 +109,6 @@ public: static const int DefaultIconNumber; static const int RecycleBinIconNumber; - static CloneFlags DefaultCloneFlags; static const QString RootAutoTypeSequence; Group* findChildByName(const QString& name); @@ -157,8 +157,8 @@ public: QSet customIconsRecursive() const; QList usernamesRecursive(int topN = -1) const; - Group* clone(Entry::CloneFlags entryFlags = Entry::DefaultCloneFlags, - CloneFlags groupFlags = DefaultCloneFlags) const; + Group* clone(Entry::CloneFlags entryFlags = Entry::CloneDefault, + Group::CloneFlags groupFlags = Group::CloneDefault) const; void copyDataFrom(const Group* other); QString print(bool recursive = false, bool flatten = false, int depth = 0); diff --git a/src/gui/group/GroupModel.cpp b/src/gui/group/GroupModel.cpp index e61410334..5feb8d6fe 100644 --- a/src/gui/group/GroupModel.cpp +++ b/src/gui/group/GroupModel.cpp @@ -262,13 +262,13 @@ bool GroupModel::dropMimeData(const QMimeData* data, targetDb->metadata()->copyCustomIcons(customIcons, sourceDb->metadata()); // Always clone the group across db's to reset UUIDs - group = dragGroup->clone(); + group = dragGroup->clone(Entry::CloneDefault | Entry::CloneIncludeHistory); if (action == Qt::MoveAction) { // Remove the original group from the sourceDb delete dragGroup; } } else if (action == Qt::CopyAction) { - group = dragGroup->clone(); + group = dragGroup->clone(Entry::CloneCopy); } group->setParent(parentGroup, row); @@ -303,13 +303,13 @@ bool GroupModel::dropMimeData(const QMimeData* data, targetDb->metadata()->addCustomIcon(customIcon, sourceDb->metadata()->customIcon(customIcon)); } - // Always clone the entry across db's to reset the UUID - entry = dragEntry->clone(); + // Reset the UUID when moving across db boundary + entry = dragEntry->clone(Entry::CloneDefault | Entry::CloneIncludeHistory); if (action == Qt::MoveAction) { delete dragEntry; } } else if (action == Qt::CopyAction) { - entry = dragEntry->clone(); + entry = dragEntry->clone(Entry::CloneCopy); } entry->setGroup(parentGroup); diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 7c24b0fc2..2463f13f6 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -1155,24 +1155,45 @@ void TestGui::testEntryPlaceholders() void TestGui::testDragAndDropEntry() { - auto* entryView = m_dbWidget->findChild("entryView"); - auto* groupView = m_dbWidget->findChild("groupView"); - QAbstractItemModel* groupModel = groupView->model(); + auto entryView = m_dbWidget->findChild("entryView"); + auto groupView = m_dbWidget->findChild("groupView"); + auto groupModel = qobject_cast(groupView->model()); QModelIndex sourceIndex = entryView->model()->index(0, 1); QModelIndex targetIndex = groupModel->index(0, 0, groupModel->index(0, 0)); QVERIFY(sourceIndex.isValid()); QVERIFY(targetIndex.isValid()); + auto targetGroup = groupModel->groupFromIndex(targetIndex); QMimeData mimeData; QByteArray encoded; QDataStream stream(&encoded, QIODevice::WriteOnly); - Entry* entry = entryView->entryFromIndex(sourceIndex); + + auto entry = entryView->entryFromIndex(sourceIndex); stream << entry->group()->database()->uuid() << entry->uuid(); mimeData.setData("application/x-keepassx-entry", encoded); + // Test Copy, UUID should change, history remain + QVERIFY(groupModel->dropMimeData(&mimeData, Qt::CopyAction, -1, 0, targetIndex)); + // Find the copied entry + auto newEntry = targetGroup->findEntryByPath(entry->title()); + QVERIFY(newEntry); + QVERIFY(entry->uuid() != newEntry->uuid()); + QCOMPARE(entry->historyItems().count(), newEntry->historyItems().count()); + + encoded.clear(); + entry = entryView->entryFromIndex(sourceIndex); + auto history = entry->historyItems().count(); + auto uuid = entry->uuid(); + stream << entry->group()->database()->uuid() << entry->uuid(); + mimeData.setData("application/x-keepassx-entry", encoded); + + // Test Move, entry pointer should remain the same + QCOMPARE(entry->group()->name(), QString("NewDatabase")); QVERIFY(groupModel->dropMimeData(&mimeData, Qt::MoveAction, -1, 0, targetIndex)); QCOMPARE(entry->group()->name(), QString("General")); + QCOMPARE(entry->uuid(), uuid); + QCOMPARE(entry->historyItems().count(), history); } void TestGui::testDragAndDropGroup()