Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Kdenlive
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
258
Issues
258
List
Boards
Labels
Service Desk
Milestones
Merge Requests
15
Merge Requests
15
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Multimedia
Kdenlive
Commits
6fb5c447
Commit
6fb5c447
authored
Jul 28, 2019
by
Jean-Baptiste Mardelle
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix inconsistent behavior of advanced timeline operations.
Related to
#225
parent
940053c4
Pipeline
#5985
passed with stage
in 27 minutes and 34 seconds
Changes
14
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
109 additions
and
67 deletions
+109
-67
src/bin/bin.cpp
src/bin/bin.cpp
+2
-0
src/bin/bin.h
src/bin/bin.h
+2
-0
src/mainwindow.cpp
src/mainwindow.cpp
+4
-0
src/project/projectmanager.cpp
src/project/projectmanager.cpp
+1
-1
src/timeline2/model/timelinefunctions.cpp
src/timeline2/model/timelinefunctions.cpp
+32
-44
src/timeline2/model/timelinefunctions.hpp
src/timeline2/model/timelinefunctions.hpp
+2
-2
src/timeline2/model/timelineitemmodel.cpp
src/timeline2/model/timelineitemmodel.cpp
+13
-0
src/timeline2/model/timelineitemmodel.hpp
src/timeline2/model/timelineitemmodel.hpp
+1
-0
src/timeline2/model/timelinemodel.cpp
src/timeline2/model/timelinemodel.cpp
+18
-8
src/timeline2/model/timelinemodel.hpp
src/timeline2/model/timelinemodel.hpp
+2
-2
src/timeline2/view/qml/TrackHead.qml
src/timeline2/view/qml/TrackHead.qml
+2
-2
src/timeline2/view/timelinecontroller.cpp
src/timeline2/view/timelinecontroller.cpp
+20
-8
src/timeline2/view/timelinecontroller.h
src/timeline2/view/timelinecontroller.h
+6
-0
tests/trimmingtest.cpp
tests/trimmingtest.cpp
+4
-0
No files found.
src/bin/bin.cpp
View file @
6fb5c447
...
...
@@ -1718,6 +1718,8 @@ void Bin::showClipProperties(const std::shared_ptr<ProjectClip> &clip, bool forc
delete
w
;
}
m_propertiesPanel
->
setProperty
(
"clipId"
,
clip
->
AbstractProjectItem
::
clipId
());
// Setup timeline targets
emit
setupTargets
(
clip
->
hasVideo
(),
clip
->
hasAudio
());
auto
*
lay
=
static_cast
<
QVBoxLayout
*>
(
m_propertiesPanel
->
layout
());
if
(
lay
==
nullptr
)
{
lay
=
new
QVBoxLayout
(
m_propertiesPanel
);
...
...
src/bin/bin.h
View file @
6fb5c447
...
...
@@ -470,6 +470,8 @@ signals:
void
clipNameChanged
(
const
QString
&
);
/** @brief A clip was updated, request panel update. */
void
refreshPanel
(
const
QString
&
id
);
/** @brief Upon selection, activate timeline target tracks. */
void
setupTargets
(
bool
hasVideo
,
bool
hasAudio
);
};
#endif
src/mainwindow.cpp
View file @
6fb5c447
...
...
@@ -251,6 +251,10 @@ void MainWindow::init()
connect
(
m_clipMonitor
,
&
Monitor
::
seekToNextSnap
,
this
,
&
MainWindow
::
slotSnapForward
);
connect
(
pCore
->
bin
(),
&
Bin
::
findInTimeline
,
this
,
&
MainWindow
::
slotClipInTimeline
,
Qt
::
DirectConnection
);
connect
(
pCore
->
bin
(),
&
Bin
::
setupTargets
,
this
,
[
&
]
(
bool
hasVideo
,
bool
hasAudio
)
{
getCurrentTimeline
()
->
controller
()
->
setTargetTracks
({
hasVideo
?
getCurrentTimeline
()
->
model
()
->
getFirstVideoTrackIndex
()
:
-
1
,
hasAudio
?
getCurrentTimeline
()
->
model
()
->
getFirstAudioTrackIndex
()
:
-
1
});
}
);
// TODO deprecated, replace with Bin methods if necessary
/*connect(m_projectList, SIGNAL(loadingIsOver()), this, SLOT(slotElapsedTime()));
...
...
src/project/projectmanager.cpp
View file @
6fb5c447
...
...
@@ -890,7 +890,7 @@ bool ProjectManager::updateTimeline(int pos, int scrollPos)
pCore
->
monitorManager
()
->
projectMonitor
()
->
setProducer
(
m_mainTimelineModel
->
producer
(),
pos
);
pCore
->
monitorManager
()
->
projectMonitor
()
->
adjustRulerSize
(
m_mainTimelineModel
->
duration
()
-
1
,
m_project
->
getGuideModel
());
pCore
->
window
()
->
getMainTimeline
()
->
controller
()
->
setZone
(
m_project
->
zone
());
pCore
->
window
()
->
getMainTimeline
()
->
controller
()
->
setTargetTracks
(
m_project
->
targetTracks
());
//
pCore->window()->getMainTimeline()->controller()->setTargetTracks(m_project->targetTracks());
pCore
->
window
()
->
getMainTimeline
()
->
controller
()
->
setScrollPos
(
m_project
->
getDocumentProperty
(
QStringLiteral
(
"scrollPos"
)).
toInt
());
int
activeTrackPosition
=
m_project
->
getDocumentProperty
(
QStringLiteral
(
"activeTrack"
),
QString
::
number
(
-
1
)).
toInt
();
if
(
activeTrackPosition
>
-
1
&&
activeTrackPosition
<
m_mainTimelineModel
->
getTracksCount
())
{
...
...
src/timeline2/model/timelinefunctions.cpp
View file @
6fb5c447
...
...
@@ -313,7 +313,6 @@ bool TimelineFunctions::extractZone(const std::shared_ptr<TimelineItemModel> &ti
std
::
function
<
bool
(
void
)
>
undo
=
[]()
{
return
true
;
};
std
::
function
<
bool
(
void
)
>
redo
=
[]()
{
return
true
;
};
bool
result
=
true
;
result
=
breakAffectedGroups
(
timeline
,
tracks
,
zone
,
undo
,
redo
);
for
(
int
&
trackId
:
tracks
)
{
...
...
@@ -323,7 +322,7 @@ bool TimelineFunctions::extractZone(const std::shared_ptr<TimelineItemModel> &ti
result
=
result
&&
TimelineFunctions
::
liftZone
(
timeline
,
trackId
,
zone
,
undo
,
redo
);
}
if
(
result
&&
!
liftOnly
)
{
result
=
TimelineFunctions
::
removeSpace
(
timeline
,
-
1
,
zone
,
undo
,
redo
);
result
=
TimelineFunctions
::
removeSpace
(
timeline
,
-
1
,
zone
,
undo
,
redo
,
tracks
);
}
pCore
->
pushUndo
(
undo
,
redo
,
liftOnly
?
i18n
(
"Lift zone"
)
:
i18n
(
"Extract zone"
));
return
result
;
...
...
@@ -340,15 +339,15 @@ bool TimelineFunctions::insertZone(const std::shared_ptr<TimelineItemModel> &tim
auto
it
=
timeline
->
m_allTracks
.
cbegin
();
while
(
it
!=
timeline
->
m_allTracks
.
cend
())
{
int
target_track
=
(
*
it
)
->
getId
();
if
(
!
trackIds
.
contains
(
target_track
)
&&
!
timeline
->
getTrackById_const
(
target_track
)
->
shouldReceiveTimelineOp
())
{
++
it
;
continue
;
if
(
timeline
->
getTrackById_const
(
target_track
)
->
shouldReceiveTimelineOp
())
{
affectedTracks
<<
target_track
;
}
else
if
(
trackIds
.
contains
(
target_track
))
{
// Track is marked as target but not active, remove it
trackIds
.
removeAll
(
target_track
);
}
affectedTracks
<<
target_track
;
++
it
;
}
result
=
breakAffectedGroups
(
timeline
,
affectedTracks
,
QPoint
(
insertFrame
,
insertFrame
+
(
zone
.
y
()
-
zone
.
x
())),
undo
,
redo
);
if
(
overwrite
)
{
// Cut all tracks
for
(
int
target_track
:
affectedTracks
)
{
...
...
@@ -367,13 +366,14 @@ bool TimelineFunctions::insertZone(const std::shared_ptr<TimelineItemModel> &tim
result
=
result
&&
TimelineFunctions
::
requestClipCut
(
timeline
,
startClipId
,
insertFrame
,
undo
,
redo
);
}
}
result
=
result
&&
TimelineFunctions
::
requestInsertSpace
(
timeline
,
QPoint
(
insertFrame
,
insertFrame
+
(
zone
.
y
()
-
zone
.
x
())),
undo
,
redo
);
result
=
result
&&
TimelineFunctions
::
requestInsertSpace
(
timeline
,
QPoint
(
insertFrame
,
insertFrame
+
(
zone
.
y
()
-
zone
.
x
())),
undo
,
redo
,
affectedTracks
);
}
if
(
result
)
{
if
(
!
trackIds
.
isEmpty
())
{
int
newId
=
-
1
;
QString
binClipId
=
QString
(
"%1/%2/%3"
).
arg
(
binId
).
arg
(
zone
.
x
()).
arg
(
zone
.
y
()
-
1
);
result
=
timeline
->
requestClipInsertion
(
binClipId
,
trackIds
.
first
(),
insertFrame
,
newId
,
true
,
true
,
useTargets
,
undo
,
redo
);
result
=
timeline
->
requestClipInsertion
(
binClipId
,
trackIds
.
first
(),
insertFrame
,
newId
,
true
,
true
,
useTargets
,
undo
,
redo
,
affectedTracks
);
}
if
(
result
)
{
pCore
->
pushUndo
(
undo
,
redo
,
overwrite
?
i18n
(
"Overwrite zone"
)
:
i18n
(
"Insert zone"
));
...
...
@@ -414,7 +414,7 @@ bool TimelineFunctions::liftZone(const std::shared_ptr<TimelineItemModel> &timel
return
true
;
}
bool
TimelineFunctions
::
removeSpace
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
int
trackId
,
QPoint
zone
,
Fun
&
undo
,
Fun
&
redo
)
bool
TimelineFunctions
::
removeSpace
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
int
trackId
,
QPoint
zone
,
Fun
&
undo
,
Fun
&
redo
,
QVector
<
int
>
allowedTracks
)
{
Q_UNUSED
(
trackId
)
...
...
@@ -422,58 +422,46 @@ bool TimelineFunctions::removeSpace(const std::shared_ptr<TimelineItemModel> &ti
auto
it
=
timeline
->
m_allTracks
.
cbegin
();
while
(
it
!=
timeline
->
m_allTracks
.
cend
())
{
int
target_track
=
(
*
it
)
->
getId
();
if
(
timeline
->
m_videoTarget
==
target_track
||
timeline
->
m_audioTarget
==
target_track
||
timeline
->
getTrackById_const
(
target_track
)
->
shouldReceiveTimelineOp
())
{
if
(
timeline
->
getTrackById_const
(
target_track
)
->
shouldReceiveTimelineOp
())
{
std
::
unordered_set
<
int
>
subs
=
timeline
->
getItemsInRange
(
target_track
,
zone
.
y
()
-
1
,
-
1
,
true
);
clips
.
insert
(
subs
.
begin
(),
subs
.
end
());
}
++
it
;
}
bool
result
=
false
;
if
(
!
clips
.
empty
())
{
int
clipId
=
*
clips
.
begin
();
if
(
clips
.
size
()
>
1
)
{
int
clipsGroup
=
timeline
->
m_groups
->
getRootId
(
clipId
);
int
res
=
timeline
->
requestClipsGroup
(
clips
,
undo
,
redo
);
if
(
res
>
-
1
)
{
result
=
timeline
->
requestGroupMove
(
clipId
,
res
,
0
,
zone
.
x
()
-
zone
.
y
(),
true
,
true
,
undo
,
redo
);
if
(
result
&&
res
!=
clipsGroup
)
{
// Only ungroup if a group was created
result
=
timeline
->
requestClipUngroup
(
clipId
,
undo
,
redo
);
}
if
(
!
result
)
{
undo
();
}
}
}
else
{
// only 1 clip to be moved
int
clipStart
=
timeline
->
getItemPosition
(
clipId
);
result
=
timeline
->
requestClipMove
(
clipId
,
timeline
->
getItemTrackId
(
clipId
),
clipStart
-
(
zone
.
y
()
-
zone
.
x
()),
true
,
true
,
true
,
true
,
undo
,
redo
);
}
timeline
->
requestSetSelection
(
clips
);
int
itemId
=
*
clips
.
begin
();
int
targetTrackId
=
timeline
->
getItemTrackId
(
itemId
);
int
targetPos
=
timeline
->
getItemPosition
(
itemId
)
+
zone
.
x
()
-
zone
.
y
();
if
(
timeline
->
m_groups
->
isInGroup
(
itemId
))
{
result
=
timeline
->
requestGroupMove
(
itemId
,
timeline
->
m_groups
->
getRootId
(
itemId
),
0
,
zone
.
x
()
-
zone
.
y
(),
true
,
true
,
undo
,
redo
,
true
,
true
,
allowedTracks
);
}
else
if
(
timeline
->
isClip
(
itemId
))
{
result
=
timeline
->
requestClipMove
(
itemId
,
targetTrackId
,
targetPos
,
true
,
true
,
true
,
true
,
undo
,
redo
);
}
else
{
result
=
timeline
->
requestCompositionMove
(
itemId
,
targetTrackId
,
timeline
->
m_allCompositions
[
itemId
]
->
getForcedTrack
(),
targetPos
,
true
,
true
,
undo
,
redo
);
}
timeline
->
requestClearSelection
();
if
(
!
result
)
{
undo
();
}
return
result
;
}
bool
TimelineFunctions
::
requestInsertSpace
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
QPoint
zone
,
Fun
&
undo
,
Fun
&
redo
,
bool
followTarget
s
)
bool
TimelineFunctions
::
requestInsertSpace
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
QPoint
zone
,
Fun
&
undo
,
Fun
&
redo
,
QVector
<
int
>
allowedTrack
s
)
{
timeline
->
requestClearSelection
();
Fun
local_undo
=
[]()
{
return
true
;
};
Fun
local_redo
=
[]()
{
return
true
;
};
std
::
unordered_set
<
int
>
items
;
if
(
!
followTargets
)
{
if
(
allowedTracks
.
isEmpty
()
)
{
// Select clips in all tracks
items
=
timeline
->
getItemsInRange
(
-
1
,
zone
.
x
(),
-
1
,
true
);
}
else
{
// Select clips in target and active tracks only
auto
it
=
timeline
->
m_allTracks
.
cbegin
();
while
(
it
!=
timeline
->
m_allTracks
.
cend
())
{
int
target_track
=
(
*
it
)
->
getId
();
if
(
timeline
->
m_videoTarget
==
target_track
||
timeline
->
m_audioTarget
==
target_track
||
timeline
->
getTrackById_const
(
target_track
)
->
shouldReceiveTimelineOp
())
{
std
::
unordered_set
<
int
>
subs
=
timeline
->
getItemsInRange
(
target_track
,
zone
.
x
(),
-
1
,
true
);
items
.
insert
(
subs
.
begin
(),
subs
.
end
());
}
++
it
;
for
(
int
target_track
:
allowedTracks
)
{
std
::
unordered_set
<
int
>
subs
=
timeline
->
getItemsInRange
(
target_track
,
zone
.
x
(),
-
1
,
true
);
items
.
insert
(
subs
.
begin
(),
subs
.
end
());
}
}
if
(
items
.
empty
())
{
...
...
@@ -488,7 +476,7 @@ bool TimelineFunctions::requestInsertSpace(const std::shared_ptr<TimelineItemMod
// TODO the three move functions should be unified in a "requestItemMove" function
if
(
timeline
->
m_groups
->
isInGroup
(
itemId
))
{
result
=
result
&&
timeline
->
requestGroupMove
(
itemId
,
timeline
->
m_groups
->
getRootId
(
itemId
),
0
,
zone
.
y
()
-
zone
.
x
(),
true
,
true
,
local_undo
,
local_redo
);
result
&&
timeline
->
requestGroupMove
(
itemId
,
timeline
->
m_groups
->
getRootId
(
itemId
),
0
,
zone
.
y
()
-
zone
.
x
(),
true
,
true
,
local_undo
,
local_redo
,
true
,
true
,
allowedTracks
);
}
else
if
(
timeline
->
isClip
(
itemId
))
{
result
=
result
&&
timeline
->
requestClipMove
(
itemId
,
targetTrackId
,
targetPos
,
true
,
true
,
true
,
true
,
local_undo
,
local_redo
);
}
else
{
...
...
src/timeline2/model/timelinefunctions.hpp
View file @
6fb5c447
...
...
@@ -83,12 +83,12 @@ struct TimelineFunctions
static
bool
requestSpacerEndOperation
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
int
itemId
,
int
startPosition
,
int
endPosition
);
static
bool
extractZone
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
QVector
<
int
>
tracks
,
QPoint
zone
,
bool
liftOnly
);
static
bool
liftZone
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
int
trackId
,
QPoint
zone
,
Fun
&
undo
,
Fun
&
redo
);
static
bool
removeSpace
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
int
trackId
,
QPoint
zone
,
Fun
&
undo
,
Fun
&
redo
);
static
bool
removeSpace
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
int
trackId
,
QPoint
zone
,
Fun
&
undo
,
Fun
&
redo
,
QVector
<
int
>
allowedTracks
=
QVector
<
int
>
()
);
/** @brief This function will insert a blank space starting at zone.x, and ending at zone.y. This will affect all the tracks
@returns true on success, false otherwise
*/
static
bool
requestInsertSpace
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
QPoint
zone
,
Fun
&
undo
,
Fun
&
redo
,
bool
followTargets
=
true
);
static
bool
requestInsertSpace
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
QPoint
zone
,
Fun
&
undo
,
Fun
&
redo
,
QVector
<
int
>
allowedTracks
=
QVector
<
int
>
()
);
static
bool
insertZone
(
const
std
::
shared_ptr
<
TimelineItemModel
>
&
timeline
,
QList
<
int
>
trackIds
,
const
QString
&
binId
,
int
insertFrame
,
QPoint
zone
,
bool
overwrite
,
bool
useTargets
=
true
);
...
...
src/timeline2/model/timelineitemmodel.cpp
View file @
6fb5c447
...
...
@@ -504,6 +504,19 @@ int TimelineItemModel::getFirstVideoTrackIndex() const
return
trackId
;
}
int
TimelineItemModel
::
getFirstAudioTrackIndex
()
const
{
int
trackId
=
-
1
;
auto
it
=
m_allTracks
.
cbegin
();
while
(
it
!=
m_allTracks
.
cend
())
{
if
((
*
it
)
->
isAudioTrack
())
{
trackId
=
(
*
it
)
->
getId
();
}
++
it
;
}
return
trackId
;
}
const
QString
TimelineItemModel
::
getTrackFullName
(
int
tid
)
const
{
QString
tag
=
getTrackTagById
(
tid
);
...
...
src/timeline2/model/timelineitemmodel.hpp
View file @
6fb5c447
...
...
@@ -86,6 +86,7 @@ public:
/** @brief returns the lower video track index in timeline.
**/
int
getFirstVideoTrackIndex
()
const
;
int
getFirstAudioTrackIndex
()
const
;
const
QString
getTrackFullName
(
int
tid
)
const
;
void
notifyChange
(
const
QModelIndex
&
topleft
,
const
QModelIndex
&
bottomright
,
bool
start
,
bool
duration
,
bool
updateThumb
)
override
;
void
notifyChange
(
const
QModelIndex
&
topleft
,
const
QModelIndex
&
bottomright
,
const
QVector
<
int
>
&
roles
)
override
;
...
...
src/timeline2/model/timelinemodel.cpp
View file @
6fb5c447
...
...
@@ -973,7 +973,7 @@ bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId,
}
bool
TimelineModel
::
requestClipInsertion
(
const
QString
&
binClipId
,
int
trackId
,
int
position
,
int
&
id
,
bool
logUndo
,
bool
refreshView
,
bool
useTargets
,
Fun
&
undo
,
Fun
&
redo
)
Fun
&
undo
,
Fun
&
redo
,
QVector
<
int
>
allowedTracks
)
{
Fun
local_undo
=
[]()
{
return
true
;
};
Fun
local_redo
=
[]()
{
return
true
;
};
...
...
@@ -1003,17 +1003,21 @@ bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId,
if
(
m_audioTarget
>=
0
&&
m_videoTarget
==
-
1
&&
useTargets
)
{
// If audio target is set but no video target, only insert audio
trackId
=
m_audioTarget
;
if
(
trackId
>
-
1
&&
getTrackById_const
(
trackId
)
->
isLocked
(
))
{
if
(
trackId
>
-
1
&&
(
getTrackById_const
(
trackId
)
->
isLocked
()
||
!
allowedTracks
.
contains
(
trackId
)
))
{
trackId
=
-
1
;
}
}
else
if
(
useTargets
&&
getTrackById_const
(
trackId
)
->
isLocked
(
))
{
}
else
if
(
useTargets
&&
(
getTrackById_const
(
trackId
)
->
isLocked
()
||
!
allowedTracks
.
contains
(
trackId
)
))
{
// Video target set but locked
trackId
=
m_audioTarget
;
if
(
trackId
>
-
1
&&
getTrackById_const
(
trackId
)
->
isLocked
(
))
{
if
(
trackId
>
-
1
&&
(
getTrackById_const
(
trackId
)
->
isLocked
()
||
!
allowedTracks
.
contains
(
trackId
)
))
{
trackId
=
-
1
;
}
}
if
(
trackId
==
-
1
)
{
if
(
!
allowedTracks
.
isEmpty
())
{
// No active tracks, aborting
return
true
;
}
pCore
->
displayMessage
(
i18n
(
"No available track for insert operation"
),
ErrorMessage
);
return
false
;
}
...
...
@@ -1026,6 +1030,9 @@ bool TimelineModel::requestClipInsertion(const QString &binClipId, int trackId,
}
else
{
target_track
=
m_audioTarget
==
-
1
?
-
1
:
getTrackById_const
(
m_audioTarget
)
->
isLocked
()
?
-
1
:
m_audioTarget
;
}
if
(
useTargets
&&
!
allowedTracks
.
contains
(
target_track
))
{
target_track
=
-
1
;
}
qDebug
()
<<
"CLIP HAS A+V: "
<<
master
->
hasAudioAndVideo
();
int
mirror
=
getMirrorTrackId
(
trackId
);
if
(
mirror
>
-
1
&&
getTrackById_const
(
mirror
)
->
isLocked
())
{
...
...
@@ -1356,7 +1363,7 @@ bool TimelineModel::requestGroupMove(int itemId, int groupId, int delta_track, i
}
bool
TimelineModel
::
requestGroupMove
(
int
itemId
,
int
groupId
,
int
delta_track
,
int
delta_pos
,
bool
updateView
,
bool
finalMove
,
Fun
&
undo
,
Fun
&
redo
,
bool
moveMirrorTracks
,
bool
allowViewRefresh
)
bool
allowViewRefresh
,
QVector
<
int
>
allowedTracks
)
{
QWriteLocker
locker
(
&
m_lock
);
Q_ASSERT
(
m_allGroups
.
count
(
groupId
)
>
0
);
...
...
@@ -1486,13 +1493,16 @@ bool TimelineModel::requestGroupMove(int itemId, int groupId, int delta_track, i
if
(
delta_track
==
0
)
{
// Special case, we are moving on same track, avoid too many calculations
for
(
int
item
:
sorted_clips
)
{
int
current_track_id
=
getItemTrackId
(
item
);
int
target_position
=
getItemPosition
(
item
)
+
delta_pos
;
int
current_track_id
=
getItemTrackId
(
item
);
if
(
!
allowedTracks
.
isEmpty
()
&&
!
allowedTracks
.
contains
(
current_track_id
))
{
continue
;
}
int
target_position
=
getItemPosition
(
item
)
+
delta_pos
;
if
(
isClip
(
item
))
{
ok
=
ok
&&
requestClipMove
(
item
,
current_track_id
,
target_position
,
moveMirrorTracks
,
updateThisView
,
finalMove
,
finalMove
,
local_undo
,
local_redo
,
true
);
}
else
{
ok
=
ok
&&
requestCompositionMove
(
item
,
current_track_id
,
m_allCompositions
[
item
]
->
getForcedTrack
(),
target_position
,
updateThisView
,
finalMove
,
local_undo
,
local_redo
);
requestCompositionMove
(
item
,
current_track_id
,
m_allCompositions
[
item
]
->
getForcedTrack
(),
target_position
,
updateThisView
,
finalMove
,
local_undo
,
local_redo
);
}
}
if
(
!
ok
)
{
...
...
src/timeline2/model/timelinemodel.hpp
View file @
6fb5c447
...
...
@@ -395,7 +395,7 @@ public:
bool
useTargets
=
true
);
/* Same function, but accumulates undo and redo*/
bool
requestClipInsertion
(
const
QString
&
binClipId
,
int
trackId
,
int
position
,
int
&
id
,
bool
logUndo
,
bool
refreshView
,
bool
useTargets
,
Fun
&
undo
,
Fun
&
redo
);
Fun
&
redo
,
QVector
<
int
>
allowedTracks
=
QVector
<
int
>
()
);
protected:
/* @brief Creates a new clip instance without inserting it.
...
...
@@ -434,7 +434,7 @@ public:
*/
bool
requestGroupMove
(
int
itemId
,
int
groupId
,
int
delta_track
,
int
delta_pos
,
bool
moveMirrorTracks
=
true
,
bool
updateView
=
true
,
bool
logUndo
=
true
);
bool
requestGroupMove
(
int
itemId
,
int
groupId
,
int
delta_track
,
int
delta_pos
,
bool
updateView
,
bool
finalMove
,
Fun
&
undo
,
Fun
&
redo
,
bool
moveMirrorTracks
=
true
,
bool
allowViewRefresh
=
true
);
bool
allowViewRefresh
=
true
,
QVector
<
int
>
allowedTracks
=
QVector
<
int
>
()
);
/* @brief Deletes all clips inside the group that contains the given clip.
This action is undoable
...
...
src/timeline2/view/qml/TrackHead.qml
View file @
6fb5c447
...
...
@@ -126,13 +126,13 @@ Rectangle {
if
(
trackHeadRoot
.
isAudio
)
{
if
(
trackHeadRoot
.
trackId
==
timeline
.
audioTarget
)
{
timeline
.
audioTarget
=
-
1
;
}
else
{
}
else
if
(
timeline
.
hasAudioTarget
)
{
timeline
.
audioTarget
=
trackHeadRoot
.
trackId
;
}
}
else
{
if
(
trackHeadRoot
.
trackId
==
timeline
.
videoTarget
)
{
timeline
.
videoTarget
=
-
1
;
}
else
{
}
else
if
(
timeline
.
hasVideoTarget
)
{
timeline
.
videoTarget
=
trackHeadRoot
.
trackId
;
}
}
...
...
src/timeline2/view/timelinecontroller.cpp
View file @
6fb5c447
...
...
@@ -107,8 +107,12 @@ void TimelineController::setModel(std::shared_ptr<TimelineItemModel> model)
void
TimelineController
::
setTargetTracks
(
QPair
<
int
,
int
>
targets
)
{
setVideoTarget
(
targets
.
first
>=
0
&&
targets
.
first
<
m_model
->
getTracksCount
()
?
m_model
->
getTrackIndexFromPosition
(
targets
.
first
)
:
-
1
);
setAudioTarget
(
targets
.
second
>=
0
&&
targets
.
second
<
m_model
->
getTracksCount
()
?
m_model
->
getTrackIndexFromPosition
(
targets
.
second
)
:
-
1
);
//setVideoTarget(targets.first >= 0 && targets.first < m_model->getTracksCount() ? m_model->getTrackIndexFromPosition(targets.first) : -1);
//setAudioTarget(targets.second >= 0 && targets.second < m_model->getTracksCount() ? m_model->getTrackIndexFromPosition(targets.second) : -1);
m_hasVideoTarget
=
targets
.
first
>=
0
;
m_hasAudioTarget
=
targets
.
second
>=
0
;
setVideoTarget
(
targets
.
first
);
setAudioTarget
(
targets
.
second
);
}
std
::
shared_ptr
<
TimelineItemModel
>
TimelineController
::
getModel
()
const
...
...
@@ -1578,11 +1582,9 @@ void TimelineController::extractZone(QPoint zone, bool liftOnly)
auto
it
=
m_model
->
m_allTracks
.
cbegin
();
while
(
it
!=
m_model
->
m_allTracks
.
cend
())
{
int
target_track
=
(
*
it
)
->
getId
();
if
(
target_track
!=
audioTarget
()
&&
target_track
!=
videoTarget
()
&&
!
m_model
->
getTrackById_const
(
target_track
)
->
shouldReceiveTimelineOp
())
{
++
it
;
continue
;
if
(
m_model
->
getTrackById_const
(
target_track
)
->
shouldReceiveTimelineOp
())
{
tracks
<<
target_track
;
}
tracks
<<
target_track
;
++
it
;
}
if
(
m_zone
==
QPoint
())
{
...
...
@@ -1870,6 +1872,16 @@ int TimelineController::videoTarget() const
return
m_model
->
m_videoTarget
;
}
bool
TimelineController
::
hasAudioTarget
()
const
{
return
m_hasAudioTarget
;
}
bool
TimelineController
::
hasVideoTarget
()
const
{
return
m_hasVideoTarget
;
}
void
TimelineController
::
resetTrackHeight
()
{
int
tracksCount
=
m_model
->
getTracksCount
();
...
...
@@ -2231,7 +2243,7 @@ bool TimelineController::endFakeMove(int clipId, int position, bool updateView,
// There is a clip, cut
res
=
res
&&
TimelineFunctions
::
requestClipCut
(
m_model
,
startClipId
,
position
,
undo
,
redo
);
}
res
=
res
&&
TimelineFunctions
::
requestInsertSpace
(
m_model
,
QPoint
(
position
,
position
+
duration
),
undo
,
redo
,
false
);
res
=
res
&&
TimelineFunctions
::
requestInsertSpace
(
m_model
,
QPoint
(
position
,
position
+
duration
),
undo
,
redo
);
}
res
=
res
&&
m_model
->
getTrackById
(
trackId
)
->
requestClipInsertion
(
clipId
,
position
,
updateView
,
invalidateTimeline
,
undo
,
redo
);
if
(
res
)
{
...
...
@@ -2345,7 +2357,7 @@ bool TimelineController::endFakeGroupMove(int clipId, int groupId, int delta_tra
res
=
res
&&
TimelineFunctions
::
requestClipCut
(
m_model
,
startClipId
,
target_position
,
undo
,
redo
);
}
}
res
=
res
&&
TimelineFunctions
::
requestInsertSpace
(
m_model
,
QPoint
(
min
,
max
),
undo
,
redo
,
false
);
res
=
res
&&
TimelineFunctions
::
requestInsertSpace
(
m_model
,
QPoint
(
min
,
max
),
undo
,
redo
);
}
for
(
int
item
:
sorted_clips
)
{
if
(
m_model
->
isClip
(
item
))
{
...
...
src/timeline2/view/timelinecontroller.h
View file @
6fb5c447
...
...
@@ -67,6 +67,8 @@ class TimelineController : public QObject
Q_PROPERTY
(
int
activeTrack
READ
activeTrack
WRITE
setActiveTrack
NOTIFY
activeTrackChanged
)
Q_PROPERTY
(
int
audioTarget
READ
audioTarget
WRITE
setAudioTarget
NOTIFY
audioTargetChanged
)
Q_PROPERTY
(
int
videoTarget
READ
videoTarget
WRITE
setVideoTarget
NOTIFY
videoTargetChanged
)
Q_PROPERTY
(
bool
hasAudioTarget
READ
hasAudioTarget
)
Q_PROPERTY
(
bool
hasVideoTarget
READ
hasVideoTarget
)
Q_PROPERTY
(
QColor
videoColor
READ
videoColor
NOTIFY
colorsChanged
)
Q_PROPERTY
(
QColor
audioColor
READ
audioColor
NOTIFY
colorsChanged
)
Q_PROPERTY
(
QColor
lockedColor
READ
lockedColor
NOTIFY
colorsChanged
)
...
...
@@ -142,6 +144,8 @@ public:
Q_INVOKABLE
int
seekPosition
()
const
{
return
m_seekPosition
;
}
Q_INVOKABLE
int
audioTarget
()
const
;
Q_INVOKABLE
int
videoTarget
()
const
;
Q_INVOKABLE
bool
hasAudioTarget
()
const
;
Q_INVOKABLE
bool
hasVideoTarget
()
const
;
Q_INVOKABLE
int
activeTrack
()
const
{
return
m_activeTrack
;
}
Q_INVOKABLE
QColor
videoColor
()
const
;
Q_INVOKABLE
QColor
audioColor
()
const
;
...
...
@@ -494,6 +498,8 @@ private:
int
m_videoTarget
;
int
m_activeTrack
;
int
m_audioRef
;
bool
m_hasAudioTarget
{
false
};
bool
m_hasVideoTarget
{
false
};
QPair
<
int
,
int
>
m_recordStart
;
int
m_recordTrack
;
QPoint
m_zone
;
...
...
tests/trimmingtest.cpp
View file @
6fb5c447
...
...
@@ -37,6 +37,7 @@ TEST_CASE("Advanced trimming operations", "[Trimming]")
int
tid1
=
TrackModel
::
construct
(
timeline
);
int
tid2
=
TrackModel
::
construct
(
timeline
);
int
tid3
=
TrackModel
::
construct
(
timeline
);
// Add an audio track
int
tid4
=
TrackModel
::
construct
(
timeline
,
-
1
,
-
1
,
QString
(),
true
);
int
cid2
=
ClipModel
::
construct
(
timeline
,
binId2
,
-
1
,
PlaylistState
::
VideoOnly
);
...
...
@@ -619,6 +620,9 @@ TEST_CASE("Insert/delete", "[Trimming2]")
timeline
->
m_audioTarget
=
tid2
;
timeline
->
m_videoTarget
=
tid1
;
// Make tracks active
timeline
->
setTrackProperty
(
tid1
,
QStringLiteral
(
"kdenlive:timeline_active"
),
QStringLiteral
(
"1"
));
timeline
->
setTrackProperty
(
tid2
,
QStringLiteral
(
"kdenlive:timeline_active"
),
QStringLiteral
(
"1"
));
REQUIRE
(
TimelineFunctions
::
insertZone
(
timeline
,
{
tid1
,
tid2
},
binId
,
3
+
2
,
{
l
/
4
,
3
*
l
/
4
},
false
));
timeline
->
m_audioTarget
=
-
1
;
timeline
->
m_videoTarget
=
-
1
;
...
...
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