Commit b4e4ea9f authored by Nicolas Carion's avatar Nicolas Carion

Fix grouping/ungrouping undo when selection is set. CC #116

parent 10f872e6
Pipeline #2251 passed with stage
in 14 minutes and 45 seconds
......@@ -1672,6 +1672,9 @@ int TimelineModel::requestClipsGroup(const std::unordered_set<int> &ids, bool lo
int TimelineModel::requestClipsGroup(const std::unordered_set<int> &ids, Fun &undo, Fun &redo, GroupType type)
{
QWriteLocker locker(&m_lock);
if (type != GroupType::Selection) {
requestClearSelection();
}
for (int id : ids) {
if (isClip(id)) {
if (getClipTrackId(id) == -1) {
......@@ -1690,6 +1693,12 @@ int TimelineModel::requestClipsGroup(const std::unordered_set<int> &ids, Fun &un
return -1;
}
int groupId = m_groups->groupItems(ids, undo, redo, type);
if (type != GroupType::Selection) {
// we make sure that the undo and the redo are going to unselect before doing anything else
Fun unselect = [this]() { return requestClearSelection(); };
PUSH_FRONT_LAMBDA(unselect, undo);
PUSH_FRONT_LAMBDA(unselect, redo);
}
return groupId;
}
......@@ -1736,7 +1745,18 @@ bool TimelineModel::requestClipUngroup(int itemId, bool logUndo)
bool TimelineModel::requestClipUngroup(int itemId, Fun &undo, Fun &redo)
{
QWriteLocker locker(&m_lock);
return m_groups->ungroupItem(itemId, undo, redo);
bool isSelection = m_groups->getType(m_groups->getRootId(itemId)) == GroupType::Selection;
if (!isSelection) {
requestClearSelection();
}
bool res = m_groups->ungroupItem(itemId, undo, redo);
if (res && !isSelection) {
// we make sure that the undo and the redo are going to unselect before doing anything else
Fun unselect = [this]() { return requestClearSelection(); };
PUSH_FRONT_LAMBDA(unselect, undo);
PUSH_FRONT_LAMBDA(unselect, redo);
}
return res;
}
bool TimelineModel::requestTrackInsertion(int position, int &id, const QString &trackName, bool audioTrack)
......
......@@ -30,7 +30,15 @@ using Fun = std::function<bool(void)>;
#define PUSH_LAMBDA(operation, lambda) \
lambda = [lambda, operation]() { \
bool v = lambda(); \
return operation() && v; \
return v && operation(); \
};
/* @brief this macro executes an operation before a given lambda
*/
#define PUSH_FRONT_LAMBDA(operation, lambda) \
lambda = [lambda, operation]() { \
bool v = operation(); \
return v && lambda(); \
};
#include <QUndoCommand>
......
......@@ -555,6 +555,78 @@ TEST_CASE("Clip manipulation", "[ClipModel]")
REQUIRE(timeline->checkConsistency());
}
SECTION("Group and selection")
{
REQUIRE(timeline->requestClipMove(cid1, tid1, 0));
REQUIRE(timeline->requestClipMove(cid2, tid1, length + 3));
REQUIRE(timeline->requestClipMove(cid3, tid1, 2 * length + 5));
auto pos_state = [&]() {
REQUIRE(timeline->checkConsistency());
REQUIRE(timeline->getTrackClipsCount(tid1) == 3);
REQUIRE(timeline->getClipTrackId(cid1) == tid1);
REQUIRE(timeline->getClipTrackId(cid2) == tid1);
REQUIRE(timeline->getClipTrackId(cid3) == tid1);
REQUIRE(timeline->getClipPosition(cid1) == 0);
REQUIRE(timeline->getClipPosition(cid2) == length + 3);
REQUIRE(timeline->getClipPosition(cid3) == 2 * length + 5);
};
auto state0 = [&]() {
pos_state();
REQUIRE_FALSE(timeline->m_groups->isInGroup(cid1));
REQUIRE_FALSE(timeline->m_groups->isInGroup(cid2));
REQUIRE_FALSE(timeline->m_groups->isInGroup(cid3));
};
state0();
REQUIRE(timeline->requestClipsGroup({cid1, cid2}));
auto state = [&]() {
pos_state();
REQUIRE_FALSE(timeline->m_groups->isInGroup(cid3));
REQUIRE(timeline->m_groups->isInGroup(cid1));
int gid = timeline->m_groups->getRootId(cid1);
REQUIRE(timeline->m_groups->getLeaves(gid) == std::unordered_set<int>{cid1, cid2});
};
state();
// undo/redo should work fine
undoStack->undo();
state0();
undoStack->redo();
state();
// Tricky case, we do a non-trivial selection before undoing
REQUIRE(timeline->requestSetSelection({cid1, cid3}));
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3});
undoStack->undo();
state0();
REQUIRE(timeline->requestSetSelection({cid1, cid3}));
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid3});
undoStack->redo();
state();
// same thing, but when ungrouping manually
REQUIRE(timeline->requestSetSelection({cid1, cid3}));
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3});
REQUIRE(timeline->requestClipUngroup(cid1));
state0();
// normal undo/redo
undoStack->undo();
state();
undoStack->redo();
state0();
// undo/redo mixed with selections
REQUIRE(timeline->requestSetSelection({cid1, cid3}));
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid3});
undoStack->undo();
state();
REQUIRE(timeline->requestSetSelection({cid1, cid3}));
REQUIRE(timeline->getCurrentSelection() == std::unordered_set<int>{cid1, cid2, cid3});
undoStack->redo();
state0();
}
SECTION("Group move")
{
REQUIRE(timeline->requestClipMove(cid1, tid1, 0));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment