Commit 504154d1 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Fix crash using spacer tool on grouped clips with a clip in the group...

Fix crash using spacer tool on grouped clips with a clip in the group positioned before spacer start operation.
BUG: 443324
parent 4eab7117
......@@ -87,7 +87,6 @@ int GroupsModel::groupItems(const std::unordered_set<int> &ids, Fun &undo, Fun &
Q_ASSERT(type != GroupType::Leaf);
Q_ASSERT(!ids.empty());
std::unordered_set<int> roots;
qDebug()<<"==========GROUPING ITEMS: "<<ids.size();
std::transform(ids.begin(), ids.end(), std::inserter(roots, roots.begin()), [&](int id) { return getRootId(id); });
if (roots.size() == 1 && !force) {
// We do not create a group with only one element. Instead, we return the id of that element
......@@ -104,7 +103,7 @@ int GroupsModel::groupItems(const std::unordered_set<int> &ids, Fun &undo, Fun &
return -1;
}
bool GroupsModel::ungroupItem(int id, Fun &undo, Fun &redo)
bool GroupsModel::ungroupItem(int id, Fun &undo, Fun &redo, bool deleteOrphan)
{
QWriteLocker locker(&m_lock);
int gid = getRootId(id);
......@@ -113,7 +112,7 @@ bool GroupsModel::ungroupItem(int id, Fun &undo, Fun &redo)
return false;
}
return destructGroupItem(gid, true, undo, redo);
return destructGroupItem(gid, deleteOrphan, undo, redo);
}
void GroupsModel::createGroupItem(int id)
......
......@@ -49,7 +49,7 @@ public:
@param undo Lambda function containing the current undo stack. Will be updated with current operation
@param redo Lambda function containing the current redo queue. Will be updated with current operation
*/
bool ungroupItem(int id, Fun &undo, Fun &redo);
bool ungroupItem(int id, Fun &undo, Fun &redo, bool deleteOrphan = true);
/** @brief Create a groupItem in the hierarchy. Initially it is not part of a group
@param id id of the groupItem
......
......@@ -337,12 +337,41 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
std::unordered_set<int> leavesToKeep;
for (int l : leaves) {
int pos = timeline->getItemPosition(l);
int checkedParent = timeline->m_groups->getDirectAncestor(l);
if (pos + timeline->getItemPlaytime(l) < position) {
leavesToRemove.insert(l);
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);
}
leavesToRemove.insert(l);
} else {
leavesToKeep.insert(l);
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);
}
int tid = timeline->getItemTrackId(l);
// Check space in all tracks
if (!firstPositions.contains(tid)) {
......@@ -392,13 +421,15 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
for (int r : groupsToRemove) {
roots.erase(r);
}
Fun undo = []() { return true; };
Fun redo = []() { return true; };
QMapIterator<int, int> i(spacerUngroupedItems);
while (i.hasNext()) {
i.next();
timeline->m_groups->ungroupItem(i.key(), undo, redo);
timeline->m_groups->ungroupItem(i.value(), undo, redo, false);
}
timeline->requestSetSelection(roots);
if (!firstPositions.isEmpty()) {
// Find minimum position, parse all tracks
......@@ -510,8 +541,13 @@ bool TimelineFunctions::requestSpacerEndOperation(const std::shared_ptr<Timeline
while (i.hasNext()) {
i.next();
if (timeline->isGroup(i.value())) {
timeline->m_groups->setInGroupOf(i.key(), i.value(), local_undo, local_redo);
} else {
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);
}
} else if (timeline->isItem(i.value())) {
std::unordered_set<int> items = {i.key(), i.value()};
timeline->m_groups->groupItems(items, local_undo, local_redo);
}
......
......@@ -5723,7 +5723,6 @@ bool TimelineModel::requestSetSelection(const std::unordered_set<int> &ids)
{
QWriteLocker locker(&m_lock);
TRACE(ids);
requestClearSelection();
// if the items are in groups, we must retrieve their topmost containing groups
std::unordered_set<int> roots;
......
......@@ -405,7 +405,7 @@ Rectangle {
property int snapping: (timeline.snap && (timeline.scaleFactor < 2 * baseUnit)) ? Math.floor(baseUnit / (timeline.scaleFactor > 3 ? timeline.scaleFactor / 2 : timeline.scaleFactor)) : -1
property var timelineSelection: timeline.selection
property int selectedMix: timeline.selectedMix
property var selectedGuides
property var selectedGuides: []
property int trackHeight
property int copiedClip: -1
property int zoomOnMouse: -1
......
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