Skip to content
GitLab
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
689e191a
Commit
689e191a
authored
Mar 03, 2020
by
Jean-Baptiste Mardelle
Browse files
Allow saving the full effect stack as an effect - kind of restores effect groups.
Related to
#4
parent
a61fcd9b
Pipeline
#15950
passed with stage
in 17 minutes
Changes
10
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/assets/abstractassetsrepository.ipp
View file @
689e191a
...
...
@@ -306,7 +306,6 @@ template <typename AssetType> QString AbstractAssetsRepository<AssetType>::getDe
template <typename AssetType> bool AbstractAssetsRepository<AssetType>::parseInfoFromXml(const QDomElement ¤tAsset, Info &res) const
{
QString tag = currentAsset.attribute(QStringLiteral("tag"), QString());
QString id = currentAsset.attribute(QStringLiteral("id"), QString());
if (id.isEmpty()) {
id = tag;
...
...
src/effects/effectlist/model/effecttreemodel.cpp
View file @
689e191a
...
...
@@ -115,9 +115,18 @@ void EffectTreeModel::reloadEffect(const QString &path)
if
(
asset
.
first
.
isEmpty
()
||
m_customCategory
==
nullptr
)
{
return
;
}
// Check if item already existed, and remove
for
(
int
i
=
0
;
i
<
m_customCategory
->
childCount
();
i
++
)
{
std
::
shared_ptr
<
TreeItem
>
item
=
m_customCategory
->
child
(
i
);
if
(
item
->
dataColumn
(
idCol
).
toString
()
==
asset
.
first
)
{
m_customCategory
->
removeChild
(
item
);
break
;
}
}
bool
isFav
=
KdenliveSettings
::
favorite_effects
().
contains
(
asset
.
first
);
QList
<
QVariant
>
data
{
asset
.
first
,
asset
.
first
,
QVariant
::
fromValue
(
EffectType
::
Custom
),
isFav
};
m_customCategory
->
appendChild
(
data
);
}
void
EffectTreeModel
::
reloadAssetMenu
(
QMenu
*
effectsMenu
,
KActionCategory
*
effectActions
)
...
...
src/effects/effectlist/view/effectlistwidget.cpp
View file @
689e191a
...
...
@@ -87,6 +87,7 @@ QString EffectListWidget::getMimeType(const QString &assetId) const
void
EffectListWidget
::
reloadCustomEffect
(
const
QString
&
path
)
{
static_cast
<
EffectTreeModel
*>
(
m_model
.
get
())
->
reloadEffect
(
path
);
m_proxyModel
->
sort
(
0
,
Qt
::
AscendingOrder
);
}
void
EffectListWidget
::
reloadEffectMenu
(
QMenu
*
effectsMenu
,
KActionCategory
*
effectActions
)
...
...
src/effects/effectsrepository.cpp
View file @
689e191a
...
...
@@ -75,8 +75,40 @@ void EffectsRepository::parseCustomAssetFile(const QString &file_name, std::unor
QDomElement
base
=
doc
.
documentElement
();
if
(
base
.
tagName
()
==
QLatin1String
(
"effectgroup"
))
{
QDomNodeList
effects
=
base
.
elementsByTagName
(
QStringLiteral
(
"effect"
));
if
(
effects
.
count
()
!=
1
)
{
qDebug
()
<<
"Error: found unsupported effect group"
<<
base
.
attribute
(
QStringLiteral
(
"name"
))
<<
" : "
<<
file_name
;
if
(
effects
.
count
()
>
1
)
{
// Effect group
//qDebug() << "Error: found unsupported effect group" << base.attribute(QStringLiteral("name"))<<" : "<<file_name;
Info
result
;
result
.
xml
=
base
;
for
(
int
i
=
0
;
i
<
effects
.
count
();
++
i
)
{
QDomNode
currentNode
=
effects
.
item
(
i
);
if
(
currentNode
.
isNull
())
{
continue
;
}
QDomElement
currentEffect
=
currentNode
.
toElement
();
QString
currentId
=
currentEffect
.
attribute
(
QStringLiteral
(
"id"
),
QString
());
if
(
currentId
.
isEmpty
())
{
currentId
=
currentEffect
.
attribute
(
QStringLiteral
(
"tag"
),
QString
());
}
if
(
!
exists
(
currentId
))
{
qDebug
()
<<
"Error: found unsupported effect in group"
<<
currentId
<<
" : "
<<
file_name
;
return
;
}
}
QString
type
=
base
.
attribute
(
QStringLiteral
(
"type"
),
QString
());
if
(
type
==
QLatin1String
(
"customAudio"
))
{
result
.
type
=
EffectType
::
CustomAudio
;
}
else
{
result
.
type
=
EffectType
::
Custom
;
}
result
.
id
=
base
.
attribute
(
QStringLiteral
(
"id"
),
QString
());
if
(
result
.
id
.
isEmpty
())
{
result
.
id
=
QFileInfo
(
file_name
).
baseName
();
}
if
(
!
result
.
id
.
isEmpty
())
{
result
.
name
=
result
.
id
;
customAssets
[
result
.
id
]
=
result
;
}
return
;
}
}
...
...
@@ -214,6 +246,17 @@ QPair<QString, QString> EffectsRepository::reloadCustom(const QString &path)
return
result
;
}
bool
EffectsRepository
::
isGroup
(
const
QString
&
assetId
)
const
{
if
(
m_assets
.
count
(
assetId
)
>
0
)
{
QDomElement
xml
=
m_assets
.
at
(
assetId
).
xml
;
if
(
xml
.
tagName
()
==
QLatin1String
(
"effectgroup"
))
{
return
true
;
}
}
return
false
;
}
QPair
<
QStringList
,
QStringList
>
EffectsRepository
::
fixDeprecatedEffects
()
{
...
...
src/effects/effectsrepository.hpp
View file @
689e191a
...
...
@@ -55,6 +55,8 @@ public:
/* @brief Check custom effects (older custom effects need an update to default and current values
* returns a list of effects that were incorrectly converted */
QPair
<
QStringList
,
QStringList
>
fixDeprecatedEffects
();
/** @brief Returns true if this is an effect group */
bool
isGroup
(
const
QString
&
assetId
)
const
;
protected:
// Constructor is protected because class is a Singleton
...
...
src/effects/effectstack/model/effectstackmodel.cpp
View file @
689e191a
...
...
@@ -420,6 +420,10 @@ bool EffectStackModel::appendEffect(const QString &effectId, bool makeCurrent)
QWriteLocker
locker
(
&
m_lock
);
std
::
unordered_set
<
int
>
previousFadeIn
=
m_fadeIns
;
std
::
unordered_set
<
int
>
previousFadeOut
=
m_fadeOuts
;
if
(
EffectsRepository
::
get
()
->
isGroup
(
effectId
))
{
QDomElement
doc
=
EffectsRepository
::
get
()
->
getXml
(
effectId
);
return
copyXmlEffect
(
doc
);
}
auto
effect
=
EffectItemModel
::
construct
(
effectId
,
shared_from_this
());
PlaylistState
::
ClipState
state
=
pCore
->
getItemState
(
m_ownerId
);
if
(
effect
->
isAudio
())
{
...
...
src/effects/effectstack/view/collapsibleeffectview.cpp
View file @
689e191a
...
...
@@ -108,6 +108,7 @@ CollapsibleEffectView::CollapsibleEffectView(const std::shared_ptr<EffectItemMod
m_colorIcon
=
new
QLabel
(
this
);
l
->
insertWidget
(
0
,
m_colorIcon
);
m_colorIcon
->
setFixedSize
(
collapseButton
->
sizeHint
());
m_colorIcon
->
setToolTip
(
effectName
);
title
=
new
KSqueezedTextLabel
(
this
);
l
->
insertWidget
(
2
,
title
);
...
...
@@ -180,6 +181,7 @@ CollapsibleEffectView::CollapsibleEffectView(const std::shared_ptr<EffectItemMod
m_view
->
setVisible
(
false
);
}
m_menu
->
addAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"document-save"
)),
i18n
(
"Save Effect"
),
this
,
SLOT
(
slotSaveEffect
()));
m_menu
->
addAction
(
QIcon
::
fromTheme
(
QStringLiteral
(
"document-save-all"
)),
i18n
(
"Save Effect Stack"
),
this
,
SIGNAL
(
saveStack
()));
if
(
!
m_regionEffect
)
{
/*if (m_info.groupIndex == -1) {
m_menu->addAction(m_groupAction);
...
...
@@ -478,7 +480,6 @@ void CollapsibleEffectView::slotSaveEffect()
QDomElement
effectprops
=
effect
.
firstChildElement
(
QStringLiteral
(
"properties"
));
effectprops
.
setAttribute
(
QStringLiteral
(
"id"
),
name
);
effectprops
.
setAttribute
(
QStringLiteral
(
"type"
),
QStringLiteral
(
"custom"
));
QFile
file
(
dir
.
absoluteFilePath
(
name
+
QStringLiteral
(
".xml"
)));
if
(
file
.
open
(
QFile
::
WriteOnly
|
QFile
::
Truncate
))
{
QTextStream
out
(
&
file
);
...
...
@@ -488,6 +489,36 @@ void CollapsibleEffectView::slotSaveEffect()
emit
reloadEffect
(
dir
.
absoluteFilePath
(
name
+
QStringLiteral
(
".xml"
)));
}
QDomDocument
CollapsibleEffectView
::
toXml
()
const
{
QDomDocument
doc
;
// Get base effect xml
QString
effectId
=
m_model
->
getAssetId
();
// Adjust param values
QVector
<
QPair
<
QString
,
QVariant
>>
currentValues
=
m_model
->
getAllParameters
();
QMap
<
QString
,
QString
>
values
;
QDomElement
effect
=
doc
.
createElement
(
QStringLiteral
(
"effect"
));
doc
.
appendChild
(
effect
);
effect
.
setAttribute
(
QStringLiteral
(
"id"
),
effectId
);
QLocale
locale
;
locale
.
setNumberOptions
(
QLocale
::
OmitGroupSeparator
);
for
(
const
auto
&
param
:
currentValues
)
{
QDomElement
xmlParam
=
doc
.
createElement
(
QStringLiteral
(
"property"
));
effect
.
appendChild
(
xmlParam
);
xmlParam
.
setAttribute
(
QStringLiteral
(
"name"
),
param
.
first
);
QString
value
;
if
(
param
.
second
.
type
()
==
QVariant
::
Double
)
{
value
=
locale
.
toString
(
param
.
second
.
toDouble
());
}
else
{
value
=
param
.
second
.
toString
();
}
QDomText
val
=
doc
.
createTextNode
(
value
);
xmlParam
.
appendChild
(
val
);
}
return
doc
;
}
void
CollapsibleEffectView
::
slotResetEffect
()
{
m_view
->
resetValues
();
...
...
src/effects/effectstack/view/collapsibleeffectview.hpp
View file @
689e191a
...
...
@@ -82,6 +82,8 @@ public:
void
setActiveKeyframe
(
int
kf
);
/** @brief Returns true if effect can be moved (false for speed effect). */
bool
isMovable
()
const
;
/** @brief Returns the effect in xml format for saving. */
QDomDocument
toXml
()
const
;
public
slots
:
void
slotSyncEffectsPos
(
int
pos
);
...
...
@@ -165,6 +167,8 @@ signals:
void
startDrag
(
QPixmap
,
std
::
shared_ptr
<
EffectItemModel
>
effectModel
);
void
activateEffect
(
std
::
shared_ptr
<
EffectItemModel
>
effectModel
);
void
refresh
();
/** @brief Requests saving the full effect stack. */
void
saveStack
();
};
#endif
src/effects/effectstack/view/effectstackview.cpp
View file @
689e191a
...
...
@@ -39,7 +39,12 @@
#include
<QScrollBar>
#include
<QTreeView>
#include
<QVBoxLayout>
#include
<QInputDialog>
#include
<QDir>
#include
<KMessageBox>
#include
<utility>
WidgetDelegate
::
WidgetDelegate
(
QObject
*
parent
)
:
QStyledItemDelegate
(
parent
)
{
...
...
@@ -230,6 +235,7 @@ void EffectStackView::loadEffects()
connect
(
view
,
&
CollapsibleEffectView
::
reloadEffect
,
this
,
&
EffectStackView
::
reloadEffect
);
connect
(
view
,
&
CollapsibleEffectView
::
switchHeight
,
this
,
&
EffectStackView
::
slotAdjustDelegate
,
Qt
::
DirectConnection
);
connect
(
view
,
&
CollapsibleEffectView
::
startDrag
,
this
,
&
EffectStackView
::
slotStartDrag
);
connect
(
view
,
&
CollapsibleEffectView
::
saveStack
,
this
,
&
EffectStackView
::
slotSaveStack
);
connect
(
view
,
&
CollapsibleEffectView
::
createGroup
,
m_model
.
get
(),
&
EffectStackModel
::
slotCreateGroup
);
connect
(
view
,
&
CollapsibleEffectView
::
activateEffect
,
this
,
&
EffectStackView
::
slotActivateEffect
);
connect
(
this
,
&
EffectStackView
::
blockWheenEvent
,
view
,
&
CollapsibleEffectView
::
blockWheenEvent
);
...
...
@@ -433,6 +439,43 @@ void EffectStackView::doActivateEffect(int row, QModelIndex activeIx, bool force
}
}
void
EffectStackView
::
slotSaveStack
()
{
QString
name
=
QInputDialog
::
getText
(
this
,
i18n
(
"Save Effect Stack"
),
i18n
(
"Name for saved stack: "
));
if
(
name
.
trimmed
().
isEmpty
())
{
return
;
}
QDir
dir
(
QStandardPaths
::
writableLocation
(
QStandardPaths
::
AppDataLocation
)
+
QStringLiteral
(
"/effects/"
));
if
(
!
dir
.
exists
())
{
dir
.
mkpath
(
QStringLiteral
(
"."
));
}
if
(
dir
.
exists
(
name
+
QStringLiteral
(
".xml"
)))
{
if
(
KMessageBox
::
questionYesNo
(
this
,
i18n
(
"File %1 already exists.
\n
Do you want to overwrite it?"
,
name
+
QStringLiteral
(
".xml"
)))
==
KMessageBox
::
No
)
{
return
;
}
}
QDomDocument
doc
;
QDomElement
effect
=
doc
.
createElement
(
QStringLiteral
(
"effectgroup"
));
effect
.
setAttribute
(
QStringLiteral
(
"id"
),
name
);
effect
.
setAttribute
(
QStringLiteral
(
"parentIn"
),
pCore
->
getItemIn
(
m_model
->
getOwnerId
()));
doc
.
appendChild
(
effect
);
for
(
int
i
=
0
;
i
<=
m_model
->
rowCount
();
++
i
)
{
CollapsibleEffectView
*
w
=
static_cast
<
CollapsibleEffectView
*>
(
m_effectsTree
->
indexWidget
(
m_model
->
index
(
i
,
0
,
QModelIndex
())));
if
(
w
)
{
effect
.
appendChild
(
doc
.
importNode
(
w
->
toXml
().
documentElement
(),
true
));
}
}
QFile
file
(
dir
.
absoluteFilePath
(
name
+
QStringLiteral
(
".xml"
)));
if
(
file
.
open
(
QFile
::
WriteOnly
|
QFile
::
Truncate
))
{
QTextStream
out
(
&
file
);
out
<<
doc
.
toString
();
}
file
.
close
();
reloadEffect
(
dir
.
absoluteFilePath
(
name
+
QStringLiteral
(
".xml"
)));
}
/*
void EffectStackView::switchBuiltStack(bool show)
{
...
...
src/effects/effectstack/view/effectstackview.hpp
View file @
689e191a
...
...
@@ -105,6 +105,9 @@ private slots:
void
loadEffects
();
void
updateTreeHeight
();
void
doActivateEffect
(
int
row
,
QModelIndex
ix
,
bool
force
=
false
);
/** @brief Save current effect stack
*/
void
slotSaveStack
();
// void switchBuiltStack(bool show);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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