Effect can now be edited in effect stack

parent 41bb542c
......@@ -51,10 +51,11 @@ AssetPanel::AssetPanel(QWidget *parent)
updatePalette();
}
void AssetPanel::showTransition(std::shared_ptr<AssetParameterModel> transitionModel)
void AssetPanel::showTransition(int tid, std::shared_ptr<AssetParameterModel> transitionModel)
{
clear();
QString transitionId = transitionModel->getAssetId();
transitionModel->setParentId(tid);
QString transitionName = TransitionsRepository::get()->getName(transitionId);
m_assetTitle->setText(i18n("Properties of transition %1", transitionName));
m_transitionWidget->setVisible(true);
......
......@@ -44,7 +44,7 @@ public:
AssetPanel(QWidget *parent);
/* @brief Shows the parameters of the given transition model */
void showTransition(std::shared_ptr<AssetParameterModel> transition_model);
void showTransition(int tid, std::shared_ptr<AssetParameterModel> transition_model);
/* @brief Shows the parameters of the given effect stack model */
void showEffectStack(int cid, std::shared_ptr<EffectStackModel> effectsModel);
......
......@@ -22,19 +22,25 @@
#include "assetcommand.hpp"
#include "transitions/transitionsrepository.hpp"
#include "effects/effectsrepository.hpp"
#include <memory>
AssetCommand::AssetCommand(std::shared_ptr<AssetParameterModel> &model, const QString &assetId, const QModelIndex &index, const QString &value, QUndoCommand *parent)
AssetCommand::AssetCommand(std::shared_ptr<AssetParameterModel> model, const QModelIndex &index, const QString &value, QUndoCommand *parent)
: QUndoCommand(parent)
, m_model(std::move(model))
, m_model(model)
, m_index(index)
, m_value(value)
, m_updateView(false)
, m_stamp(QTime::currentTime())
{
m_name = m_model->data(index, AssetParameterModel::NameRole).toString();
setText(i18n("Edit %1", TransitionsRepository::get()->getName(assetId)));
const QString id = model->getAssetId();
if (EffectsRepository::get()->exists(id)) {
setText(i18n("Edit %1", EffectsRepository::get()->getName(id)));
} else if (TransitionsRepository::get()->exists(id)) {
setText(i18n("Edit %1", TransitionsRepository::get()->getName(id)));
}
m_oldValue = m_model->data(index, AssetParameterModel::ValueRole).toString();
}
......
......@@ -29,7 +29,7 @@
class AssetCommand : public QUndoCommand
{
public:
AssetCommand(std::shared_ptr<AssetParameterModel> &model, const QString &assetId, const QModelIndex &index, const QString &value, QUndoCommand *parent = nullptr);
AssetCommand(std::shared_ptr<AssetParameterModel> model, const QModelIndex &index, const QString &value, QUndoCommand *parent = nullptr);
void undo() override;
void redo() override;
int id() const override;
......
......@@ -20,7 +20,6 @@
***************************************************************************/
#include "assetparametermodel.hpp"
#include "assetcommand.hpp"
#include "core.h"
#include "klocalizedstring.h"
#include "kdenlivesettings.h"
......@@ -32,9 +31,10 @@
AssetParameterModel::AssetParameterModel(Mlt::Properties *asset, const QDomElement &assetXml, const QString &assetId, Kdenlive::MonitorId monitor,
QObject *parent)
: QAbstractListModel(parent)
, monitorId(monitor)
, m_xml(assetXml)
, m_assetId(assetId)
, monitorId(monitor)
, m_parentId(-1)
, m_asset(asset)
{
Q_ASSERT(asset->is_valid());
......@@ -122,8 +122,9 @@ void AssetParameterModel::setParameter(const QString &name, const QString &value
}
}
// refresh monitor after asset change
QSize range(m_asset->get_int("in"), m_asset->get_int("out"));
pCore->refreshProjectRange(range);
if (m_parentId >= 0) {
pCore->refreshProjectItem(m_parentId);
}
}
AssetParameterModel::~AssetParameterModel() = default;
......@@ -331,11 +332,13 @@ void AssetParameterModel::setParameters(const QVector<QPair<QString, QVariant>>
}
}
void AssetParameterModel::commitChanges(const QModelIndex &index, const QString &value)
void AssetParameterModel::setParentId(int id)
{
std::shared_ptr<AssetParameterModel> ptr = shared_from_this();
AssetCommand *command = new AssetCommand(ptr, m_assetId, index, value);
pCore->pushUndo(command);
m_parentId = id;
}
int AssetParameterModel::parentId() const
{
return m_parentId;
}
......@@ -105,18 +105,14 @@ public:
*/
void setParameters(const QVector<QPair<QString, QVariant>> &params);
/* @brief Apply a change of parameter sent by the view
@param index is the index corresponding to the modified param
@param value is the new value of the parameter
*/
void commitChanges(const QModelIndex &index, const QString &value);
/* Which monitor is attached to this asset (clip/project)
*/
Kdenlive::MonitorId monitorId;
QVariant data(const QModelIndex &index, int role) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
void setParentId(int id);
int parentId() const;
protected:
/* @brief Helper function to retrieve the type of a parameter given the string corresponding to it*/
......@@ -140,6 +136,7 @@ protected:
QDomElement m_xml;
QString m_assetId;
int m_parentId;
std::unordered_map<QString, ParamRow> m_params; // Store all parameters by name
std::unordered_map<QString, QVariant> m_fixedParams; // We store values of fixed parameters aside
QVector<QString> m_rows; // We store the params name in order of parsing. The order is important (cf some effects like sox)
......
......@@ -22,7 +22,9 @@
#include "assetparameterview.hpp"
#include "assets/model/assetparametermodel.hpp"
#include "assets/model/assetcommand.hpp"
#include "assets/view/widgets/abstractparamwidget.hpp"
#include "core.h"
#include <QDebug>
#include <QFontDatabase>
......@@ -49,12 +51,18 @@ void AssetParameterView::setModel(const std::shared_ptr<AssetParameterModel> &mo
for (int i = 0; i < model->rowCount(); ++i) {
QModelIndex index = model->index(i, 0);
auto w = AbstractParamWidget::construct(model, index, this);
connect(w, &AbstractParamWidget::valueChanged, model.get(), &AssetParameterModel::commitChanges);
connect(w, &AbstractParamWidget::valueChanged, this, &AssetParameterView::commitChanges);
m_lay->addWidget(w);
m_widgets.push_back(w);
}
}
void AssetParameterView::commitChanges(const QModelIndex &index, const QString &value)
{
AssetCommand *command = new AssetCommand(m_model, index, value);
pCore->pushUndo(command);
}
void AssetParameterView::unsetModel()
{
if (m_model) {
......
......@@ -59,6 +59,13 @@ protected:
QVBoxLayout *m_lay;
std::shared_ptr<AssetParameterModel> m_model;
std::vector<AbstractParamWidget *> m_widgets;
private slots:
/** @brief Apply a change of parameter sent by the view
@param index is the index corresponding to the modified param
@param value is the new value of the parameter
*/
void commitChanges(const QModelIndex &index, const QString &value);
};
#endif
......@@ -307,6 +307,11 @@ void Core::refreshProjectRange(QSize range)
m_monitorManager->refreshProjectRange(range);
}
void Core::refreshProjectItem(int itemId)
{
m_projectManager->refreshItem(itemId);
}
KdenliveDoc *Core::currentDoc()
{
return m_projectManager->current();
......
......@@ -115,6 +115,8 @@ public:
void requestMonitorRefresh();
/** @brief Request project monitor refresh if current position is inside range*/
void refreshProjectRange(QSize range);
/** @brief Request project monitor refresh if referenced item is under cursor */
void refreshProjectItem(int itemId);
/** @brief Returns a reference to a monitor (clip or project monitor) */
Monitor *getMonitor(int id);
......
......@@ -38,10 +38,11 @@ std::shared_ptr<EffectStackModel> EffectStackModel::construct(std::weak_ptr<Mlt:
return self;
}
void EffectStackModel::appendEffect(const QString &effectId)
void EffectStackModel::appendEffect(const QString &effectId, int cid)
{
auto effect = EffectItemModel::construct(effectId, shared_from_this(), rootItem);
effect->setEffectStackEnabled(m_effectStackEnabled);
effect->setParentId(cid);
effect->plant(m_service);
rootItem->appendChild(effect);
QModelIndex ix = getIndexFromItem(effect);
......
......@@ -44,7 +44,7 @@ protected:
public:
/* @brief Add an effect at the bottom of the stack */
void appendEffect(const QString &effectId);
void appendEffect(const QString &effectId, int cid);
/* @brief This function change the global (timeline-wise) enabled state of the effects
*/
......
......@@ -25,6 +25,9 @@
#include "kdenlivesettings.h"
#include "mltcontroller/effectscontroller.h"
#include "utils/KoIconUtils.h"
#include "effects/effectstack/model/effectitemmodel.hpp"
#include "effects/effectsrepository.hpp"
#include "assets/view/assetparameterview.hpp"
#include "kdenlive_debug.h"
#include <QDialog>
......@@ -46,11 +49,8 @@
#include <KMessageBox>
#include <KRecentDirs>
#include <klocalizedstring.h>
#include <assets/model/assetparametermodel.hpp>
#include <effects/effectsrepository.hpp>
#include <assets/view/assetparameterview.hpp>
CollapsibleEffectView::CollapsibleEffectView(std::shared_ptr<AssetParameterModel> effectModel, QWidget *parent)
CollapsibleEffectView::CollapsibleEffectView(std::shared_ptr<EffectItemModel> effectModel, QImage icon, QWidget *parent)
: AbstractCollapsibleWidget(parent)
/* , m_effect(effect)
, m_itemInfo(info)
......@@ -122,29 +122,8 @@ CollapsibleEffectView::CollapsibleEffectView(std::shared_ptr<AssetParameterModel
effectName.append(':' + QUrl(EffectsList::parameter(m_effect, QStringLiteral("resource"))).fileName());
}
// Create color thumb
QPixmap pix(iconSize);
QColor col(m_effect.attribute(QStringLiteral("effectcolor")));
QFont ft = font();
ft.setBold(true);
bool isAudio = m_effect.attribute(QStringLiteral("type")) == QLatin1String("audio");
if (isAudio) {
pix.fill(Qt::transparent);
} else {
pix.fill(col);
}
QPainter p(&pix);
if (isAudio) {
p.setPen(Qt::NoPen);
p.setBrush(col);
p.drawEllipse(pix.rect());
p.setPen(QPen());
}
p.setFont(ft);
p.drawText(pix.rect(), Qt::AlignCenter, effectName.at(0));
p.end();
m_iconPix = pix;
m_colorIcon->setPixmap(pix);
// Color thumb
m_colorIcon->setPixmap(QPixmap::fromImage(icon));
title->setText(effectName);
if (!m_regionEffect) {
......@@ -154,7 +133,7 @@ CollapsibleEffectView::CollapsibleEffectView(std::shared_ptr<AssetParameterModel
m_menu->addAction(KoIconUtils::themedIcon(QStringLiteral("folder-new")), i18n("Create Region"), this, SLOT(slotCreateRegion()));
}
m_view = new AssetParameterView(this);
m_view->setModel(effectModel);
m_view->setModel(std::static_pointer_cast<AssetParameterModel>(effectModel));
QVBoxLayout *lay = new QVBoxLayout(widgetFrame);
lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0);
......@@ -346,6 +325,7 @@ void CollapsibleEffectView::mouseReleaseEvent(QMouseEvent *event)
void CollapsibleEffectView::slotDisable(bool disable, bool emitInfo)
{
title->setEnabled(!disable);
m_colorIcon->setEnabled(!disable);
m_enabledButton->setActive(disable);
m_effect.setAttribute(QStringLiteral("disable"), disable ? 1 : 0);
if (!disable || KdenliveSettings::disable_effect_parameters()) {
......
......@@ -32,7 +32,7 @@
class QLabel;
class KDualAction;
class AssetParameterModel;
class EffectItemModel;
class AssetParameterView;
/**)
......@@ -46,7 +46,7 @@ class CollapsibleEffectView : public AbstractCollapsibleWidget
Q_OBJECT
public:
explicit CollapsibleEffectView(std::shared_ptr<AssetParameterModel> effectModel, QWidget *parent = nullptr);
explicit CollapsibleEffectView(std::shared_ptr<EffectItemModel> effectModel, QImage icon, QWidget *parent = nullptr);
~CollapsibleEffectView();
QLabel *title;
......
......@@ -24,11 +24,13 @@
#include "effects/effectstack/model/effectstackmodel.hpp"
#include "effects/effectstack/model/effectitemmodel.hpp"
#include "assets/view/assetparameterview.hpp"
#include "assets/assetlist/view/qmltypes/asseticonprovider.hpp"
#include <QVBoxLayout>
#include <QFontDatabase>
EffectStackView::EffectStackView(QWidget *parent) : QWidget(parent)
, m_thumbnailer(new AssetIconProvider(true))
{
m_lay = new QVBoxLayout(this);
m_lay->setContentsMargins(0, 0, 0, 0);
......@@ -36,13 +38,21 @@ EffectStackView::EffectStackView(QWidget *parent) : QWidget(parent)
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
}
EffectStackView::~EffectStackView()
{
delete m_thumbnailer;
}
void EffectStackView::setModel(std::shared_ptr<EffectStackModel>model)
{
unsetModel();
m_model = model;
int max = m_model->rowCount();
for (int i = 0; i < max; i++) {
CollapsibleEffectView *view = new CollapsibleEffectView(m_model->effect(i), this);
std::shared_ptr<EffectItemModel> effectModel = m_model->effect(i);
QSize size;
QImage effectIcon = m_thumbnailer->requestImage(effectModel->getAssetId(), &size, QSize(QStyle::PM_SmallIconSize,QStyle::PM_SmallIconSize));
CollapsibleEffectView *view = new CollapsibleEffectView(effectModel, effectIcon, this);
m_lay->addWidget(view);
m_widgets.push_back(view);
}
......@@ -55,7 +65,10 @@ void EffectStackView::refresh(const QModelIndex &topLeft, const QModelIndex &bot
unsetModel(false);
int max = m_model->rowCount();
for (int i = 0; i < max; i++) {
CollapsibleEffectView *view = new CollapsibleEffectView(m_model->effect(i), this);
std::shared_ptr<EffectItemModel> effectModel = m_model->effect(i);
QSize size;
QImage effectIcon = m_thumbnailer->requestImage(effectModel->getAssetId(), &size, QSize(QStyle::PM_SmallIconSize,QStyle::PM_SmallIconSize));
CollapsibleEffectView *view = new CollapsibleEffectView(effectModel, effectIcon, this);
m_lay->addWidget(view);
m_widgets.push_back(view);
}
......
......@@ -30,6 +30,7 @@ class QVBoxLayout;
class CollapsibleEffectView;
class AssetParameterModel;
class EffectStackModel;
class AssetIconProvider;
class EffectStackView : public QWidget
{
......@@ -37,6 +38,7 @@ Q_OBJECT
public:
EffectStackView(QWidget *parent = nullptr);
virtual ~EffectStackView();
void setModel(std::shared_ptr<EffectStackModel>model);
void unsetModel(bool reset = true);
......@@ -44,6 +46,7 @@ private:
QVBoxLayout *m_lay;
std::shared_ptr<EffectStackModel> m_model;
std::vector<CollapsibleEffectView *> m_widgets;
AssetIconProvider *m_thumbnailer;
const QString getStyleSheet();
private slots:
......
......@@ -307,17 +307,10 @@ void MainWindow::init()
m_projectBinDock = addDock(i18n("Project Bin"), QStringLiteral("project_bin"), pCore->bin());
// TODO REFAC delete this
auto trans = TransitionsRepository::get()->getTransition(QStringLiteral("wipe"));
auto transxml = TransitionsRepository::get()->getXml(QStringLiteral("wipe"));
std::shared_ptr<AssetParameterModel> model = std::make_shared<AssetParameterModel>(trans, transxml, QStringLiteral("wipe"));
// END delete
m_assetPanel = new AssetPanel(this);
connect(m_timelineTabs, &TimelineTabs::showTransitionModel, m_assetPanel, &AssetPanel::showTransition);
connect(m_timelineTabs, &TimelineTabs::showClipEffectStack, m_assetPanel, &AssetPanel::showEffectStack);
m_assetPanel->showTransition(model);
m_effectStackDock = addDock(i18n("Properties"), QStringLiteral("effect_stack"), m_assetPanel);
......
......@@ -889,7 +889,7 @@ std::shared_ptr<EffectStackModel> ClipController::getEffectStack() const
}
void ClipController::addEffect(const QString &effectId)
{
m_effectStack->appendEffect(effectId);
m_effectStack->appendEffect(effectId, clipId().toInt());
}
std::shared_ptr<MarkerListModel> ClipController::getMarkerModel() const
......
......@@ -876,6 +876,11 @@ void ProjectManager::activateAsset(const QVariantMap data)
pCore->window()->getMainTimeline()->controller()->addAsset(data);
}
void ProjectManager::refreshItem(int id)
{
pCore->window()->getMainTimeline()->controller()->refreshItem(id);
}
std::shared_ptr<MarkerListModel> ProjectManager::getGuideModel()
{
return current()->getGuideModel();
......
......@@ -136,6 +136,8 @@ public slots:
void adjustProjectDuration();
/** @brief Add an asset in timeline (effect, transition). */
void activateAsset(const QVariantMap data);
/** @brief Request monitor refresh if item is under cursor. */
void refreshItem(int id);
private slots:
void slotRevert();
......
......@@ -33,6 +33,7 @@
// this can be deleted
#include "bin/model/markerlistmodel.hpp"
#include "gentime.h"
#include <effects/effectsrepository.hpp>
ClipModel::ClipModel(std::weak_ptr<TimelineModel> parent, std::shared_ptr<Mlt::Producer> prod, const QString &binClipId, int id)
: MoveableItem<Mlt::Producer>(std::move(parent), id)
......@@ -185,7 +186,11 @@ void ClipModel::setTimelineEffectsEnabled(bool enabled)
bool ClipModel::addEffect(const QString &effectId)
{
READ_LOCK();
m_effectStack->appendEffect(effectId);
m_effectStack->appendEffect(effectId, m_id);
// refresh monitor
if (EffectsRepository::get()->getType(effectId) != EffectType::Audio) {
pCore->refreshProjectItem(m_id);
}
return true;
}
......
......@@ -1205,6 +1205,22 @@ int TimelineModel::getCompositionPlaytime(int compoId) const
return playtime;
}
int TimelineModel::getItemPosition(int itemId) const
{
if (isClip(itemId)) {
return getClipPosition(itemId);
}
return getCompositionPosition(itemId);
}
int TimelineModel::getItemPlaytime(int itemId) const
{
if (isClip(itemId)) {
return getClipPlaytime(itemId);
}
return getCompositionPlaytime(itemId);
}
int TimelineModel::getTrackCompositionsCount(int compoId) const
{
return getTrackById_const(compoId)->getCompositionsCount();
......
......@@ -258,6 +258,11 @@ public:
Q_INVOKABLE int suggestCompositionMove(int compoId, int trackId, int position);
int getCompositionPlaytime(int compoId) const;
/* Returns an item position, item can be clip or composition */
int getItemPosition(int itemId) const;
/* Returns an item duration, item can be clip or composition */
int getItemPlaytime(int itemId) const;
/* @brief Given an intended move, try to suggest a more valid one
(accounting for snaps and missing UI calls) @param clipId id of the clip to
move @param trackId id of the target track @param position target position
......
......@@ -387,7 +387,7 @@ void TimelineController::showAsset(int id)
{
qDebug() << "show asset" << id;
if (m_model->isComposition(id)) {
emit showTransitionModel(m_model->getCompositionParameterModel(id));
emit showTransitionModel(id, m_model->getCompositionParameterModel(id));
} else if (m_model->isClip(id)) {
emit showClipEffectStack(id, m_model->getClipEffectStackModel(id));
}
......@@ -482,9 +482,9 @@ void TimelineController::seekCurrentClip(bool seekToEnd)
{
bool foundClip = false;
for (int cid : m_selection.selectedClips) {
int start = m_model->getClipPosition(cid);
int start = m_model->getItemPosition(cid);
if (seekToEnd) {
start += m_model->getClipPlaytime(cid);
start += m_model->getItemPlaytime(cid);
}
seek(start);
foundClip = true;
......@@ -492,6 +492,17 @@ void TimelineController::seekCurrentClip(bool seekToEnd)
}
}
void TimelineController::refreshItem(int id)
{
int in = m_model->getItemPosition(id);
if (in > m_position) {
return;
}
if (m_position <= in + m_model->getItemPlaytime(id)) {
pCore->requestMonitorRefresh();
}
}
QPoint TimelineController::getTracksCount() const
{
int audioTracks = 0;
......
......@@ -203,6 +203,9 @@ public:
/* @brief Returns the number of tracks (audioTrakcs, videoTracks)
*/
QPoint getTracksCount() const;
/* @brief Request monitor refresh if item (clip or composition) is under timeline cursor
*/
void refreshItem(int id);
public slots:
void selectMultitrack();
......@@ -248,7 +251,7 @@ signals:
void zoneChanged();
void zoneMoved(const QPoint &zone);
/* @brief Requests that a given parameter model is displayed in the asset panel */
void showTransitionModel(std::shared_ptr<AssetParameterModel>);
void showTransitionModel(int tid, std::shared_ptr<AssetParameterModel>);
void showClipEffectStack(int cid, std::shared_ptr<EffectStackModel>);
};
......
......@@ -70,7 +70,7 @@ signals:
*/
void changeZoom(int value, bool zoomOnMouse);
/* @brief Requests that a given parameter model is displayed in the asset panel */
void showTransitionModel(std::shared_ptr<AssetParameterModel>);
void showTransitionModel(int tid, std::shared_ptr<AssetParameterModel>);
/* @brief Requests that a given effectstack model is displayed in the asset panel */
void showClipEffectStack(int cid, std::shared_ptr<EffectStackModel>);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment