Fix drag overwrite broken for multi stream clips

parent 865f17f4
Pipeline #20406 passed with stage
in 9 minutes and 38 seconds
......@@ -724,7 +724,7 @@ bool TimelineModel::requestClipMoveAttempt(int clipId, int trackId, int position
return res;
}
int TimelineModel::suggestItemMove(int itemId, int trackId, int position, int cursorPosition, int snapDistance)
QVariantList TimelineModel::suggestItemMove(int itemId, int trackId, int position, int cursorPosition, int snapDistance)
{
if (isClip(itemId)) {
return suggestClipMove(itemId, trackId, position, cursorPosition, snapDistance);
......@@ -732,21 +732,21 @@ int TimelineModel::suggestItemMove(int itemId, int trackId, int position, int cu
return suggestCompositionMove(itemId, trackId, position, cursorPosition, snapDistance);
}
int TimelineModel::suggestClipMove(int clipId, int trackId, int position, int cursorPosition, int snapDistance, bool moveMirrorTracks)
QVariantList TimelineModel::suggestClipMove(int clipId, int trackId, int position, int cursorPosition, int snapDistance, bool moveMirrorTracks)
{
QWriteLocker locker(&m_lock);
TRACE(clipId, trackId, position, cursorPosition, snapDistance);
Q_ASSERT(isClip(clipId));
Q_ASSERT(isTrack(trackId));
int currentPos = getClipPosition(clipId);
int sourceTrackId = getClipTrackId(clipId);
int sourceTrackId = (m_editMode != TimelineMode::NormalEdit) ? m_allClips[clipId]->getFakeTrackId() : getClipTrackId(clipId);
if (sourceTrackId > -1 && getTrackById_const(trackId)->isAudioTrack() != getTrackById_const(sourceTrackId)->isAudioTrack()) {
// Trying move on incompatible track type, stay on same track
trackId = sourceTrackId;
}
if (currentPos == position && m_editMode == TimelineMode::NormalEdit && sourceTrackId == trackId) {
TRACE_RES(position);
return position;
return {position, trackId};
}
bool after = position > currentPos;
if (snapDistance > 0) {
......@@ -784,25 +784,27 @@ int TimelineModel::suggestClipMove(int clipId, int trackId, int position, int cu
}*/
if (possible) {
TRACE_RES(position);
return position;
if (m_editMode != TimelineMode::NormalEdit) {
trackId = m_allClips[clipId]->getFakeTrackId();
}
return {position, trackId};
}
if (sourceTrackId == -1) {
// not clear what to do hear, if the current move doesn't work. We could try to find empty space, but it might end up being far away...
// not clear what to do here, if the current move doesn't work. We could try to find empty space, but it might end up being far away...
TRACE_RES(currentPos);
return currentPos;
return {currentPos, -1};
}
// Find best possible move
if (!m_groups->isInGroup(clipId)) {
// Try same track move
if (trackId != sourceTrackId && sourceTrackId != -1) {
qDebug() << "// TESTING SAME TRACVK MOVE: " << trackId << " = " << sourceTrackId;
trackId = sourceTrackId;
possible = requestClipMove(clipId, trackId, position, moveMirrorTracks, true, false, false);
if (!possible) {
qDebug() << "CANNOT MOVE CLIP : " << clipId << " ON TK: " << trackId << ", AT POS: " << position;
} else {
TRACE_RES(position);
return position;
return {position, trackId};
}
}
......@@ -816,16 +818,22 @@ int TimelineModel::suggestClipMove(int clipId, int trackId, int position, int cu
}
} else {
TRACE_RES(currentPos);
return currentPos;
return {currentPos, sourceTrackId};
}
possible = requestClipMove(clipId, trackId, position, moveMirrorTracks, true, false, false);
TRACE_RES(possible ? position : currentPos);
return possible ? position : currentPos;
if (possible) {
return {position, trackId};
}
return {currentPos, sourceTrackId};
}
if (trackId != sourceTrackId) {
// Try same track move
possible = requestClipMove(clipId, sourceTrackId, position, moveMirrorTracks, true, false, false);
return possible ? position : currentPos;
if (possible) {
return {position, sourceTrackId};
}
return {currentPos, sourceTrackId};
}
// find best pos for groups
int groupId = m_groups->getRootId(clipId);
......@@ -889,14 +897,14 @@ int TimelineModel::suggestClipMove(int clipId, int trackId, int position, int cu
possible = requestClipMove(clipId, trackId, updatedPos, moveMirrorTracks, true, false, false);
if (possible) {
TRACE_RES(updatedPos);
return updatedPos;
return {updatedPos, trackId};
}
}
TRACE_RES(currentPos);
return currentPos;
return {currentPos, sourceTrackId};
}
int TimelineModel::suggestCompositionMove(int compoId, int trackId, int position, int cursorPosition, int snapDistance)
QVariantList TimelineModel::suggestCompositionMove(int compoId, int trackId, int position, int cursorPosition, int snapDistance)
{
QWriteLocker locker(&m_lock);
TRACE(compoId, trackId, position, cursorPosition, snapDistance);
......@@ -910,7 +918,7 @@ int TimelineModel::suggestCompositionMove(int compoId, int trackId, int position
}
if (currentPos == position && currentTrack == trackId) {
TRACE_RES(position);
return position;
return {position, trackId};
}
if (snapDistance > 0) {
......@@ -943,7 +951,7 @@ int TimelineModel::suggestCompositionMove(int compoId, int trackId, int position
qDebug() << "Original move success" << possible;
if (possible) {
TRACE_RES(position);
return position;
return {position, trackId};
}
/*bool after = position > currentPos;
int blank_length = getTrackById(trackId)->getBlankSizeNearComposition(compoId, after);
......@@ -956,7 +964,7 @@ int TimelineModel::suggestCompositionMove(int compoId, int trackId, int position
}
return position;*/
TRACE_RES(currentPos);
return currentPos;
return {currentPos, currentTrack};
}
bool TimelineModel::requestClipCreation(const QString &binClipId, int &id, PlaylistState::ClipState state, int audioStream, double speed, bool warp_pitch, Fun &undo, Fun &redo)
......@@ -1227,7 +1235,6 @@ bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId,
} else {
qDebug()<<"=== DROPPING VIDEO, STREAMS: "<<streamsCount;
}
// QList<int> possibleTracks = m_audioTarget >= 0 ? QList<int>() << m_audioTarget : getLowerTracksId(trackId, TrackType::AudioTrack);
int newId;
res = requestClipCreation(binIdWithInOut, newId, currentDropIsAudio ? PlaylistState::AudioOnly : PlaylistState::VideoOnly, currentDropIsAudio ? mirrorAudioStream : -1, 1.0, false, audio_undo, audio_redo);
if (res) {
......@@ -1448,6 +1455,8 @@ bool TimelineModel::requestFakeGroupMove(int clipId, int groupId, int delta_trac
// Check if there is a track move
// First, remove clips
bool hasAudio = false;
bool hasVideo = false;
std::unordered_map<int, int> old_track_ids, old_position, old_forced_track;
for (int item : all_items) {
int old_trackId = getItemTrackId(item);
......@@ -1455,7 +1464,13 @@ bool TimelineModel::requestFakeGroupMove(int clipId, int groupId, int delta_trac
if (old_trackId != -1) {
if (isClip(item)) {
old_position[item] = m_allClips[item]->getPosition();
if (!hasAudio && getTrackById_const(old_trackId)->isAudioTrack()) {
hasAudio = true;
} else if (!hasVideo && !getTrackById_const(old_trackId)->isAudioTrack()) {
hasVideo = true;
}
} else {
hasVideo = true;
old_position[item] = m_allCompositions[item]->getPosition();
old_forced_track[item] = m_allCompositions[item]->getForcedTrack();
}
......@@ -1468,9 +1483,17 @@ bool TimelineModel::requestFakeGroupMove(int clipId, int groupId, int delta_trac
if (getTrackById(old_track_ids[clipId])->isAudioTrack()) {
// Master clip is audio, so reverse delta for video clips
video_delta = -delta_track;
if (hasAudio) {
video_delta = -delta_track;
} else {
video_delta = 0;
}
} else {
audio_delta = -delta_track;
if (hasVideo) {
audio_delta = -delta_track;
} else {
audio_delta = 0;
}
}
bool trackChanged = false;
......@@ -1478,7 +1501,7 @@ bool TimelineModel::requestFakeGroupMove(int clipId, int groupId, int delta_trac
for (int item : all_items) {
int current_track_id = old_track_ids[item];
int current_track_position = getTrackPosition(current_track_id);
int d = getTrackById(current_track_id)->isAudioTrack() ? audio_delta : video_delta;
int d = getTrackById_const(current_track_id)->isAudioTrack() ? audio_delta : video_delta;
int target_track_position = current_track_position + d;
if (target_track_position >= 0 && target_track_position < getTracksCount()) {
auto it = m_allTracks.cbegin();
......
......@@ -374,7 +374,7 @@ public:
bool requestFakeGroupMove(int clipId, int groupId, int delta_track, int delta_pos, bool updateView, bool finalMove, Fun &undo, Fun &redo,
bool allowViewRefresh = true);
/* @brief Given an intended move, try to suggest a more valid one
/** @brief Given an intended move, try to suggest a more valid one
(accounting for snaps and missing UI calls)
@param clipId id of the clip to
move
......@@ -383,10 +383,11 @@ public:
@param snapDistance the maximum distance for a snap result, -1 for no snapping
of the clip
@param dontRefreshMasterClip when false, no view refresh is attempted
@returns a list in the form {position, trackId}
*/
Q_INVOKABLE int suggestItemMove(int itemId, int trackId, int position, int cursorPosition, int snapDistance = -1);
Q_INVOKABLE int suggestClipMove(int clipId, int trackId, int position, int cursorPosition, int snapDistance = -1, bool moveMirrorTracks = true);
Q_INVOKABLE int suggestCompositionMove(int compoId, int trackId, int position, int cursorPosition, int snapDistance = -1);
Q_INVOKABLE QVariantList suggestItemMove(int itemId, int trackId, int position, int cursorPosition, int snapDistance = -1);
Q_INVOKABLE QVariantList suggestClipMove(int clipId, int trackId, int position, int cursorPosition, int snapDistance = -1, bool moveMirrorTracks = true);
Q_INVOKABLE QVariantList suggestCompositionMove(int compoId, int trackId, int position, int cursorPosition, int snapDistance = -1);
/* @brief Request clip insertion at given position. This action is undoable
Returns true on success. If it fails, nothing is modified.
......
......@@ -513,8 +513,9 @@ Rectangle {
// we want insert/overwrite mode, make a fake insert at end of timeline, then move to position
clipBeingDroppedId = insertAndMaybeGroup(timeline.activeTrack, timeline.fullDuration, clipBeingDroppedData)
if (clipBeingDroppedId > -1) {
fakeFrame = controller.suggestClipMove(clipBeingDroppedId, timeline.activeTrack, frame, root.consumerPosition, root.snapping)
fakeTrack = timeline.activeTrack
var moveData = controller.suggestClipMove(clipBeingDroppedId, timeline.activeTrack, frame, root.consumerPosition, root.snapping)
fakeFrame = moveData[0]
fakeTrack = moveData[1]
} else {
drag.accepted = false
}
......@@ -538,22 +539,32 @@ Rectangle {
if (clipBeingMovedId == -1) {
var track = Logic.getTrackIndexFromPos(drag.y + scrollView.contentY)
if (track >= 0 && track < tracksRepeater.count) {
timeline.activeTrack = tracksRepeater.itemAt(track).trackInternalId
//timeline.activeTrack = tracksRepeater.itemAt(track).trackInternalId
var targetTrack = tracksRepeater.itemAt(track).trackInternalId
var frame = Math.round((drag.x + scrollView.contentX) / timeline.scaleFactor)
if (clipBeingDroppedId >= 0) {
fakeFrame = controller.suggestClipMove(clipBeingDroppedId, timeline.activeTrack, frame, root.consumerPosition, root.snapping)
fakeTrack = timeline.activeTrack
if (clipBeingDroppedId > -1) {
var moveData = controller.suggestClipMove(clipBeingDroppedId, targetTrack, frame, root.consumerPosition, root.snapping)
fakeFrame = moveData[0]
fakeTrack = moveData[1]
timeline.activeTrack = fakeTrack
console.log('+++ GOT DRAG FAKE TRACK: ', moveData[1])
//controller.requestClipMove(clipBeingDroppedId, timeline.activeTrack, frame, true, false, false)
continuousScrolling(drag.x + scrollView.contentX, drag.y + scrollView.contentY)
} else {
frame = controller.suggestSnapPoint(frame, root.snapping)
if (controller.normalEdit()) {
clipBeingDroppedId = insertAndMaybeGroup(timeline.activeTrack, frame, drag.getDataAsString('kdenlive/producerslist'), false, true)
timeline.activeTrack = targetTrack
clipBeingDroppedId = insertAndMaybeGroup(targetTrack, frame, drag.getDataAsString('kdenlive/producerslist'), false, true)
} else {
// we want insert/overwrite mode, make a fake insert at end of timeline, then move to position
clipBeingDroppedId = insertAndMaybeGroup(timeline.activeTrack, timeline.fullDuration, clipBeingDroppedData)
fakeFrame = controller.suggestClipMove(clipBeingDroppedId, timeline.activeTrack, frame, root.consumerPosition, root.snapping)
fakeTrack = timeline.activeTrack
clipBeingDroppedId = insertAndMaybeGroup(targetTrack, timeline.fullDuration, clipBeingDroppedData)
if (clipBeingDroppedId > -1) {
var moveData = controller.suggestClipMove(clipBeingDroppedId, targetTrack, frame, root.consumerPosition, root.snapping)
fakeFrame = moveData[0]
fakeTrack = moveData[1]
timeline.activeTrack = fakeTrack
console.log('+++ GOT DRAG FAKE TWO TRACK: ', moveData[1])
}
}
continuousScrolling(drag.x + scrollView.contentX, drag.y + scrollView.contentY)
}
......@@ -596,7 +607,7 @@ Rectangle {
var frame = Math.round((drag.x + scrollView.contentX) / timeline.scaleFactor)
if (clipBeingDroppedId >= 0) {
//fakeFrame = controller.suggestClipMove(clipBeingDroppedId, timeline.activeTrack, frame, root.consumerPosition, Math.floor(root.snapping))
fakeTrack = timeline.activeTrack
//fakeTrack = timeline.activeTrack
//controller.requestClipMove(clipBeingDroppedId, timeline.activeTrack, frame, true, false, false)
continuousScrolling(drag.x + scrollView.contentX, drag.y + scrollView.contentY)
} else {
......@@ -907,7 +918,7 @@ Rectangle {
// Move group
var track = controller.getItemTrackId(spacerGroup)
var frame = Math.round((mouse.x + scrollView.contentX) / timeline.scaleFactor) + spacerFrame - spacerClickFrame
frame = controller.suggestItemMove(spacerGroup, track, frame, root.consumerPosition, (mouse.modifiers & Qt.ShiftModifier) ? 0 : root.snapping)
frame = controller.suggestItemMove(spacerGroup, track, frame, root.consumerPosition, (mouse.modifiers & Qt.ShiftModifier) ? 0 : root.snapping)[0]
continuousScrolling(mouse.x + scrollView.contentX, mouse.y + scrollView.contentY)
}
scim = true
......@@ -1180,8 +1191,9 @@ Rectangle {
}
}
if (dragProxy.isComposition) {
dragFrame = controller.suggestCompositionMove(dragProxy.draggedItem, tId, posx, root.consumerPosition, dragProxyArea.snapping)
timeline.activeTrack = timeline.getItemMovingTrack(dragProxy.draggedItem)
var moveData = controller.suggestCompositionMove(dragProxy.draggedItem, tId, posx, root.consumerPosition, dragProxyArea.snapping)
dragFrame = moveData[0]
timeline.activeTrack = moveData[1]
} else {
if (!controller.normalEdit() && dragProxy.masterObject.parent != dragContainer) {
var pos = dragProxy.masterObject.mapToGlobal(dragProxy.masterObject.x, dragProxy.masterObject.y)
......@@ -1191,8 +1203,10 @@ Rectangle {
dragProxy.masterObject.y = pos.y
//console.log('bringing item to front')
}
dragFrame = controller.suggestClipMove(dragProxy.draggedItem, tId, posx, root.consumerPosition, dragProxyArea.snapping, moveMirrorTracks)
timeline.activeTrack = timeline.getItemMovingTrack(dragProxy.draggedItem)
var moveData = controller.suggestClipMove(dragProxy.draggedItem, tId, posx, root.consumerPosition, dragProxyArea.snapping, moveMirrorTracks)
dragFrame = moveData[0]
timeline.activeTrack = moveData[1]
//timeline.getItemMovingTrack(dragProxy.draggedItem)
}
var delta = dragFrame - dragProxy.sourceFrame
if (delta != 0) {
......
......@@ -2015,32 +2015,61 @@ bool TimelineController::insertClipZone(const QString &binId, int tid, int posit
dropType = PlaylistState::VideoOnly;
bid = bid.remove(0, 1);
}
int aTrack = -1;
QList <int> audioTracks;
int vTrack = -1;
std::shared_ptr<ProjectClip> clip = pCore->bin()->getBinClip(bid);
if (out <= in) {
out = (int)clip->frameDuration() - 1;
}
QList <int> audioStreams = m_model->m_binAudioTargets.keys();
if (dropType == PlaylistState::VideoOnly) {
vTrack = tid;
} else if (dropType == PlaylistState::AudioOnly) {
aTrack = tid;
audioTracks << tid;
if (audioStreams.size() > 1) {
// insert the other audio streams
QList <int> lower = m_model->getLowerTracksId(tid, TrackType::AudioTrack);
while (audioStreams.size() > 1 && !lower.isEmpty()) {
audioTracks << lower.takeFirst();
audioStreams.takeFirst();
}
}
} else {
if (m_model->getTrackById_const(tid)->isAudioTrack()) {
aTrack = tid;
vTrack = clip->hasAudioAndVideo() ? m_model->getMirrorVideoTrackId(aTrack) : -1;
audioTracks << tid;
if (audioStreams.size() > 1) {
// insert the other audio streams
QList <int> lower = m_model->getLowerTracksId(tid, TrackType::AudioTrack);
while (audioStreams.size() > 1 && !lower.isEmpty()) {
audioTracks << lower.takeFirst();
audioStreams.takeFirst();
}
}
vTrack = clip->hasAudioAndVideo() ? m_model->getMirrorVideoTrackId(tid) : -1;
} else {
vTrack = tid;
aTrack = clip->hasAudioAndVideo() ? m_model->getMirrorAudioTrackId(vTrack) : -1;
if (clip->hasAudioAndVideo()) {
int firstAudio = m_model->getMirrorAudioTrackId(vTrack);
audioTracks << firstAudio;
if (audioStreams.size() > 1) {
// insert the other audio streams
QList <int> lower = m_model->getLowerTracksId(firstAudio, TrackType::AudioTrack);
while (audioStreams.size() > 1 && !lower.isEmpty()) {
audioTracks << lower.takeFirst();
audioStreams.takeFirst();
}
}
}
}
}
QList<int> target_tracks;
if (vTrack > -1) {
target_tracks << vTrack;
}
if (aTrack > -1) {
target_tracks << aTrack;
if (!audioTracks.isEmpty()) {
target_tracks << audioTracks;
}
qDebug()<<"=====================\n\nREADY TO INSERT IN TRACKS: "<<audioTracks<<" / VIDEO: "<<vTrack<<"\n\n=========";
std::function<bool(void)> undo = []() { return true; };
std::function<bool(void)> redo = []() { return true; };
bool overwrite = m_model->m_editMode == TimelineMode::OverwriteEdit;
......
......@@ -1786,8 +1786,8 @@ TEST_CASE("Snapping", "[Snapping]")
int beg = 30;
// in the absence of other clips, a valid move shouldn't be modified
for (int snap = -1; snap <= 5; ++snap) {
REQUIRE(timeline->suggestClipMove(cid2, tid2, beg, -1, snap) == beg);
REQUIRE(timeline->suggestClipMove(cid2, tid2, beg + length, -1, snap) == beg + length);
REQUIRE(timeline->suggestClipMove(cid2, tid2, beg, -1, snap).at(0) == beg);
REQUIRE(timeline->suggestClipMove(cid2, tid2, beg + length, -1, snap).at(0) == beg + length);
REQUIRE(timeline->checkConsistency());
}
......@@ -1797,11 +1797,11 @@ TEST_CASE("Snapping", "[Snapping]")
// Now a clip in second track should snap to beginning
auto check_snap = [&](int pos, int perturb, int snap) {
if (snap >= perturb) {
REQUIRE(timeline->suggestClipMove(cid2, tid2, pos + perturb, -1, snap) == pos);
REQUIRE(timeline->suggestClipMove(cid2, tid2, pos - perturb, -1, snap) == pos);
REQUIRE(timeline->suggestClipMove(cid2, tid2, pos + perturb, -1, snap).at(0) == pos);
REQUIRE(timeline->suggestClipMove(cid2, tid2, pos - perturb, -1, snap).at(0) == pos);
} else {
REQUIRE(timeline->suggestClipMove(cid2, tid2, pos + perturb, -1, snap) == pos + perturb);
REQUIRE(timeline->suggestClipMove(cid2, tid2, pos - perturb, -1, snap) == pos - perturb);
REQUIRE(timeline->suggestClipMove(cid2, tid2, pos + perturb, -1, snap).at(0) == pos + perturb);
REQUIRE(timeline->suggestClipMove(cid2, tid2, pos - perturb, -1, snap).at(0) == pos - perturb);
}
};
for (int snap = -1; snap <= 5; ++snap) {
......
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