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
1de9399b
Commit
1de9399b
authored
Oct 31, 2021
by
Jean-Baptiste Mardelle
Browse files
Refactor keyframe selection, now in sync between timeline and effect stack.
Related to
#1118
#1227
parent
eeaec722
Pipeline
#92667
canceled with stage
Changes
22
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
src/assets/keyframes/model/keyframemodel.cpp
View file @
1de9399b
...
...
@@ -65,13 +65,18 @@ bool KeyframeModel::addKeyframe(GenTime pos, KeyframeType type, QVariant value,
QVariant
oldValue
=
m_keyframeList
[
pos
].
second
;
local_undo
=
updateKeyframe_lambda
(
pos
,
oldType
,
oldValue
,
notify
);
local_redo
=
updateKeyframe_lambda
(
pos
,
type
,
value
,
notify
);
if
(
local_redo
())
{
UPDATE_UNDO_REDO
(
local_redo
,
local_undo
,
undo
,
redo
);
return
true
;
}
}
else
{
local_redo
=
addKeyframe_lambda
(
pos
,
type
,
value
,
notify
);
local_undo
=
deleteKeyframe_lambda
(
pos
,
notify
);
}
if
(
local_redo
())
{
UPDATE_UNDO_REDO
(
local_redo
,
local_undo
,
undo
,
redo
);
return
true
;
Fun
redo_first
=
addKeyframe_lambda
(
pos
,
type
,
value
,
notify
);
if
(
redo_first
())
{
local_redo
=
addKeyframe_lambda
(
pos
,
type
,
value
,
true
);
local_undo
=
deleteKeyframe_lambda
(
pos
,
true
);
UPDATE_UNDO_REDO
(
local_redo
,
local_undo
,
undo
,
redo
);
return
true
;
}
}
return
false
;
}
...
...
@@ -100,7 +105,7 @@ bool KeyframeModel::addKeyframe(GenTime pos, KeyframeType type, QVariant value)
return
res
;
}
bool
KeyframeModel
::
removeKeyframe
(
GenTime
pos
,
Fun
&
undo
,
Fun
&
redo
,
bool
notify
)
bool
KeyframeModel
::
removeKeyframe
(
GenTime
pos
,
Fun
&
undo
,
Fun
&
redo
,
bool
notify
,
bool
updateSelection
)
{
qDebug
()
<<
"Going to remove keyframe at "
<<
pos
.
frames
(
pCore
->
getCurrentFps
())
<<
" NOTIFY: "
<<
notify
;
qDebug
()
<<
"before"
<<
getAnimProperty
();
...
...
@@ -108,11 +113,46 @@ bool KeyframeModel::removeKeyframe(GenTime pos, Fun &undo, Fun &redo, bool notif
Q_ASSERT
(
m_keyframeList
.
count
(
pos
)
>
0
);
KeyframeType
oldType
=
m_keyframeList
[
pos
].
first
;
QVariant
oldValue
=
m_keyframeList
[
pos
].
second
;
Fun
local_undo
=
addKeyframe_lambda
(
pos
,
oldType
,
oldValue
,
notify
);
Fun
local_redo
=
deleteKeyframe_lambda
(
pos
,
notify
);
if
(
local_redo
())
{
Fun
select_undo
=
[]()
{
return
true
;
};
Fun
select_redo
=
[]()
{
return
true
;
};
if
(
updateSelection
)
{
if
(
auto
ptr
=
m_model
.
lock
())
{
if
(
!
ptr
->
m_selectedKeyframes
.
isEmpty
())
{
int
ix
=
getIndexForPos
(
pos
);
QVector
<
int
>
selection
;
QVector
<
int
>
prevSelection
=
ptr
->
m_selectedKeyframes
;
for
(
auto
&
kf
:
prevSelection
)
{
if
(
kf
==
ix
)
{
continue
;
}
if
(
kf
<
ix
)
{
selection
<<
kf
;
}
else
{
selection
<<
(
kf
-
1
);
}
}
setActiveKeyframe
(
-
1
);
std
::
sort
(
selection
.
begin
(),
selection
.
end
());
select_redo
=
[
this
,
selection
]()
{
setSelectedKeyframes
(
selection
);
return
true
;
};
select_undo
=
[
this
,
prevSelection
]()
{
setSelectedKeyframes
(
prevSelection
);
return
true
;
};
}
}
}
Fun
redo_first
=
deleteKeyframe_lambda
(
pos
,
notify
);
if
(
redo_first
())
{
Fun
local_undo
=
addKeyframe_lambda
(
pos
,
oldType
,
oldValue
,
true
);
Fun
local_redo
=
deleteKeyframe_lambda
(
pos
,
true
);
select_redo
();
qDebug
()
<<
"after"
<<
getAnimProperty
();
UPDATE_UNDO_REDO
(
local_redo
,
local_undo
,
undo
,
redo
);
UPDATE_UNDO_REDO
(
select_redo
,
select_undo
,
undo
,
redo
);
return
true
;
}
return
false
;
...
...
@@ -156,7 +196,96 @@ bool KeyframeModel::removeKeyframe(GenTime pos)
return
res
;
}
bool
KeyframeModel
::
moveKeyframe
(
GenTime
oldPos
,
GenTime
pos
,
QVariant
newVal
,
Fun
&
undo
,
Fun
&
redo
)
GenTime
KeyframeModel
::
getPosAtIndex
(
int
ix
)
const
{
QList
<
GenTime
>
positions
=
getKeyframePos
();
std
::
sort
(
positions
.
begin
(),
positions
.
end
());
if
(
ix
<
0
||
ix
>=
positions
.
count
())
{
return
GenTime
();
}
return
positions
.
at
(
ix
);
}
bool
KeyframeModel
::
moveKeyframe
(
GenTime
oldPos
,
GenTime
pos
,
QVariant
newVal
,
Fun
&
undo
,
Fun
&
redo
,
bool
updateView
)
{
qDebug
()
<<
"starting to move keyframe"
<<
oldPos
.
frames
(
pCore
->
getCurrentFps
())
<<
pos
.
frames
(
pCore
->
getCurrentFps
());
QWriteLocker
locker
(
&
m_lock
);
// Check if we have several selected keyframes
if
(
oldPos
==
pos
)
{
if
(
!
newVal
.
isValid
())
{
// no change
return
true
;
}
}
if
(
auto
ptr
=
m_model
.
lock
())
{
if
(
ptr
->
m_selectedKeyframes
.
size
()
>
1
)
{
// We have several selected keyframes, move them all
QVector
<
GenTime
>
positions
;
for
(
auto
&
kf
:
ptr
->
m_selectedKeyframes
)
{
if
(
kf
>
0
)
{
positions
<<
getPosAtIndex
(
kf
);
}
}
GenTime
delta
=
pos
-
oldPos
;
if
(
pos
>
oldPos
)
{
// Moving right, reverse sort
std
::
sort
(
positions
.
rbegin
(),
positions
.
rend
());
// Check max pos
bool
ok
=
false
;
GenTime
test
=
positions
.
first
();
auto
next
=
getNextKeyframe
(
test
,
&
ok
);
if
(
ok
)
{
delta
=
qMin
(
delta
,
next
.
first
-
GenTime
(
1
,
pCore
->
getCurrentFps
())
-
test
);
}
}
else
{
// Moving left
std
::
sort
(
positions
.
begin
(),
positions
.
end
());
// Check min pos
bool
ok
=
false
;
GenTime
test
=
positions
.
first
();
auto
next
=
getPrevKeyframe
(
test
,
&
ok
);
if
(
ok
)
{
delta
=
qMax
(
delta
,
(
next
.
first
+
GenTime
(
1
,
pCore
->
getCurrentFps
()))
-
test
);
}
}
if
(
delta
==
GenTime
())
{
if
(
!
newVal
.
isValid
())
{
// no change
return
true
;
}
}
bool
res
=
true
;
for
(
auto
&
p
:
positions
)
{
if
(
p
==
oldPos
)
{
res
=
res
&&
moveOneKeyframe
(
oldPos
,
oldPos
+
delta
,
newVal
,
undo
,
redo
,
updateView
);
}
else
{
res
=
res
&&
moveOneKeyframe
(
p
,
p
+
delta
,
QVariant
(),
undo
,
redo
,
updateView
);
}
}
return
res
;
}
else
{
if
(
pos
>
oldPos
)
{
// Moving right
bool
ok
=
false
;
auto
next
=
getNextKeyframe
(
oldPos
,
&
ok
);
if
(
ok
)
{
pos
=
qMin
(
pos
,
next
.
first
-
GenTime
(
1
,
pCore
->
getCurrentFps
()));
}
}
else
{
// Moving left
bool
ok
=
false
;
auto
next
=
getPrevKeyframe
(
oldPos
,
&
ok
);
if
(
ok
)
{
pos
=
qMax
(
pos
,
next
.
first
+
GenTime
(
1
,
pCore
->
getCurrentFps
()));
}
}
return
moveOneKeyframe
(
oldPos
,
pos
,
newVal
,
undo
,
redo
,
updateView
);
}
}
return
false
;
}
bool
KeyframeModel
::
moveOneKeyframe
(
GenTime
oldPos
,
GenTime
pos
,
QVariant
newVal
,
Fun
&
undo
,
Fun
&
redo
,
bool
updateView
)
{
qDebug
()
<<
"starting to move keyframe"
<<
oldPos
.
frames
(
pCore
->
getCurrentFps
())
<<
pos
.
frames
(
pCore
->
getCurrentFps
());
QWriteLocker
locker
(
&
m_lock
);
...
...
@@ -184,7 +313,7 @@ bool KeyframeModel::moveKeyframe(GenTime oldPos, GenTime pos, QVariant newVal, F
Fun
local_redo
=
[]()
{
return
true
;
};
qDebug
()
<<
getAnimProperty
();
// TODO: use the new Animation::key_set_frame to move a keyframe
bool
res
=
removeKeyframe
(
oldPos
,
local_undo
,
local_redo
);
bool
res
=
removeKeyframe
(
oldPos
,
local_undo
,
local_redo
,
true
,
false
);
qDebug
()
<<
"Move keyframe finished deletion:"
<<
res
;
qDebug
()
<<
getAnimProperty
();
if
(
res
)
{
...
...
@@ -192,14 +321,14 @@ bool KeyframeModel::moveKeyframe(GenTime oldPos, GenTime pos, QVariant newVal, F
if
(
!
newVal
.
isValid
())
{
newVal
=
oldValue
;
}
res
=
addKeyframe
(
pos
,
oldType
,
newVal
,
true
,
local_undo
,
local_redo
);
res
=
addKeyframe
(
pos
,
oldType
,
newVal
,
updateView
,
local_undo
,
local_redo
);
}
else
if
(
newVal
.
isValid
())
{
QVariant
result
=
getNormalizedValue
(
newVal
.
toDouble
());
if
(
result
.
isValid
())
{
res
=
addKeyframe
(
pos
,
oldType
,
result
,
true
,
local_undo
,
local_redo
);
res
=
addKeyframe
(
pos
,
oldType
,
result
,
updateView
,
local_undo
,
local_redo
);
}
}
else
{
res
=
addKeyframe
(
pos
,
oldType
,
oldValue
,
true
,
local_undo
,
local_redo
);
res
=
addKeyframe
(
pos
,
oldType
,
oldValue
,
updateView
,
local_undo
,
local_redo
);
}
qDebug
()
<<
"Move keyframe finished insertion:"
<<
res
;
qDebug
()
<<
getAnimProperty
();
...
...
@@ -427,6 +556,8 @@ QHash<int, QByteArray> KeyframeModel::roleNames() const
roles
[
FrameRole
]
=
"frame"
;
roles
[
TypeRole
]
=
"type"
;
roles
[
ValueRole
]
=
"value"
;
roles
[
SelectedRole
]
=
"selected"
;
roles
[
ActiveRole
]
=
"active"
;
roles
[
NormalizedValueRole
]
=
"normalizedValue"
;
return
roles
;
}
...
...
@@ -496,6 +627,16 @@ QVariant KeyframeModel::data(const QModelIndex &index, int role) const
return
it
->
first
.
frames
(
pCore
->
getCurrentFps
());
case
TypeRole
:
return
QVariant
::
fromValue
<
KeyframeType
>
(
it
->
second
.
first
);
case
SelectedRole
:
if
(
auto
ptr
=
m_model
.
lock
())
{
return
ptr
->
m_selectedKeyframes
.
contains
(
index
.
row
());
}
break
;
case
ActiveRole
:
if
(
auto
ptr
=
m_model
.
lock
())
{
return
ptr
->
m_activeKeyframe
==
index
.
row
();
}
break
;
}
return
QVariant
();
}
...
...
@@ -591,6 +732,10 @@ bool KeyframeModel::removeAllKeyframes(Fun &undo, Fun &redo)
Fun
local_undo
=
[]()
{
return
true
;
};
Fun
local_redo
=
[]()
{
return
true
;
};
int
kfrCount
=
int
(
m_keyframeList
.
size
())
-
1
;
// Clear selection
if
(
auto
ptr
=
m_model
.
lock
())
{
ptr
->
m_selectedKeyframes
=
{};
}
if
(
kfrCount
<=
0
)
{
// Nothing to do
UPDATE_UNDO_REDO
(
local_redo
,
local_undo
,
undo
,
redo
);
...
...
@@ -1225,6 +1370,16 @@ bool KeyframeModel::removeNextKeyframes(GenTime pos, Fun &undo, Fun &redo)
all_pos
.
push_back
(
m
.
first
);
}
int
kfrCount
=
int
(
all_pos
.
size
());
// Remove deleted keyframes from selection
if
(
auto
ptr
=
m_model
.
lock
())
{
QVector
<
int
>
selection
;
for
(
auto
&
ix
:
ptr
->
m_selectedKeyframes
)
{
if
(
ix
<
kfrCount
)
{
selection
<<
ix
;
}
}
ptr
->
m_selectedKeyframes
=
selection
;
}
// we trigger only one global remove/insertrow event
Fun
update_redo_start
=
[
this
,
firstPos
,
kfrCount
]()
{
beginRemoveRows
(
QModelIndex
(),
firstPos
,
kfrCount
);
...
...
@@ -1260,3 +1415,83 @@ bool KeyframeModel::removeNextKeyframes(GenTime pos, Fun &undo, Fun &redo)
UPDATE_UNDO_REDO
(
local_redo
,
local_undo
,
undo
,
redo
);
return
true
;
}
void
KeyframeModel
::
setSelectedKeyframe
(
int
ix
,
bool
add
)
{
QVector
<
int
>
previous
;
if
(
auto
ptr
=
m_model
.
lock
())
{
if
(
add
)
{
if
(
ptr
->
m_selectedKeyframes
.
contains
(
ix
))
{
// remove from selection
ptr
->
m_selectedKeyframes
.
removeAll
(
ix
);
}
else
{
ptr
->
m_selectedKeyframes
<<
ix
;
}
}
else
{
previous
=
ptr
->
m_selectedKeyframes
;
ptr
->
m_selectedKeyframes
=
{
ix
};
}
}
if
(
!
add
)
{
for
(
auto
&
ix2
:
previous
)
{
if
(
ix2
>
-
1
)
{
emit
requestModelUpdate
(
index
(
ix2
),
index
(
ix2
),
{
SelectedRole
});
}
}
}
if
(
ix
>
-
1
)
{
emit
requestModelUpdate
(
index
(
ix
),
index
(
ix
),
{
SelectedRole
});
}
}
void
KeyframeModel
::
setSelectedKeyframes
(
QVector
<
int
>
selection
)
{
QVector
<
int
>
previous
;
selection
.
removeAll
(
-
1
);
std
::
sort
(
selection
.
begin
(),
selection
.
end
());
if
(
auto
ptr
=
m_model
.
lock
())
{
previous
=
ptr
->
m_selectedKeyframes
;
ptr
->
m_selectedKeyframes
=
selection
;
}
if
(
!
selection
.
isEmpty
())
{
emit
requestModelUpdate
(
index
(
selection
.
first
()),
index
(
selection
.
last
()),
{
SelectedRole
});
}
for
(
auto
&
ix
:
previous
)
{
if
(
ix
>
-
1
&&
!
selection
.
contains
(
ix
))
{
emit
requestModelUpdate
(
index
(
ix
),
index
(
ix
),
{
SelectedRole
});
}
}
}
int
KeyframeModel
::
activeKeyframe
()
const
{
if
(
auto
ptr
=
m_model
.
lock
())
{
return
ptr
->
m_activeKeyframe
;
}
return
-
1
;
}
void
KeyframeModel
::
setActiveKeyframe
(
int
ix
)
{
int
oldActive
=
-
1
;
if
(
auto
ptr
=
m_model
.
lock
())
{
oldActive
=
ptr
->
m_activeKeyframe
;
if
(
oldActive
==
ix
)
{
// Keyframe already active
return
;
}
ptr
->
m_activeKeyframe
=
ix
;
}
emit
requestModelUpdate
(
index
(
ix
),
index
(
ix
),
{
ActiveRole
});
if
(
oldActive
>
-
1
)
{
emit
requestModelUpdate
(
index
(
oldActive
),
index
(
oldActive
),
{
ActiveRole
});
}
}
int
KeyframeModel
::
getIndexForPos
(
const
GenTime
pos
)
const
{
if
(
m_keyframeList
.
count
(
pos
)
==
0
)
{
return
-
1
;
}
return
static_cast
<
int
>
(
std
::
distance
(
m_keyframeList
.
begin
(),
m_keyframeList
.
find
(
pos
)));
}
src/assets/keyframes/model/keyframemodel.hpp
View file @
1de9399b
...
...
@@ -44,7 +44,7 @@ public:
explicit
KeyframeModel
(
std
::
weak_ptr
<
AssetParameterModel
>
model
,
const
QModelIndex
&
index
,
std
::
weak_ptr
<
DocUndoStack
>
undo_stack
,
QObject
*
parent
=
nullptr
);
enum
{
TypeRole
=
Qt
::
UserRole
+
1
,
PosRole
,
FrameRole
,
ValueRole
,
NormalizedValueRole
};
enum
{
TypeRole
=
Qt
::
UserRole
+
1
,
PosRole
,
FrameRole
,
ValueRole
,
NormalizedValueRole
,
SelectedRole
,
ActiveRole
};
friend
class
KeyframeModelList
;
friend
class
KeyframeWidget
;
friend
class
KeyframeImport
;
...
...
@@ -77,7 +77,7 @@ protected:
protected:
/** @brief Same function but accumulates undo/redo */
bool
removeKeyframe
(
GenTime
pos
,
Fun
&
undo
,
Fun
&
redo
,
bool
notify
=
true
);
bool
removeKeyframe
(
GenTime
pos
,
Fun
&
undo
,
Fun
&
redo
,
bool
notify
=
true
,
bool
updateSelection
=
true
);
public:
/** @brief moves a keyframe
...
...
@@ -88,7 +88,7 @@ public:
bool
moveKeyframe
(
int
oldPos
,
int
pos
,
bool
logUndo
);
bool
offsetKeyframes
(
int
oldPos
,
int
pos
,
bool
logUndo
);
bool
moveKeyframe
(
GenTime
oldPos
,
GenTime
pos
,
QVariant
newVal
,
bool
logUndo
);
bool
moveKeyframe
(
GenTime
oldPos
,
GenTime
pos
,
QVariant
newVal
,
Fun
&
undo
,
Fun
&
redo
);
bool
moveKeyframe
(
GenTime
oldPos
,
GenTime
pos
,
QVariant
newVal
,
Fun
&
undo
,
Fun
&
redo
,
bool
updateView
=
true
);
/** @brief updates the value of a keyframe
@param old is the position of the keyframe
...
...
@@ -147,6 +147,14 @@ public:
QVariant
updateInterpolated
(
const
QVariant
&
interpValue
,
double
val
);
/** @brief Return the real value from a normalized one */
QVariant
getNormalizedValue
(
double
newVal
)
const
;
/** @brief Set or add a keyframe to selection */
Q_INVOKABLE
void
setSelectedKeyframe
(
int
ix
,
bool
add
);
void
setSelectedKeyframes
(
QVector
<
int
>
selection
);
Q_INVOKABLE
int
activeKeyframe
()
const
;
Q_INVOKABLE
void
setActiveKeyframe
(
int
ix
);
int
getIndexForPos
(
const
GenTime
pos
)
const
;
GenTime
getPosAtIndex
(
int
ix
)
const
;
// Mandatory overloads
Q_INVOKABLE
QVariant
data
(
const
QModelIndex
&
index
,
int
role
)
const
override
;
...
...
@@ -197,9 +205,11 @@ private:
mutable
QReadWriteLock
m_lock
;
std
::
map
<
GenTime
,
std
::
pair
<
KeyframeType
,
QVariant
>>
m_keyframeList
;
bool
moveOneKeyframe
(
GenTime
oldPos
,
GenTime
pos
,
QVariant
newVal
,
Fun
&
undo
,
Fun
&
redo
,
bool
updateView
=
true
);
signals:
void
modelChanged
();
void
requestModelUpdate
(
const
QModelIndex
&
,
const
QModelIndex
&
,
const
QVector
<
int
>&
);
public:
// this is to enable for range loops
...
...
src/assets/keyframes/model/keyframemodellist.cpp
View file @
1de9399b
...
...
@@ -40,6 +40,42 @@ const QString KeyframeModelList::getAssetId()
return
{};
}
QVector
<
int
>
KeyframeModelList
::
selectedKeyframes
()
const
{
if
(
auto
ptr
=
m_model
.
lock
())
{
return
ptr
->
m_selectedKeyframes
;
}
return
{};
}
int
KeyframeModelList
::
activeKeyframe
()
const
{
if
(
auto
ptr
=
m_model
.
lock
())
{
return
ptr
->
m_activeKeyframe
;
}
return
-
1
;
}
void
KeyframeModelList
::
setActiveKeyframe
(
int
ix
)
{
m_parameters
.
begin
()
->
second
->
setActiveKeyframe
(
ix
);
}
void
KeyframeModelList
::
removeFromSelected
(
int
ix
)
{
m_parameters
.
begin
()
->
second
->
setSelectedKeyframe
(
ix
,
true
);
}
void
KeyframeModelList
::
setSelectedKeyframes
(
QVector
<
int
>
list
)
{
m_parameters
.
begin
()
->
second
->
setSelectedKeyframes
(
list
);
}
void
KeyframeModelList
::
appendSelectedKeyframe
(
int
ix
)
{
m_parameters
.
begin
()
->
second
->
setSelectedKeyframe
(
ix
,
true
);
}
const
QString
KeyframeModelList
::
getAssetRow
()
{
if
(
auto
ptr
=
m_model
.
lock
())
{
...
...
@@ -52,9 +88,19 @@ void KeyframeModelList::addParameter(const QModelIndex &index)
{
std
::
shared_ptr
<
KeyframeModel
>
parameter
(
new
KeyframeModel
(
m_model
,
index
,
m_undoStack
));
connect
(
parameter
.
get
(),
&
KeyframeModel
::
modelChanged
,
this
,
&
KeyframeModelList
::
modelChanged
);
connect
(
parameter
.
get
(),
&
KeyframeModel
::
requestModelUpdate
,
this
,
&
KeyframeModelList
::
slotUpdateModels
);
m_parameters
.
insert
({
index
,
std
::
move
(
parameter
)});
}
void
KeyframeModelList
::
slotUpdateModels
(
const
QModelIndex
&
ix1
,
const
QModelIndex
&
ix2
,
const
QVector
<
int
>
&
roles
)
{
// Propagate change to all keyframe models
for
(
const
auto
&
param
:
m_parameters
)
{
param
.
second
->
dataChanged
(
ix1
,
ix2
,
roles
);
}
emit
modelDisplayChanged
();
}
bool
KeyframeModelList
::
applyOperation
(
const
std
::
function
<
bool
(
std
::
shared_ptr
<
KeyframeModel
>
,
Fun
&
,
Fun
&
)
>
&
op
,
const
QString
&
undoString
)
{
QWriteLocker
locker
(
&
m_lock
);
...
...
@@ -169,11 +215,11 @@ bool KeyframeModelList::removeNextKeyframes(GenTime pos)
return
applyOperation
(
op
,
i18n
(
"Delete keyframes"
));
}
bool
KeyframeModelList
::
moveKeyframe
(
GenTime
oldPos
,
GenTime
pos
,
bool
logUndo
)
bool
KeyframeModelList
::
moveKeyframe
(
GenTime
oldPos
,
GenTime
pos
,
bool
logUndo
,
bool
updateView
)
{
QWriteLocker
locker
(
&
m_lock
);
Q_ASSERT
(
m_parameters
.
size
()
>
0
);
auto
op
=
[
oldPos
,
pos
](
std
::
shared_ptr
<
KeyframeModel
>
param
,
Fun
&
undo
,
Fun
&
redo
)
{
return
param
->
moveKeyframe
(
oldPos
,
pos
,
QVariant
(),
undo
,
redo
);
};
auto
op
=
[
oldPos
,
pos
,
updateView
](
std
::
shared_ptr
<
KeyframeModel
>
param
,
Fun
&
undo
,
Fun
&
redo
)
{
return
param
->
moveKeyframe
(
oldPos
,
pos
,
QVariant
(),
undo
,
redo
,
updateView
);
};
return
applyOperation
(
op
,
logUndo
?
i18nc
(
"@action"
,
"Move keyframe"
)
:
QString
());
}
...
...
@@ -558,12 +604,12 @@ void KeyframeModelList::checkConsistency()
GenTime
KeyframeModelList
::
getPosAtIndex
(
int
ix
)
{
QList
<
GenTime
>
positions
=
m_parameters
.
begin
()
->
second
->
get
KeyframePos
(
);
std
::
sort
(
positions
.
begin
(),
positions
.
end
());
if
(
ix
<
0
||
ix
>=
positions
.
count
())
{
return
GenTime
();
}
return
positions
.
at
(
ix
);
return
m_parameters
.
begin
()
->
second
->
get
PosAtIndex
(
ix
);
}
int
KeyframeModelList
::
getIndexForPos
(
GenTime
pos
)
{
return
m_parameters
.
begin
()
->
second
->
getIndexForPos
(
pos
);
}
QModelIndex
KeyframeModelList
::
getIndexAtRow
(
int
row
)
...
...
src/assets/keyframes/model/keyframemodellist.hpp
View file @
1de9399b
...
...
@@ -62,7 +62,7 @@ public:
@param pos defines the new position of the keyframe, relative to the clip
@param logUndo if true, then an undo object is created
*/
bool
moveKeyframe
(
GenTime
oldPos
,
GenTime
pos
,
bool
logUndo
);
bool
moveKeyframe
(
GenTime
oldPos
,
GenTime
pos
,
bool
logUndo
,
bool
updateView
=
true
);
bool
moveKeyframeWithUndo
(
GenTime
oldPos
,
GenTime
pos
,
Fun
&
undo
,
Fun
&
redo
);
/** @brief updates the value of a keyframe
...
...
@@ -128,6 +128,20 @@ public:
const
QString
getAssetId
();
const
QString
getAssetRow
();
/** @brief Returns the list of selected keyframes */
QVector
<
int
>
selectedKeyframes
()
const
;
/** @brief Remove a position from selected keyframes */
void
removeFromSelected
(
int
pos
);
/** @brief Replace list of selected keyframes */
void
setSelectedKeyframes
(
QVector
<
int
>
list
);
/** @brief Append a keyframe to selection */
void
appendSelectedKeyframe
(
int
frame
);
/** @brief Get the currently active keyframe */
int
activeKeyframe
()
const
;
/** @brief Set the currently active keyframe */
void
setActiveKeyframe
(
int
pos
);
/** @brief Parent item size change, update keyframes*/
void
resizeKeyframes
(
int
oldIn
,
int
oldOut
,
int
in
,
int
out
,
int
offset
,
bool
adjustFromEnd
,
Fun
&
undo
,
Fun
&
redo
);
...
...
@@ -136,6 +150,7 @@ public:
/** @brief Return position of the nth keyframe (ix = nth)*/
GenTime
getPosAtIndex
(
int
ix
);
int
getIndexForPos
(
GenTime
pos
);
QModelIndex
getIndexAtRow
(
int
row
);
/** @brief Check that all keyframable parameters have the same keyframes on loading
...
...
@@ -148,6 +163,7 @@ protected:
signals:
void
modelChanged
();
void
modelDisplayChanged
();
private:
std
::
weak_ptr
<
AssetParameterModel
>
m_model
;
...
...
@@ -157,6 +173,9 @@ private:
QModelIndex
m_inTimelineIndex
;
mutable
QReadWriteLock
m_lock
;
// This is a lock that ensures safety in case of concurrent access
private
slots
:
void
slotUpdateModels
(
const
QModelIndex
&
ix1
,
const
QModelIndex
&
ix2
,
const
QVector
<
int
>
&
roles
);
public:
// this is to enable for range loops
auto
begin
()
->
decltype
(
m_parameters
.
begin
()
->
second
->
begin
())
{
return
m_parameters
.
begin
()
->
second
->
begin
();
}
...
...
src/assets/keyframes/view/keyframeview.cpp
View file @
1de9399b
This diff is collapsed.
Click to expand it.
src/assets/keyframes/view/keyframeview.hpp
View file @
1de9399b
...
...
@@ -19,7 +19,7 @@ class KeyframeView : public QWidget
Q_OBJECT
public:
explicit
KeyframeView
(
std
::
shared_ptr
<
KeyframeModelList
>
model
,
int
duration
,
int
inPoint
,
QWidget
*
parent
=
nullptr
);
explicit
KeyframeView
(
std
::
shared_ptr
<
KeyframeModelList
>
model
,
int
duration
,
QWidget
*
parent
=
nullptr
);
void
setDuration
(
int
dur
,
int
inPoint
);
const
QString
getAssetId
();
/** @brief Copy a keyframe parameter to selected keyframes. */
...
...
@@ -46,6 +46,7 @@ public slots:
void
slotGoToNext
();
void
slotGoToPrev
();
void
slotModelChanged
();
void
slotModelDisplayChanged
();
void
slotEditType
(
int
type
,
const
QPersistentModelIndex
&
index
);
/** @brief Emit initial info for monitor. */
void
initKeyframePos
();
...
...
@@ -63,9 +64,7 @@ protected:
private:
std
::
shared_ptr
<
KeyframeModelList
>
m_model
;
int
m_duration
;
int
m_inPoint
;
int
m_position
;
int
m_currentKeyframe
;
int
m_currentKeyframeOriginal
;
QVector
<
int
>
m_selectedKeyframes
;
int
m_hoverKeyframe
;
...
...
src/assets/model/assetparametermodel.cpp
View file @
1de9399b
...
...
@@ -27,6 +27,7 @@ AssetParameterModel::AssetParameterModel(std::unique_ptr<Mlt::Properties> asset,
,
m_active
(
false
)
,
m_asset
(
std
::
move
(
asset
))
,
m_keyframes
(
nullptr
)
,
m_activeKeyframe
(
-
1
)
,
m_filterProgress
(
0
)
{