Commit bda79320 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

more cleanup

parent 6237b839
......@@ -134,7 +134,7 @@ list(APPEND kdenlive_SRCS
gentime.cpp
doc/kthumb.cpp
mainwindow.cpp
renderer.cpp
# renderer.cpp
statusbarmessagelabel.cpp
timecode.cpp
timecodedisplay.cpp
......
......@@ -27,7 +27,6 @@
#include "profiles/profilerepository.hpp"
#include "profilesdialog.h"
#include "project/dialogs/profilewidget.h"
#include "renderer.h"
#ifdef USE_V4L
......
......@@ -38,7 +38,6 @@
#include "profiles/profilemodel.hpp"
#include "profiles/profilerepository.hpp"
#include "project/projectcommands.h"
#include "renderer.h"
#include "titler/titlewidget.h"
#include "transitions/transitionsrepository.hpp"
......
add_subdirectory(widgets/curves)
set(kdenlive_SRCS
${kdenlive_SRCS}
effectstack/abstractcollapsiblewidget.cpp
effectstack/collapsibleeffect.cpp
effectstack/collapsiblegroup.cpp
# effectstack/abstractcollapsiblewidget.cpp
# effectstack/collapsibleeffect.cpp
# effectstack/collapsiblegroup.cpp
# effectstack/effectstackedit.cpp
# effectstack/effectstackview2.cpp
effectstack/graphicsscenerectmove.cpp
......
/***************************************************************************
* Copyright (C) 2012 by Jean-Baptiste Mardelle (jb@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) 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 "abstractcollapsiblewidget.h"
AbstractCollapsibleWidget::AbstractCollapsibleWidget(QWidget *parent)
: QWidget(parent)
{
setupUi(this);
}
/***************************************************************************
* Copyright (C) 2012 by Jean-Baptiste Mardelle (jb@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) 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 ABSTRACTCOLLAPSIBLEWIDGET_H
#define ABSTRACTCOLLAPSIBLEWIDGET_H
#include "ui_collapsiblewidget_ui.h"
#include <QDomElement>
#include <QWidget>
class AbstractCollapsibleWidget : public QWidget, public Ui::CollapsibleWidget_UI
{
Q_OBJECT
public:
explicit AbstractCollapsibleWidget(QWidget *parent = nullptr);
virtual void setActive(bool activate) = 0;
virtual bool isGroup() const = 0;
signals:
void addEffect(const QDomElement &e);
/** @brief Move effects in the stack one step up or down. */
void changeEffectPosition(const QList<int> &, bool upwards);
/** @brief Move effects in the stack. */
void moveEffect(const QList<int> &current_pos, int new_pos, int groupIndex, const QString &groupName);
/** @brief An effect was saved, trigger effect list reload. */
void reloadEffects();
};
#endif
This diff is collapsed.
/***************************************************************************
* Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@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) 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 COLLAPSIBLEEFFECT_H
#define COLLAPSIBLEEFFECT_H
#include "abstractcollapsiblewidget.h"
#include "mltcontroller/effectscontroller.h"
#include "parametercontainer.h"
#include "timecode.h"
#include <QDomElement>
class QLabel;
class QTimeLine;
class KDualAction;
/**)
* @class CollapsibleEffect
* @brief A dialog for editing markers and guides.
* @author Jean-Baptiste Mardelle
*/
class CollapsibleEffect : public AbstractCollapsibleWidget
{
Q_OBJECT
public:
explicit CollapsibleEffect(const QDomElement &effect, const QDomElement &original_effect, const ItemInfo &info, EffectMetaInfo *metaInfo, bool canMoveUp,
bool lastEffect, QWidget *parent = nullptr);
~CollapsibleEffect();
QLabel *title;
void setupWidget(const ItemInfo &info, EffectMetaInfo *metaInfo);
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. */
void updateWidget(const ItemInfo &info, const QDomElement &effect, EffectMetaInfo *metaInfo);
/** @brief Returns effect xml. */
QDomElement effect() const;
/** @brief Returns effect xml with keyframe offset for saving. */
QDomElement effectForSave() const;
int groupIndex() const;
bool isGroup() const override;
int effectIndex() const;
void setGroupIndex(int ix);
void setGroupName(const QString &groupName);
/** @brief Remove this effect from its group. */
void removeFromGroup();
QString infoString() const;
bool isActive() const;
bool isEnabled() const;
/** @brief Should the wheel event be sent to parent widget for scrolling. */
bool filterWheelEvent;
/** @brief Parent group was collapsed, update. */
void groupStateChanged(bool collapsed);
/** @brief Show / hide up / down buttons. */
void adjustButtons(int ix, int max);
/** @brief Returns this effect's monitor scene type if any is needed. */
MonitorSceneType needsMonitorEffectScene() const;
/** @brief Set clip in / out points. */
void setRange(int inPoint, int outPoint);
/** @brief Import keyframes from a clip's data. */
void setKeyframes(const QString &tag, const QString &keyframes);
/** @brief Pass frame size info (dar, etc). */
void updateFrameInfo();
/** @brief Select active keyframe. */
void setActiveKeyframe(int kf);
/** @brief Returns true if effect can be moved (false for speed effect). */
bool isMovable() const;
public slots:
void slotSyncEffectsPos(int pos);
void slotDisable(bool disable, bool emitInfo = true);
void slotResetEffect();
void importKeyframes(const QString &keyframes);
private slots:
void setWidgetHeight(qreal value);
private slots:
void slotSwitch();
void slotShow(bool show);
void slotDeleteEffect();
void slotEffectUp();
void slotEffectDown();
void slotSaveEffect();
void slotCreateGroup();
void slotCreateRegion();
void slotUnGroup();
/** @brief A sub effect parameter was changed */
void slotUpdateRegionEffectParams(const QDomElement & /*old*/, const QDomElement & /*e*/, int /*ix*/);
/** @brief Dis/enable effect before processing an operation (color picker) */
void slotDisableEffect(bool disable);
void prepareImportClipKeyframes();
private:
ParameterContainer *m_paramWidget;
QList<CollapsibleEffect *> m_subParamWidgets;
QDomElement m_effect;
ItemInfo m_itemInfo;
QDomElement m_original_effect;
QList<QDomElement> m_subEffects;
QMenu *m_menu;
QPoint m_clickPoint;
EffectInfo m_info;
bool m_isMovable;
QTimeLine *m_animation;
/** @brief True if this is a region effect, which behaves in a special way, like a group. */
bool m_regionEffect;
/** @brief The add group action. */
QAction *m_groupAction;
KDualAction *m_enabledButton;
QLabel *m_colorIcon;
QPixmap m_iconPix;
/** @brief Check if collapsed state changed and inform MLT. */
void updateCollapsedState();
protected:
void mouseDoubleClickEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event) override;
void dragLeaveEvent(QDragLeaveEvent *event) override;
void dropEvent(QDropEvent *event) override;
signals:
void parameterChanged(const QDomElement &, const QDomElement &, int, bool update = true);
void syncEffectsPos(int);
void effectStateChanged(bool, int ix, MonitorSceneType effectNeedsMonitorScene);
void deleteEffect(const QDomElement &);
void activateEffect(int);
void checkMonitorPosition(int);
void seekTimeline(int);
/** @brief Start an MLT filter job on this clip. */
void startFilterJob(QMap<QString, QString> &, QMap<QString, QString> &, QMap<QString, QString> &);
/** @brief An effect was reset, trigger param reload. */
void resetEffect(int ix);
/** @brief Ask for creation of a group. */
void createGroup(int ix);
void unGroup(CollapsibleEffect *);
void createRegion(int, const QUrl &);
void deleteGroup(const QDomDocument &);
void importClipKeyframes(GraphicsRectItem, ItemInfo, QDomElement, const QMap<QString, QString> &keyframes = QMap<QString, QString>());
};
#endif
/***************************************************************************
* Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@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) 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 "collapsiblegroup.h"
#include "kdenlive_debug.h"
#include <QDir>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QFontDatabase>
#include <QInputDialog>
#include <QMenu>
#include <QMimeData>
#include <QMutexLocker>
#include <QStandardPaths>
#include <QVBoxLayout>
#include <KColorScheme>
#include <KDualAction>
#include <KMessageBox>
#include <klocalizedstring.h>
MyEditableLabel::MyEditableLabel(QWidget *parent)
: QLineEdit(parent)
{
setFrame(false);
setReadOnly(true);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
}
void MyEditableLabel::mouseDoubleClickEvent(QMouseEvent *e)
{
setReadOnly(false);
selectAll();
e->accept();
}
CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, const EffectInfo &info, QWidget *parent)
: AbstractCollapsibleWidget(parent)
{
m_info.groupIndex = ix;
m_subWidgets = QList<CollapsibleEffect *>();
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
frame->setObjectName(QStringLiteral("framegroup"));
decoframe->setObjectName(QStringLiteral("decoframegroup"));
QHBoxLayout *l = static_cast<QHBoxLayout *>(frame->layout());
m_title = new MyEditableLabel(this);
l->insertWidget(2, m_title);
m_title->setText(info.groupName.isEmpty() ? i18n("Effect Group") : info.groupName);
m_info.groupName = m_title->text();
connect(m_title, &QLineEdit::editingFinished, this, &CollapsibleGroup::slotRenameGroup);
buttonUp->setIcon(QIcon::fromTheme(QStringLiteral("kdenlive-up")));
buttonUp->setToolTip(i18n("Move effect up"));
buttonDown->setIcon(QIcon::fromTheme(QStringLiteral("kdenlive-down")));
buttonDown->setToolTip(i18n("Move effect down"));
buttonDel->setIcon(QIcon::fromTheme(QStringLiteral("kdenlive-deleffect")));
buttonDel->setToolTip(i18n("Delete effect"));
if (firstGroup) {
buttonUp->setVisible(false);
}
if (lastGroup) {
buttonDown->setVisible(false);
}
m_menu = new QMenu;
m_menu->addAction(QIcon::fromTheme(QStringLiteral("view-refresh")), i18n("Reset Group"), this, SLOT(slotResetGroup()));
m_menu->addAction(QIcon::fromTheme(QStringLiteral("document-save")), i18n("Save Group"), this, SLOT(slotSaveGroup()));
m_menu->addAction(QIcon::fromTheme(QStringLiteral("list-remove")), i18n("Ungroup"), this, SLOT(slotUnGroup()));
setAcceptDrops(true);
menuButton->setIcon(QIcon::fromTheme(QStringLiteral("kdenlive-menu")));
menuButton->setMenu(m_menu);
m_enabledButton = new KDualAction(i18n("Disable Effect"), i18n("Enable Effect"), this);
m_enabledButton->setActiveIcon(QIcon::fromTheme(QStringLiteral("hint")));
m_enabledButton->setInactiveIcon(QIcon::fromTheme(QStringLiteral("visibility")));
enabledButton->setDefaultAction(m_enabledButton);
if (info.groupIsCollapsed) {
slotShow(false);
}
connect(collapseButton, &QAbstractButton::clicked, this, &CollapsibleGroup::slotSwitch);
connect(m_enabledButton, SIGNAL(activeChangedByUser(bool)), this, SLOT(slotEnable(bool)));
connect(buttonUp, &QAbstractButton::clicked, this, &CollapsibleGroup::slotEffectUp);
connect(buttonDown, &QAbstractButton::clicked, this, &CollapsibleGroup::slotEffectDown);
connect(buttonDel, &QAbstractButton::clicked, this, &CollapsibleGroup::slotDeleteGroup);
}
CollapsibleGroup::~CollapsibleGroup()
{
delete m_menu;
}
void CollapsibleGroup::slotUnGroup()
{
emit unGroup(this);
}
bool CollapsibleGroup::isActive() const
{
return decoframe->property("active").toBool();
}
void CollapsibleGroup::setActive(bool activate)
{
decoframe->setProperty("active", activate);
decoframe->setStyleSheet(decoframe->styleSheet());
}
void CollapsibleGroup::mouseDoubleClickEvent(QMouseEvent *event)
{
if (frame->underMouse() && collapseButton->isEnabled()) {
slotSwitch();
}
QWidget::mouseDoubleClickEvent(event);
}
void CollapsibleGroup::slotEnable(bool disable, bool emitInfo)
{
m_title->setEnabled(!disable);
for (int i = 0; i < m_subWidgets.count(); ++i) {
m_subWidgets.at(i)->slotDisable(disable, emitInfo);
}
}
void CollapsibleGroup::slotDeleteGroup()
{
QDomDocument doc;
// delete effects from the last one to the first, otherwise each deletion would trigger an update
// in other effects's kdenlive_ix index.
for (int i = m_subWidgets.count() - 1; i >= 0; --i) {
doc.appendChild(doc.importNode(m_subWidgets.at(i)->effect(), true));
}
doc.documentElement().setAttribute(QStringLiteral("name"), m_info.groupName);
emit deleteGroup(doc);
}
void CollapsibleGroup::slotEffectUp()
{
QList<int> indexes;
indexes.reserve(m_subWidgets.count());
for (int i = 0; i < m_subWidgets.count(); ++i) {
indexes << m_subWidgets.at(i)->effectIndex();
}
emit changeEffectPosition(indexes, true);
}
void CollapsibleGroup::slotEffectDown()
{
QList<int> indexes;
indexes.reserve(m_subWidgets.count());
for (int i = 0; i < m_subWidgets.count(); ++i) {
indexes << m_subWidgets.at(i)->effectIndex();
}
emit changeEffectPosition(indexes, false);
}
void CollapsibleGroup::slotSaveGroup()
{
QString name = QInputDialog::getText(this, i18n("Save Group"), i18n("Name for saved group: "), QLineEdit::Normal, m_title->text());
if (name.isEmpty()) {
return;
}
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/effects/"));
if (!dir.exists()) {
dir.mkpath(QStringLiteral("."));
}
if (dir.exists(name + QStringLiteral(".xml"))) {
if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", name + QStringLiteral(".xml"))) == KMessageBox::No) {
return;
}
}
QDomDocument doc = effectsData();
QDomElement base = doc.documentElement();
QDomNodeList effects = base.elementsByTagName(QStringLiteral("effect"));
for (int i = 0; i < effects.count(); ++i) {
QDomElement eff = effects.at(i).toElement();
eff.removeAttribute(QStringLiteral("kdenlive_ix"));
EffectInfo info;
info.fromString(eff.attribute(QStringLiteral("kdenlive_info")));
// Make sure all effects have the correct new group name
info.groupName = name;
// Saved effect group should have a group index of -1
info.groupIndex = -1;
eff.setAttribute(QStringLiteral("kdenlive_info"), info.toString());
}
base.setAttribute(QStringLiteral("name"), name);
base.setAttribute(QStringLiteral("id"), name);
base.setAttribute(QStringLiteral("type"), QStringLiteral("custom"));
QFile file(dir.absoluteFilePath(name + QStringLiteral(".xml")));
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
QTextStream out(&file);
out << doc.toString();
}
file.close();
emit reloadEffects();
}
void CollapsibleGroup::slotResetGroup()
{
QMutexLocker lock(&m_mutex);
for (int i = 0; i < m_subWidgets.count(); ++i) {
m_subWidgets.at(i)->slotResetEffect();
}
}
void CollapsibleGroup::slotSwitch()
{
bool enable = !widgetFrame->isVisible();
slotShow(enable);
}
void CollapsibleGroup::slotShow(bool show)
{
widgetFrame->setVisible(show);
if (show) {
collapseButton->setArrowType(Qt::DownArrow);
m_info.groupIsCollapsed = false;
} else {
collapseButton->setArrowType(Qt::RightArrow);
m_info.groupIsCollapsed = true;
}
if (!m_subWidgets.isEmpty()) {
m_subWidgets.at(0)->groupStateChanged(m_info.groupIsCollapsed);
}
}
QWidget *CollapsibleGroup::title() const
{
return m_title;
}
void CollapsibleGroup::addGroupEffect(CollapsibleEffect *effect)
{
QMutexLocker lock(&m_mutex);
QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
if (vbox == nullptr) {
vbox = new QVBoxLayout();
vbox->setContentsMargins(0, 0, 0, 0);
vbox->setSpacing(2);
widgetFrame->setLayout(vbox);
}
effect->setGroupIndex(groupIndex());
effect->setGroupName(m_title->text());
effect->decoframe->setObjectName(QStringLiteral("decoframesub"));
m_subWidgets.append(effect);
vbox->addWidget(effect);
}
QString CollapsibleGroup::infoString() const
{
return m_info.toString();
}
void CollapsibleGroup::removeGroup(int ix, QVBoxLayout *layout)
{
QMutexLocker lock(&m_mutex);
QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
if (vbox == nullptr) {
return;
}
for (int i = m_subWidgets.count() - 1; i >= 0; --i) {
vbox->removeWidget(m_subWidgets.at(i));
layout->insertWidget(ix, m_subWidgets.at(i));
m_subWidgets.at(i)->decoframe->setObjectName(QStringLiteral("decoframe"));
m_subWidgets.at(i)->removeFromGroup();
}
m_subWidgets.clear();
}
int CollapsibleGroup::groupIndex() const
{
return m_info.groupIndex;
}
bool CollapsibleGroup::isGroup() const
{
return true;
}
void CollapsibleGroup::updateTimecodeFormat()
{
QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
if (vbox == nullptr) {
return;
}
for (int j = vbox->count() - 1; j >= 0; --j) {
CollapsibleEffect *e = static_cast<CollapsibleEffect *>(vbox->itemAt(j)->widget());
if (e) {
e->updateTimecodeFormat();