Copy history when drag/drop entries and groups

* Fix #5809
This commit is contained in:
Jonathan White 2020-12-12 09:46:23 -05:00
parent 4b5248ee98
commit a74e2391e8
6 changed files with 36 additions and 19 deletions

View File

@ -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))

View File

@ -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;

View File

@ -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)

View File

@ -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<QUuid> customIconsRecursive() const;
QList<QString> 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);

View File

@ -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);

View File

@ -1155,24 +1155,45 @@ void TestGui::testEntryPlaceholders()
void TestGui::testDragAndDropEntry()
{
auto* entryView = m_dbWidget->findChild<EntryView*>("entryView");
auto* groupView = m_dbWidget->findChild<GroupView*>("groupView");
QAbstractItemModel* groupModel = groupView->model();
auto entryView = m_dbWidget->findChild<EntryView*>("entryView");
auto groupView = m_dbWidget->findChild<GroupView*>("groupView");
auto groupModel = qobject_cast<GroupModel*>(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()