Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
Multimedia
Kdenlive
Commits
b8afadba
Commit
b8afadba
authored
Jan 13, 2021
by
Jean-Baptiste Mardelle
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
improve subtitle track integration: add context menu, highlight on active
Related to
#666
parent
30ec7007
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
92 additions
and
15 deletions
+92
-15
src/bin/model/subtitlemodel.cpp
src/bin/model/subtitlemodel.cpp
+18
-0
src/bin/model/subtitlemodel.hpp
src/bin/model/subtitlemodel.hpp
+3
-0
src/mainwindow.cpp
src/mainwindow.cpp
+1
-0
src/timeline2/model/timelinefunctions.cpp
src/timeline2/model/timelinefunctions.cpp
+7
-1
src/timeline2/view/qml/Clip.qml
src/timeline2/view/qml/Clip.qml
+1
-1
src/timeline2/view/qml/Track.qml
src/timeline2/view/qml/Track.qml
+0
-1
src/timeline2/view/qml/timeline.qml
src/timeline2/view/qml/timeline.qml
+50
-10
src/timeline2/view/timelinecontroller.cpp
src/timeline2/view/timelinecontroller.cpp
+12
-2
No files found.
src/bin/model/subtitlemodel.cpp
View file @
b8afadba
...
...
@@ -1141,3 +1141,21 @@ QDomElement SubtitleModel::toXml(int sid, QDomDocument &document)
return
container
;
}
int
SubtitleModel
::
getBlankSizeAtPos
(
int
pos
)
const
{
GenTime
matchPos
(
pos
,
pCore
->
getCurrentFps
());
std
::
unordered_set
<
int
>
matching
;
GenTime
min
;
GenTime
max
;
for
(
const
auto
&
subtitles
:
m_subtitleList
)
{
if
(
subtitles
.
first
>
matchPos
&&
(
max
==
GenTime
()
||
subtitles
.
first
<
max
))
{
// Outside range
max
=
subtitles
.
first
;
}
if
(
subtitles
.
second
.
second
<
matchPos
&&
(
min
==
GenTime
()
||
subtitles
.
second
.
second
>
min
))
{
min
=
subtitles
.
second
.
second
;
}
}
return
max
.
frames
(
pCore
->
getCurrentFps
())
-
min
.
frames
(
pCore
->
getCurrentFps
());
}
src/bin/model/subtitlemodel.hpp
View file @
b8afadba
...
...
@@ -139,7 +139,10 @@ public:
void
loadProperties
(
QMap
<
QString
,
QString
>
subProperties
);
/** @brief Add all subtitle items to snaps */
void
allSnaps
(
std
::
vector
<
int
>
&
snaps
);
/** @brief Returns an xml representation of the subtitle with id @sid */
QDomElement
toXml
(
int
sid
,
QDomDocument
&
document
);
/** @brief Returns the size of the space between subtitles */
int
getBlankSizeAtPos
(
int
pos
)
const
;
public
slots
:
/** @brief Function that parses through a subtitle file */
...
...
src/mainwindow.cpp
View file @
b8afadba
...
...
@@ -601,6 +601,7 @@ void MainWindow::init()
//Timeline subtitle menu
QMenu
*
timelineSubtitleMenu
=
new
QMenu
(
this
);
timelineSubtitleMenu
->
addAction
(
actionCollection
()
->
action
(
QStringLiteral
(
"edit_copy"
)));
timelineSubtitleMenu
->
addAction
(
actionCollection
()
->
action
(
QStringLiteral
(
"delete_subtitle_clip"
)));
// Timeline headers menu
...
...
src/timeline2/model/timelinefunctions.cpp
View file @
b8afadba
...
...
@@ -1812,7 +1812,13 @@ bool TimelineFunctions::pasteTimelineClips(const std::shared_ptr<TimelineItemMod
bool
TimelineFunctions
::
requestDeleteBlankAt
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
int
trackId
,
int
position
,
bool
affectAllTracks
)
{
// find blank duration
int
spaceDuration
=
timeline
->
getTrackById_const
(
trackId
)
->
getBlankSizeAtPos
(
position
);
int
spaceDuration
;
if
(
trackId
==
-
2
)
{
// Subtitle track
spaceDuration
=
timeline
->
getSubtitleModel
()
->
getBlankSizeAtPos
(
position
);
}
else
{
spaceDuration
=
timeline
->
getTrackById_const
(
trackId
)
->
getBlankSizeAtPos
(
position
);
}
int
cid
=
requestSpacerStartOperation
(
timeline
,
affectAllTracks
?
-
1
:
trackId
,
position
);
if
(
cid
==
-
1
)
{
return
false
;
...
...
src/timeline2/view/qml/Clip.qml
View file @
b8afadba
...
...
@@ -1065,7 +1065,7 @@ Rectangle {
anchors.top
:
parent
.
top
anchors.right
:
clipRoot
.
fadeOut
>
0
?
undefined
:
parent
.
right
anchors.horizontalCenter
:
clipRoot
.
fadeOut
>
0
?
parent
.
horizontalCenter
:
undefined
width
:
fadeOutMouseArea
.
containsMouse
||
Drag
.
active
?
parent
.
width
:
5
width
:
fadeOutMouseArea
.
containsMouse
||
Drag
.
active
?
parent
.
width
:
parent
.
width
/
3
height
:
width
radius
:
width
/
2
color
:
'
darkred
'
...
...
src/timeline2/view/qml/Track.qml
View file @
b8afadba
...
...
@@ -26,7 +26,6 @@ Item{
property
alias
rootIndex
:
trackModel
.
rootIndex
property
bool
isAudio
property
real
timeScale
:
1.0
property
bool
isCurrentTrack
:
false
property
bool
isLocked
:
false
property
int
trackInternalId
:
-
42
property
int
trackThumbsFormat
...
...
src/timeline2/view/qml/timeline.qml
View file @
b8afadba
...
...
@@ -51,6 +51,14 @@ Rectangle {
scrollView
.
contentX
=
pos
}
function
switchSubtitleTrack
()
{
if
(
subtitleTrack
.
height
>
root
.
collapsedHeight
)
{
subtitleTrack
.
height
=
root
.
collapsedHeight
}
else
{
subtitleTrack
.
height
=
5
*
root
.
baseUnit
}
}
function
checkDeletion
(
itemId
)
{
if
(
dragProxy
.
draggedItem
==
itemId
)
{
endDrag
()
...
...
@@ -74,12 +82,29 @@ Rectangle {
}
function
moveSelectedTrack
(
offset
)
{
var
cTrack
=
Logic
.
getTrackIndexFromId
(
timeline
.
activeTrack
)
var
newTrack
=
cTrack
+
offset
var
newTrack
if
(
timeline
.
activeTrack
<
0
)
{
if
(
offset
<
0
)
{
newTrack
=
-
2
}
else
{
newTrack
=
max
}
}
else
{
var
cTrack
=
Logic
.
getTrackIndexFromId
(
timeline
.
activeTrack
)
newTrack
=
cTrack
+
offset
}
var
max
=
tracksRepeater
.
count
;
if
(
newTrack
<
0
)
{
if
(
showSubtitles
&&
newTrack
==
-
1
)
{
timeline
.
activeTrack
=
-
2
return
}
newTrack
=
max
-
1
;
}
else
if
(
newTrack
>=
max
)
{
if
(
showSubtitles
)
{
timeline
.
activeTrack
=
-
2
return
}
newTrack
=
0
;
}
timeline
.
activeTrack
=
tracksRepeater
.
itemAt
(
newTrack
).
trackInternalId
...
...
@@ -716,12 +741,19 @@ Rectangle {
scrollView
.
contentY
=
Math
.
max
(
newScroll
,
0
)
}
}
Item
{
Rectangle
{
id
:
subtitleTrackHeader
width
:
trackHeaders
.
width
height
:
subtitleTrack
.
height
property
bool
collapsed
:
subtitleTrack
.
height
==
root
.
collapsedHeight
visible
:
height
>
0
color
:
(
timeline
.
activeTrack
==
-
2
)
?
Qt
.
tint
(
getTrackColor
(
false
,
false
),
selectedTrackColor
)
:
getTrackColor
(
false
,
false
)
MouseArea
{
anchors.fill
:
parent
onClicked
:
{
timeline
.
activeTrack
=
-
2
}
}
ToolButton
{
id
:
expandSubButton
focusPolicy
:
Qt
.
NoFocus
...
...
@@ -880,7 +912,7 @@ Rectangle {
width
:
root
.
baseUnit
/
2
Rectangle
{
id
:
resizer
height
:
trackHeaders
.
height
height
:
trackHeaders
.
height
+
subtitleTrackHeader
.
height
width
:
root
.
baseUnit
/
2
x
:
root
.
headerWidth
-
2
color
:
'
red
'
...
...
@@ -1013,13 +1045,14 @@ Rectangle {
proxy
.
position
=
Math
.
min
((
scrollView
.
contentX
+
mouse
.
x
)
/
timeline
.
scaleFactor
,
timeline
.
fullDuration
-
1
)
}
}
else
if
(
mouse
.
button
&
Qt
.
RightButton
)
{
if
(
mouse
.
y
>
ruler
.
height
+
subtitleTrack
.
height
)
{
timeline
.
activeTrack
=
tracksRepeater
.
itemAt
(
Logic
.
getTrackIndexFromPos
(
mouse
.
y
-
ruler
.
height
+
scrollView
.
contentY
-
subtitleTrack
.
height
)).
trackInternalId
if
(
mouse
.
y
>
ruler
.
height
)
{
if
(
mouse
.
y
>
ruler
.
height
+
subtitleTrack
.
height
)
{
timeline
.
activeTrack
=
tracksRepeater
.
itemAt
(
Logic
.
getTrackIndexFromPos
(
mouse
.
y
-
ruler
.
height
+
scrollView
.
contentY
-
subtitleTrack
.
height
)).
trackInternalId
}
else
{
timeline
.
activeTrack
=
-
2
}
root
.
mainFrame
=
Math
.
floor
((
mouse
.
x
+
scrollView
.
contentX
)
/
timeline
.
scaleFactor
)
root
.
showTimelineMenu
()
}
else
if
(
mouse
.
y
>
ruler
.
height
)
{
//TODO:
// subtitle track menu
}
else
{
// ruler menu
root
.
showRulerMenu
()
...
...
@@ -1205,6 +1238,13 @@ Rectangle {
// These make the striped background for the tracks.
// It is important that these are not part of the track visual hierarchy;
// otherwise, the clips will be obscured by the Track's background.
Rectangle
{
width
:
scrollView
.
width
border.width
:
1
border.color
:
root
.
frameColor
height
:
subtitleTrack
.
height
color
:
(
timeline
.
activeTrack
==
-
2
)
?
Qt
.
tint
(
getTrackColor
(
false
,
false
),
selectedTrackColor
)
:
getTrackColor
(
false
,
false
)
}
Column
{
y
:
subtitleTrack
.
height
topPadding
:
-
scrollView
.
contentY
...
...
@@ -1258,6 +1298,7 @@ Rectangle {
onWheel
:
zoomByWheel
(
wheel
)
//cursorShape: dragProxyArea.drag.active ? Qt.ClosedHandCursor : tracksArea.cursorShape
}
Repeater
{
id
:
subtitlesRepeater
;
model
:
subtitleDelegateModel
}
}
Item
{
...
...
@@ -1577,7 +1618,6 @@ Rectangle {
height
:
trackHeight
isAudio
:
audio
trackThumbsFormat
:
thumbsFormat
isCurrentTrack
:
item
===
timeline
.
activeTrack
trackInternalId
:
item
z
:
tracksRepeater
.
count
-
index
}
...
...
src/timeline2/view/timelinecontroller.cpp
View file @
b8afadba
...
...
@@ -1918,7 +1918,7 @@ QMap<QString, QString> TimelineController::documentProperties()
QMap
<
QString
,
QString
>
props
=
pCore
->
currentDoc
()
->
documentProperties
();
int
audioTarget
=
m_model
->
m_audioTarget
.
isEmpty
()
?
-
1
:
m_model
->
getTrackPosition
(
m_model
->
m_audioTarget
.
firstKey
());
int
videoTarget
=
m_model
->
m_videoTarget
==
-
1
?
-
1
:
m_model
->
getTrackPosition
(
m_model
->
m_videoTarget
);
int
activeTrack
=
m_activeTrack
==
-
1
?
-
1
:
m_model
->
getTrackPosition
(
m_activeTrack
);
int
activeTrack
=
m_activeTrack
<
0
?
m_activeTrack
:
m_model
->
getTrackPosition
(
m_activeTrack
);
props
.
insert
(
QStringLiteral
(
"audioTarget"
),
QString
::
number
(
audioTarget
));
props
.
insert
(
QStringLiteral
(
"videoTarget"
),
QString
::
number
(
videoTarget
));
props
.
insert
(
QStringLiteral
(
"activeTrack"
),
QString
::
number
(
activeTrack
));
...
...
@@ -2572,6 +2572,9 @@ void TimelineController::switchTrackActive(int trackId)
if
(
trackId
==
-
1
)
{
trackId
=
m_activeTrack
;
}
if
(
trackId
<
0
)
{
return
;
}
bool
active
=
m_model
->
getTrackById_const
(
trackId
)
->
isTimelineActive
();
m_model
->
setTrackProperty
(
trackId
,
QStringLiteral
(
"kdenlive:timeline_active"
),
active
?
QStringLiteral
(
"0"
)
:
QStringLiteral
(
"1"
));
m_activeSnaps
.
clear
();
...
...
@@ -3705,8 +3708,15 @@ void TimelineController::collapseActiveTrack()
if
(
m_activeTrack
==
-
1
)
{
return
;
}
if
(
m_activeTrack
==
-
2
)
{
// Subtitle track
QMetaObject
::
invokeMethod
(
m_root
,
"switchSubtitleTrack"
,
Qt
::
QueuedConnection
);
return
;
}
int
collapsed
=
m_model
->
getTrackProperty
(
m_activeTrack
,
QStringLiteral
(
"kdenlive:collapsed"
)).
toInt
();
m_model
->
setTrackProperty
(
m_activeTrack
,
QStringLiteral
(
"kdenlive:collapsed"
),
collapsed
>
0
?
QStringLiteral
(
"0"
)
:
QStringLiteral
(
"5"
));
// Default unit for timeline.qml objects size
int
baseUnit
=
qMax
(
28
,
(
int
)
(
QFontInfo
(
QFontDatabase
::
systemFont
(
QFontDatabase
::
SmallestReadableFont
)).
pixelSize
()
*
1.8
+
0.5
));
m_model
->
setTrackProperty
(
m_activeTrack
,
QStringLiteral
(
"kdenlive:collapsed"
),
collapsed
>
0
?
QStringLiteral
(
"0"
)
:
QString
::
number
(
baseUnit
));
}
void
TimelineController
::
setActiveTrackProperty
(
const
QString
&
name
,
const
QString
&
value
)
...
...
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