Skip to content
This repository has been archived by the owner on Sep 16, 2021. It is now read-only.

Commit

Permalink
fix "Keep Both" in library merge (fixes #75), add Cancel button
Browse files Browse the repository at this point in the history
  • Loading branch information
cpdt committed Sep 25, 2018
1 parent 9e25e47 commit 15f87cc
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 12 deletions.
39 changes: 33 additions & 6 deletions editor/model/Library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,38 +33,65 @@ void Library::import(
currentEntries.insert(entry->baseUuid(), entry.get());
}

// merge, checking for duplicates
// build a list of merge actions, checking for duplicates
// if we hit a duplicate, we have two possible actions:
// - if the modification UUID is the same as the local one, they're the same and we can just keep what we've got
// - if not, there's a desync, and we need to ask the user which one they want to keep
std::vector<std::unique_ptr<LibraryEntry>> addEntries;
std::vector<LibraryEntry *> removeEntries;
std::vector<std::pair<LibraryEntry *, LibraryEntry *>> conflictRenameEntries;
for (auto &entry : library->_entries) {
auto currentEntry = currentEntries.find(entry->baseUuid());

if (currentEntry == currentEntries.end()) {
// no conflict, just add the entry
addEntry(std::move(entry));
addEntries.push_back(std::move(entry));
} else {
auto curEntry = currentEntry.value();
if (entry->modificationUuid() != curEntry->modificationUuid()) {
// different modification IDs, one of them has to go
auto resolution = resolveConflict(curEntry, entry.get());

switch (resolution) {
case ConflictResolution::CANCEL:
// cancel everything by just exiting - since merging is transactional, this works fine
return;
case ConflictResolution::KEEP_OLD:
// no action needed
break;
case ConflictResolution::KEEP_NEW:
currentEntries.remove(curEntry->baseUuid());
curEntry->remove();
addEntry(std::move(entry));
removeEntries.push_back(curEntry);
addEntries.push_back(std::move(entry));
break;
case ConflictResolution::KEEP_BOTH:
// todo
conflictRenameEntries.emplace_back(curEntry, entry.get());
addEntries.push_back(std::move(entry));
break;
}
}
}
}

// apply the transaction, making sure it's ordered so we don't have any duplicates or dangling references
for (const auto &conflict : conflictRenameEntries) {
auto originalEntry = conflict.first;
auto newEntry = conflict.second;
originalEntry->setName(originalEntry->name() + " (original)");
newEntry->setName(newEntry->name() + " (imported)");

// old entry becomes an entirely different entry, meaning if the library is imported in the future again,
// the conflict won't show up
originalEntry->setBaseUuid(QUuid());
}

for (const auto &removeEntry : removeEntries) {
currentEntries.remove(removeEntry->baseUuid());
removeEntry->remove();
}

for (auto &newEntry : addEntries) {
addEntry(std::move(newEntry));
}
}

void Library::setActiveTag(const QString &activeTag) {
Expand Down
2 changes: 1 addition & 1 deletion editor/model/Library.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace AxiomModel {

class Library : public AxiomCommon::Hookable {
public:
enum class ConflictResolution { KEEP_OLD, KEEP_NEW, KEEP_BOTH };
enum class ConflictResolution { CANCEL, KEEP_OLD, KEEP_NEW, KEEP_BOTH };

AxiomCommon::Event<LibraryEntry *> entryAdded;
AxiomCommon::Event<const QString &> activeTagChanged;
Expand Down
4 changes: 4 additions & 0 deletions editor/model/LibraryEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ void LibraryEntry::setName(const QString &newName) {
}
}

void LibraryEntry::setBaseUuid(QUuid newUuid) {
_baseUuid = newUuid;
}

void LibraryEntry::addTag(const QString &tag) {
if (_tags.insert(tag).second) {
tagAdded.trigger(tag);
Expand Down
2 changes: 2 additions & 0 deletions editor/model/LibraryEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ namespace AxiomModel {

void setName(const QString &newName);

void setBaseUuid(QUuid newUuid);

const QUuid &baseUuid() const { return _baseUuid; }

const QUuid &modificationUuid() const { return _modificationUuid; }
Expand Down
15 changes: 10 additions & 5 deletions editor/widgets/windows/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ void MainWindow::importLibraryFrom(const QString &path) {
QMessageBox msgBox(
QMessageBox::Warning, "Module import conflict",
tr("Heads up! One of the modules in the imported library is conflicting with one you already had.\n\n"
"Current module (") +
"Original module (") +
(currentNewer ? "newer" : "older") +
")\n"
"Name: " +
Expand All @@ -351,7 +351,7 @@ void MainWindow::importLibraryFrom(const QString &path) {
"Last edit: " +
oldEntry->modificationDateTime().toLocalTime().toString() +
"\n\n"
"New module (" +
"Imported module (" +
(currentNewer ? "older" : "newer") +
")\n"
"Name: " +
Expand All @@ -361,18 +361,23 @@ void MainWindow::importLibraryFrom(const QString &path) {
newEntry->modificationDateTime().toLocalTime().toString() +
"\n\n"
"Would you like to keep the current module, imported one, or both?");
auto cancelBtn = msgBox.addButton(QMessageBox::Cancel);
auto currentBtn = msgBox.addButton("Current", QMessageBox::ActionRole);
auto importedBtn = msgBox.addButton("Imported", QMessageBox::ActionRole);
msgBox.addButton("Both", QMessageBox::ActionRole);
auto bothBtn = msgBox.addButton("Both", QMessageBox::ActionRole);
msgBox.setDefaultButton(importedBtn);
msgBox.exec();

if (msgBox.clickedButton() == currentBtn)
if (msgBox.clickedButton() == cancelBtn)
return AxiomModel::Library::ConflictResolution::CANCEL;
else if (msgBox.clickedButton() == currentBtn)
return AxiomModel::Library::ConflictResolution::KEEP_OLD;
else if (msgBox.clickedButton() == importedBtn)
return AxiomModel::Library::ConflictResolution::KEEP_NEW;
else
else if (msgBox.clickedButton() == bothBtn)
return AxiomModel::Library::ConflictResolution::KEEP_BOTH;
else
unreachable;
});
}

Expand Down

0 comments on commit 15f87cc

Please sign in to comment.