Fix various issues related to monitor scene and effects:

* monitor scene remaining after effect deletion
* monitor scene not correctly showing keyframe state on start
* crash on move effect
* Fix active effect when adding / removing an effect
parent e7091e00
......@@ -70,6 +70,11 @@ void KeyframeView::slotSetPosition(int pos)
}
}
void KeyframeView::initKeyframePos()
{
emit atKeyframe(m_model->hasKeyframe(m_position), m_model->singleKeyframe());
}
void KeyframeView::slotAddKeyframe(int pos)
{
if (pos < 0) {
......
......@@ -54,6 +54,8 @@ public slots:
void slotGoToPrev();
void slotModelChanged();
void slotEditType(int type, const QPersistentModelIndex &index);
/* @brief Emit initial info for monitor. */
void initKeyframePos();
protected:
void paintEvent(QPaintEvent *event) override;
......
......@@ -189,3 +189,19 @@ int AssetParameterView::contentHeight() const
{
return m_lay->sizeHint().height();
}
MonitorSceneType AssetParameterView::needsMonitorEffectScene() const
{
if (m_mainKeyframeWidget) {
return MonitorSceneGeometry;
}
return MonitorSceneDefault;
}
void AssetParameterView::initKeyframeView()
{
if (m_mainKeyframeWidget) {
m_mainKeyframeWidget->initMonitor();
}
}
......@@ -22,6 +22,7 @@
#ifndef ASSETPARAMETERVIEW_H
#define ASSETPARAMETERVIEW_H
#include "definitions.h"
#include <QModelIndex>
#include <QMutex>
#include <QVector>
......@@ -58,6 +59,12 @@ public:
/** The parent clip in/out points changed, update effects */
void setRange(QPair<int, int> range);
/** Returns the type of monitor overlay required by this effect */
MonitorSceneType needsMonitorEffectScene() const;
/** Make sure the monitor displays correct info depending on current position */
void initKeyframeView();
protected:
/** @brief This is a handler for the dataChanged slot of the model.
......
......@@ -96,11 +96,13 @@ KeyframeWidget::KeyframeWidget(std::shared_ptr<AssetParameterModel> model, QMode
m_lay->addWidget(m_keyframeview);
m_lay->addWidget(toolbar);
// slotSetPosition(0, false);
monitorSeek(monitor->position());
connect(m_time, &TimecodeDisplay::timeCodeEditingFinished, [&]() { slotSetPosition(-1, true); });
connect(m_keyframeview, &KeyframeView::seekToPos, [&](int p) { slotSetPosition(p, true); });
connect(m_keyframeview, &KeyframeView::atKeyframe, this, &KeyframeWidget::slotAtKeyframe);
connect(m_keyframeview, &KeyframeView::modified, this, &KeyframeWidget::slotRefreshParams);
connect(this, &KeyframeWidget::initMonitor, m_keyframeview, &KeyframeView::initKeyframePos);
connect(m_buttonAddDelete, &QAbstractButton::pressed, m_keyframeview, &KeyframeView::slotAddRemove);
connect(m_buttonPrevious, &QAbstractButton::pressed, m_keyframeview, &KeyframeView::slotGoToPrev);
......
......@@ -75,6 +75,9 @@ private:
TimecodeDisplay *m_time;
std::unordered_map<QPersistentModelIndex, QWidget *> m_parameters;
signals:
void initMonitor();
};
#endif
......@@ -87,9 +87,11 @@ void EffectStackModel::removeEffect(std::shared_ptr<EffectItemModel> effect)
int parentId = -1;
if (auto ptr = effect->parentItem().lock()) parentId = ptr->getId();
int current = 0;
bool currentChanged = false;
if (auto srv = m_service.lock()) {
current = srv->get_int("kdenlive:activeeffect");
if (current >= rootItem->childCount() - 1) {
currentChanged = true;
srv->set("kdenlive:activeeffect", --current);
}
}
......@@ -100,10 +102,28 @@ void EffectStackModel::removeEffect(std::shared_ptr<EffectItemModel> effect)
fadeIns.removeAll(effect->getId());
fadeOuts.removeAll(effect->getId());
QString effectName = EffectsRepository::get()->getName(effect->getAssetId());
Fun update = [this, current, currentChanged]() {
// Required to build the effect view
if (currentChanged) {
if (current < 0 || rowCount() == 0) {
// Stack is now empty
dataChanged(QModelIndex(), QModelIndex(), QVector<int>());
} else {
std::shared_ptr<EffectItemModel> effectItem = std::static_pointer_cast<EffectItemModel>(rootItem->child(current));
QModelIndex ix = getIndexFromItem(effectItem);
dataChanged(ix, ix, QVector<int>());
}
}
//TODO: only update if effect is fade or keyframe
pCore->updateItemKeyframes(m_ownerId);
return true;
};
update();
PUSH_LAMBDA(update, redo);
PUSH_LAMBDA(update, undo);
PUSH_UNDO(undo, redo, i18n("Delete effect %1", effectName));
}
// TODO: integrate in undo/redo, change active effect
pCore->updateItemKeyframes(m_ownerId);
}
void EffectStackModel::copyEffect(std::shared_ptr<AbstractEffectItem> sourceItem)
......@@ -128,7 +148,7 @@ void EffectStackModel::copyEffect(std::shared_ptr<AbstractEffectItem> sourceItem
}
}
void EffectStackModel::appendEffect(const QString &effectId)
void EffectStackModel::appendEffect(const QString &effectId, bool makeCurrent)
{
auto effect = EffectItemModel::construct(effectId, shared_from_this());
Fun undo = removeItem_lambda(effect->getId());
......@@ -136,6 +156,13 @@ void EffectStackModel::appendEffect(const QString &effectId)
Fun redo = addItem_lambda(effect, rootItem->getId());
connect(effect.get(), &AssetParameterModel::modelChanged, this, &EffectStackModel::modelChanged);
connect(effect.get(), &AssetParameterModel::replugEffect, this, &EffectStackModel::replugEffect);
int currentActive = getActiveEffect();
if (makeCurrent) {
auto srvPtr = m_service.lock();
if (srvPtr) {
srvPtr->set("kdenlive:activeeffect", rowCount());
}
}
bool res = redo();
if (res) {
if (effectId == QLatin1String("fadein") || effectId == QLatin1String("fade_from_black")) {
......@@ -152,6 +179,11 @@ void EffectStackModel::appendEffect(const QString &effectId)
PUSH_LAMBDA(update, redo);
PUSH_LAMBDA(update, undo);
PUSH_UNDO(undo, redo, i18n("Add effect %1", effectName));
} else if (makeCurrent) {
auto srvPtr = m_service.lock();
if (srvPtr) {
srvPtr->set("kdenlive:activeeffect", currentActive);
}
}
}
......@@ -462,7 +494,7 @@ int EffectStackModel::getActiveEffect() const
if (ptr) {
return ptr->get_int("kdenlive:activeeffect");
}
return -1;
return 0;
}
void EffectStackModel::slotCreateGroup(std::shared_ptr<EffectItemModel> childEffect)
......
......@@ -58,7 +58,7 @@ protected:
public:
/* @brief Add an effect at the bottom of the stack */
void appendEffect(const QString &effectId);
void appendEffect(const QString &effectId, bool makeCurrent = false);
/* @brief Copy an existing effect and append it at the bottom of the stack */
void copyEffect(std::shared_ptr<AbstractEffectItem> sourceItem);
/* @brief Import all effects from the given effect stack
......
......@@ -31,7 +31,6 @@ class AbstractCollapsibleWidget : public QWidget, public Ui::CollapsibleWidget_U
public:
explicit AbstractCollapsibleWidget(QWidget *parent = nullptr);
virtual void setActive(bool activate) = 0;
virtual bool isGroup() const = 0;
signals:
......
......@@ -23,6 +23,7 @@
#include "assets/view/assetparameterview.hpp"
#include "core.h"
#include "dialogs/clipcreationdialog.h"
#include "monitor/monitor.h"
#include "effects/effectsrepository.hpp"
#include "effects/effectstack/model/effectitemmodel.hpp"
#include "effectslist/effectslist.h"
......@@ -295,31 +296,14 @@ bool CollapsibleEffectView::isEnabled() const
void CollapsibleEffectView::slotActivateEffect(QModelIndex ix)
{
decoframe->setProperty("active", ix.row() == m_model->row());
// m_colorIcon->setEnabled(active);
bool active = ix.row() == m_model->row();
decoframe->setProperty("active", active);
decoframe->setStyleSheet(decoframe->styleSheet());
}
void CollapsibleEffectView::setActive(bool activate)
{
Q_UNUSED(activate)
/*
decoframe->setProperty("active", activate);
decoframe->setStyleSheet(decoframe->styleSheet());
if (m_paramWidget) {
m_paramWidget->connectMonitor(activate);
if (active) {
pCore->getMonitor(m_model->monitorId)->slotShowEffectScene(needsMonitorEffectScene());
m_view->initKeyframeView();
}
if (activate) {
m_colorIcon->setPixmap(m_iconPix);
} else {
// desaturate icon
QPixmap alpha = m_iconPix;
QPainter p(&alpha);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(alpha.rect(), QColor(80, 80, 80, 80));
p.end();
m_colorIcon->setPixmap(alpha);
}
*/
}
void CollapsibleEffectView::mousePressEvent(QMouseEvent *e)
......@@ -736,12 +720,10 @@ void CollapsibleEffectView::adjustButtons(int ix, int max)
MonitorSceneType CollapsibleEffectView::needsMonitorEffectScene() const
{
/*
if ((m_paramWidget != nullptr) && !m_enabledButton->isActive()) {
return m_paramWidget->needsMonitorEffectScene();
if (!m_model->isEnabled() || !m_view) {
return MonitorSceneDefault;
}
*/
return MonitorSceneDefault;
return m_view->needsMonitorEffectScene();
}
void CollapsibleEffectView::setRange(QPair<int, int> range)
......
......@@ -52,7 +52,6 @@ public:
void setupWidget(const ItemInfo &info);
void updateTimecodeFormat();
void setActive(bool activate) override;
/** @brief Install event filter so that scrolling with mouse wheel does not change parameter value. */
bool eventFilter(QObject *o, QEvent *e) override;
/** @brief Update effect GUI to reflect parameted changes. */
......
......@@ -26,6 +26,7 @@
#include "builtstack.hpp"
#include "collapsibleeffectview.hpp"
#include "core.h"
#include "monitor/monitor.h"
#include "effects/effectstack/model/effectitemmodel.hpp"
#include "effects/effectstack/model/effectstackmodel.hpp"
#include "kdenlivesettings.h"
......@@ -134,8 +135,12 @@ void EffectStackView::dropEvent(QDropEvent *event)
}
}
if (event->source() == this) {
int oldRow = event->mimeData()->data(QStringLiteral("kdenlive/effectrow")).toInt();
QString sourceData = event->mimeData()->data(QStringLiteral("kdenlive/effectsource"));
int oldRow = sourceData.section(QLatin1Char('-'), 2, 2).toInt();
qDebug() << "// MOVING EFFECT FROM : " << oldRow << " TO " << row;
if (row == oldRow || (row == m_model->rowCount() && oldRow == row - 1)) {
return;
}
m_model->moveEffect(row, m_model->getEffectStackRow(oldRow));
} else {
if (row < m_model->rowCount()) {
......@@ -143,6 +148,10 @@ void EffectStackView::dropEvent(QDropEvent *event)
m_model->moveEffect(row, m_model->getEffectStackRow(m_model->rowCount() - 1));
} else {
m_model->appendEffect(effectId);
std::shared_ptr<AbstractEffectItem> item = m_model->getEffectStackRow(m_model->rowCount() - 1);
if (item) {
slotActivateEffect(std::static_pointer_cast<EffectItemModel>(item));
}
}
}
}
......@@ -171,15 +180,23 @@ void EffectStackView::setModel(std::shared_ptr<EffectStackModel> model, QPair<in
void EffectStackView::loadEffects(QPair<int, int> range, int start, int end)
{
Q_UNUSED(start)
qDebug() << "MUTEX LOCK!!!!!!!!!!!! loadEffects";
qDebug() << "MUTEX LOCK!!!!!!!!!!!! loadEffects: "<<start<<" to "<<end;
QMutexLocker lock(&m_mutex);
m_range = range;
int max = m_model->rowCount();
if (max == 0) {
// blank stack
ObjectId item = m_model->getOwnerId();
pCore->getMonitor(item.first == ObjectType::BinClip ? Kdenlive::ClipMonitor : Kdenlive::ProjectMonitor)->slotShowEffectScene(MonitorSceneDefault);
return;
}
if (end == -1) {
end = max;
}
int active = m_model->getActiveEffect();
for (int i = 0; i < end; i++) {
int active = qBound(0, m_model->getActiveEffect(), max - 1);
std::shared_ptr<AbstractEffectItem> activeItem = m_model->getEffectStackRow(active);
std::shared_ptr<EffectItemModel> activeModel = std::static_pointer_cast<EffectItemModel>(activeItem);
for (int i = 0; i < max; i++) {
std::shared_ptr<AbstractEffectItem> item = m_model->getEffectStackRow(i);
QSize size;
if (item->childCount() > 0) {
......@@ -187,30 +204,36 @@ void EffectStackView::loadEffects(QPair<int, int> range, int start, int end)
continue;
}
std::shared_ptr<EffectItemModel> effectModel = std::static_pointer_cast<EffectItemModel>(item);
QImage effectIcon = m_thumbnailer->requestImage(effectModel->getAssetId(), &size, QSize(QStyle::PM_SmallIconSize, QStyle::PM_SmallIconSize));
CollapsibleEffectView *view = new CollapsibleEffectView(effectModel, range, m_sourceFrameSize, effectIcon, this);
qDebug() << "__ADDING EFFECT: " << effectModel->filter().get("id") << ", ACT: " << active;
if (i == active) {
view->slotActivateEffect(m_model->getIndexFromItem(effectModel));
CollapsibleEffectView *view = nullptr;
if (i >= start && i <= end) {
// We need to rebuild the effect view
QImage effectIcon = m_thumbnailer->requestImage(effectModel->getAssetId(), &size, QSize(QStyle::PM_SmallIconSize, QStyle::PM_SmallIconSize));
view = new CollapsibleEffectView(effectModel, range, m_sourceFrameSize, effectIcon, this);
connect(view, &CollapsibleEffectView::deleteEffect, m_model.get(), &EffectStackModel::removeEffect);
connect(view, &CollapsibleEffectView::moveEffect, m_model.get(), &EffectStackModel::moveEffect);
connect(view, &CollapsibleEffectView::switchHeight, this, &EffectStackView::slotAdjustDelegate, Qt::DirectConnection);
connect(view, &CollapsibleEffectView::startDrag, this, &EffectStackView::slotStartDrag);
connect(view, &CollapsibleEffectView::createGroup, m_model.get(), &EffectStackModel::slotCreateGroup);
connect(view, &CollapsibleEffectView::activateEffect, this, &EffectStackView::slotActivateEffect);
connect(view, &CollapsibleEffectView::seekToPos, [this](int pos) {
// at this point, the effects returns a pos relative to the clip. We need to convert it to a global time
int clipIn = pCore->getItemPosition(m_model->getOwnerId());
emit seekToPos(pos + clipIn);
});
connect(this, &EffectStackView::doActivateEffect, view, &CollapsibleEffectView::slotActivateEffect);
QModelIndex ix = m_model->getIndexFromItem(effectModel);
m_effectsTree->setIndexWidget(ix, view);
WidgetDelegate *del = static_cast<WidgetDelegate *>(m_effectsTree->itemDelegate(ix));
del->setHeight(ix, view->height());
} else {
QModelIndex ix = m_model->getIndexFromItem(effectModel);
auto w = m_effectsTree->indexWidget(ix);
view = static_cast<CollapsibleEffectView *>(w);
}
view->slotActivateEffect(m_model->getIndexFromItem(activeModel));
view->buttonUp->setEnabled(i > 0);
view->buttonDown->setEnabled(i < max - 1);
connect(view, &CollapsibleEffectView::deleteEffect, m_model.get(), &EffectStackModel::removeEffect);
connect(view, &CollapsibleEffectView::moveEffect, m_model.get(), &EffectStackModel::moveEffect);
connect(view, &CollapsibleEffectView::switchHeight, this, &EffectStackView::slotAdjustDelegate, Qt::DirectConnection);
connect(view, &CollapsibleEffectView::startDrag, this, &EffectStackView::slotStartDrag);
connect(view, &CollapsibleEffectView::createGroup, m_model.get(), &EffectStackModel::slotCreateGroup);
connect(view, &CollapsibleEffectView::activateEffect, this, &EffectStackView::slotActivateEffect);
connect(view, &CollapsibleEffectView::seekToPos, [this](int pos) {
// at this point, the effects returns a pos relative to the clip. We need to convert it to a global time
int clipIn = pCore->getItemPosition(m_model->getOwnerId());
emit seekToPos(pos + clipIn);
});
connect(this, &EffectStackView::doActivateEffect, view, &CollapsibleEffectView::slotActivateEffect);
QModelIndex ix = m_model->getIndexFromItem(effectModel);
m_effectsTree->setIndexWidget(ix, view);
WidgetDelegate *del = static_cast<WidgetDelegate *>(m_effectsTree->itemDelegate(ix));
del->setHeight(ix, view->height());
}
updateTreeHeight();
qDebug() << "MUTEX UNLOCK!!!!!!!!!!!! loadEffects";
......@@ -276,7 +299,7 @@ void EffectStackView::slotAdjustDelegate(std::shared_ptr<EffectItemModel> effect
void EffectStackView::refresh(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
Q_UNUSED(roles)
loadEffects(m_range, topLeft.row(), bottomRight.row() + 1);
loadEffects(m_range, topLeft.row(), bottomRight.row());
}
void EffectStackView::unsetModel(bool reset)
......
......@@ -831,7 +831,7 @@ std::shared_ptr<EffectStackModel> ClipController::getEffectStack() const
}
void ClipController::addEffect(const QString &effectId)
{
m_effectStack->appendEffect(effectId);
m_effectStack->appendEffect(effectId, true);
}
bool ClipController::copyEffect(std::shared_ptr<EffectStackModel> stackModel, int rowId)
......
......@@ -415,7 +415,6 @@ void GeometryWidget::connectMonitor(bool activate)
}
m_active = activate;
if (activate) {
m_monitor->slotShowEffectScene(MonitorSceneGeometry);
connect(m_monitor, &Monitor::effectChanged, this, &GeometryWidget::slotUpdateGeometryRect, Qt::UniqueConnection);
QRect rect(m_spinX->value(), m_spinY->value(), m_spinWidth->value(), m_spinHeight->value());
m_monitor->setUpEffectGeometry(rect);
......@@ -431,7 +430,6 @@ void GeometryWidget::connectMonitor(bool activate)
}
}*/
} else {
m_monitor->slotShowEffectScene(MonitorSceneDefault);
disconnect(m_monitor, &Monitor::effectChanged, this, &GeometryWidget::slotUpdateGeometryRect);
}
}
......
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