Fix spacer/insert/remove space with grouped clips on both sides of the move

BUG: 390668
Related to #973
parent b46a4739
......@@ -69,6 +69,7 @@ RTTR_REGISTRATION
QStringList waitingBinIds;
QMap<QString, QString> mappedIds;
QMap<int, int> tracksMap;
QMap<int, int> spacerUngroupedItems;
QSemaphore semaphore(1);
bool TimelineFunctions::cloneClip(const std::shared_ptr<TimelineItemModel> &timeline, int clipId, int &newId, PlaylistState::ClipState state, Fun &undo,
......@@ -325,8 +326,51 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
{
std::unordered_set<int> clips = timeline->getItemsInRange(trackId, position, -1);
if (!clips.empty()) {
timeline->requestSetSelection(clips);
return (*clips.cbegin());
// Remove grouped items that are before the click position
// First get top groups ids
std::unordered_set<int> roots;
spacerUngroupedItems.clear();
std::transform(clips.begin(), clips.end(), std::inserter(roots, roots.begin()), [&](int id) { return timeline->m_groups->getRootId(id); });
std::unordered_set<int> groupsToRemove;
for (int r : roots) {
if (timeline->isGroup(r)) {
std::unordered_set<int> leaves = timeline->m_groups->getLeaves(r);
std::unordered_set<int> leavesToRemove;
std::unordered_set<int> leavesToKeep;
for (int l : leaves) {
if (timeline->getItemPosition(l) + timeline->getItemPlaytime(l) < position) {
leavesToRemove.insert(l);
} else {
leavesToKeep.insert(l);
}
}
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);
}
groupsToRemove.insert(r);
} else {
for (int l : leavesToRemove) {
spacerUngroupedItems.insert(l, r);
}
}
}
}
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->requestSetSelection(roots);
return (*roots.cbegin());
}
return -1;
}
......@@ -389,6 +433,20 @@ bool TimelineFunctions::requestSpacerEndOperation(const std::shared_ptr<Timeline
} else {
pCore->pushUndo(undo, redo, i18n("Remove space"));
}
// Regroup temporarily ungrouped items
QMapIterator<int, int> i(spacerUngroupedItems);
Fun local_undo = []() { return true; };
Fun local_redo = []() { return true; };
while (i.hasNext()) {
i.next();
if (timeline->isGroup(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);
}
}
spacerUngroupedItems.clear();
return true;
} else {
undo();
......
......@@ -1250,7 +1250,7 @@ Rectangle {
if (root.activeTool === 0 || mouse.y < ruler.height) {
proxy.position = Math.max(0, Math.min((scrollView.contentX + mouse.x) / timeline.scaleFactor, timeline.fullDuration - 1))
} else if (root.activeTool === 2 && spacerGroup > -1) {
// Move group
// Spacer tool, move group
var track = controller.getItemTrackId(spacerGroup)
var frame = Math.round((mouse.x + scrollView.contentX) / timeline.scaleFactor) + spacerFrame - spacerClickFrame
finalSpacerFrame = controller.suggestItemMove(spacerGroup, track, frame, root.consumerPosition, (mouse.modifiers & Qt.ShiftModifier) ? 0 : root.snapping)[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