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
d0ad55ee
Commit
d0ad55ee
authored
May 16, 2018
by
Jean-Baptiste Mardelle
Browse files
Update timeline headers to have icons on first line
Introduce split video, fix issues with audio split
parent
fe0ed6e0
Changes
10
Hide whitespace changes
Inline
Side-by-side
src/timeline2/model/timelinefunctions.cpp
View file @
d0ad55ee
...
...
@@ -447,7 +447,7 @@ bool TimelineFunctions::requestSplitAudio(std::shared_ptr<TimelineItemModel> tim
// Now clear selection so we don't mess with groups
pCore
->
clearSelection
();
for
(
int
cid
:
clips
)
{
if
(
!
timeline
->
getClipPtr
(
cid
)
->
audioEnabled
()
||
timeline
->
getClipPtr
(
cid
)
->
clipState
()
==
PlaylistState
::
AudioOnly
)
{
if
(
!
timeline
->
getClipPtr
(
cid
)
->
canBeAudio
()
||
timeline
->
getClipPtr
(
cid
)
->
clipState
()
==
PlaylistState
::
AudioOnly
)
{
// clip without audio or audio only, skip
continue
;
}
...
...
@@ -489,6 +489,57 @@ bool TimelineFunctions::requestSplitAudio(std::shared_ptr<TimelineItemModel> tim
return
done
;
}
bool
TimelineFunctions
::
requestSplitVideo
(
std
::
shared_ptr
<
TimelineItemModel
>
timeline
,
int
clipId
,
int
videoTarget
)
{
std
::
function
<
bool
(
void
)
>
undo
=
[]()
{
return
true
;
};
std
::
function
<
bool
(
void
)
>
redo
=
[]()
{
return
true
;
};
const
std
::
unordered_set
<
int
>
clips
=
timeline
->
getGroupElements
(
clipId
);
bool
done
=
false
;
// Now clear selection so we don't mess with groups
pCore
->
clearSelection
();
for
(
int
cid
:
clips
)
{
if
(
!
timeline
->
getClipPtr
(
cid
)
->
canBeVideo
()
||
timeline
->
getClipPtr
(
cid
)
->
clipState
()
==
PlaylistState
::
VideoOnly
)
{
// clip without audio or audio only, skip
continue
;
}
int
position
=
timeline
->
getClipPosition
(
cid
);
int
track
=
timeline
->
getClipTrackId
(
cid
);
QList
<
int
>
possibleTracks
=
QList
<
int
>
()
<<
videoTarget
;
if
(
possibleTracks
.
isEmpty
())
{
// No available audio track for splitting, abort
undo
();
pCore
->
displayMessage
(
i18n
(
"No available video track for split operation"
),
ErrorMessage
);
return
false
;
}
int
newId
;
bool
res
=
copyClip
(
timeline
,
cid
,
newId
,
PlaylistState
::
VideoOnly
,
undo
,
redo
);
if
(
!
res
)
{
bool
undone
=
undo
();
Q_ASSERT
(
undone
);
pCore
->
displayMessage
(
i18n
(
"Video split failed"
),
ErrorMessage
);
return
false
;
}
bool
success
=
false
;
while
(
!
success
&&
!
possibleTracks
.
isEmpty
())
{
int
newTrack
=
possibleTracks
.
takeFirst
();
success
=
timeline
->
requestClipMove
(
newId
,
newTrack
,
position
,
true
,
false
,
undo
,
redo
);
}
TimelineFunctions
::
changeClipState
(
timeline
,
cid
,
PlaylistState
::
AudioOnly
,
undo
,
redo
);
success
=
success
&&
timeline
->
m_groups
->
createGroupAtSameLevel
(
cid
,
std
::
unordered_set
<
int
>
{
newId
},
GroupType
::
AVSplit
,
undo
,
redo
);
if
(
!
success
)
{
bool
undone
=
undo
();
Q_ASSERT
(
undone
);
pCore
->
displayMessage
(
i18n
(
"Video split failed"
),
ErrorMessage
);
return
false
;
}
done
=
true
;
}
if
(
done
)
{
pCore
->
pushUndo
(
undo
,
redo
,
i18n
(
"Split Video"
));
}
return
done
;
}
void
TimelineFunctions
::
setCompositionATrack
(
std
::
shared_ptr
<
TimelineItemModel
>
timeline
,
int
cid
,
int
aTrack
)
{
std
::
function
<
bool
(
void
)
>
undo
=
[]()
{
return
true
;
};
...
...
src/timeline2/model/timelinefunctions.hpp
View file @
d0ad55ee
...
...
@@ -87,6 +87,7 @@ struct TimelineFunctions
static
bool
changeClipState
(
std
::
shared_ptr
<
TimelineItemModel
>
timeline
,
int
clipId
,
PlaylistState
::
ClipState
status
,
Fun
&
undo
,
Fun
&
redo
);
static
bool
requestSplitAudio
(
std
::
shared_ptr
<
TimelineItemModel
>
timeline
,
int
clipId
,
int
audioTarget
);
static
bool
requestSplitVideo
(
std
::
shared_ptr
<
TimelineItemModel
>
timeline
,
int
clipId
,
int
videoTarget
);
static
void
setCompositionATrack
(
std
::
shared_ptr
<
TimelineItemModel
>
timeline
,
int
cid
,
int
aTrack
);
};
...
...
src/timeline2/model/timelineitemmodel.cpp
View file @
d0ad55ee
...
...
@@ -199,6 +199,8 @@ QHash<int, QByteArray> TimelineItemModel::roleNames() const
roles
[
ItemIdRole
]
=
"item"
;
roles
[
ItemATrack
]
=
"a_track"
;
roles
[
HasAudio
]
=
"hasAudio"
;
roles
[
CanBeAudioRole
]
=
"canBeAudio"
;
roles
[
CanBeVideoRole
]
=
"canBeVideo"
;
roles
[
ReloadThumbRole
]
=
"reloadThumb"
;
return
roles
;
}
...
...
@@ -259,6 +261,10 @@ QVariant TimelineItemModel::data(const QModelIndex &index, int role) const
return
clip
->
audioEnabled
();
case
IsAudioRole
:
return
clip
->
isAudioOnly
();
case
CanBeAudioRole
:
return
clip
->
canBeAudio
();
case
CanBeVideoRole
:
return
clip
->
canBeVideo
();
case
MarkersRole
:
{
return
QVariant
::
fromValue
<
MarkerListModel
*>
(
clip
->
getMarkerModel
().
get
());
}
...
...
src/timeline2/model/timelinemodel.hpp
View file @
d0ad55ee
...
...
@@ -119,6 +119,8 @@ public:
FramerateRole
,
/// clip only
GroupedRole
,
/// clip only
HasAudio
,
/// clip only
CanBeAudioRole
,
/// clip only
CanBeVideoRole
,
/// clip only
IsMuteRole
,
/// track only
IsHiddenRole
,
/// track only
IsAudioRole
,
...
...
src/timeline2/view/qml/Clip.qml
View file @
d0ad55ee
...
...
@@ -61,6 +61,8 @@ Rectangle {
property
int
draggedX
:
x
property
bool
selected
:
false
property
bool
hasAudio
property
bool
canBeAudio
property
bool
canBeVideo
property
string
hash
:
'
ccc
'
//TODO
property
double
speed
:
1.0
property
color
borderColor
:
'
black
'
...
...
@@ -280,7 +282,7 @@ Rectangle {
}
}
onPositionChanged
:
{
if
(
pressed
)
{
if
(
pressed
&&
mouse
.
buttons
===
Qt
.
LeftButton
)
{
var
trackIndex
=
Logic
.
getTrackIndexFromId
(
clipRoot
.
trackId
)
if
((
mouse
.
y
<
0
&&
trackIndex
>
0
)
||
(
mouse
.
y
>
height
&&
trackIndex
<
tracksRepeater
.
count
-
1
))
{
var
mapped
=
parentTrack
.
mapFromItem
(
clipRoot
,
mouse
.
x
,
mouse
.
y
).
x
...
...
@@ -327,6 +329,8 @@ Rectangle {
clipMenu
.
clipStatus
=
clipRoot
.
clipStatus
clipMenu
.
grouped
=
clipRoot
.
grouped
clipMenu
.
trackId
=
clipRoot
.
trackId
clipMenu
.
canBeAudio
=
clipRoot
.
canBeAudio
clipMenu
.
canBeVideo
=
clipRoot
.
canBeVideo
clipMenu
.
popup
()
}
}
...
...
src/timeline2/view/qml/ClipMenu.qml
View file @
d0ad55ee
...
...
@@ -8,6 +8,8 @@ OLD.Menu {
property
int
clipStatus
property
int
trackId
property
bool
grouped
property
bool
canBeAudio
property
bool
canBeVideo
function
show
()
{
//mergeItem.visible = timeline.mergeClipWithNext(trackIndex, index, true)
menu
.
popup
()
...
...
@@ -51,7 +53,12 @@ OLD.Menu {
OLD.MenuItem
{
text
:
i18n
(
'
Split Audio
'
)
onTriggered
:
timeline
.
splitAudio
(
clipId
)
visible
:
clipStatus
==
ClipState
.
VideoOnly
visible
:
canBeAudio
&&
clipStatus
==
ClipState
.
VideoOnly
}
OLD.MenuItem
{
text
:
i18n
(
'
Split Video
'
)
onTriggered
:
timeline
.
splitVideo
(
clipId
)
visible
:
canBeVideo
&&
clipStatus
==
ClipState
.
AudioOnly
}
OLD.MenuItem
{
text
:
i18n
(
'
Remove
'
)
...
...
src/timeline2/view/qml/Track.qml
View file @
d0ad55ee
...
...
@@ -211,6 +211,8 @@ Column{
item
.
isAudio
=
model
.
audio
item
.
markers
=
model
.
markers
item
.
hasAudio
=
model
.
hasAudio
item
.
canBeAudio
=
model
.
canBeAudio
item
.
canBeVideo
=
model
.
canBeVideo
//item.binId= model.binId
}
else
{
console
.
log
(
'
loaded composition:
'
,
model
.
start
,
'
, ID:
'
,
model
.
item
,
'
, index:
'
,
trackRoot
.
DelegateModel
.
itemsIndex
)
...
...
src/timeline2/view/qml/TrackHead.qml
View file @
d0ad55ee
...
...
@@ -125,7 +125,7 @@ Rectangle {
onClicked
:
{
trackHeadRoot
.
myTrackHeight
=
trackHeadRoot
.
collapsed
?
Math
.
max
(
collapsedHeight
*
1.5
,
controller
.
getTrackProperty
(
trackId
,
"
kdenlive:trackheight
"
))
:
collapsedHeight
}
tooltip
:
buttonBar
.
visible
?
i18n
(
'
Minimize
'
)
:
i18n
(
'
Expand
'
)
tooltip
:
trackLabel
.
visible
?
i18n
(
'
Minimize
'
)
:
i18n
(
'
Expand
'
)
}
Item
{
width
:
nameEdit
.
height
...
...
@@ -203,6 +203,66 @@ Rectangle {
]
}
}
Rectangle
{
// Spacer
color
:
"
transparent
"
Layout.fillWidth
:
true
Layout.fillHeight
:
true
}
ToolButton
{
id
:
muteButton
implicitHeight
:
trackHeadRoot
.
iconSize
implicitWidth
:
trackHeadRoot
.
iconSize
visible
:
isAudio
iconName
:
isMute
?
'
kdenlive-hide-audio
'
:
'
kdenlive-show-audio
'
iconSource
:
isMute
?
'
qrc:///pics/kdenlive-hide-audio.svgz
'
:
'
qrc:///pics/kdenlive-show-audio.svgz
'
onClicked
:
controller
.
setTrackProperty
(
trackId
,
"
hide
"
,
isMute
?
isHidden
?
'
1
'
:
'
0
'
:
isHidden
?
'
3
'
:
'
2
'
)
tooltip
:
isMute
?
i18n
(
'
Unmute
'
)
:
i18n
(
'
Mute
'
)
}
ToolButton
{
id
:
hideButton
implicitHeight
:
trackHeadRoot
.
iconSize
implicitWidth
:
trackHeadRoot
.
iconSize
visible
:
!
isAudio
iconName
:
isHidden
?
'
kdenlive-hide-video
'
:
'
kdenlive-show-video
'
iconSource
:
isHidden
?
'
qrc:///pics/kdenlive-hide-video.svgz
'
:
'
qrc:///pics/kdenlive-show-video.svgz
'
onClicked
:
{
controller
.
setTrackProperty
(
trackId
,
"
hide
"
,
isHidden
?
isMute
?
'
2
'
:
'
0
'
:
isMute
?
'
3
'
:
'
1
'
)
timeline
.
requestRefresh
()
}
tooltip
:
isHidden
?
i18n
(
'
Show
'
)
:
i18n
(
'
Hide
'
)
}
ToolButton
{
id
:
lockButton
implicitHeight
:
trackHeadRoot
.
iconSize
implicitWidth
:
trackHeadRoot
.
iconSize
iconName
:
isLocked
?
'
kdenlive-lock
'
:
'
kdenlive-unlock
'
iconSource
:
isLocked
?
'
qrc:///pics/kdenlive-lock.svg
'
:
'
qrc:///pics/kdenlive-unlock.svg
'
onClicked
:
controller
.
setTrackProperty
(
trackId
,
"
kdenlive:locked_track
"
,
isLocked
?
'
0
'
:
'
1
'
)
tooltip
:
isLocked
?
i18n
(
'
Unlock track
'
)
:
i18n
(
'
Lock track
'
)
SequentialAnimation
{
id
:
flashLock
loops
:
1
ScaleAnimator
{
target
:
lockButton
from
:
1
to
:
2
duration
:
500
}
ScaleAnimator
{
target
:
lockButton
from
:
2
to
:
1
duration
:
500
}
}
}
Layout.rightMargin
:
4
}
RowLayout
{
Rectangle
{
id
:
trackLabel
color
:
'
transparent
'
...
...
@@ -210,6 +270,7 @@ Rectangle {
radius
:
2
border.color
:
trackNameMouseArea
.
containsMouse
?
activePalette
.
highlight
:
'
transparent
'
height
:
nameEdit
.
height
visible
:
(
trackHeadRoot
.
height
>=
trackLabel
.
height
+
muteButton
.
height
+
resizer
.
height
)
MouseArea
{
id
:
trackNameMouseArea
anchors.fill
:
parent
...
...
@@ -271,69 +332,6 @@ Rectangle {
}
}
}
RowLayout
{
spacing
:
root
.
baseUnit
/
2
id
:
buttonBar
visible
:
(
trackHeadRoot
.
height
>=
trackLabel
.
height
+
muteButton
.
height
+
resizer
.
height
)
Layout.rightMargin
:
4
Rectangle
{
// Spacer
color
:
"
transparent
"
Layout.fillWidth
:
true
Layout.fillHeight
:
true
}
ToolButton
{
id
:
muteButton
implicitHeight
:
trackHeadRoot
.
iconSize
implicitWidth
:
trackHeadRoot
.
iconSize
visible
:
isAudio
iconName
:
isMute
?
'
kdenlive-hide-audio
'
:
'
kdenlive-show-audio
'
iconSource
:
isMute
?
'
qrc:///pics/kdenlive-hide-audio.svgz
'
:
'
qrc:///pics/kdenlive-show-audio.svgz
'
onClicked
:
controller
.
setTrackProperty
(
trackId
,
"
hide
"
,
isMute
?
isHidden
?
'
1
'
:
'
0
'
:
isHidden
?
'
3
'
:
'
2
'
)
tooltip
:
isMute
?
i18n
(
'
Unmute
'
)
:
i18n
(
'
Mute
'
)
}
ToolButton
{
id
:
hideButton
implicitHeight
:
trackHeadRoot
.
iconSize
implicitWidth
:
trackHeadRoot
.
iconSize
visible
:
!
isAudio
iconName
:
isHidden
?
'
kdenlive-hide-video
'
:
'
kdenlive-show-video
'
iconSource
:
isHidden
?
'
qrc:///pics/kdenlive-hide-video.svgz
'
:
'
qrc:///pics/kdenlive-show-video.svgz
'
onClicked
:
{
controller
.
setTrackProperty
(
trackId
,
"
hide
"
,
isHidden
?
isMute
?
'
2
'
:
'
0
'
:
isMute
?
'
3
'
:
'
1
'
)
timeline
.
requestRefresh
()
}
tooltip
:
isHidden
?
i18n
(
'
Show
'
)
:
i18n
(
'
Hide
'
)
}
ToolButton
{
id
:
lockButton
implicitHeight
:
trackHeadRoot
.
iconSize
implicitWidth
:
trackHeadRoot
.
iconSize
iconName
:
isLocked
?
'
kdenlive-lock
'
:
'
kdenlive-unlock
'
iconSource
:
isLocked
?
'
qrc:///pics/kdenlive-lock.svg
'
:
'
qrc:///pics/kdenlive-unlock.svg
'
onClicked
:
controller
.
setTrackProperty
(
trackId
,
"
kdenlive:locked_track
"
,
isLocked
?
'
0
'
:
'
1
'
)
tooltip
:
isLocked
?
i18n
(
'
Unlock track
'
)
:
i18n
(
'
Lock track
'
)
SequentialAnimation
{
id
:
flashLock
loops
:
1
ScaleAnimator
{
target
:
lockButton
from
:
1
to
:
2
duration
:
500
}
ScaleAnimator
{
target
:
lockButton
from
:
2
to
:
1
duration
:
500
}
}
}
}
Rectangle
{
// Spacer
color
:
"
transparent
"
...
...
src/timeline2/view/timelinecontroller.cpp
View file @
d0ad55ee
...
...
@@ -1472,6 +1472,11 @@ void TimelineController::splitAudio(int clipId)
TimelineFunctions
::
requestSplitAudio
(
m_model
,
clipId
,
audioTarget
());
}
void
TimelineController
::
splitVideo
(
int
clipId
)
{
TimelineFunctions
::
requestSplitVideo
(
m_model
,
clipId
,
videoTarget
());
}
void
TimelineController
::
switchTrackLock
(
bool
applyToAll
)
{
if
(
!
applyToAll
)
{
...
...
src/timeline2/view/timelinecontroller.h
View file @
d0ad55ee
...
...
@@ -261,6 +261,7 @@ public:
Q_INVOKABLE
void
extract
(
int
clipId
);
Q_INVOKABLE
void
splitAudio
(
int
clipId
);
Q_INVOKABLE
void
splitVideo
(
int
clipId
);
/* @brief Seeks to selected clip start / end
*/
...
...
Write
Preview
Markdown
is supported
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