Commit 75cbe22a authored by Julius Künzel's avatar Julius Künzel
Browse files

Fix ripple in several scenarios with groups

parent d0a4f2d9
......@@ -326,6 +326,18 @@ void GroupsModel::setGroup(int id, int groupId, bool changeState)
}
}
QString GroupsModel::debugString() {
QString string;
for (auto item : m_downLink) {
QStringList leafs;
for (auto leaf : item.second) {
leafs << QString::number(leaf);
}
string.append((QStringLiteral("ID: %1 Leafs: %2; ").arg(item.first).arg(leafs.join(" "))));
}
return string;
}
void GroupsModel::removeFromGroup(int id)
{
QWriteLocker locker(&m_lock);
......
......@@ -156,6 +156,20 @@ public:
*/
bool checkConsistency(bool failOnSingleGroups = true, bool checkTimelineConsistency = false);
/** @brief Remove an item from all the groups it belongs to.
@param id of the groupItem
*/
void removeFromGroup(int id);
/** @brief change the group of a given item
@param id of the groupItem
@param groupId id of the group to assign it to
@param changeState when false, the grouped role for item won't be updated (for selection)
*/
void setGroup(int id, int groupId, bool changeState = true);
QString debugString();
protected:
/** @brief Destruct a groupItem in the hierarchy.
All its children will become their own roots
......@@ -169,18 +183,6 @@ protected:
/* Lambda version */
Fun destructGroupItem_lambda(int id);
/** @brief change the group of a given item
@param id of the groupItem
@param groupId id of the group to assign it to
@param changeState when false, the grouped role for item won't be updated (for selection)
*/
void setGroup(int id, int groupId, bool changeState = true);
/** @brief Remove an item from all the groups it belongs to.
@param id of the groupItem
*/
void removeFromGroup(int id);
/** @brief This is the actual recursive implementation of the copy function. */
bool processCopy(int gid, std::unordered_map<int, int> &mapping, Fun &undo, Fun &redo);
......
......@@ -337,47 +337,17 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
std::unordered_set<int> leavesToKeep;
for (int l : leaves) {
int pos = timeline->getItemPosition(l);
bool outOfRange = pos + timeline->getItemPlaytime(l) < position;
int tid = timeline->getItemTrackId(l);
bool unaffectedTrack = ignoreMultiTrackGroups && trackId > -1 && tid != trackId;
if (allowGroupBreaking) {
int checkedParent = timeline->m_groups->getDirectAncestor(l);
if (pos + timeline->getItemPlaytime(l) < position) {
if (checkedParent == r) {
leavesToRemove.insert(l);
} else {
int grandParent = timeline->m_groups->getDirectAncestor(checkedParent);
while (grandParent != r) {
checkedParent = grandParent;
grandParent = timeline->m_groups->getDirectAncestor(checkedParent);
}
leavesToRemove.insert(checkedParent);
}
} else if (ignoreMultiTrackGroups && trackId > -1 && timeline->getItemTrackId(l) != trackId) {
if (checkedParent == r) {
leavesToRemove.insert(l);
} else {
int grandParent = timeline->m_groups->getDirectAncestor(checkedParent);
while (grandParent != r) {
checkedParent = grandParent;
grandParent = timeline->m_groups->getDirectAncestor(checkedParent);
}
leavesToRemove.insert(checkedParent);
}
if (outOfRange || unaffectedTrack) {
leavesToRemove.insert(l);
} else {
if (checkedParent == r) {
leavesToKeep.insert(l);
} else {
int grandParent = timeline->m_groups->getDirectAncestor(checkedParent);
while (grandParent != r) {
checkedParent = grandParent;
grandParent = timeline->m_groups->getDirectAncestor(checkedParent);
}
leavesToKeep.insert(checkedParent);
}
leavesToKeep.insert(l);
}
}
if (!(pos + timeline->getItemPlaytime(l) < position || (ignoreMultiTrackGroups && trackId > -1 && timeline->getItemTrackId(l) != trackId))) {
int tid = timeline->getItemTrackId(l);
if (!outOfRange && !unaffectedTrack) {
// Check space in all tracks
if (!firstPositions.contains(tid)) {
firstPositions.insert(tid, pos);
......@@ -393,18 +363,16 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
}
}
}
if (leavesToKeep.size() == 1) {
// Only 1 item left in group, group will be deleted
int master = *leavesToKeep.begin();
roots.insert(master);
for (int l : leavesToRemove) {
spacerUngroupedItems.insert(l, master);
for (int l : leavesToRemove) {
int checkedParent = timeline->m_groups->getDirectAncestor(l);
if (checkedParent < 0) {
checkedParent = l;
}
spacerUngroupedItems.insert(l, checkedParent);
}
if (leavesToKeep.size() == 1) {
roots.insert(*leavesToKeep.begin());
groupsToRemove.insert(r);
} else {
for (int l : leavesToRemove) {
spacerUngroupedItems.insert(l, r);
}
}
} else {
int pos = timeline->getItemPosition(r);
......@@ -432,7 +400,7 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
QMapIterator<int, int> i(spacerUngroupedItems);
while (i.hasNext()) {
i.next();
timeline->m_groups->ungroupItem(i.value(), undo, redo, false);
timeline->m_groups->removeFromGroup(i.key());
}
timeline->requestSetSelection(roots);
......@@ -543,18 +511,26 @@ bool TimelineFunctions::requestSpacerEndOperation(const std::shared_ptr<Timeline
QMapIterator<int, int> i(spacerUngroupedItems);
Fun local_undo = []() { return true; };
Fun local_redo = []() { return true; };
std::unordered_set<int> newlyGrouped;
while (i.hasNext()) {
i.next();
if (timeline->isGroup(i.value())) {
if (timeline->isItem(i.value())) {
if (newlyGrouped.count(i.value()) > 0) {
Q_ASSERT(timeline->m_groups->isInGroup(i.value()));
timeline->m_groups->setInGroupOf(i.key(), i.value(), local_undo, local_redo);
} else {
std::unordered_set<int> items = {i.key(), i.value()};
timeline->m_groups->groupItems(items, local_undo, local_redo);
newlyGrouped.insert(i.value());
}
} else {
// i.value() is either a group (detectable via timeline->isGroup) or an empty group
if (timeline->isGroup(i.key())) {
std::unordered_set<int> items = {i.key(), i.value()};
timeline->m_groups->groupItems(items, local_undo, local_redo);
} else {
timeline->m_groups->setInGroupOf(i.key(), i.value(), local_undo, local_redo);
timeline->m_groups->setGroup(i.key(), i.value());
}
} else if (timeline->isItem(i.value())) {
std::unordered_set<int> items = {i.key(), i.value()};
timeline->m_groups->groupItems(items, local_undo, local_redo);
}
}
spacerUngroupedItems.clear();
......
......@@ -3691,7 +3691,7 @@ bool TimelineModel::requestItemRippleResize(const std::shared_ptr<TimelineItemMo
if (right && getTrackById_const(trackId)->isLastClip(getItemPosition(itemId))) {
return true;
}
int cid = TimelineFunctions::requestSpacerStartOperation(timeline, affectAllTracks ? -1 : trackId, position, true, true);
int cid = TimelineFunctions::requestSpacerStartOperation(timeline, affectAllTracks ? -1 : trackId, position + 1, true, true);
if (cid == -1) {
return false;
}
......@@ -3701,7 +3701,7 @@ bool TimelineModel::requestItemRippleResize(const std::shared_ptr<TimelineItemMo
return true;
};
if (delta > 0) {
if(right) {
if (right) {
int position = getItemPosition(itemId) + getItemPlaytime(itemId);
if (!spacerOperation(position)) {
return false;
......@@ -3719,7 +3719,7 @@ bool TimelineModel::requestItemRippleResize(const std::shared_ptr<TimelineItemMo
local_undo();
}
if (result && delta < 0) {
if(right) {
if (right) {
int position = getItemPosition(itemId) + getItemPlaytime(itemId) - delta;
if (!spacerOperation(position)) {
return false;
......@@ -3783,7 +3783,7 @@ int TimelineModel::requestSlipSelection(int offset, bool logUndo) {
int TimelineModel::requestClipSlip(int itemId, int offset, bool logUndo, bool allowSingleResize)
{
QWriteLocker locker(&m_lock);
TRACE(itemId, size, right, logUndo, snapDistance, allowSingleResize)
TRACE(itemId, offset, logUndo, allowSingleResize)
Q_ASSERT(isClip(itemId));
Fun undo = []() { return true; };
Fun redo = []() { return true; };
......
......@@ -357,7 +357,7 @@ Item{
if (root.activeTool === ProjectTool.RippleTool) {
timeline.requestItemRippleResize(clip.clipId, clip.originalDuration, false, false, 0, shiftTrim)
} else {
timeline.requestItemResize(clip.clipId, clip.originalDuration, false, false, 0, shiftTrim)
controller.requestItemResize(clip.clipId, clip.originalDuration, false, false, 0, shiftTrim)
}
if (root.activeTool === ProjectTool.SelectTool && controlTrim) {
......
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