diff --git a/data/effects/CMakeLists.txt b/data/effects/CMakeLists.txt
index b90cc4180..764e5c6b2 100644
--- a/data/effects/CMakeLists.txt
+++ b/data/effects/CMakeLists.txt
@@ -1,138 +1,138 @@
INSTALL (FILES
audiowave.xml
audiowaveform.xml
automask.xml
audiobalance.xml
audiopan.xml
boxblur.xml
brightness.xml
channelcopy.xml
charcoal.xml
chroma_hold.xml
chroma.xml
crop.xml
dust.xml
dynamictext.xml
freeze.xml
gamma.xml
grain.xml
greyscale.xml
invert.xml
loudness.xml
luma.xml
mirror.xml
mute.xml
normalise.xml
oldfilm.xml
pan_zoom.xml
obscure.xml
region.xml
rotation.xml
rotation_keyframable.xml
scratchlines.xml
sepia.xml
sox_bass.xml
sox_gain.xml
sox_phaser.xml
sox_band.xml
sox_echo.xml
sox_flanger.xml
sox_stretch.xml
threshold.xml
volume.xml
wave.xml
fadein.xml
fadeout.xml
frei0r_alpha0ps.xml
frei0r_alphagrad.xml
frei0r_alphaspot.xml
frei0r_balanc0r.xml
frei0r_baltan.xml
frei0r_bezier_curves.xml
frei0r_brightness.xml
frei0r_cartoon.xml
frei0r_cluster.xml
frei0r_colgate.xml
frei0r_coloradj_rgb.xml
frei0r_colordistance.xml
frei0r_colortap.xml
frei0r_contrast0r.xml
frei0r_c0rners.xml
frei0r_curves.xml
frei0r_d90stairsteppingfix.xml
frei0r_defish0r.xml
frei0r_delay0r.xml
frei0r_delaygrab.xml
frei0r_distort0r.xml
frei0r_edgeglow.xml
frei0r_equaliz0r.xml
frei0r_flippo.xml
frei0r_glow.xml
frei0r_hqdn3d.xml
frei0r_hueshift0r.xml
frei0r_iirblur.xml
frei0r_keyspillm0pup.xml
frei0r_lenscorrection.xml
frei0r_letterb0xed.xml
frei0r_levels.xml
frei0r_lightgraffiti.xml
frei0r_luminance.xml
frei0r_mask0mate.xml
frei0r_medians.xml
frei0r_nervous.xml
frei0r_nosync0r.xml
frei0r_pixeliz0r.xml
frei0r_pr0be.xml
frei0r_pr0file.xml
frei0r_primaries.xml
frei0r_rgbparade.xml
frei0r_saturat0r.xml
frei0r_scale0tilt.xml
frei0r_scanline0r.xml
frei0r_select0r.xml
frei0r_sharpness.xml
frei0r_sobel.xml
frei0r_sopsat.xml
frei0r_squareblur.xml
frei0r_tehroxx0r.xml
frei0r_three_point_balance.xml
frei0r_threelay0r.xml
frei0r_threshold0r.xml
frei0r_timeout.xml
frei0r_tint0r.xml
frei0r_twolay0r.xml
frei0r_vectorscope.xml
frei0r_vertigo.xml
frei0r_vignette.xml
frei0r_facebl0r.xml
frei0r_facedetect.xml
fade_from_black.xml
fade_to_black.xml
gain.xml
lift_gamma_gain.xml
movit_blur.xml
movit_deconvolution_sharpen.xml
movit_diffusion.xml
movit_glow.xml
movit_lift_gamma_gain.xml
movit_mirror.xml
movit_opacity.xml
movit_rect.xml
movit_saturation.xml
movit_unsharp_mask.xml
movit_vignette.xml
movit_white_balance.xml
qtblend.xml
rotoscoping.xml
speed.xml
swapchannels.xml
tcolor.xml
-vignette.xml
tracker.xml
-
+vignette.xml
+vidstab.xml
DESTINATION ${DATA_INSTALL_DIR}/kdenlive/effects)
add_subdirectory(update)
add_subdirectory(avfilter)
diff --git a/data/effects/vidstab.xml b/data/effects/vidstab.xml
new file mode 100644
index 000000000..823de46be
--- /dev/null
+++ b/data/effects/vidstab.xml
@@ -0,0 +1,64 @@
+
+
+ Stabilize
+ Adjust audio volume with keyframes
+ Dan Dennedy
+
+ Accuracy
+ Accuracy of Shakiness detection
+
+
+ Shakiness
+ How shaky is the Video
+
+
+ Stepsize
+ Stepsize of Detection process minimum around
+
+
+ Min. contrast
+ Below this Contrast Field is discarded
+
+
+ Smoothing
+ Number of frames for lowpass filtering
+
+
+ Max shift
+ Max number of pixels to shift (-1 = no limit)
+
+
+ Max angle
+ Max angle to rotate (in rad)
+
+
+ Crop
+ Disabled = keep border, enabled = black background
+
+
+ Zoom
+ Additional zoom during transform
+
+
+ Optimal Zoom
+ Automatically determine optimal zoom. 1 - static zoom, 2 - adaptive zoom
+
+
+ Optimal Zoom Speed
+ Zoom per frame (used when optimal zoom = 2)
+
+
+ Sharpen
+ Sharpen transformed image
+
+
+ Show fields
+ 0 = draw nothing 1 or 2 = show fields and transforms
+
+
+ Tripod
+ Reference frame
+
+
+
+
diff --git a/src/assets/view/assetparameterview.cpp b/src/assets/view/assetparameterview.cpp
index 409816c7e..19221b4fc 100644
--- a/src/assets/view/assetparameterview.cpp
+++ b/src/assets/view/assetparameterview.cpp
@@ -1,352 +1,352 @@
/***************************************************************************
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive. See www.kdenlive.org. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) version 3 or any later version accepted by the *
* membership of KDE e.V. (or its successor approved by the membership *
* of KDE e.V.), which shall act as a proxy defined in Section 14 of *
* version 3 of the license. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see . *
***************************************************************************/
#include "assetparameterview.hpp"
#include "assets/model/assetcommand.hpp"
#include "assets/model/assetparametermodel.hpp"
#include "assets/view/widgets/abstractparamwidget.hpp"
#include "assets/view/widgets/keyframewidget.hpp"
#include "core.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
AssetParameterView::AssetParameterView(QWidget *parent)
: QWidget(parent)
{
m_lay = new QVBoxLayout(this);
m_lay->setContentsMargins(0, 0, 0, 2);
m_lay->setSpacing(0);
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
// Presets Combo
m_presetMenu = new QMenu(this);
}
void AssetParameterView::setModel(const std::shared_ptr &model, QSize frameSize, bool addSpacer)
{
unsetModel();
QMutexLocker lock(&m_lock);
m_model = model;
const QString paramTag = model->getAssetId();
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/effects/presets/"));
const QString presetFile = dir.absoluteFilePath(QString("%1.json").arg(paramTag));
connect(this, &AssetParameterView::updatePresets, [this, presetFile](const QString &presetName) {
m_presetMenu->clear();
m_presetGroup.reset(new QActionGroup(this));
m_presetGroup->setExclusive(true);
m_presetMenu->addAction(QIcon::fromTheme(QStringLiteral("view-refresh")), i18n("Reset Effect"), this, SLOT(resetValues()));
// Save preset
m_presetMenu->addAction(QIcon::fromTheme(QStringLiteral("document-save-as-template")), i18n("Save preset"), this, SLOT(slotSavePreset()));
m_presetMenu->addAction(QIcon::fromTheme(QStringLiteral("document-save-as-template")), i18n("Update current preset"), this, SLOT(slotUpdatePreset()));
m_presetMenu->addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("Delete preset"), this, SLOT(slotDeletePreset()));
m_presetMenu->addSeparator();
QStringList presets = m_model->getPresetList(presetFile);
for (const QString &pName : presets) {
QAction *ac = m_presetMenu->addAction(pName, this, SLOT(slotLoadPreset()));
m_presetGroup->addAction(ac);
ac->setData(pName);
ac->setCheckable(true);
if (pName == presetName) {
ac->setChecked(true);
}
}
});
emit updatePresets();
connect(m_model.get(), &AssetParameterModel::dataChanged, this, &AssetParameterView::refresh);
if (paramTag.endsWith(QStringLiteral("lift_gamma_gain"))) {
// Special case, the colorwheel widget manages several parameters
QModelIndex index = model->index(0, 0);
auto w = AbstractParamWidget::construct(model, index, frameSize, this);
connect(w, &AbstractParamWidget::valuesChanged, this, &AssetParameterView::commitMultipleChanges);
connect(w, &AbstractParamWidget::valueChanged, this, &AssetParameterView::commitChanges);
m_lay->addWidget(w);
m_widgets.push_back(w);
} else {
for (int i = 0; i < model->rowCount(); ++i) {
QModelIndex index = model->index(i, 0);
auto type = model->data(index, AssetParameterModel::TypeRole).value();
if (m_mainKeyframeWidget &&
(type == ParamType::Geometry || type == ParamType::Animated || type == ParamType::RestrictedAnim || type == ParamType::KeyframeParam)) {
// Keyframe widget can have some extra params that shouldn't build a new widget
qDebug() << "// FOUND ADDED PARAM";
m_mainKeyframeWidget->addParameter(index);
} else {
auto w = AbstractParamWidget::construct(model, index, frameSize, this);
connect(this, &AssetParameterView::initKeyframeView, w, &AbstractParamWidget::slotInitMonitor);
if (type == ParamType::KeyframeParam || type == ParamType::AnimatedRect || type == ParamType::Roto_spline) {
m_mainKeyframeWidget = static_cast(w);
}
connect(w, &AbstractParamWidget::valueChanged, this, &AssetParameterView::commitChanges);
connect(w, &AbstractParamWidget::seekToPos, this, &AssetParameterView::seekToPos);
m_lay->addWidget(w);
m_widgets.push_back(w);
}
}
}
if (addSpacer) {
m_lay->addStretch();
}
}
QVector> AssetParameterView::getDefaultValues() const
{
QLocale locale;
QVector> values;
for (int i = 0; i < m_model->rowCount(); ++i) {
QModelIndex index = m_model->index(i, 0);
QString name = m_model->data(index, AssetParameterModel::NameRole).toString();
auto type = m_model->data(index, AssetParameterModel::TypeRole).value();
QVariant defaultValue = m_model->data(index, AssetParameterModel::DefaultRole);
if (type == ParamType::KeyframeParam || type == ParamType::AnimatedRect) {
QString val = type == ParamType::KeyframeParam ? locale.toString(defaultValue.toDouble()) : defaultValue.toString();
if (!val.contains(QLatin1Char('='))) {
val.prepend(QStringLiteral("%1=").arg(m_model->data(index, AssetParameterModel::ParentInRole).toInt()));
defaultValue = QVariant(val);
}
}
values.append({name, defaultValue});
}
return values;
}
void AssetParameterView::resetValues()
{
const QVector> values = getDefaultValues();
auto *command = new AssetUpdateCommand(m_model, values);
pCore->pushUndo(command);
// Unselect preset if any
QAction *ac = m_presetGroup->checkedAction();
if (ac) {
ac->setChecked(false);;
}
}
void AssetParameterView::commitChanges(const QModelIndex &index, const QString &value, bool storeUndo)
{
// Warning: please note that some widgets (for example keyframes) do NOT send the valueChanged signal and do modifications on their own
auto *command = new AssetCommand(m_model, index, value);
- if (storeUndo) {
+ if (storeUndo && m_model->getOwnerId().second != -1) {
pCore->pushUndo(command);
} else {
command->redo();
delete command;
}
}
void AssetParameterView::commitMultipleChanges(const QList indexes, const QStringList &values, bool storeUndo)
{
// Warning: please note that some widgets (for example keyframes) do NOT send the valueChanged signal and do modifications on their own
auto *command = new AssetMultiCommand(m_model, indexes, values);
if (storeUndo) {
pCore->pushUndo(command);
} else {
command->redo();
delete command;
}
}
void AssetParameterView::unsetModel()
{
QMutexLocker lock(&m_lock);
if (m_model) {
// if a model is already there, we have to disconnect signals first
disconnect(m_model.get(), &AssetParameterModel::dataChanged, this, &AssetParameterView::refresh);
}
m_mainKeyframeWidget = nullptr;
// clear layout
m_widgets.clear();
QLayoutItem *child;
while ((child = m_lay->takeAt(0)) != nullptr) {
if (child->layout()) {
QLayoutItem *subchild;
while ((subchild = child->layout()->takeAt(0)) != nullptr) {
delete subchild->widget();
delete subchild->spacerItem();
}
}
delete child->widget();
delete child->spacerItem();
}
// Release ownership of smart pointer
m_model.reset();
}
void AssetParameterView::refresh(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles)
{
QMutexLocker lock(&m_lock);
if (m_widgets.size() == 0) {
// no visible param for this asset, abort
return;
}
Q_UNUSED(roles);
// We are expecting indexes that are children of the root index, which is "invalid"
Q_ASSERT(!topLeft.parent().isValid());
// We make sure the range is valid
if (m_mainKeyframeWidget) {
m_mainKeyframeWidget->slotRefresh();
} else {
auto type = m_model->data(m_model->index(topLeft.row(), 0), AssetParameterModel::TypeRole).value();
if (type == ParamType::ColorWheel) {
// Some special widgets, like colorwheel handle multiple params so we can have cases where param index row is greater than the number of widgets.
// Should be better managed
m_widgets[0]->slotRefresh();
return;
}
int max;
if (!bottomRight.isValid()) {
max = (int)m_widgets.size() - 1;
} else {
max = bottomRight.row();
}
Q_ASSERT(max < (int)m_widgets.size());
for (auto i = (size_t)topLeft.row(); i <= max; ++i) {
m_widgets[i]->slotRefresh();
}
}
}
int AssetParameterView::contentHeight() const
{
return m_lay->minimumSize().height();
}
MonitorSceneType AssetParameterView::needsMonitorEffectScene() const
{
if (m_mainKeyframeWidget) {
return m_mainKeyframeWidget->requiredScene();
}
for (int i = 0; i < m_model->rowCount(); ++i) {
QModelIndex index = m_model->index(i, 0);
auto type = m_model->data(index, AssetParameterModel::TypeRole).value();
if (type == ParamType::Geometry) {
return MonitorSceneGeometry;
}
}
return MonitorSceneDefault;
}
/*void AssetParameterView::initKeyframeView()
{
if (m_mainKeyframeWidget) {
m_mainKeyframeWidget->initMonitor();
} else {
for (int i = 0; i < m_model->rowCount(); ++i) {
QModelIndex index = m_model->index(i, 0);
auto type = m_model->data(index, AssetParameterModel::TypeRole).value();
if (type == ParamType::Geometry) {
return MonitorSceneGeometry;
}
}
}
}*/
void AssetParameterView::slotRefresh()
{
refresh(m_model->index(0, 0), m_model->index(m_model->rowCount() - 1, 0), {});
}
bool AssetParameterView::keyframesAllowed() const
{
return m_mainKeyframeWidget != nullptr;
}
bool AssetParameterView::modelHideKeyframes() const
{
return m_mainKeyframeWidget != nullptr && !m_mainKeyframeWidget->keyframesVisible();
}
void AssetParameterView::toggleKeyframes(bool enable)
{
if (m_mainKeyframeWidget) {
m_mainKeyframeWidget->showKeyframes(enable);
}
}
void AssetParameterView::slotDeletePreset()
{
QAction *ac = m_presetGroup->checkedAction();
if (!ac) {
return;
}
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/effects/presets/"));
if (!dir.exists()) {
dir.mkpath(QStringLiteral("."));
}
const QString presetFile = dir.absoluteFilePath(QString("%1.json").arg(m_model->getAssetId()));
m_model->deletePreset(presetFile, ac->data().toString());
emit updatePresets();
}
void AssetParameterView::slotUpdatePreset()
{
QAction *ac = m_presetGroup->checkedAction();
if (!ac) {
return;
}
slotSavePreset(ac->data().toString());
}
void AssetParameterView::slotSavePreset(QString presetName)
{
if (presetName.isEmpty()) {
bool ok;
presetName = QInputDialog::getText(this, i18n("Enter preset name"), i18n("Enter the name of this preset"), QLineEdit::Normal, QString(), &ok);
if (!ok) return;
}
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/effects/presets/"));
if (!dir.exists()) {
dir.mkpath(QStringLiteral("."));
}
const QString presetFile = dir.absoluteFilePath(QString("%1.json").arg(m_model->getAssetId()));
m_model->savePreset(presetFile, presetName);
emit updatePresets(presetName);
}
void AssetParameterView::slotLoadPreset()
{
auto *action = qobject_cast(sender());
if (!action) {
return;
}
const QString presetName = action->data().toString();
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/effects/presets/"));
const QString presetFile = dir.absoluteFilePath(QString("%1.json").arg(m_model->getAssetId()));
const QVector> params = m_model->loadPreset(presetFile, presetName);
auto *command = new AssetUpdateCommand(m_model, params);
pCore->pushUndo(command);
}
QMenu *AssetParameterView::presetMenu()
{
return m_presetMenu;
}
diff --git a/src/project/clipstabilize.cpp b/src/project/clipstabilize.cpp
index f37c348c8..dbf730fa0 100644
--- a/src/project/clipstabilize.cpp
+++ b/src/project/clipstabilize.cpp
@@ -1,234 +1,155 @@
/***************************************************************************
* Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
* Copyright (C) 2011 by Marco Gittler (marco@gitma.de) *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#include "clipstabilize.h"
#include "bin/projectclip.h"
#include "bin/projectitemmodel.h"
#include "core.h"
#include "widgets/doublewidget.h"
#include "widgets/positionwidget.h"
+#include "assets/view/assetparameterview.hpp"
+#include "assets/model/assetparametermodel.hpp"
+#include "effects/effectsrepository.hpp"
#include "kdenlivesettings.h"
#include
#include
#include
ClipStabilize::ClipStabilize(const std::vector &binIds, QString filterName, int out, QWidget *parent)
: QDialog(parent)
, m_filtername(std::move(filterName))
, m_binIds(binIds)
, m_vbox(nullptr)
+ , m_assetModel(nullptr)
{
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
setupUi(this);
setWindowTitle(i18n("Stabilize Clip"));
auto_add->setText(i18np("Add clip to project", "Add clips to project", m_binIds.size()));
auto_add->setChecked(KdenliveSettings::add_new_clip());
// QString stylesheet = EffectStackView2::getStyleSheet();
// setStyleSheet(stylesheet);
Q_ASSERT(binIds.size() > 0);
auto firstBinClip = pCore->projectItemModel()->getClipByBinID(m_binIds.front());
auto firstUrl = firstBinClip->url();
if (m_binIds.size() == 1) {
QString newFile = firstUrl;
newFile.append(QStringLiteral(".mlt"));
dest_url->setMode(KFile::File);
dest_url->setUrl(QUrl(newFile));
} else {
label_dest->setText(i18n("Destination folder"));
dest_url->setMode(KFile::Directory | KFile::ExistingOnly);
dest_url->setUrl(QUrl(firstUrl).adjusted(QUrl::RemoveFilename));
}
-
+ m_vbox = new QVBoxLayout(optionsbox);
if (m_filtername == QLatin1String("vidstab") || m_filtername == QLatin1String("videostab2")) {
- m_fixedParams[QStringLiteral("algo")] = QStringLiteral("1");
- m_fixedParams[QStringLiteral("relative")] = QStringLiteral("1");
- fillParameters(
- QStringList() << QStringLiteral("accuracy,type,int,value,8,min,1,max,10,tooltip,Accuracy of Shakiness detection")
- << QStringLiteral("shakiness,type,int,value,4,min,1,max,10,tooltip,How shaky is the Video")
- << QStringLiteral("stepsize,type,int,value,6,min,0,max,100,tooltip,Stepsize of Detection process minimum around")
- << QStringLiteral("mincontrast,type,double,value,0.3,min,0,max,1,factor,1,decimals,2,tooltip,Below this Contrast Field is discarded")
- << QStringLiteral("smoothing,type,int,value,10,min,0,max,100,tooltip,number of frames for lowpass filtering")
- << QStringLiteral("maxshift,type,int,value,-1,min,-1,max,1000,tooltip,max number of pixels to shift")
- << QStringLiteral("maxangle,type,double,value,-1,min,-1,max,3.14,decimals,2,tooltip,max angle to rotate (in rad)")
- << QStringLiteral("crop,type,bool,value,0,min,0,max,1,tooltip,0 = keep border 1 = black background")
- << QStringLiteral("zoom,type,int,value,0,min,-500,max,500,tooltip,additional zoom during transform")
- << QStringLiteral("optzoom,type,bool,value,1,min,0,max,1,tooltip,use optimal zoom (calculated from transforms)")
- << QStringLiteral("sharpen,type,double,value,0.8,min,0,max,1,decimals,1,tooltip,sharpen transformed image")
- << QStringLiteral("tripod,type,position,value,0,min,0,max,100000,tooltip,reference frame"));
-
- } else if (m_filtername == QLatin1String("videostab")) {
- fillParameters(QStringList(QStringLiteral("shutterangle,type,int,value,0,min,0,max,180,tooltip,Angle that Images could be maximum rotated")));
+ AssetParameterView *view = new AssetParameterView(this);
+ std::unique_ptr asset = EffectsRepository::get()->getEffect(m_filtername);
+ auto prop = std::make_unique(asset->get_properties());
+ QDomElement xml = EffectsRepository::get()->getXml(m_filtername);
+ m_assetModel.reset(new AssetParameterModel(std::move(prop), xml, m_filtername, {ObjectType::NoItem, -1}));
+ view->setModel(m_assetModel, QSize(1920, 1080));
+ m_vbox->addWidget(view);
}
connect(buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &ClipStabilize::slotValidate);
-
- m_vbox = new QVBoxLayout(optionsbox);
- QHashIterator> hi(m_ui_params);
- m_tc.setFormat(KdenliveSettings::project_fps());
- while (hi.hasNext()) {
- hi.next();
- QHash val = hi.value();
- if (val[QStringLiteral("type")] == QLatin1String("int") || val[QStringLiteral("type")] == QLatin1String("double")) {
- DoubleWidget *dbl = new DoubleWidget(hi.key() /*name*/, val[QStringLiteral("value")].toDouble(), val[QStringLiteral("min")].toDouble(),
- val[QStringLiteral("max")].toDouble(), val[QStringLiteral("value")].toDouble(), 1,
- /*default*/
- QString(), /*comment*/
- 0 /*id*/, QString(), /*suffix*/
- val[QStringLiteral("decimals")] != QString() ? val[QStringLiteral("decimals")].toInt() : 0, this);
- dbl->setObjectName(hi.key());
- dbl->setToolTip(val[QStringLiteral("tooltip")]);
- connect(dbl, &DoubleWidget::valueChanged, this, &ClipStabilize::slotUpdateParams);
- m_vbox->addWidget(dbl);
- } else if (val[QStringLiteral("type")] == QLatin1String("bool")) {
- auto *ch = new QCheckBox(hi.key(), this);
- ch->setCheckState(val[QStringLiteral("value")] == QLatin1String("0") ? Qt::Unchecked : Qt::Checked);
- ch->setObjectName(hi.key());
- connect(ch, &QCheckBox::stateChanged, this, &ClipStabilize::slotUpdateParams);
- ch->setToolTip(val[QStringLiteral("tooltip")]);
- m_vbox->addWidget(ch);
- } else if (val[QStringLiteral("type")] == QLatin1String("position")) {
- PositionWidget *posedit = new PositionWidget(hi.key(), 0, 0, out, m_tc, QString(), this);
- posedit->setToolTip(val[QStringLiteral("tooltip")]);
- posedit->setObjectName(hi.key());
- m_vbox->addWidget(posedit);
- connect(posedit, &PositionWidget::valueChanged, this, &ClipStabilize::slotUpdateParams);
- }
- }
adjustSize();
}
ClipStabilize::~ClipStabilize()
{
/*if (m_stabilizeProcess.state() != QProcess::NotRunning) {
m_stabilizeProcess.close();
}*/
KdenliveSettings::setAdd_new_clip(auto_add->isChecked());
}
std::unordered_map ClipStabilize::filterParams() const
{
+ QVector> result = m_assetModel->getAllParameters();
std::unordered_map params;
+ QLocale locale;
- for (const auto &it : m_fixedParams) {
- params[it.first] = it.second;
- }
-
- QHashIterator> it(m_ui_params);
- while (it.hasNext()) {
- it.next();
- params[it.key()] = it.value().value(QStringLiteral("value"));
+ for (const auto &it : result) {
+ if (it.second.type() == QVariant::Double) {
+ params[it.first] = locale.toString(it.second.toDouble());
+ } else {
+ params[it.first] = it.second.toString();
+ }
}
return params;
}
QString ClipStabilize::filterName() const
{
return m_filtername;
}
QString ClipStabilize::destination() const
{
QString path = dest_url->url().toLocalFile();
if (m_binIds.size() > 1 && !path.endsWith(QDir::separator())) {
path.append(QDir::separator());
}
return path;
}
QString ClipStabilize::desc() const
{
return i18n("Stabilize clip");
}
-void ClipStabilize::slotUpdateParams()
-{
- for (int i = 0; i < m_vbox->count(); ++i) {
- QWidget *w = m_vbox->itemAt(i)->widget();
- QString name = w->objectName();
- if (!name.isEmpty() && m_ui_params.contains(name)) {
- if (m_ui_params[name][QStringLiteral("type")] == QLatin1String("int") || m_ui_params[name][QStringLiteral("type")] == QLatin1String("double")) {
- auto *dbl = static_cast(w);
- m_ui_params[name][QStringLiteral("value")] = QString::number((double)(dbl->getValue()));
- } else if (m_ui_params[name][QStringLiteral("type")] == QLatin1String("bool")) {
- auto *ch = (QCheckBox *)w;
- m_ui_params[name][QStringLiteral("value")] = ch->checkState() == Qt::Checked ? QStringLiteral("1") : QStringLiteral("0");
- } else if (m_ui_params[name][QStringLiteral("type")] == QLatin1String("position")) {
- auto *pos = (PositionWidget *)w;
- m_ui_params[name][QStringLiteral("value")] = QString::number(pos->getPosition());
- }
- }
- }
-}
-
bool ClipStabilize::autoAddClip() const
{
return auto_add->isChecked();
}
-void ClipStabilize::fillParameters(QStringList lst)
-{
-
- m_ui_params.clear();
- while (!lst.isEmpty()) {
- QString vallist = lst.takeFirst();
- QStringList cont = vallist.split(QLatin1Char(','));
- QString name = cont.takeFirst();
- while (!cont.isEmpty()) {
- QString valname = cont.takeFirst();
- QString val;
- if (!cont.isEmpty()) {
- val = cont.takeFirst();
- }
- m_ui_params[name][valname] = val;
- }
- }
-}
-
void ClipStabilize::slotValidate()
{
if (m_binIds.size() == 1) {
if (QFile::exists(dest_url->url().toLocalFile())) {
if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", dest_url->url().toLocalFile())) ==
KMessageBox::No) {
return;
}
}
} else {
QDir folder(dest_url->url().toLocalFile());
QStringList existingFiles;
for (const QString &binId : m_binIds) {
auto binClip = pCore->projectItemModel()->getClipByBinID(binId);
auto url = binClip->url();
if (folder.exists(url + QStringLiteral(".mlt"))) {
existingFiles.append(folder.absoluteFilePath(url + QStringLiteral(".mlt")));
}
}
if (!existingFiles.isEmpty()) {
if (KMessageBox::warningContinueCancelList(this, i18n("The stabilize job will overwrite the following files:"), existingFiles) ==
KMessageBox::Cancel) {
return;
}
}
}
accept();
}
diff --git a/src/project/clipstabilize.h b/src/project/clipstabilize.h
index a4e5331e7..8bcd0b92d 100644
--- a/src/project/clipstabilize.h
+++ b/src/project/clipstabilize.h
@@ -1,65 +1,64 @@
/***************************************************************************
* Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
* Copyright (C) 2011 by Marco Gittler (marco@gitma.de) *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#ifndef CLIPSTABILIZE_H
#define CLIPSTABILIZE_H
#include "definitions.h"
#include "timecode.h"
#include "ui_clipstabilize_ui.h"
#include
#include
+class AssetParameterModel;
+
class ClipStabilize : public QDialog, public Ui::ClipStabilize_UI
{
Q_OBJECT
public:
explicit ClipStabilize(const std::vector &binIds, QString filterName, int out, QWidget *parent = nullptr);
~ClipStabilize() override;
/** @brief Should the generated clip be added to current project. */
bool autoAddClip() const;
/** @brief Return the filter parameters, filter name as value of "filter" entry. */
std::unordered_map filterParams() const;
/** @brief Return the destination file or folder. */
QString destination() const;
/** @brief Return the job description. */
QString desc() const;
/* Return the name of the actual mlt filter used */
QString filterName() const;
private slots:
- void slotUpdateParams();
void slotValidate();
private:
QString m_filtername;
std::vector m_binIds;
- QHash> m_ui_params;
QVBoxLayout *m_vbox;
- void fillParameters(QStringList);
- std::unordered_map m_fixedParams;
Timecode m_tc;
+ std::shared_ptrm_assetModel;
signals:
void addClip(const QUrl &url);
};
#endif