Skip to content
GitLab
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
952c69bb
Commit
952c69bb
authored
Apr 02, 2020
by
Jean-Baptiste Mardelle
Browse files
Fix crash on undo and other issues in expand playlist.
Related to
#300
parent
dc8661ee
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/timeline2/model/timelinefunctions.cpp
View file @
952c69bb
...
...
@@ -1058,7 +1058,8 @@ void TimelineFunctions::saveTimelineSelection(const std::shared_ptr<TimelineItem
std
::
sort
(
compositions
.
begin
(),
compositions
.
end
(),
[](
Mlt
::
Transition
*
a
,
Mlt
::
Transition
*
b
)
{
return
a
->
get_b_track
()
<
b
->
get_b_track
();
});
while
(
!
compositions
.
isEmpty
())
{
QScopedPointer
<
Mlt
::
Transition
>
t
(
compositions
.
takeFirst
());
if
(
sourceTracks
.
contains
(
t
->
get_a_track
())
&&
sourceTracks
.
contains
(
t
->
get_b_track
()))
{
int
a_track
=
t
->
get_a_track
();
if
((
sourceTracks
.
contains
(
a_track
)
||
a_track
==
0
)
&&
sourceTracks
.
contains
(
t
->
get_b_track
()))
{
Mlt
::
Transition
newComposition
(
*
newTractor
.
profile
(),
t
->
get
(
"mlt_service"
));
Mlt
::
Properties
sourceProps
(
t
->
get_properties
());
newComposition
.
inherit
(
sourceProps
);
...
...
@@ -1066,7 +1067,9 @@ void TimelineFunctions::saveTimelineSelection(const std::shared_ptr<TimelineItem
int
in
=
qMax
(
0
,
t
->
get_in
()
-
offset
);
int
out
=
t
->
get_out
()
-
offset
;
newComposition
.
set_in_and_out
(
in
,
out
);
int
a_track
=
sourceTracks
.
value
(
t
->
get_a_track
());
if
(
sourceTracks
.
contains
(
a_track
))
{
a_track
=
sourceTracks
.
value
(
a_track
);
}
int
b_track
=
sourceTracks
.
value
(
t
->
get_b_track
());
field
->
plant_transition
(
newComposition
,
a_track
,
b_track
);
}
...
...
@@ -1271,7 +1274,7 @@ bool TimelineFunctions::pasteClips(const std::shared_ptr<TimelineItemModel> &tim
mappedIds
.
clear
();
// Check available tracks
QPair
<
QList
<
int
>
,
QList
<
int
>>
projectTracks
=
TimelineFunctions
::
getAVTracksIds
(
timeline
);
int
masterSourceTrack
=
copiedItems
.
documentElement
().
attribute
(
QStringLiteral
(
"masterTrack"
)).
toInt
();
int
masterSourceTrack
=
copiedItems
.
documentElement
().
attribute
(
QStringLiteral
(
"masterTrack"
)
,
QStringLiteral
(
"-1"
)
).
toInt
();
QDomNodeList
clips
=
copiedItems
.
documentElement
().
elementsByTagName
(
QStringLiteral
(
"clip"
));
QDomNodeList
compositions
=
copiedItems
.
documentElement
().
elementsByTagName
(
QStringLiteral
(
"composition"
));
// find paste tracks
...
...
@@ -1297,7 +1300,7 @@ bool TimelineFunctions::pasteClips(const std::shared_ptr<TimelineItemModel> &tim
audioTracks
<<
trackPos
;
}
int
videoMirror
=
prod
.
attribute
(
QStringLiteral
(
"mirrorTrack"
)).
toInt
();
if
(
videoMirror
==
-
1
)
{
if
(
videoMirror
==
-
1
||
masterSourceTrack
==
-
1
)
{
if
(
singleAudioTracks
.
contains
(
trackPos
))
{
continue
;
}
...
...
@@ -1402,13 +1405,15 @@ bool TimelineFunctions::pasteClips(const std::shared_ptr<TimelineItemModel> &tim
int
audioOffset
=
0
;
for
(
const
auto
&
mirror
:
audioMirrors
)
{
int
videoIx
=
tracksMap
.
value
(
mirror
.
second
);
qDebug
()
<<
"==== INSERTING MIRROR AUDIO:"
<<
mirror
.
first
<<
" = "
<<
timeline
->
getMirrorAudioTrackId
(
videoIx
)
<<
" (MIRROR FROM: "
<<
videoIx
;
tracksMap
.
insert
(
mirror
.
first
,
timeline
->
getMirrorAudioTrackId
(
videoIx
));
if
(
!
audioOffsetCalculated
)
{
int
oldPosition
=
mirror
.
first
;
int
currentPosition
=
timeline
->
getTrackPosition
(
tracksMap
.
value
(
oldPosition
));
audioOffset
=
currentPosition
-
oldPosition
;
audioOffsetCalculated
=
true
;
int
mirrorIx
=
timeline
->
getMirrorAudioTrackId
(
videoIx
);
if
(
mirrorIx
>
0
)
{
tracksMap
.
insert
(
mirror
.
first
,
mirrorIx
);
if
(
!
audioOffsetCalculated
)
{
int
oldPosition
=
mirror
.
first
;
int
currentPosition
=
timeline
->
getTrackPosition
(
tracksMap
.
value
(
oldPosition
));
audioOffset
=
currentPosition
-
oldPosition
;
audioOffsetCalculated
=
true
;
}
}
}
if
(
!
audioOffsetCalculated
&&
audioMaster
)
{
...
...
@@ -1501,7 +1506,9 @@ bool TimelineFunctions::pasteClips(const std::shared_ptr<TimelineItemModel> &tim
}
}
if
(
!
clipsImported
)
{
return
TimelineFunctions
::
pasteTimelineClips
(
timeline
,
copiedItems
,
position
);
QTimer
::
singleShot
(
200
,
timeline
.
get
(),
[
timeline
,
copiedItems
,
position
]()
{
TimelineFunctions
::
pasteTimelineClips
(
timeline
,
copiedItems
,
position
);
});
}
qDebug
()
<<
"++++++++++++
\n
WAITIND FOR BIN INSERTION: "
<<
waitingBinIds
<<
"
\n\n
+++++++++++++"
;
return
true
;
...
...
@@ -1557,7 +1564,8 @@ bool TimelineFunctions::pasteTimelineClips(const std::shared_ptr<TimelineItemMod
std
::
shared_ptr
<
EffectStackModel
>
destStack
=
timeline
->
getClipEffectStackModel
(
newId
);
destStack
->
fromXml
(
prod
.
firstChildElement
(
QStringLiteral
(
"effects"
)),
timeline_undo
,
timeline_redo
);
}
else
{
//break;
qDebug
()
<<
"=== COULD NOT PASTE CLIP: "
<<
newId
<<
" ON TRACK: "
<<
curTrackId
<<
" AT: "
<<
position
;
break
;
}
}
// Compositions
...
...
@@ -1598,7 +1606,7 @@ bool TimelineFunctions::pasteTimelineClips(const std::shared_ptr<TimelineItemMod
timeline
->
m_groups
->
fromJsonWithOffset
(
groupsData
,
tracksMap
,
position
-
offset
,
timeline_undo
,
timeline_redo
);
}
// Ensure to clear selection in undo/redo too.
Fun
unselect
=
[
&
]()
{
Fun
unselect
=
[
timeline
]()
{
qDebug
()
<<
"starting undo or redo. Selection "
<<
timeline
->
m_currentSelection
;
timeline
->
requestClearSelection
();
qDebug
()
<<
"after Selection "
<<
timeline
->
m_currentSelection
;
...
...
@@ -1606,8 +1614,8 @@ bool TimelineFunctions::pasteTimelineClips(const std::shared_ptr<TimelineItemMod
};
PUSH_FRONT_LAMBDA
(
unselect
,
timeline_undo
);
PUSH_FRONT_LAMBDA
(
unselect
,
timeline_redo
);
pCore
->
pushUndo
(
timeline_undo
,
timeline_redo
,
i18n
(
"Paste clips"
));
//UPDATE_UNDO_REDO_NOLOCK(timeline_redo, timeline_undo, undo, redo);
pCore
->
pushUndo
(
timeline_undo
,
timeline_redo
,
i18n
(
"Paste timeline clips"
));
semaphore
.
release
(
1
);
return
true
;
}
...
...
@@ -1764,7 +1772,6 @@ QDomDocument TimelineFunctions::extractClip(const std::shared_ptr<TimelineItemMo
if
(
audioTrack
)
{
clipElement
.
setAttribute
(
QLatin1String
(
"audioTrack"
),
1
);
int
mirror
=
audioTrack
+
videoTracks
-
track
-
1
;
qDebug
()
<<
"=== GOT MIRROR FOR: "
<<
track
<<
" = "
<<
mirror
;
if
(
track
<=
videoTracks
)
{
clipElement
.
setAttribute
(
QLatin1String
(
"mirrorTrack"
),
mirror
);
}
else
{
...
...
@@ -1776,9 +1783,8 @@ QDomDocument TimelineFunctions::extractClip(const std::shared_ptr<TimelineItemMo
}
else
{
clipElement
.
setAttribute
(
QStringLiteral
(
"speed"
),
1
);
}
position
+=
(
out
-
in
);
position
+=
(
out
-
in
+
1
);
QDomNodeList
effects
=
currentElement
.
elementsByTagName
(
QLatin1String
(
"filter"
));
qDebug
()
<<
"=== FOUND effects for clip: "
<<
effects
.
count
();
if
(
effects
.
count
()
==
0
)
{
continue
;
}
...
...
@@ -1788,7 +1794,6 @@ QDomDocument TimelineFunctions::extractClip(const std::shared_ptr<TimelineItemMo
for
(
int
k
=
0
;
k
<
effects
.
count
();
++
k
)
{
QDomElement
effect
=
effects
.
item
(
k
).
toElement
();
QString
filterId
=
Xml
::
getXmlProperty
(
effect
,
QLatin1String
(
"kdenlive_id"
));
qDebug
()
<<
"=== FOUND effects : "
<<
filterId
;
QDomElement
clipEffect
=
destDoc
.
createElement
(
QStringLiteral
(
"effect"
));
effectsList
.
appendChild
(
clipEffect
);
clipEffect
.
setAttribute
(
QStringLiteral
(
"id"
),
filterId
);
...
...
@@ -1831,8 +1836,8 @@ QDomDocument TimelineFunctions::extractClip(const std::shared_ptr<TimelineItemMo
composition
.
setAttribute
(
QLatin1String
(
"in"
),
in
);
composition
.
setAttribute
(
QLatin1String
(
"out"
),
out
);
composition
.
setAttribute
(
QLatin1String
(
"composition"
),
compoId
);
composition
.
setAttribute
(
QLatin1String
(
"a_track"
),
track
+
Xml
::
getXmlProperty
(
currentCompo
,
QLatin1String
(
"a_track"
)).
toInt
());
composition
.
setAttribute
(
QLatin1String
(
"track"
),
track
+
Xml
::
getXmlProperty
(
currentCompo
,
QLatin1String
(
"b_track"
)).
toInt
());
composition
.
setAttribute
(
QLatin1String
(
"a_track"
),
Xml
::
getXmlProperty
(
currentCompo
,
QLatin1String
(
"a_track"
)).
toInt
());
composition
.
setAttribute
(
QLatin1String
(
"track"
),
Xml
::
getXmlProperty
(
currentCompo
,
QLatin1String
(
"b_track"
)).
toInt
());
QDomNodeList
properties
=
currentCompo
.
childNodes
();
for
(
int
l
=
0
;
l
<
properties
.
count
();
++
l
)
{
QDomElement
prop
=
properties
.
item
(
l
).
toElement
();
...
...
@@ -1841,7 +1846,6 @@ QDomDocument TimelineFunctions::extractClip(const std::shared_ptr<TimelineItemMo
}
}
}
qDebug
()
<<
"=== GOT CONVERTED DOCUMENT
\n\n
"
<<
destDoc
.
toString
();
return
destDoc
;
}
...
...
src/timeline2/model/trackmodel.cpp
View file @
952c69bb
...
...
@@ -241,7 +241,7 @@ bool TrackModel::requestClipInsertion(int clipId, int position, bool updateView,
Fun
local_redo
=
[]()
{
return
true
;
};
bool
res
=
true
;
if
(
ptr
->
getClipPtr
(
clipId
)
->
clipState
()
!=
PlaylistState
::
Disabled
)
{
res
=
res
&&
ptr
->
getClipPtr
(
clipId
)
->
setClipState
(
isAudioTrack
()
?
PlaylistState
::
AudioOnly
:
PlaylistState
::
VideoOnly
,
local_undo
,
local_redo
);
res
=
ptr
->
getClipPtr
(
clipId
)
->
setClipState
(
isAudioTrack
()
?
PlaylistState
::
AudioOnly
:
PlaylistState
::
VideoOnly
,
local_undo
,
local_redo
);
}
int
duration
=
trackDuration
();
auto
operation
=
requestClipInsertion_lambda
(
clipId
,
position
,
updateView
,
finalMove
,
groupMove
);
...
...
src/timeline2/view/timelinecontroller.cpp
View file @
952c69bb
...
...
@@ -3214,8 +3214,6 @@ void TimelineController::expandActiveClip()
{
std
::
unordered_set
<
int
>
ids
=
m_model
->
getCurrentSelection
();
std
::
unordered_set
<
int
>
items_list
;
std
::
function
<
bool
(
void
)
>
undo
=
[]()
{
return
true
;
};
std
::
function
<
bool
(
void
)
>
redo
=
[]()
{
return
true
;
};
for
(
int
i
:
ids
)
{
if
(
m_model
->
isGroup
(
i
))
{
std
::
unordered_set
<
int
>
children
=
m_model
->
m_groups
->
getLeaves
(
i
);
...
...
@@ -3226,29 +3224,29 @@ void TimelineController::expandActiveClip()
}
m_model
->
requestClearSelection
();
bool
result
=
true
;
int
processed
=
0
;
for
(
int
id
:
items_list
)
{
if
(
result
&&
m_model
->
isClip
(
id
))
{
std
::
shared_ptr
<
ClipModel
>
clip
=
m_model
->
getClipPtr
(
id
);
if
(
clip
->
clipType
()
==
ClipType
::
Playlist
)
{
int
pos
=
clip
->
getPosition
();
std
::
function
<
bool
(
void
)
>
undo
=
[]()
{
return
true
;
};
std
::
function
<
bool
(
void
)
>
redo
=
[]()
{
return
true
;
};
if
(
m_model
->
m_groups
->
isInGroup
(
id
))
{
int
targetRoot
=
m_model
->
m_groups
->
getRootId
(
id
);
if
(
m_model
->
isGroup
(
targetRoot
))
{
m_model
->
requestClipUngroup
(
targetRoot
,
undo
,
redo
);
}
}
int
pos
=
clip
->
getPosition
();
QDomDocument
doc
=
TimelineFunctions
::
extractClip
(
m_model
,
id
,
getClipBinId
(
id
));
m_model
->
requestClipDeletion
(
id
,
undo
,
redo
);
result
=
TimelineFunctions
::
pasteClips
(
m_model
,
doc
.
toString
(),
m_activeTrack
,
pos
,
undo
,
redo
);
processed
++
;
if
(
result
)
{
pCore
->
pushUndo
(
undo
,
redo
,
i18n
(
"Expand clip"
));
}
else
{
undo
();
pCore
->
displayMessage
(
i18n
(
"Could not expand clip"
),
InformationMessage
,
500
);
}
}
}
}
if
(
result
&&
processed
>
0
)
{
pCore
->
pushUndo
(
undo
,
redo
,
i18n
(
"Expand clip"
));
}
else
{
undo
();
pCore
->
displayMessage
(
i18n
(
"Could not expand clip"
),
InformationMessage
,
500
);
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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