Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit d02efb7b authored by Nicolas Carion's avatar Nicolas Carion

Some fixes to the keyframe model

parent 7b91ff7b
......@@ -34,8 +34,10 @@ KeyframeModel::KeyframeModel(std::weak_ptr<AssetParameterModel> model, const QMo
, m_model(std::move(model))
, m_undoStack(std::move(undo_stack))
, m_index(index)
, m_lastData()
, m_lock(QReadWriteLock::Recursive)
{
qDebug() <<"Construct keyframemodel. Checking model:"<<m_model.expired();
setup();
refresh();
}
......@@ -55,7 +57,7 @@ void KeyframeModel::setup()
connect(this, &KeyframeModel::modelChanged, this, &KeyframeModel::sendModification);
}
bool KeyframeModel::addKeyframe(GenTime pos, KeyframeType type, double value, Fun &undo, Fun &redo)
bool KeyframeModel::addKeyframe(GenTime pos, KeyframeType type, double value, bool notify, Fun &undo, Fun &redo)
{
QWriteLocker locker(&m_lock);
Fun local_undo = []() { return true; };
......@@ -67,11 +69,11 @@ bool KeyframeModel::addKeyframe(GenTime pos, KeyframeType type, double value, Fu
// In this case we simply change the type and value
KeyframeType oldType = m_keyframeList[pos].first;
double oldValue = m_keyframeList[pos].second;
local_undo = updateKeyframe_lambda(pos, oldType, oldValue);
local_redo = updateKeyframe_lambda(pos, type, value);
local_undo = updateKeyframe_lambda(pos, oldType, oldValue, notify);
local_redo = updateKeyframe_lambda(pos, type, value, notify);
} else {
local_redo = addKeyframe_lambda(pos, type, value);
local_undo = deleteKeyframe_lambda(pos);
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);
......@@ -87,7 +89,7 @@ bool KeyframeModel::addKeyframe(GenTime pos, KeyframeType type, double value)
Fun redo = []() { return true; };
bool update = (m_keyframeList.count(pos) > 0);
bool res = addKeyframe(pos, type, value, undo, redo);
bool res = addKeyframe(pos, type, value, true, undo, redo);
if (res) {
PUSH_UNDO(undo, redo, update ? i18n("Change keyframe type") : i18n("Add keyframe"));
}
......@@ -100,8 +102,8 @@ bool KeyframeModel::removeKeyframe(GenTime pos, Fun &undo, Fun &redo)
Q_ASSERT(m_keyframeList.count(pos) > 0);
KeyframeType oldType = m_keyframeList[pos].first;
double oldValue = m_keyframeList[pos].second;
Fun local_undo = addKeyframe_lambda(pos, oldType, oldValue);
Fun local_redo = deleteKeyframe_lambda(pos);
Fun local_undo = addKeyframe_lambda(pos, oldType, oldValue, true);
Fun local_redo = deleteKeyframe_lambda(pos, true);
if (local_redo()) {
UPDATE_UNDO_REDO(local_redo, local_undo, undo, redo);
return true;
......@@ -137,7 +139,7 @@ bool KeyframeModel::moveKeyframe(GenTime oldPos, GenTime pos, Fun &undo, Fun &re
Fun local_redo = []() { return true; };
bool res = removeKeyframe(oldPos, local_undo, local_redo);
if (res) {
res = addKeyframe(pos, oldType, oldValue, local_undo, local_redo);
res = addKeyframe(pos, oldType, oldValue, true, local_undo, local_redo);
}
if (res) {
UPDATE_UNDO_REDO(local_redo, local_undo, undo, redo);
......@@ -169,8 +171,8 @@ bool KeyframeModel::updateKeyframe(GenTime pos, double value, Fun &undo, Fun &re
KeyframeType oldType = m_keyframeList[pos].first;
double oldValue = m_keyframeList[pos].second;
if (qAbs(oldValue - value) < 1e-6) return true;
auto operation = updateKeyframe_lambda(pos, oldType, oldValue);
auto reverse = updateKeyframe_lambda(pos, oldType, value);
auto operation = updateKeyframe_lambda(pos, oldType, oldValue, true);
auto reverse = updateKeyframe_lambda(pos, oldType, value, true);
bool res = operation();
if (res) {
UPDATE_UNDO_REDO(operation, reverse, undo, redo);
......@@ -192,23 +194,24 @@ bool KeyframeModel::updateKeyframe(GenTime pos, double value)
return res;
}
Fun KeyframeModel::updateKeyframe_lambda(GenTime pos, KeyframeType type, double value)
Fun KeyframeModel::updateKeyframe_lambda(GenTime pos, KeyframeType type, double value, bool notify)
{
QWriteLocker locker(&m_lock);
return [this, pos, type, value]() {
return [this, pos, type, value, notify]() {
Q_ASSERT(m_keyframeList.count(pos) > 0);
int row = static_cast<int>(std::distance(m_keyframeList.begin(), m_keyframeList.find(pos)));
m_keyframeList[pos].first = type;
m_keyframeList[pos].second = value;
emit dataChanged(index(row), index(row), QVector<int>() << TypeRole << ValueRole);
if (notify)
emit dataChanged(index(row), index(row), QVector<int>() << TypeRole << ValueRole);
return true;
};
}
Fun KeyframeModel::addKeyframe_lambda(GenTime pos, KeyframeType type, double value)
Fun KeyframeModel::addKeyframe_lambda(GenTime pos, KeyframeType type, double value, bool notify)
{
QWriteLocker locker(&m_lock);
return [this, pos, type, value]() {
return [this, notify, pos, type, value]() {
Q_ASSERT(m_keyframeList.count(pos) == 0);
// We determine the row of the newly added marker
auto insertionIt = m_keyframeList.lower_bound(pos);
......@@ -216,24 +219,28 @@ Fun KeyframeModel::addKeyframe_lambda(GenTime pos, KeyframeType type, double val
if (insertionIt != m_keyframeList.end()) {
insertionRow = static_cast<int>(std::distance(m_keyframeList.begin(), insertionIt));
}
beginInsertRows(QModelIndex(), insertionRow, insertionRow);
if (notify)
beginInsertRows(QModelIndex(), insertionRow, insertionRow);
m_keyframeList[pos].first = type;
m_keyframeList[pos].second = value;
endInsertRows();
if (notify)
endInsertRows();
return true;
};
}
Fun KeyframeModel::deleteKeyframe_lambda(GenTime pos)
Fun KeyframeModel::deleteKeyframe_lambda(GenTime pos, bool notify)
{
QWriteLocker locker(&m_lock);
return [this, pos]() {
return [this, pos, notify]() {
Q_ASSERT(m_keyframeList.count(pos) > 0);
Q_ASSERT(pos != GenTime()); // cannot delete initial point
int row = static_cast<int>(std::distance(m_keyframeList.begin(), m_keyframeList.find(pos)));
beginRemoveRows(QModelIndex(), row, row);
if (notify)
beginRemoveRows(QModelIndex(), row, row);
m_keyframeList.erase(pos);
endRemoveRows();
if (notify)
endRemoveRows();
return true;
};
}
......@@ -458,7 +465,7 @@ void KeyframeModel::parseAnimProperty(const QString &prop)
mlt_keyframe_type type;
anim->key_get(i, frame, type);
double value = mlt_prop.anim_get_double("key", frame);
addKeyframe(GenTime(frame, pCore->getCurrentFps()), convertFromMltType(type), value, undo, redo);
addKeyframe(GenTime(frame, pCore->getCurrentFps()), convertFromMltType(type), value, false, undo, redo);
}
delete anim;
......@@ -520,31 +527,50 @@ double KeyframeModel::getInterpolatedValue(const GenTime &pos) const
return prop.anim_get_double("keyframe", p);
}
void KeyframeModel::sendModification() const
void KeyframeModel::sendModification()
{
if (auto ptr = m_model.lock()) {
Q_ASSERT(m_index.isValid());
QString name = ptr->data(m_index, AssetParameterModel::NameRole).toString();
auto type = ptr->data(m_index, AssetParameterModel::TypeRole).value<ParamType>();
QString data;
if (type == ParamType::KeyframeParam) {
ptr->setParameter(name, getAnimProperty());
data = getAnimProperty();
ptr->setParameter(name, data);
} else {
Q_ASSERT(false); //Not implemented, TODO
}
m_lastData = data;
ptr->dataChanged(m_index, m_index);
}
}
void KeyframeModel::refresh()
{
qDebug() << "REFRESHING KEYFRAME";
if (auto ptr = m_model.lock()) {
Q_ASSERT(m_index.isValid());
auto type = ptr->data(m_index, AssetParameterModel::TypeRole).value<ParamType>();
if (type == ParamType::KeyframeParam) {
parseAnimProperty(ptr->data(m_index, AssetParameterModel::ValueRole).toString());
QString data = ptr->data(m_index, AssetParameterModel::ValueRole).toString();
qDebug() << "FOUND DATA KEYFRAME" << data;
if (data == m_lastData) {
// nothing to do
return;
}
// first, try to convert to double
bool ok = false;
double value = data.toDouble(&ok);
if (ok) {
Fun undo = []() { return true; };
Fun redo = []() { return true; };
addKeyframe(GenTime(), KeyframeType::Linear, value, false, undo, redo);
qDebug() << "KEYFRAME ADDED"<<value;
} else if (type == ParamType::KeyframeParam) {
parseAnimProperty(data);
} else {
Q_ASSERT(false); //Not implemented, TODO
}
ptr->dataChanged(m_index, m_index);
} else {
qDebug() << "WARNING : unable to access keyframe's model";
}
}
......@@ -72,8 +72,10 @@ public:
bool addKeyframe(GenTime pos, KeyframeType type, double value);
protected:
/* @brief Same function but accumulates undo/redo */
bool addKeyframe(GenTime pos, KeyframeType type, double value, Fun &undo, Fun &redo);
/* @brief Same function but accumulates undo/redo
@param notify: if true, send a signal to model
*/
bool addKeyframe(GenTime pos, KeyframeType type, double value, bool notify, Fun &undo, Fun &redo);
public:
/* @brief Removes the keyframe at the given position. */
......@@ -145,19 +147,19 @@ public:
protected:
/** @brief Helper function that generate a lambda to change type / value of given keyframe */
Fun updateKeyframe_lambda(GenTime pos, KeyframeType type, double value);
Fun updateKeyframe_lambda(GenTime pos, KeyframeType type, double value, bool notify);
/** @brief Helper function that generate a lambda to add given keyframe */
Fun addKeyframe_lambda(GenTime pos, KeyframeType type, double value);
Fun addKeyframe_lambda(GenTime pos, KeyframeType type, double value, bool notify);
/** @brief Helper function that generate a lambda to remove given keyframe */
Fun deleteKeyframe_lambda(GenTime pos);
Fun deleteKeyframe_lambda(GenTime pos, bool notify);
/* @brief Connects the signals of this object */
void setup();
/* @brief Commit the modification to the model */
void sendModification() const;
void sendModification();
/** @brief returns the keyframes as a Mlt Anim Property string.
It is defined as pairs of frame and value, separated by ;
......@@ -174,6 +176,7 @@ private:
std::weak_ptr<AssetParameterModel> m_model;
std::weak_ptr<DocUndoStack> m_undoStack;
QPersistentModelIndex m_index;
QString m_lastData;
mutable QReadWriteLock m_lock; // This is a lock that ensures safety in case of concurrent access
......
......@@ -35,6 +35,7 @@ KeyframeModelList::KeyframeModelList(std::weak_ptr<AssetParameterModel> model, c
, m_undoStack(undo_stack)
, m_lock(QReadWriteLock::Recursive)
{
qDebug() <<"Construct keyframemodellist. Checking model:"<<m_model.expired();
addParameter(index);
connect(m_parameters.begin()->second.get(), &KeyframeModel::modelChanged, this, &KeyframeModelList::modelChanged);
}
......@@ -75,7 +76,7 @@ bool KeyframeModelList::addKeyframe(GenTime pos, KeyframeType type)
bool update = (m_parameters.begin()->second->hasKeyframe(pos) > 0);
auto op = [pos, type](std::shared_ptr<KeyframeModel> param, Fun &undo, Fun &redo){
double value = param->getInterpolatedValue(pos);
return param->addKeyframe(pos, type, value, undo, redo);
return param->addKeyframe(pos, type, value, true, undo, redo);
};
return applyOperation(op, update ? i18n("Change keyframe type") : i18n("Add keyframe"));
}
......
......@@ -33,7 +33,7 @@
#include <klocalizedstring.h>
KeyframeWidget::KeyframeWidget(std::shared_ptr<AssetParameterModel> model, QModelIndex index, QWidget *parent)
: AbstractParamWidget(std::move(model), index, parent)
: AbstractParamWidget(model, index, parent)
{
m_keyframes = std::shared_ptr<KeyframeModelList>(new KeyframeModelList(model, index, pCore->undoStack()));
......
......@@ -61,8 +61,6 @@ public:
*/
virtual void unplant(const std::weak_ptr<Mlt::Service> &service) = 0;
/* @brief This function connect the dataChanged signal of the effects to the dataChanged signal of the model. This workarounds limitation with signal when using multiple inheritance */
virtual void connectDataChanged() = 0;
protected:
/* @brief Toogles the mlt effect according to the current activation state*/
virtual void updateEnable() = 0;
......
......@@ -73,10 +73,3 @@ void EffectGroupModel::unplant(const std::weak_ptr<Mlt::Service> &service)
}
}
void EffectGroupModel::connectDataChanged()
{
for (int i = 0; i < childCount(); ++i) {
std::static_pointer_cast<AbstractEffectItem>(child(i))->connectDataChanged();
}
}
......@@ -47,8 +47,6 @@ public:
*/
void unplant(const std::weak_ptr<Mlt::Service> &service) override;
/* @brief This function connect the dataChanged signal of the effects to the dataChanged signal of the model. This workarounds limitation with signal when using multiple inheritance */
void connectDataChanged();
protected:
EffectGroupModel(const QList<QVariant> &data, const QString &name, const std::shared_ptr<AbstractTreeModel> &stack, bool isRoot = false);
......
......@@ -125,10 +125,3 @@ bool EffectItemModel::isAudio() const
return EffectsRepository::get()->getType(getAssetId()) == EffectType::Audio;
}
void EffectItemModel::connectDataChanged()
{
if (auto ptr = m_model.lock()) {
auto model = std::static_pointer_cast<EffectStackModel>(ptr);
connect(this, &EffectItemModel::dataChanged, model.get(), &EffectStackModel::dataChanged);
}
}
......@@ -53,8 +53,6 @@ public:
/* @brief Return true if the effect applies only to audio */
bool isAudio() const override;
/* @brief This function connect the dataChanged signal of the effects to the dataChanged signal of the model. This workarounds limitation with signal when using multiple inheritance */
void connectDataChanged();
protected:
EffectItemModel(const QList<QVariant> &data, Mlt::Properties *effect, const QDomElement &xml, const QString &effectId,
......
......@@ -246,7 +246,6 @@ void EffectStackModel::registerItem(const std::shared_ptr<TreeItem> &item)
effectItem->plant(m_service);
effectItem->setEffectStackEnabled(m_effectStackEnabled);
ix = getIndexFromItem(effectItem);
effectItem->connectDataChanged();
if (!effectItem->isAudio()) {
pCore->refreshProjectItem(m_ownerId);
}
......
......@@ -143,6 +143,7 @@ void EffectStackView::dropEvent(QDropEvent *event)
void EffectStackView::setModel(std::shared_ptr<EffectStackModel> model, QPair<int, int> range)
{
qDebug()<<"MUTEX LOCK!!!!!!!!!!!! setmodel";
m_mutex.lock();
unsetModel();
m_model = model;
......@@ -154,12 +155,14 @@ void EffectStackView::setModel(std::shared_ptr<EffectStackModel> model, QPair<in
m_effectsTree->setDragEnabled(true);
m_effectsTree->setUniformRowHeights(false);
m_mutex.unlock();
qDebug()<<"MUTEX UNLOCK!!!!!!!!!!!! setmodel";
loadEffects(range);
connect(m_model.get(), &EffectStackModel::dataChanged, this, &EffectStackView::refresh);
}
void EffectStackView::loadEffects(QPair<int, int> range, int start, int end)
{
qDebug()<<"MUTEX LOCK!!!!!!!!!!!! loadEffects";
QMutexLocker lock (&m_mutex);
m_range = range;
int max = m_model->rowCount();
......@@ -198,14 +201,17 @@ void EffectStackView::loadEffects(QPair<int, int> range, int start, int end)
QModelIndex ix = m_model->getIndexFromItem(effectModel);
m_effectsTree->setIndexWidget(ix, view);
}
qDebug()<<"MUTEX UNLOCK!!!!!!!!!!!! loadEffects";
}
void EffectStackView::slotActivateEffect(std::shared_ptr<EffectItemModel> effectModel)
{
qDebug()<<"MUTEX LOCK!!!!!!!!!!!! slotactivateeffect";
QMutexLocker lock (&m_mutex);
m_model->setActiveEffect(effectModel->row());
QModelIndex activeIx = m_model->getIndexFromItem(effectModel);
emit doActivateEffect(activeIx);
qDebug()<<"MUTEX UNLOCK!!!!!!!!!!!! slotactivateeffect";
}
void EffectStackView::slotStartDrag(QPixmap pix, std::shared_ptr<EffectItemModel> effectModel)
......@@ -232,10 +238,12 @@ void EffectStackView::slotStartDrag(QPixmap pix, std::shared_ptr<EffectItemModel
void EffectStackView::slotAdjustDelegate(std::shared_ptr<EffectItemModel> effectModel, int height)
{
qDebug()<<"MUTEX LOCK!!!!!!!!!!!! adjustdelegate";
QMutexLocker lock (&m_mutex);
QModelIndex ix = m_model->getIndexFromItem(effectModel);
WidgetDelegate *del = static_cast<WidgetDelegate *>(m_effectsTree->itemDelegate(ix));
del->setHeight(ix, height);
qDebug()<<"MUTEX UNLOCK!!!!!!!!!!!! adjustdelegate";
}
void EffectStackView::refresh(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
......@@ -253,6 +261,7 @@ void EffectStackView::unsetModel(bool reset)
void EffectStackView::setRange(int in, int out)
{
qDebug()<<"MUTEX LOCK!!!!!!!!!!!! setrange";
QMutexLocker lock (&m_mutex);
m_range.first = in;
m_range.second = out;
......
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