Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Multimedia
Kdenlive
Commits
026f2109
Commit
026f2109
authored
Nov 19, 2021
by
Jean-Baptiste Mardelle
Browse files
Another round of mix resize issues, with added tests
parent
4a7218d6
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/timeline2/model/timelinefunctions.cpp
View file @
026f2109
...
...
@@ -79,8 +79,8 @@ bool TimelineFunctions::cloneClip(const std::shared_ptr<TimelineItemModel> &time
int
duration
=
timeline
->
getClipPlaytime
(
clipId
);
int
init_duration
=
timeline
->
getClipPlaytime
(
newId
);
if
(
duration
!=
init_duration
)
{
in
t
i
n
=
timeline
->
m_allClips
[
clipId
]
->
getIn
();
res
=
res
&&
timeline
->
requestItemResize
(
newId
,
init_duration
-
in
,
false
,
true
,
undo
,
redo
);
in
it_duratio
n
-
=
timeline
->
m_allClips
[
clipId
]
->
getIn
();
res
=
res
&&
timeline
->
requestItemResize
(
newId
,
init_duration
,
false
,
true
,
undo
,
redo
);
res
=
res
&&
timeline
->
requestItemResize
(
newId
,
duration
,
true
,
true
,
undo
,
redo
);
}
if
(
!
res
)
{
...
...
@@ -133,14 +133,16 @@ bool TimelineFunctions::processClipCut(const std::shared_ptr<TimelineItemModel>
// Check if clip has an end Mix
bool
res
=
cloneClip
(
timeline
,
clipId
,
newId
,
state
,
undo
,
redo
);
timeline
->
m_blockRefresh
=
true
;
res
=
res
&&
timeline
->
requestItemResize
(
clipId
,
position
-
start
,
true
,
true
,
undo
,
redo
);
int
updatedDuration
=
position
-
start
;
res
=
res
&&
timeline
->
requestItemResize
(
clipId
,
updatedDuration
,
true
,
true
,
undo
,
redo
);
int
newDuration
=
timeline
->
getClipPlaytime
(
clipId
);
// parse effects
std
::
shared_ptr
<
EffectStackModel
>
sourceStack
=
timeline
->
getClipEffectStackModel
(
clipId
);
sourceStack
->
cleanFadeEffects
(
true
,
undo
,
redo
);
std
::
shared_ptr
<
EffectStackModel
>
destStack
=
timeline
->
getClipEffectStackModel
(
newId
);
destStack
->
cleanFadeEffects
(
false
,
undo
,
redo
);
res
=
res
&&
timeline
->
requestItemResize
(
newId
,
duration
-
newDuration
,
false
,
true
,
undo
,
redo
);
updatedDuration
=
duration
-
newDuration
;
res
=
res
&&
timeline
->
requestItemResize
(
newId
,
updatedDuration
,
false
,
true
,
undo
,
redo
);
// The next requestclipmove does not check for duration change since we don't invalidate timeline, so check duration change now
bool
durationChanged
=
trackDuration
!=
timeline
->
getTrackById_const
(
trackId
)
->
trackDuration
();
timeline
->
m_allClips
[
newId
]
->
setSubPlaylistIndex
(
timeline
->
m_allClips
[
clipId
]
->
getSubPlaylistIndex
(),
trackId
);
...
...
src/timeline2/model/timelinemodel.cpp
View file @
026f2109
...
...
@@ -1586,9 +1586,11 @@ bool TimelineModel::requestClipCreation(const QString &binClipId, int &id, Playl
int
initLength
=
m_allClips
[
clipId
]
->
getPlaytime
();
bool
res
=
true
;
if
(
in
!=
0
)
{
res
=
requestItemResize
(
clipId
,
initLength
-
in
,
false
,
true
,
local_undo
,
local_redo
);
initLength
-=
in
;
res
=
requestItemResize
(
clipId
,
initLength
,
false
,
true
,
local_undo
,
local_redo
);
}
res
=
res
&&
requestItemResize
(
clipId
,
out
-
in
+
1
,
true
,
true
,
local_undo
,
local_redo
);
int
updatedDuration
=
out
-
in
+
1
;
res
=
res
&&
requestItemResize
(
clipId
,
updatedDuration
,
true
,
true
,
local_undo
,
local_redo
);
if
(
!
res
)
{
bool
undone
=
local_undo
();
Q_ASSERT
(
undone
);
...
...
@@ -2796,7 +2798,8 @@ void TimelineModel::processGroupResize(QVariantList startPos, QVariantList endPo
}
for
(
int
id
:
qAsConst
(
changedItems
))
{
QPair
<
int
,
int
>
endItemPos
=
endData
.
value
(
id
);
result
=
result
&
requestItemResize
(
id
,
endItemPos
.
second
,
right
,
true
,
undo
,
redo
,
false
);
int
duration
=
endItemPos
.
second
;
result
=
result
&
requestItemResize
(
id
,
duration
,
right
,
true
,
undo
,
redo
,
false
);
if
(
!
result
)
{
break
;
}
...
...
@@ -3079,7 +3082,7 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
if
(
getTrackById_const
(
tid
)
->
hasEndMix
(
itemId
))
{
tracksWithMixes
<<
tid
;
std
::
pair
<
MixInfo
,
MixInfo
>
mixData
=
getTrackById_const
(
tid
)
->
getMixInfo
(
itemId
);
if
(
in
+
size
<
=
mixData
.
second
.
secondClipInOut
.
first
+
m_allClips
[
mixData
.
second
.
secondClipId
]
->
getMixDuration
()
-
m_allClips
[
mixData
.
second
.
secondClipId
]
->
getMixCutPosition
())
{
if
(
in
+
size
<
mixData
.
second
.
secondClipInOut
.
first
+
m_allClips
[
mixData
.
second
.
secondClipId
]
->
getMixDuration
()
-
m_allClips
[
mixData
.
second
.
secondClipId
]
->
getMixCutPosition
())
{
// Clip resized outside of mix zone, mix will be deleted
bool
res
=
removeMixWithUndo
(
mixData
.
second
.
secondClipId
,
undo
,
redo
);
if
(
res
)
{
...
...
@@ -3263,6 +3266,9 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
finalSize
=
qMax
(
0
,
getItemPosition
(
id
))
+
getItemPlaytime
(
id
)
-
finalPos
;
}
result
=
result
&&
requestItemResize
(
id
,
finalSize
,
right
,
logUndo
,
undo
,
redo
);
if
(
id
==
itemId
)
{
size
=
finalSize
;
}
resizedCount
++
;
}
if
(
!
result
||
resizedCount
==
0
)
{
...
...
@@ -3293,7 +3299,7 @@ int TimelineModel::requestItemResize(int itemId, int size, bool right, bool logU
return
res
;
}
bool
TimelineModel
::
requestItemResize
(
int
itemId
,
int
size
,
bool
right
,
bool
logUndo
,
Fun
&
undo
,
Fun
&
redo
,
bool
blockUndo
)
bool
TimelineModel
::
requestItemResize
(
int
itemId
,
int
&
size
,
bool
right
,
bool
logUndo
,
Fun
&
undo
,
Fun
&
redo
,
bool
blockUndo
)
{
Q_UNUSED
(
blockUndo
)
Fun
local_undo
=
[]()
{
return
true
;
};
...
...
@@ -6195,10 +6201,12 @@ void TimelineModel::requestResizeMix(int cid, int duration, MixAlignment align,
updatedDurationRight
=
qMin
(
updatedDurationRight
,
m_allClips
.
at
(
cid
)
->
getPlaytime
()
+
rightMax
);
}
if
(
updatedDurationLeft
!=
0
)
{
requestItemResize
(
cid
,
m_allClips
.
at
(
cid
)
->
getPlaytime
()
+
updatedDurationLeft
,
false
,
true
,
undo
,
redo
);
int
updatedDurL
=
m_allClips
.
at
(
cid
)
->
getPlaytime
()
+
updatedDurationLeft
;
requestItemResize
(
cid
,
updatedDurL
,
false
,
true
,
undo
,
redo
);
}
if
(
updatedDurationRight
!=
0
)
{
requestItemResize
(
clipToResize
,
m_allClips
.
at
(
clipToResize
)
->
getPlaytime
()
+
updatedDurationRight
,
true
,
true
,
undo
,
redo
);
int
updatedDurR
=
m_allClips
.
at
(
clipToResize
)
->
getPlaytime
()
+
updatedDurationRight
;
requestItemResize
(
clipToResize
,
updatedDurR
,
true
,
true
,
undo
,
redo
);
}
int
mixCutPos
=
m_allClips
.
at
(
clipToResize
)
->
getPosition
()
+
m_allClips
.
at
(
clipToResize
)
->
getPlaytime
()
-
cutPos
;
int
updatedDuration
=
m_allClips
.
at
(
clipToResize
)
->
getPosition
()
+
m_allClips
.
at
(
clipToResize
)
->
getPlaytime
()
-
m_allClips
.
at
(
cid
)
->
getPosition
();
...
...
src/timeline2/model/timelinemodel.hpp
View file @
026f2109
...
...
@@ -506,7 +506,7 @@ public:
Q_INVOKABLE
int
requestItemResize
(
int
itemId
,
int
size
,
bool
right
,
bool
logUndo
=
true
,
int
snapDistance
=
-
1
,
bool
allowSingleResize
=
false
);
/** @brief Same function, but accumulates undo and redo and doesn't deal with snapping*/
bool
requestItemResize
(
int
itemId
,
int
size
,
bool
right
,
bool
logUndo
,
Fun
&
undo
,
Fun
&
redo
,
bool
blockUndo
=
false
);
bool
requestItemResize
(
int
itemId
,
int
&
size
,
bool
right
,
bool
logUndo
,
Fun
&
undo
,
Fun
&
redo
,
bool
blockUndo
=
false
);
/** @brief @todo TODO */
Q_INVOKABLE
int
requestItemRippleResize
(
int
itemId
,
int
size
,
bool
right
,
bool
logUndo
=
true
,
int
snapDistance
=
-
1
,
bool
allowSingleResize
=
false
);
...
...
src/timeline2/model/trackmodel.cpp
View file @
026f2109
...
...
@@ -654,7 +654,6 @@ Fun TrackModel::requestClipResize_lambda(int clipId, int in, int out, bool right
if
(
delta
==
0
)
{
return
[]()
{
return
true
;
};
}
// qDebug() << "RESIZING CLIP: " << clipId << " FROM: " << delta<<", ON PLAYLIST: "<<target_track;
if
(
delta
>
0
)
{
// we shrink clip
return
[
right
,
target_clip
,
target_track
,
clip_position
,
delta
,
in
,
out
,
clipId
,
update_snaps
,
this
]()
{
if
(
isLocked
())
return
false
;
...
...
@@ -686,10 +685,19 @@ Fun TrackModel::requestClipResize_lambda(int clipId, int in, int out, bool right
};
}
int
blank
=
-
1
;
int
other_blank_end
=
getBlankEnd
(
clip_position
,
1
-
target_track
);
int
startPos
=
clip_position
;
if
(
hasMix
)
{
startPos
+=
m_allClips
[
clipId
]
->
getMixCutPosition
();
}
int
endPos
=
m_allClips
[
clipId
]
->
getPosition
()
+
out
;
int
other_blank_end
=
getBlankEnd
(
startPos
,
1
-
target_track
);
if
(
right
)
{
if
(
target_clip
==
m_playlists
[
target_track
].
count
()
-
1
&&
(
hasMix
||
other_blank_end
>=
out
))
{
if
(
target_clip
==
m_playlists
[
target_track
].
count
()
-
1
&&
(
hasMix
||
other_blank_end
>=
endPos
))
{
// clip is last, it can always be extended
if
(
hasMix
&&
other_blank_end
<
endPos
&&
!
hasEndMix
(
clipId
))
{
// If clip has a start mix only, limit to next clip on other track
return
[]()
{
return
false
;
};
}
return
[
this
,
target_clip
,
target_track
,
in
,
out
,
update_snaps
,
clipId
]()
{
if
(
isLocked
())
return
false
;
// color, image and title clips can have unlimited resize
...
...
src/timeline2/model/trackmodel.hpp
View file @
026f2109
...
...
@@ -158,6 +158,7 @@ protected:
@param in is the new starting on the clip
@param out is the new ending on the clip
@param right is true if we change the right side of the clip, false otherwise
@param hasMix is true if we change the right side of the clip, false otherwise
*/
Fun
requestClipResize_lambda
(
int
clipId
,
int
in
,
int
out
,
bool
right
,
bool
hasMix
=
false
);
...
...
src/timeline2/view/qml/Clip.qml
View file @
026f2109
...
...
@@ -410,6 +410,7 @@ Rectangle {
drag.axis
:
Drag
.
XAxis
drag.smoothed
:
false
drag.maximumX
:
clipRoot
.
width
-
1
drag.minimumX
:
(
clipRoot
.
mixDuration
-
clipRoot
.
mixCut
)
*
clipRoot
.
timeScale
property
bool
sizeChanged
:
false
cursorShape
:
(
containsMouse
?
Qt
.
SizeHorCursor
:
Qt
.
ClosedHandCursor
)
onPressed
:
{
...
...
@@ -585,6 +586,9 @@ Rectangle {
var
currentClipPos
=
clipRoot
.
modelStart
var
delta
=
currentFrame
-
currentClipPos
if
(
delta
!==
0
)
{
if
(
delta
>
0
&&
(
clipRoot
.
mixDuration
-
clipRoot
.
mixCut
-
delta
<
0
))
{
return
}
var
newDuration
=
0
;
if
(
root
.
activeTool
===
ProjectTool
.
RippleTool
)
{
newDuration
=
clipRoot
.
originalDuration
-
delta
...
...
src/timeline2/view/timelinecontroller.cpp
View file @
026f2109
...
...
@@ -3579,9 +3579,10 @@ void TimelineController::editItemDuration(int id)
result
=
m_model
->
requestCompositionMove
(
id
,
trackId
,
m_model
->
m_allCompositions
[
id
]
->
getForcedTrack
(),
newPos
,
true
,
true
,
undo
,
redo
);
}
if
(
result
&&
newIn
!=
in
)
{
m_model
->
requestItemResize
(
id
,
duration
+
(
in
-
newIn
),
false
,
true
,
undo
,
redo
);
int
updatedDuration
=
duration
+
(
in
-
newIn
);
m_model
->
requestItemResize
(
id
,
updatedDuration
,
false
,
true
,
undo
,
redo
);
if
(
result
&&
partner
>
-
1
)
{
result
=
m_model
->
requestItemResize
(
partner
,
duration
+
(
in
-
newIn
)
,
false
,
true
,
undo
,
redo
);
result
=
m_model
->
requestItemResize
(
partner
,
updatedDuration
,
false
,
true
,
undo
,
redo
);
}
}
if
(
newDuration
!=
duration
+
(
in
-
newIn
))
{
...
...
@@ -3593,9 +3594,10 @@ void TimelineController::editItemDuration(int id)
}
else
{
// perform resize first
if
(
newIn
!=
in
)
{
result
=
m_model
->
requestItemResize
(
id
,
duration
+
(
in
-
newIn
),
false
,
true
,
undo
,
redo
);
int
updatedDuration
=
duration
+
(
in
-
newIn
);
result
=
m_model
->
requestItemResize
(
id
,
updatedDuration
,
false
,
true
,
undo
,
redo
);
if
(
result
&&
partner
>
-
1
)
{
result
=
m_model
->
requestItemResize
(
partner
,
duration
+
(
in
-
newIn
)
,
false
,
true
,
undo
,
redo
);
result
=
m_model
->
requestItemResize
(
partner
,
updatedDuration
,
false
,
true
,
undo
,
redo
);
}
}
if
(
newDuration
!=
duration
+
(
in
-
newIn
))
{
...
...
tests/mixtest.cpp
View file @
026f2109
...
...
@@ -46,9 +46,9 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
int
tid4
=
TrackModel
::
construct
(
timeline
);
// Create clip with audio
QString
binId
=
createProducerWithSound
(
profile_mix
,
binModel
,
5
0
);
QString
binId
=
createProducerWithSound
(
profile_mix
,
binModel
,
10
0
);
// Create
clip with audio
// Create
video clip
QString
binId2
=
createProducer
(
profile_mix
,
"red"
,
binModel
,
50
,
false
);
// Setup insert stream data
QMap
<
int
,
QString
>
audioInfo
;
...
...
@@ -317,6 +317,21 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
REQUIRE
(
timeline
->
m_allClips
[
cid4
]
->
getSubPlaylistIndex
()
==
0
);
undoStack
->
undo
();
state2
();
// Resize right clip before left clip, should limit the resize to left clip position
REQUIRE
(
timeline
->
requestItemResize
(
cid4
,
50
,
false
,
true
)
==
40
);
REQUIRE
(
timeline
->
getTrackById_const
(
tid2
)
->
mixCount
()
==
1
);
REQUIRE
(
timeline
->
m_allClips
[
cid3
]
->
getSubPlaylistIndex
()
==
0
);
REQUIRE
(
timeline
->
m_allClips
[
cid4
]
->
getSubPlaylistIndex
()
==
1
);
undoStack
->
undo
();
state2
();
// Resize left clip past right clip, should limit the resize to left clip position
REQUIRE
(
timeline
->
requestItemResize
(
cid3
,
100
,
true
,
true
)
==
40
);
REQUIRE
(
timeline
->
getTrackById_const
(
tid2
)
->
mixCount
()
==
1
);
REQUIRE
(
timeline
->
m_allClips
[
cid3
]
->
getSubPlaylistIndex
()
==
0
);
REQUIRE
(
timeline
->
m_allClips
[
cid4
]
->
getSubPlaylistIndex
()
==
1
);
undoStack
->
undo
();
state2
();
undoStack
->
undo
();
state0
();
}
...
...
@@ -327,7 +342,8 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
// CID 1 length=10, pos=100, CID2 length=10, pos=110
REQUIRE
(
timeline
->
m_allClips
[
cid1
]
->
getPlaytime
()
==
10
);
REQUIRE
(
timeline
->
m_allClips
[
cid2
]
->
getPlaytime
()
==
10
);
REQUIRE
(
timeline
->
requestItemResize
(
cid2
,
50
,
true
,
true
)
==
50
);
// Resize clip in to have some space for mix
REQUIRE
(
timeline
->
requestItemResize
(
cid2
,
90
,
true
,
true
)
==
90
);
REQUIRE
(
timeline
->
requestItemResize
(
cid2
,
30
,
false
,
true
)
==
30
);
REQUIRE
(
timeline
->
requestClipMove
(
cid2
,
tid2
,
130
));
REQUIRE
(
timeline
->
requestItemResize
(
cid1
,
30
,
true
,
true
)
==
30
);
...
...
@@ -368,6 +384,23 @@ TEST_CASE("Simple Mix", "[SameTrackMix]")
REQUIRE
(
timeline
->
m_allClips
[
cid2
]
->
getSubPlaylistIndex
()
==
0
);
undoStack
->
undo
();
state3
();
// Resize right clip before left clip, should limit to left clip position
REQUIRE
(
timeline
->
requestItemResize
(
cid2
,
80
,
false
,
true
)
==
60
);
REQUIRE
(
timeline
->
getTrackById_const
(
tid2
)
->
mixCount
()
==
1
);
REQUIRE
(
timeline
->
getTrackById_const
(
tid3
)
->
mixCount
()
==
1
);
REQUIRE
(
timeline
->
m_allClips
[
cid1
]
->
getSubPlaylistIndex
()
==
0
);
REQUIRE
(
timeline
->
m_allClips
[
cid2
]
->
getSubPlaylistIndex
()
==
1
);
undoStack
->
undo
();
state3
();
// Resize left clip after right clip, should limit to right clip duration
REQUIRE
(
timeline
->
requestItemResize
(
cid1
,
80
,
true
,
true
)
==
60
);
REQUIRE
(
timeline
->
getTrackById_const
(
tid2
)
->
mixCount
()
==
1
);
REQUIRE
(
timeline
->
getTrackById_const
(
tid3
)
->
mixCount
()
==
1
);
REQUIRE
(
timeline
->
m_allClips
[
cid1
]
->
getSubPlaylistIndex
()
==
0
);
REQUIRE
(
timeline
->
m_allClips
[
cid2
]
->
getSubPlaylistIndex
()
==
1
);
undoStack
->
undo
();
state3
();
undoStack
->
undo
();
undoStack
->
undo
();
undoStack
->
undo
();
undoStack
->
undo
();
...
...
tests/modeltest.cpp
View file @
026f2109
...
...
@@ -1653,7 +1653,8 @@ TEST_CASE("Undo and Redo", "[ClipModel]")
{
std
::
function
<
bool
(
void
)
>
undo
=
[]()
{
return
true
;
};
std
::
function
<
bool
(
void
)
>
redo
=
[]()
{
return
true
;
};
REQUIRE
(
timeline
->
requestItemResize
(
cid6
,
l
-
5
,
true
,
true
,
undo
,
redo
,
false
));
int
size
=
l
-
5
;
REQUIRE
(
timeline
->
requestItemResize
(
cid6
,
size
,
true
,
true
,
undo
,
redo
,
false
));
pCore
->
pushUndo
(
undo
,
redo
,
QString
());
}
auto
state2
=
[
&
]()
{
...
...
@@ -1682,7 +1683,8 @@ TEST_CASE("Undo and Redo", "[ClipModel]")
{
std
::
function
<
bool
(
void
)
>
undo
=
[]()
{
return
true
;
};
std
::
function
<
bool
(
void
)
>
redo
=
[]()
{
return
true
;
};
REQUIRE
(
timeline
->
requestItemResize
(
cid6
,
l
-
6
,
false
,
true
,
undo
,
redo
,
false
));
int
size
=
l
-
6
;
REQUIRE
(
timeline
->
requestItemResize
(
cid6
,
size
,
false
,
true
,
undo
,
redo
,
false
));
pCore
->
pushUndo
(
undo
,
redo
,
QString
());
}
auto
state4
=
[
&
]()
{
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment