diff --git a/src/assets/CMakeLists.txt b/src/assets/CMakeLists.txt
index aeb6b162b..045a60567 100644
--- a/src/assets/CMakeLists.txt
+++ b/src/assets/CMakeLists.txt
@@ -1,20 +1,23 @@
set(kdenlive_SRCS
${kdenlive_SRCS}
assets/assetlist/view/qmltypes/asseticonprovider.cpp
assets/assetlist/view/assetlistwidget.cpp
assets/assetlist/model/assetfilter.cpp
assets/assetlist/model/assettreemodel.cpp
assets/assetpanel.cpp
+ assets/keyframes/model/keyframemodel.cpp
+ assets/keyframes/model/keyframemodellist.cpp
+ assets/keyframes/view/keyframeview.cpp
assets/model/assetparametermodel.cpp
assets/model/assetcommand.cpp
assets/view/assetparameterview.cpp
assets/view/widgets/abstractparamwidget.cpp
#assets/view/widgets/animationwidget.cpp
assets/view/widgets/boolparamwidget.cpp
assets/view/widgets/doubleparamwidget.cpp
# assets/view/widgets/keyframeedit.cpp
assets/view/widgets/keyframewidget.cpp
assets/view/widgets/listparamwidget.cpp
# assets/view/widgets/positioneditwidget.cpp
PARENT_SCOPE)
diff --git a/src/effects/keyframes/keyframemodel.cpp b/src/assets/keyframes/model/keyframemodel.cpp
similarity index 100%
rename from src/effects/keyframes/keyframemodel.cpp
rename to src/assets/keyframes/model/keyframemodel.cpp
diff --git a/src/effects/keyframes/keyframemodel.hpp b/src/assets/keyframes/model/keyframemodel.hpp
similarity index 100%
rename from src/effects/keyframes/keyframemodel.hpp
rename to src/assets/keyframes/model/keyframemodel.hpp
diff --git a/src/effects/keyframes/keyframemodellist.cpp b/src/assets/keyframes/model/keyframemodellist.cpp
similarity index 100%
rename from src/effects/keyframes/keyframemodellist.cpp
rename to src/assets/keyframes/model/keyframemodellist.cpp
diff --git a/src/effects/keyframes/keyframemodellist.hpp b/src/assets/keyframes/model/keyframemodellist.hpp
similarity index 100%
rename from src/effects/keyframes/keyframemodellist.hpp
rename to src/assets/keyframes/model/keyframemodellist.hpp
diff --git a/src/effects/keyframes/view/keyframeview.cpp b/src/assets/keyframes/view/keyframeview.cpp
similarity index 99%
rename from src/effects/keyframes/view/keyframeview.cpp
rename to src/assets/keyframes/view/keyframeview.cpp
index 5d4766ddc..f4acdb092 100644
--- a/src/effects/keyframes/view/keyframeview.cpp
+++ b/src/assets/keyframes/view/keyframeview.cpp
@@ -1,279 +1,280 @@
/***************************************************************************
* Copyright (C) 2011 by Till Theato (root@ttill.de) *
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive (www.kdenlive.org). *
* *
* Kdenlive 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. *
* *
* Kdenlive 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 Kdenlive. If not, see . *
***************************************************************************/
#include "keyframeview.hpp"
+#include "assets/keyframes/model/keyframemodellist.hpp"
#include "core.h"
#include "kdenlivesettings.h"
#include
#include
#include
#include
KeyframeView::KeyframeView(std::shared_ptr model, QWidget *parent)
: QWidget(parent)
, m_model(model)
, m_duration(1)
, m_position(0)
, m_currentKeyframe(-1)
, m_currentKeyframeOriginal(-1)
, m_hoverKeyframe(-1)
, m_scale(1)
, m_currentType(KeyframeType::Linear)
{
setMouseTracking(true);
setMinimumSize(QSize(150, 20));
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum));
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
QPalette p = palette();
KColorScheme scheme(p.currentColorGroup(), KColorScheme::Window, KSharedConfig::openConfig(KdenliveSettings::colortheme()));
m_colSelected = palette().highlight().color();
m_colKeyframe = scheme.foreground(KColorScheme::NormalText).color();
m_size = QFontInfo(font()).pixelSize() * 1.8;
m_lineHeight = m_size / 2;
setMinimumHeight(m_size);
setMaximumHeight(m_size);
connect(m_model.get(), &KeyframeModelList::modelChanged, [&](){
emit atKeyframe(m_model->hasKeyframe(m_position));
update();
});
}
void KeyframeView::slotSetPosition(int pos)
{
if (pos != m_position) {
m_position = pos;
emit atKeyframe(m_model->hasKeyframe(pos));
emit positionChanged(pos);
update();
}
}
void KeyframeView::slotAddKeyframe(int pos)
{
if (pos < 0) {
pos = m_position;
}
m_model->addKeyframe(GenTime(pos, pCore->getCurrentFps()), m_currentType);
}
void KeyframeView::slotAddRemove()
{
if (m_model->hasKeyframe(m_position)) {
slotRemoveKeyframe(m_position);
} else {
slotAddKeyframe(m_position);
}
}
void KeyframeView::slotRemoveKeyframe(int pos)
{
if (pos < 0) {
pos = m_position;
}
m_model->removeKeyframe(GenTime(pos, pCore->getCurrentFps()));
}
void KeyframeView::setDuration(int dur)
{
m_duration = dur;
}
void KeyframeView::slotGoToNext()
{
if (m_position == m_duration) {
return;
}
bool ok;
auto next = m_model->getNextKeyframe(GenTime(m_position, pCore->getCurrentFps()), &ok);
if (ok) {
slotSetPosition(next.first.frames(pCore->getCurrentFps()));
} else {
// no keyframe after current position
slotSetPosition(m_duration);
}
}
void KeyframeView::slotGoToPrev()
{
if (m_position == 0) {
return;
}
bool ok;
auto prev = m_model->getPrevKeyframe(GenTime(m_position, pCore->getCurrentFps()), &ok);
if (ok) {
slotSetPosition(prev.first.frames(pCore->getCurrentFps()));
} else {
// no keyframe after current position
slotSetPosition(m_duration);
}
}
void KeyframeView::mousePressEvent(QMouseEvent *event)
{
int pos = event->x() / m_scale;
if (event->y() < m_lineHeight && event->button() == Qt::LeftButton) {
bool ok;
GenTime position(pos, pCore->getCurrentFps());
auto keyframe = m_model->getClosestKeyframe(position, &ok);
if (ok && qAbs(keyframe.first.frames(pCore->getCurrentFps()) - pos) < 5) {
m_currentKeyframeOriginal = keyframe.first.frames(pCore->getCurrentFps());
if (m_model->moveKeyframe(keyframe.first, position, false)) {
m_currentKeyframe = pos;
slotSetPosition(pos);
return;
}
}
}
// no keyframe next to mouse
m_currentKeyframe = m_currentKeyframeOriginal = -1;
slotSetPosition(pos);
update();
}
void KeyframeView::mouseMoveEvent(QMouseEvent *event)
{
int pos = qBound(0, (int)(event->x() / m_scale), m_duration);
GenTime position(pos, pCore->getCurrentFps());
if ((event->buttons() & Qt::LeftButton) != 0u) {
if (m_currentKeyframe >= 0) {
if (!m_model->hasKeyframe(pos)) {
// snap to position cursor
if (KdenliveSettings::snaptopoints() && qAbs(pos - m_position) < 5 && !m_model->hasKeyframe(m_position)) {
pos = m_position;
}
GenTime currentPos(m_currentKeyframe, pCore->getCurrentFps());
if (m_model->moveKeyframe(currentPos, position, false)) {
m_currentKeyframe = pos;
}
}
}
slotSetPosition(pos);
return;
}
if (event->y() < m_lineHeight) {
bool ok;
auto keyframe = m_model->getClosestKeyframe(position, &ok);
if (ok && qAbs(keyframe.first.frames(pCore->getCurrentFps()) - pos) < 5) {
m_hoverKeyframe = keyframe.first.frames(pCore->getCurrentFps());
setCursor(Qt::PointingHandCursor);
update();
return;
}
}
if (m_hoverKeyframe != -1) {
m_hoverKeyframe = -1;
setCursor(Qt::ArrowCursor);
update();
}
}
void KeyframeView::mouseReleaseEvent(QMouseEvent *event)
{
Q_UNUSED(event)
if (m_currentKeyframe >= 0) {
GenTime initPos(m_currentKeyframeOriginal, pCore->getCurrentFps());
GenTime targetPos(m_currentKeyframe, pCore->getCurrentFps());
m_model->moveKeyframe(targetPos, initPos, false);
m_model->moveKeyframe(initPos, targetPos, true);
}
}
void KeyframeView::mouseDoubleClickEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && event->y() < m_lineHeight) {
int pos = qBound(0, (int)(event->x() / m_scale), m_duration);
GenTime position(pos, pCore->getCurrentFps());
bool ok;
auto keyframe = m_model->getClosestKeyframe(position, &ok);
if (ok && qAbs(keyframe.first.frames(pCore->getCurrentFps()) - pos) < 5) {
m_model->removeKeyframe(keyframe.first);
if (keyframe.first.frames(pCore->getCurrentFps()) == m_currentKeyframe) {
m_currentKeyframe = m_currentKeyframeOriginal = -1;
}
if (keyframe.first.frames(pCore->getCurrentFps()) == m_position) {
emit atKeyframe(false);
}
return;
}
// add new keyframe
m_model->addKeyframe(position, m_currentType);
} else {
QWidget::mouseDoubleClickEvent(event);
}
}
void KeyframeView::wheelEvent(QWheelEvent *event)
{
int change = event->delta() < 0 ? -1 : 1;
int pos = qBound(0, m_position + change, m_duration);
slotSetPosition(pos);
}
void KeyframeView::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QStylePainter p(this);
m_scale = width() / (double)(m_duration);
// p.translate(0, m_lineHeight);
int headOffset = m_lineHeight / 1.5;
/*
* keyframes
*/
for (const auto &keyframe : *m_model.get()) {
int pos = keyframe.first.frames(pCore->getCurrentFps());
if (pos == m_currentKeyframe || pos == m_hoverKeyframe) {
p.setBrush(m_colSelected);
} else {
p.setBrush(m_colKeyframe);
}
int scaledPos = pos * m_scale;
p.drawLine(scaledPos, headOffset, scaledPos, m_lineHeight + (headOffset / 2));
p.drawEllipse(scaledPos - headOffset / 2, 0, headOffset, headOffset);
}
p.setPen(palette().dark().color());
/*
* Time-"line"
*/
p.setPen(m_colKeyframe);
p.drawLine(0, m_lineHeight + (headOffset / 2), width(), m_lineHeight + (headOffset / 2));
/*
* current position
*/
QPolygon pa(3);
int cursorwidth = (m_size - (m_lineHeight + headOffset / 2)) / 2 + 1;
QPolygonF position = QPolygonF() << QPointF(-cursorwidth, m_size) << QPointF(cursorwidth, m_size) << QPointF(0, m_lineHeight + (headOffset / 2) + 1);
position.translate(m_position * m_scale, 0);
p.setBrush(m_colKeyframe);
p.drawPolygon(position);
}
diff --git a/src/effects/keyframes/view/keyframeview.hpp b/src/assets/keyframes/view/keyframeview.hpp
similarity index 96%
rename from src/effects/keyframes/view/keyframeview.hpp
rename to src/assets/keyframes/view/keyframeview.hpp
index 52c2f4393..ce0e4cae0 100644
--- a/src/effects/keyframes/view/keyframeview.hpp
+++ b/src/assets/keyframes/view/keyframeview.hpp
@@ -1,85 +1,85 @@
/***************************************************************************
* Copyright (C) 2011 by Till Theato (root@ttill.de) *
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive (www.kdenlive.org). *
* *
* Kdenlive 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. *
* *
* Kdenlive 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 Kdenlive. If not, see . *
***************************************************************************/
#ifndef KEYFRAMEVIEW_H
#define KEYFRAMEVIEW_H
-#include "effects/keyframes/keyframemodel.hpp"
-#include "effects/keyframes/keyframemodellist.hpp"
+#include "assets/keyframes/model/keyframemodel.hpp"
+#include "assets/keyframes/model/keyframemodellist.hpp"
#include
#include
class KeyframeModelList;
class KeyframeView : public QWidget
{
Q_OBJECT
public:
explicit KeyframeView(std::shared_ptr model, QWidget *parent = nullptr);
void setDuration(int dur);
public slots:
/* @brief moves the current position*/
void slotSetPosition(int pos);
/* @brief remove the keyframe at given position
If pos is negative, we remove keyframe at current position
*/
void slotRemoveKeyframe(int pos);
/* @brief Add a keyframe with given parameter value at given pos.
If pos is negative, then keyframe is added at current position
*/
void slotAddKeyframe(int pos = -1);
/* @brief If there is a keyframe at current position, it is removed.
Otherwise, we add a new one with given value.
*/
void slotAddRemove();
void slotGoToNext();
void slotGoToPrev();
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
private:
std::shared_ptr m_model;
int m_duration;
int m_position;
int m_currentKeyframe;
int m_currentKeyframeOriginal;
int m_hoverKeyframe;
int m_lineHeight;
double m_scale;
int m_size;
KeyframeType m_currentType;
QColor m_colSelected;
QColor m_colKeyframe;
QColor m_colKeyframeBg;
signals:
void positionChanged(int pos);
void atKeyframe(bool);
};
#endif
diff --git a/src/assets/view/widgets/keyframewidget.cpp b/src/assets/view/widgets/keyframewidget.cpp
index ada1ad529..98b6c81dc 100644
--- a/src/assets/view/widgets/keyframewidget.cpp
+++ b/src/assets/view/widgets/keyframewidget.cpp
@@ -1,131 +1,131 @@
/***************************************************************************
* Copyright (C) 2011 by Till Theato (root@ttill.de) *
* Copyright (C) 2017 by Nicolas Carion *
* This file is part of Kdenlive (www.kdenlive.org). *
* *
* Kdenlive 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. *
* *
* Kdenlive 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 Kdenlive. If not, see . *
***************************************************************************/
#include "keyframewidget.hpp"
-#include "effects/keyframes/view/keyframeview.hpp"
-#include "effects/keyframes/keyframemodellist.hpp"
+#include "assets/keyframes/view/keyframeview.hpp"
+#include "assets/keyframes/model/keyframemodellist.hpp"
#include "timecodedisplay.h"
#include "utils/KoIconUtils.h"
#include "core.h"
#include
#include
#include
KeyframeWidget::KeyframeWidget(std::shared_ptr model, QModelIndex index, double init_value, const Timecode &t, int duration, QWidget *parent)
: QWidget(parent)
, m_model(model)
, m_index(index)
, m_keyframes(new KeyframeModelList(init_value, model, index, pCore->undoStack()))
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
auto *l = new QGridLayout(this);
m_keyframeview = new KeyframeView(m_keyframes, this);
m_keyframeview->setDuration(duration);
m_buttonAddDelete = new QToolButton(this);
m_buttonAddDelete->setAutoRaise(true);
m_buttonAddDelete->setIcon(KoIconUtils::themedIcon(QStringLiteral("list-add")));
m_buttonAddDelete->setToolTip(i18n("Add keyframe"));
m_buttonPrevious = new QToolButton(this);
m_buttonPrevious->setAutoRaise(true);
m_buttonPrevious->setIcon(KoIconUtils::themedIcon(QStringLiteral("media-skip-backward")));
m_buttonPrevious->setToolTip(i18n("Go to previous keyframe"));
m_buttonNext = new QToolButton(this);
m_buttonNext->setAutoRaise(true);
m_buttonNext->setIcon(KoIconUtils::themedIcon(QStringLiteral("media-skip-forward")));
m_buttonNext->setToolTip(i18n("Go to next keyframe"));
m_time = new TimecodeDisplay(t, this);
m_time->setRange(0, duration);
l->addWidget(m_keyframeview, 0, 0, 1, -1);
l->addWidget(m_buttonPrevious, 1, 0);
l->addWidget(m_buttonAddDelete, 1, 1);
l->addWidget(m_buttonNext, 1, 2);
l->addWidget(m_time, 1, 3, Qt::AlignRight);
connect(m_time, &TimecodeDisplay::timeCodeEditingFinished, [&](){slotSetPosition(-1, true);});
connect(m_keyframeview, &KeyframeView::positionChanged, [&](int p){slotSetPosition(p, true);});
connect(m_keyframeview, &KeyframeView::atKeyframe, this, &KeyframeWidget::slotAtKeyframe);
connect(m_buttonAddDelete, &QAbstractButton::pressed, m_keyframeview, &KeyframeView::slotAddRemove);
connect(m_buttonPrevious, &QAbstractButton::pressed, m_keyframeview, &KeyframeView::slotGoToPrev);
connect(m_buttonNext, &QAbstractButton::pressed, m_keyframeview, &KeyframeView::slotGoToNext);
}
KeyframeWidget::~KeyframeWidget()
{
delete m_keyframeview;
delete m_buttonAddDelete;
delete m_buttonPrevious;
delete m_buttonNext;
delete m_time;
}
void KeyframeWidget::slotSetPosition(int pos, bool update)
{
if (pos < 0) {
pos = m_time->getValue();
m_keyframeview->slotSetPosition(pos);
} else {
m_time->setValue(pos);
m_keyframeview->slotSetPosition(pos);
}
if (update) {
emit positionChanged(pos);
}
}
int KeyframeWidget::getPosition() const
{
return m_time->getValue();
}
void KeyframeWidget::addKeyframe(int pos)
{
blockSignals(true);
m_keyframeview->slotAddKeyframe(pos);
blockSignals(false);
setEnabled(true);
}
void KeyframeWidget::updateTimecodeFormat()
{
m_time->slotUpdateTimeCodeFormat();
}
void KeyframeWidget::slotAtKeyframe(bool atKeyframe)
{
if (atKeyframe) {
m_buttonAddDelete->setIcon(KoIconUtils::themedIcon(QStringLiteral("list-remove")));
m_buttonAddDelete->setToolTip(i18n("Delete keyframe"));
} else {
m_buttonAddDelete->setIcon(KoIconUtils::themedIcon(QStringLiteral("list-add")));
m_buttonAddDelete->setToolTip(i18n("Add keyframe"));
}
}
diff --git a/src/effects/CMakeLists.txt b/src/effects/CMakeLists.txt
index 72f2df542..ddc0a6617 100644
--- a/src/effects/CMakeLists.txt
+++ b/src/effects/CMakeLists.txt
@@ -1,19 +1,16 @@
set(kdenlive_SRCS
${kdenlive_SRCS}
effects/effectlist/model/effectfilter.cpp
effects/effectlist/model/effecttreemodel.cpp
effects/effectlist/view/effectlistwidget.cpp
effects/effectlist/view/effectlistwidget.cpp
effects/effectsrepository.cpp
effects/effectstack/model/abstracteffectitem.cpp
effects/effectstack/model/effectgroupmodel.cpp
effects/effectstack/model/effectitemmodel.cpp
effects/effectstack/model/effectstackmodel.cpp
effects/effectstack/view/abstractcollapsiblewidget.cpp
effects/effectstack/view/collapsibleeffectview.cpp
effects/effectstack/view/effectstackview.cpp
- effects/keyframes/keyframemodel.cpp
- effects/keyframes/keyframemodellist.cpp
- effects/keyframes/view/keyframeview.cpp
PARENT_SCOPE)