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
f435261a
Commit
f435261a
authored
Nov 11, 2020
by
Jean-Baptiste Mardelle
Browse files
Various subtitle fixes (moving, allow selecting)
parent
38ce0af8
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/bin/model/subtitlemodel.cpp
View file @
f435261a
...
...
@@ -34,12 +34,11 @@
SubtitleModel
::
SubtitleModel
(
Mlt
::
Tractor
*
tractor
,
QObject
*
parent
)
:
QAbstractListModel
(
parent
)
,
m_tractor
(
tractor
)
,
m_lock
(
QReadWriteLock
::
Recursive
)
,
m_subtitleFilter
(
new
Mlt
::
Filter
(
pCore
->
getCurrentProfile
()
->
profile
(),
"avfilter.subtitles"
))
,
m_tractor
(
tractor
)
{
qDebug
()
<<
"subtitle constructor"
;
m_subtitleFilter
=
nullptr
;
m_subtitleFilter
.
reset
(
new
Mlt
::
Filter
(
pCore
->
getCurrentProfile
()
->
profile
(),
"avfilter.subtitles"
));
qDebug
()
<<
"Filter!"
;
if
(
tractor
!=
nullptr
)
{
qDebug
()
<<
"Tractor!"
;
...
...
@@ -334,6 +333,16 @@ QList<SubtitledTime> SubtitleModel::getAllSubtitles() const
return
subtitle
;
}
SubtitledTime
SubtitleModel
::
getSubtitle
(
GenTime
startFrame
)
const
{
for
(
const
auto
&
subtitles
:
m_subtitleList
)
{
if
(
subtitles
.
first
==
startFrame
)
{
return
SubtitledTime
(
subtitles
.
first
,
subtitles
.
second
.
first
,
subtitles
.
second
.
second
);
}
}
return
SubtitledTime
(
GenTime
(),
QString
(),
GenTime
());
}
void
SubtitleModel
::
registerSnap
(
const
std
::
weak_ptr
<
SnapInterface
>
&
snapModel
)
{
// make sure ptr is valid
...
...
src/bin/model/subtitlemodel.hpp
View file @
f435261a
...
...
@@ -63,6 +63,9 @@ public:
/** @brief Returns all subtitles in the model */
QList
<
SubtitledTime
>
getAllSubtitles
()
const
;
/** @brief Get subtitle at position */
SubtitledTime
getSubtitle
(
GenTime
startFrame
)
const
;
/** @brief Registers a snap model to the subtitle model */
void
registerSnap
(
const
std
::
weak_ptr
<
SnapInterface
>
&
snapModel
);
...
...
@@ -107,8 +110,8 @@ private:
std
::
weak_ptr
<
DocUndoStack
>
m_undoStack
;
std
::
map
<
GenTime
,
std
::
pair
<
QString
,
GenTime
>>
m_subtitleList
;
QString
scriptInfoSection
=
""
,
styleSection
=
""
,
eventSection
=
""
;
QString
styleName
=
""
;
QString
scriptInfoSection
,
styleSection
,
eventSection
;
QString
styleName
;
QString
m_subFilePath
;
//To get subtitle file from effects parameter:
...
...
src/timeline2/model/timelinemodel.cpp
View file @
f435261a
...
...
@@ -4632,6 +4632,10 @@ bool TimelineModel::requestClearSelection(bool onDeletion)
m_selectedMix
=
-
1
;
emit
selectedMixChanged
(
-
1
,
nullptr
);
}
if
(
m_selectedSubtitle
>
-
1
)
{
m_selectedSubtitle
=
-
1
;
emit
selectedSubtitleChanged
(
-
1
);
}
if
(
m_currentSelection
==
-
1
)
{
TRACE_RES
(
true
);
return
true
;
...
...
@@ -4681,6 +4685,13 @@ void TimelineModel::requestMixSelection(int cid)
}
}
void
TimelineModel
::
requestSubtitleSelection
(
int
startFrame
)
{
requestClearSelection
();
m_selectedSubtitle
=
startFrame
;
emit
selectedSubtitleChanged
(
startFrame
);
}
void
TimelineModel
::
requestClearSelection
(
bool
onDeletion
,
Fun
&
undo
,
Fun
&
redo
)
{
Fun
operation
=
[
this
,
onDeletion
]()
{
...
...
src/timeline2/model/timelinemodel.hpp
View file @
f435261a
...
...
@@ -684,6 +684,10 @@ public:
@param cid clip id
*/
Q_INVOKABLE
void
requestMixSelection
(
int
cid
);
/** @brief Select a given subtitle in timeline
@param startFrame The start position (frame) of the subtitle
*/
Q_INVOKABLE
void
requestSubtitleSelection
(
int
startFrame
);
/** @brief Add the given item to the selection
If @param clear is true, the selection is first cleared
...
...
@@ -806,6 +810,8 @@ signals:
void
selectionChanged
();
/* @brief Signal sent whenever the selected mix changes */
void
selectedMixChanged
(
int
cid
,
const
std
::
shared_ptr
<
AssetParameterModel
>
&
asset
);
/* @brief Signal sent whenever the selected subtitle changes */
void
selectedSubtitleChanged
(
int
startframe
);
/* @brief Signal when a track is deleted so we make sure we don't store its id */
void
checkTrackDeletion
(
int
tid
);
/* @brief Emitted when a clip is deleted to check if it was not used in timeline qml */
...
...
@@ -850,6 +856,7 @@ protected:
// (in that case we cannot further group it because the selection would have only one child, which is prohibited by design)
int
m_currentSelection
=
-
1
;
int
m_selectedMix
=
-
1
;
int
m_selectedSubtitle
=
-
1
;
// The index of the temporary overlay track in tractor, or -1 if not connected
int
m_overlayTrackCount
;
...
...
src/timeline2/view/qml/Clip.qml
View file @
f435261a
...
...
@@ -81,6 +81,7 @@ Rectangle {
property
var
groupTrimData
property
int
scrollStart
:
scrollView
.
contentX
-
(
clipRoot
.
modelStart
*
timeline
.
scaleFactor
)
property
int
mouseXPos
:
mouseArea
.
mouseX
property
double
clipNameOffset
:
isAudio
||
parentTrack
.
trackThumbsFormat
>
0
?
clipRoot
.
border
.
width
:
(
clipRoot
.
border
.
width
+
(
container
.
height
*
root
.
dar
*
2
))
<
container
.
width
?
clipRoot
.
border
.
width
+
container
.
height
*
root
.
dar
:
clipRoot
.
border
.
width
width
:
clipDuration
*
timeScale
opacity
:
dragProxyArea
.
drag
.
active
&&
dragProxy
.
draggedItem
==
clipId
?
0.8
:
1.0
...
...
@@ -183,10 +184,10 @@ Rectangle {
onTimeScaleChanged
:
{
x
=
modelStart
*
timeScale
;
width
=
clipDuration
*
timeScale
;
labelRect
.
x
=
scrollX
>
modelStart
*
timeScale
?
scrollX
-
modelStart
*
timeScale
:
clipRoot
.
border
.
width
labelRect
.
x
=
scrollX
>
modelStart
*
timeScale
?
scrollX
-
modelStart
*
timeScale
:
clipRoot
.
clipNameOffset
}
onScrollXChanged
:
{
labelRect
.
x
=
scrollX
>
modelStart
*
timeScale
?
scrollX
-
modelStart
*
timeScale
:
clipRoot
.
border
.
width
labelRect
.
x
=
scrollX
>
modelStart
*
timeScale
?
scrollX
-
modelStart
*
timeScale
:
clipRoot
.
clipNameOffset
}
border.color
:
(
clipStatus
==
ClipStatus
.
StatusMissing
||
ClipStatus
==
ClipStatus
.
StatusWaiting
||
clipStatus
==
ClipStatus
.
StatusDeleting
)
?
"
#ff0000
"
:
selected
?
root
.
selectionColor
:
grouped
?
root
.
groupColor
:
borderColor
...
...
src/timeline2/view/qml/SubTitle.qml
View file @
f435261a
...
...
@@ -9,15 +9,12 @@ Item {
property
real
duration
:
(
model
.
endframe
-
model
.
startframe
)
property
int
oldStartX
property
double
oldStartFrame
:
subtitleBase
.
x
Rectangle
{
Item
{
id
:
subtitleBase
width
:
duration
*
timeScale
// to make width change wrt timeline scale factor
height
:
parent
.
height
x
:
model
.
startframe
*
timeScale
;
property
bool
textEditBegin
:
false
color
:
'
yellow
'
border.width
:
1
border.color
:
'
orange
'
clip
:
true
/*Text {
id: subtitleText
...
...
@@ -44,6 +41,7 @@ Item {
cursorShape
:
(
pressed
?
Qt
.
ClosedHandCursor
:
((
startMouseArea
.
drag
.
active
||
endMouseArea
.
drag
.
active
)?
Qt
.
SizeHorCursor
:
Qt
.
PointingHandCursor
));
drag.target
:
subtitleBase
drag.axis
:
Drag
.
XAxis
drag.minimumX
:
0
onPressed
:
{
console
.
log
(
'
IT IS PRESSED
'
)
if
(
mouse
.
button
==
Qt
.
RightButton
)
{
...
...
@@ -56,21 +54,9 @@ Item {
oldStartFrame
=
subtitleBase
.
x
originalDuration
=
subtitleBase
.
width
/
timeScale
console
.
log
(
"
originalDuration
"
,
originalDuration
)
controller
.
requestSubtitleSelection
(
model
.
startframe
);
}
}
onPositionChanged
:
{
if
(
pressed
)
{
newStart
=
Math
.
round
((
subtitleBase
.
x
+
(
mouseX
-
oldStartX
))
/
timeScale
)
if
(
mouseX
!=
oldStartX
)
{
diff
=
(
mouseX
-
oldStartX
)
/
timeScale
subtitleBase
.
x
=
subtitleBase
.
x
+
diff
delta
=
subtitleBase
.
x
/
timeline
.
scaleFactor
-
oldStartFrame
/
timeline
.
scaleFactor
var
diffDelta
=
delta
-
oldDelta
oldDelta
=
delta
subtitleBase
.
width
=
originalDuration
*
timeline
.
scaleFactor
}
}
}
onReleased
:
{
console
.
log
(
'
IT IS RELEASED
'
)
root
.
autoScrolling
=
timeline
.
autoScroll
...
...
@@ -107,10 +93,10 @@ Item {
wrapMode
:
TextField
.
WordWrap
horizontalAlignment
:
displayText
==
text
?
TextInput
.
AlignHCenter
:
TextInput
.
AlignLeft
background
:
Rectangle
{
color
:
'
yellow
'
color
:
root
.
selectedSubtitle
==
model
.
startframe
?
"
#fff
"
:
'
#ccccff
'
border
{
width
:
1
color
:
'
orange
'
color
:
root
.
selectedSubtitle
==
model
.
startframe
?
root
.
selectionColor
:
"
#000
"
width
:
2
}
}
color
:
'
black
'
...
...
src/timeline2/view/qml/timeline.qml
View file @
f435261a
...
...
@@ -295,6 +295,7 @@ Rectangle {
property
int
snapping
:
(
timeline
.
snap
&&
(
timeline
.
scaleFactor
<
2
*
baseUnit
))
?
Math
.
floor
(
baseUnit
/
(
timeline
.
scaleFactor
>
3
?
timeline
.
scaleFactor
/
2
:
timeline
.
scaleFactor
))
:
-
1
property
var
timelineSelection
:
timeline
.
selection
property
int
selectedMix
:
timeline
.
selectedMix
property
int
selectedSubtitle
:
timeline
.
selectedSubtitle
property
int
trackHeight
property
int
copiedClip
:
-
1
property
int
zoomOnMouse
:
-
1
...
...
@@ -1074,7 +1075,7 @@ Rectangle {
Item
{
id
:
subtitleTrack
width
:
tracksContainerArea
.
width
height
:
showSubtitles
?
root
.
baseUnit
*
3
:
0
height
:
showSubtitles
?
root
.
baseUnit
*
4
:
0
Repeater
{
id
:
subtitlesRepeater
;
model
:
subtitleDelegateModel
}
MouseArea
{
anchors.fill
:
parent
...
...
src/timeline2/view/timelinecontroller.cpp
View file @
f435261a
...
...
@@ -127,6 +127,9 @@ void TimelineController::setModel(std::shared_ptr<TimelineItemModel> model)
emit
showMixModel
(
cid
,
asset
);
emit
selectedMixChanged
();
});
connect
(
m_model
.
get
(),
&
TimelineModel
::
selectedSubtitleChanged
,
[
this
]
(
int
startFrame
)
{
emit
selectedSubtitleChanged
();
});
connect
(
m_model
.
get
(),
&
TimelineModel
::
checkTrackDeletion
,
this
,
&
TimelineController
::
checkTrackDeletion
,
Qt
::
DirectConnection
);
}
...
...
@@ -312,6 +315,12 @@ int TimelineController::selectedMix() const
return
m_model
->
m_selectedMix
;
}
int
TimelineController
::
selectedSubtitle
()
const
{
qDebug
()
<<
"=== GOT SELECTED SUB: "
<<
m_model
->
m_selectedSubtitle
<<
"
\n\n
=========="
;
return
m_model
->
m_selectedSubtitle
;
}
void
TimelineController
::
selectItems
(
const
QList
<
int
>
&
ids
)
{
std
::
unordered_set
<
int
>
ids_s
(
ids
.
begin
(),
ids
.
end
());
...
...
@@ -486,6 +495,11 @@ void TimelineController::deleteSelectedClips()
if
(
m_model
->
m_selectedMix
>
-
1
&&
m_model
->
isClip
(
m_model
->
m_selectedMix
))
{
m_model
->
removeMix
(
m_model
->
m_selectedMix
);
}
if
(
m_model
->
m_selectedSubtitle
>
-
1
)
{
auto
subtitleModel
=
pCore
->
projectManager
()
->
current
()
->
getSubtitleModel
();
SubtitledTime
t
=
subtitleModel
->
getSubtitle
(
GenTime
(
m_model
->
m_selectedSubtitle
,
pCore
->
getCurrentFps
()));
deleteSubtitle
(
m_model
->
m_selectedSubtitle
,
t
.
end
().
frames
(
pCore
->
getCurrentFps
()),
t
.
subtitle
());
}
return
;
}
// only need to delete the first item, the others will be deleted in cascade
...
...
src/timeline2/view/timelinecontroller.h
View file @
f435261a
...
...
@@ -41,6 +41,7 @@ class TimelineController : public QObject
*/
Q_PROPERTY
(
QList
<
int
>
selection
READ
selection
NOTIFY
selectionChanged
)
Q_PROPERTY
(
int
selectedMix
READ
selectedMix
NOTIFY
selectedMixChanged
)
Q_PROPERTY
(
int
selectedSubtitle
READ
selectedSubtitle
NOTIFY
selectedSubtitleChanged
)
/* @brief holds the timeline zoom factor
*/
Q_PROPERTY
(
double
scaleFactor
READ
scaleFactor
WRITE
setScaleFactor
NOTIFY
scaleFactorChanged
)
...
...
@@ -349,6 +350,9 @@ public:
/* @brief Returns the id of the currently selected mix's clip, -1 if no mix selected
*/
int
selectedMix
()
const
;
/* @brief Returns the start frame id of the currently selected subtitle, -1 if no selection
*/
int
selectedSubtitle
()
const
;
/* @brief Add an asset (effect, composition)
*/
...
...
@@ -653,6 +657,7 @@ signals:
void
selected
(
Mlt
::
Producer
*
producer
);
void
selectionChanged
();
void
selectedMixChanged
();
void
selectedSubtitleChanged
();
void
frameFormatChanged
();
void
trackHeightChanged
();
void
scaleFactorChanged
();
...
...
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