From 4f16ab3780bd444f7c85bc70e0df18bffcc8cba4 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Wed, 28 Mar 2012 20:31:35 +0200 Subject: [PATCH] New widget for effect group --- src/CMakeLists.txt | 1 + src/effectstack/CMakeLists.txt | 2 + src/effectstack/abstractcollapsiblewidget.cpp | 28 ++ src/effectstack/abstractcollapsiblewidget.h | 37 +++ src/effectstack/collapsibleeffect.cpp | 127 +++----- src/effectstack/collapsibleeffect.h | 19 +- src/effectstack/collapsiblegroup.cpp | 298 ++++++++++++++++++ src/effectstack/collapsiblegroup.h | 99 ++++++ src/effectstack/effectstackview2.cpp | 39 +-- src/effectstack/effectstackview2.h | 5 +- src/effectstackedit.cpp | 2 +- src/widgets/collapsiblegroup_ui.ui | 222 +++++++++++++ 12 files changed, 757 insertions(+), 122 deletions(-) create mode 100644 src/effectstack/abstractcollapsiblewidget.cpp create mode 100644 src/effectstack/abstractcollapsiblewidget.h create mode 100644 src/effectstack/collapsiblegroup.cpp create mode 100644 src/effectstack/collapsiblegroup.h create mode 100644 src/widgets/collapsiblegroup_ui.ui diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fdbd92b4..e7a73b4e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -197,6 +197,7 @@ kde4_add_ui_files(kdenlive_UIS widgets/clipproperties_ui.ui widgets/cliptranscode_ui.ui widgets/collapsiblewidget_ui.ui + widgets/collapsiblegroup_ui.ui widgets/clipstabilize_ui.ui widgets/colorclip_ui.ui widgets/colorplaneexport_ui.ui diff --git a/src/effectstack/CMakeLists.txt b/src/effectstack/CMakeLists.txt index de217223..613236cc 100644 --- a/src/effectstack/CMakeLists.txt +++ b/src/effectstack/CMakeLists.txt @@ -1,6 +1,8 @@ set(kdenlive_SRCS ${kdenlive_SRCS} + effectstack/abstractcollapsiblewidget.cpp effectstack/collapsibleeffect.cpp + effectstack/collapsiblegroup.cpp effectstack/effectstackview2.cpp PARENT_SCOPE ) diff --git a/src/effectstack/abstractcollapsiblewidget.cpp b/src/effectstack/abstractcollapsiblewidget.cpp new file mode 100644 index 00000000..1820a501 --- /dev/null +++ b/src/effectstack/abstractcollapsiblewidget.cpp @@ -0,0 +1,28 @@ +/*************************************************************************** + * 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) +{ + +} \ No newline at end of file diff --git a/src/effectstack/abstractcollapsiblewidget.h b/src/effectstack/abstractcollapsiblewidget.h new file mode 100644 index 00000000..9177d7bb --- /dev/null +++ b/src/effectstack/abstractcollapsiblewidget.h @@ -0,0 +1,37 @@ +/*************************************************************************** + * 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 + +class AbstractCollapsibleWidget : public QWidget +{ + Q_OBJECT + +public: + AbstractCollapsibleWidget(QWidget * parent = 0); + virtual void setActive(bool activate) = 0; + virtual bool isGroup() const = 0; + +}; + +#endif diff --git a/src/effectstack/collapsibleeffect.cpp b/src/effectstack/collapsibleeffect.cpp index 550f2d66..8431bfa5 100644 --- a/src/effectstack/collapsibleeffect.cpp +++ b/src/effectstack/collapsibleeffect.cpp @@ -118,14 +118,12 @@ void MySpinBox::focusOutEvent(QFocusEvent*) } -CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_effect, ItemInfo info, int ix, EffectMetaInfo *metaInfo, bool lastEffect, bool isGroup, QWidget * parent) : - QWidget(parent), +CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_effect, ItemInfo info, EffectMetaInfo *metaInfo, bool lastEffect, QWidget * parent) : + AbstractCollapsibleWidget(parent), m_paramWidget(NULL), m_effect(effect), m_original_effect(original_effect), - m_lastEffect(lastEffect), - m_isGroup(isGroup), - m_index(ix) + m_lastEffect(lastEffect) { setupUi(this); filterWheelEvent = true; @@ -154,25 +152,19 @@ CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_ef m_menu->addAction(KIcon("view-refresh"), i18n("Reset effect"), this, SLOT(slotResetEffect())); m_menu->addAction(KIcon("document-save"), i18n("Save effect"), this, SLOT(slotSaveEffect())); - if (!m_isGroup) { - QDomElement namenode = m_effect.firstChildElement("name"); - if (namenode.isNull()) return; - title->setText(i18n(namenode.text().toUtf8().data())); - QString type = m_effect.attribute("type", QString()); - KIcon icon; - if (type == "audio") icon = KIcon("kdenlive-show-audio"); - else if (m_effect.attribute("tag") == "region") icon = KIcon("kdenlive-mask-effect"); - else if (type == "custom") icon = KIcon("kdenlive-custom-effect"); - else icon = KIcon("kdenlive-show-video"); - effecticon->setPixmap(icon.pixmap(16,16)); - m_menu->addAction(KIcon("folder-new"), i18n("Create Group"), this, SLOT(slotCreateGroup())); - setupWidget(info, ix, metaInfo); - } - else { - title->setText(i18n("Effect Group")); - effecticon->setPixmap(KIcon("folder").pixmap(16,16)); - m_menu->addAction(KIcon("list-remove"), i18n("Ungroup"), this, SLOT(slotUnGroup())); - } + QDomElement namenode = m_effect.firstChildElement("name"); + if (namenode.isNull()) return; + title->setText(i18n(namenode.text().toUtf8().data())); + QString type = m_effect.attribute("type", QString()); + KIcon icon; + if (type == "audio") icon = KIcon("kdenlive-show-audio"); + else if (m_effect.attribute("tag") == "region") icon = KIcon("kdenlive-mask-effect"); + else if (type == "custom") icon = KIcon("kdenlive-custom-effect"); + else icon = KIcon("kdenlive-show-video"); + effecticon->setPixmap(icon.pixmap(16,16)); + m_menu->addAction(KIcon("folder-new"), i18n("Create Group"), this, SLOT(slotCreateGroup())); + setupWidget(info, metaInfo); + setAcceptDrops(true); menuButton->setIcon(KIcon("kdenlive-menu")); menuButton->setMenu(m_menu); @@ -225,7 +217,7 @@ const QString CollapsibleEffect::getStyleSheet(QPalette p) KColorScheme scheme2(p.currentColorGroup(), KColorScheme::Window, KSharedConfig::openConfig(KdenliveSettings::colortheme())); QColor normal_bg2 = scheme2.background(KColorScheme::NormalBackground).color(); - QString stylesheet(QString("QFrame#decoframe {border-radius:5px;border:0px solid %1;border-top:0px;background:%6;} QFrame:hover#decoframe {background:%7;} QFrame#decoframe[active=\"true\"] {background:%5;} QFrame#frame[active=\"true\"] {background:%3;} QProgressBar::chunk:horizontal {background: %6;border-top-left-radius: 4px;border-bottom-left-radius: 4px;} QProgressBar::chunk:horizontal#dragOnly {background: %5;border-top-left-radius: 4px;border-bottom-left-radius: 4px;} QProgressBar::chunk:horizontal:hover {background: %3;}\ + QString stylesheet(QString("QLineEdit#title { background-color: transparent;} QFrame#decoframe {border-radius:5px;border:0px solid %1;background:%6;} QFrame#decoframegroup {border-radius:5px;border:1px solid %1;background:%6;} QFrame:hover#decoframe {background:%7;} QFrame#decoframe[active=\"true\"] {background:%5;} QFrame#decoframegroup[active=\"true\"] {background:%5;} QFrame#frame[active=\"true\"] {background:%3;} QProgressBar::chunk:horizontal {background: %6;border-top-left-radius: 4px;border-bottom-left-radius: 4px;} QProgressBar::chunk:horizontal#dragOnly {background: %5;border-top-left-radius: 4px;border-bottom-left-radius: 4px;} QProgressBar::chunk:horizontal:hover {background: %3;}\ QProgressBar:horizontal {border: 1px solid %1;border-top-left-radius: 4px;border-bottom-left-radius: 4px;border-right:0px;background:%5;padding: 0px;text-align:left center}\ QProgressBar:horizontal:disabled {border: 1px solid %6} QProgressBar:horizontal#dragOnly {background: %5}\ QProgressBar:horizontal[inTimeline=\"true\"] { border: 1px solid %2;border-right: 0px;background: %4;padding: 0px;text-align:left center } QProgressBar::chunk:horizontal[inTimeline=\"true\"] {background: %2;}\ @@ -350,35 +342,26 @@ void CollapsibleEffect::slotEnable(bool enable) enabledBox->blockSignals(true); enabledBox->setChecked(enable); enabledBox->blockSignals(false); - if (m_isGroup) { - QVBoxLayout *vbox = static_cast(widgetFrame->layout()); - if (vbox == NULL) return; - for (int i = 0; i < vbox->count(); i++) { - CollapsibleEffect *e = static_cast(vbox->itemAt(i)->widget()); - if (e) e->enabledBox->setChecked(enable);// slotEnable(enable); - } - } else { - m_effect.setAttribute("disable", enable ? 0 : 1); - if (enable || KdenliveSettings::disable_effect_parameters()) { - widgetFrame->setEnabled(enable); - } - emit effectStateChanged(!enable, effectIndex()); + m_effect.setAttribute("disable", enable ? 0 : 1); + if (enable || KdenliveSettings::disable_effect_parameters()) { + widgetFrame->setEnabled(enable); } + emit effectStateChanged(!enable, effectIndex()); } void CollapsibleEffect::slotDeleteEffect() { - if (!m_isGroup) emit deleteEffect(m_effect); + emit deleteEffect(m_effect); } void CollapsibleEffect::slotEffectUp() { - if (!m_isGroup) emit changeEffectPosition(effectIndex(), true); + emit changeEffectPosition(effectIndex(), true); } void CollapsibleEffect::slotEffectDown() { - if (!m_isGroup) emit changeEffectPosition(effectIndex(), false); + emit changeEffectPosition(effectIndex(), false); } void CollapsibleEffect::slotSaveEffect() @@ -453,18 +436,6 @@ void CollapsibleEffect::setGroupIndex(int ix) m_info.groupIndex = ix; } -void CollapsibleEffect::addGroupEffect(CollapsibleEffect *effect) -{ - QVBoxLayout *vbox = static_cast(widgetFrame->layout()); - if (vbox == NULL) { - vbox = new QVBoxLayout(); - vbox->setContentsMargins(10, 0, 0, 0); - vbox->setSpacing(2); - widgetFrame->setLayout(vbox); - } - effect->setGroupIndex(groupIndex()); - vbox->addWidget(effect); -} QString CollapsibleEffect::infoString() const { @@ -485,20 +456,9 @@ void CollapsibleEffect::removeGroup(int ix, QVBoxLayout *layout) } } -int CollapsibleEffect::index() const -{ - return m_index; -} - int CollapsibleEffect::groupIndex() const { - if (m_isGroup) return m_index; - return -1; -} - -bool CollapsibleEffect::isGroup() const -{ - return m_isGroup; + return m_info.groupIndex; } int CollapsibleEffect::effectIndex() const @@ -507,7 +467,7 @@ int CollapsibleEffect::effectIndex() const return m_effect.attribute("kdenlive_ix").toInt(); } -void CollapsibleEffect::updateWidget(ItemInfo info, int index, QDomElement effect, EffectMetaInfo *metaInfo) +void CollapsibleEffect::updateWidget(ItemInfo info, QDomElement effect, EffectMetaInfo *metaInfo) { if (m_paramWidget) { // cleanup @@ -515,10 +475,10 @@ void CollapsibleEffect::updateWidget(ItemInfo info, int index, QDomElement effec m_paramWidget = NULL; } m_effect = effect; - setupWidget(info, index, metaInfo); + setupWidget(info, metaInfo); } -void CollapsibleEffect::setupWidget(ItemInfo info, int index, EffectMetaInfo *metaInfo) +void CollapsibleEffect::setupWidget(ItemInfo info, EffectMetaInfo *metaInfo) { if (m_effect.isNull()) { // kDebug() << "// EMPTY EFFECT STACK"; @@ -533,9 +493,9 @@ void CollapsibleEffect::setupWidget(ItemInfo info, int index, EffectMetaInfo *me QDomNodeList origin_effects = m_original_effect.elementsByTagName("effect"); QWidget *container = new QWidget(widgetFrame); vbox->addWidget(container); - m_paramWidget = new ParameterContainer(m_effect.toElement(), info, metaInfo, index, container); + m_paramWidget = new ParameterContainer(m_effect.toElement(), info, metaInfo, container); for (int i = 0; i < effects.count(); i++) { - CollapsibleEffect *coll = new CollapsibleEffect(effects.at(i).toElement(), origin_effects.at(i).toElement(), info, i, metaInfo, container); + CollapsibleEffect *coll = new CollapsibleEffect(effects.at(i).toElement(), origin_effects.at(i).toElement(), info, metaInfo, container); m_subParamWidgets.append(coll); //container = new QWidget(widgetFrame); vbox->addWidget(coll); @@ -544,7 +504,7 @@ void CollapsibleEffect::setupWidget(ItemInfo info, int index, EffectMetaInfo *me } else { - m_paramWidget = new ParameterContainer(m_effect, info, metaInfo, index, widgetFrame); + m_paramWidget = new ParameterContainer(m_effect, info, metaInfo, widgetFrame); if (m_effect.firstChildElement("parameter").isNull()) { // Effect has no parameter, don't allow expand collapseButton->setEnabled(false); @@ -569,6 +529,11 @@ void CollapsibleEffect::setupWidget(ItemInfo info, int index, EffectMetaInfo *me } +bool CollapsibleEffect::isGroup() const +{ + return false; +} + void CollapsibleEffect::updateTimecodeFormat() { m_paramWidget->updateTimecodeFormat(); @@ -622,23 +587,12 @@ void CollapsibleEffect::dropEvent(QDropEvent *event) emit addEffect(e); return; } - int new_index = -1; - if (m_isGroup) { - QVBoxLayout *vbox = static_cast(widgetFrame->layout()); - if (vbox == NULL) return; - CollapsibleEffect *e = static_cast(vbox->itemAt(vbox->count() -1)->widget()); - new_index = e->effectIndex(); - } - else { - new_index = effectIndex(); - } - emit moveEffect(ix, new_index, this); + emit moveEffect(ix, effectIndex(), groupIndex()); event->setDropAction(Qt::MoveAction); event->accept(); } -ParameterContainer::ParameterContainer(QDomElement effect, ItemInfo info, EffectMetaInfo *metaInfo, int index, QWidget * parent) : - m_index(index), +ParameterContainer::ParameterContainer(QDomElement effect, ItemInfo info, EffectMetaInfo *metaInfo, QWidget * parent) : m_keyframeEditor(NULL), m_geometryWidget(NULL), m_metaInfo(metaInfo), @@ -1332,11 +1286,6 @@ QString ParameterContainer::getWipeString(wipeInfo info) return QString(start + ";-1=" + end); } -int ParameterContainer::index() const -{ - return m_index; -} - void ParameterContainer::slotStartFilterJobAction() { QDomNodeList namenode = m_effect.elementsByTagName("parameter"); diff --git a/src/effectstack/collapsibleeffect.h b/src/effectstack/collapsibleeffect.h index 235d5a83..d5e54043 100644 --- a/src/effectstack/collapsibleeffect.h +++ b/src/effectstack/collapsibleeffect.h @@ -24,6 +24,7 @@ #include "ui_collapsiblewidget_ui.h" +#include "abstractcollapsiblewidget.h" #include "timecode.h" #include "keyframeedit.h" @@ -68,11 +69,10 @@ class ParameterContainer : public QObject Q_OBJECT public: - ParameterContainer(QDomElement effect, ItemInfo info, EffectMetaInfo *metaInfo, int index, QWidget * parent = 0); + ParameterContainer(QDomElement effect, ItemInfo info, EffectMetaInfo *metaInfo, QWidget * parent = 0); ~ParameterContainer(); void updateTimecodeFormat(); void updateProjectFormat(MltVideoProfile profile, Timecode t); - int index() const; private slots: void slotCollectAllParameters(); @@ -89,7 +89,6 @@ private: int m_in; int m_out; - int m_index; QList m_uiItems; QMap m_valueItems; Timecode m_timecode; @@ -117,23 +116,21 @@ signals: * @author Jean-Baptiste Mardelle */ -class CollapsibleEffect : public QWidget, public Ui::CollapsibleWidget_UI +class CollapsibleEffect : public AbstractCollapsibleWidget, public Ui::CollapsibleWidget_UI { Q_OBJECT public: - CollapsibleEffect(QDomElement effect, QDomElement original_effect, ItemInfo info, int ix, EffectMetaInfo *metaInfo, bool lastEffect, bool isGroup = false, QWidget * parent = 0); + CollapsibleEffect(QDomElement effect, QDomElement original_effect, ItemInfo info, EffectMetaInfo *metaInfo, bool lastEffect, QWidget * parent = 0); ~CollapsibleEffect(); static QMap iconCache; - void setupWidget(ItemInfo info, int index, EffectMetaInfo *metaInfo); + void setupWidget(ItemInfo info, EffectMetaInfo *metaInfo); void updateTimecodeFormat(); void setActive(bool activate); virtual bool eventFilter( QObject * o, QEvent * e ); /** @brief Update effect GUI to reflect parameted changes. */ - void updateWidget(ItemInfo info, int index, QDomElement effect, EffectMetaInfo *metaInfo); + void updateWidget(ItemInfo info, QDomElement effect, EffectMetaInfo *metaInfo); QDomElement effect() const; - void addGroupEffect(CollapsibleEffect *effect); - int index() const; int groupIndex() const; bool isGroup() const; int effectIndex() const; @@ -171,10 +168,8 @@ private: bool m_lastEffect; int m_in; int m_out; - bool m_isGroup; QMenu *m_menu; QPoint m_clickPoint; - int m_index; EffectInfo m_info; void updateGroupIndex(int groupIndex); @@ -203,7 +198,7 @@ signals: void resetEffect(int ix); /** @brief Ask for creation of a group. */ void createGroup(int ix); - void moveEffect(int current_pos, int new_pos, CollapsibleEffect *target); + void moveEffect(int current_pos, int new_pos, int groupIndex); void unGroup(CollapsibleEffect *); void addEffect(QDomElement e); }; diff --git a/src/effectstack/collapsiblegroup.cpp b/src/effectstack/collapsiblegroup.cpp new file mode 100644 index 00000000..11fb7493 --- /dev/null +++ b/src/effectstack/collapsiblegroup.cpp @@ -0,0 +1,298 @@ +/*************************************************************************** + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, QWidget * parent) : + AbstractCollapsibleWidget(parent), + m_index(ix) +{ + setupUi(this); + setFont(KGlobalSettings::smallestReadableFont()); + + buttonUp->setIcon(KIcon("kdenlive-up")); + buttonUp->setToolTip(i18n("Move effect up")); + buttonDown->setIcon(KIcon("kdenlive-down")); + buttonDown->setToolTip(i18n("Move effect down")); + + buttonDel->setIcon(KIcon("kdenlive-deleffect")); + buttonDel->setToolTip(i18n("Delete effect")); + if (firstGroup) buttonUp->setVisible(false); + if (lastGroup) buttonDown->setVisible(false); + m_menu = new QMenu; + m_menu->addAction(KIcon("view-refresh"), i18n("Reset effect"), this, SLOT(slotResetEffect())); + m_menu->addAction(KIcon("document-save"), i18n("Save effect"), this, SLOT(slotSaveEffect())); + + title->setText(i18n("Effect Group")); + effecticon->setPixmap(KIcon("folder").pixmap(16,16)); + m_menu->addAction(KIcon("list-remove"), i18n("Ungroup"), this, SLOT(slotUnGroup())); + setAcceptDrops(true); + menuButton->setIcon(KIcon("kdenlive-menu")); + menuButton->setMenu(m_menu); + + enabledBox->setChecked(true); + + connect(collapseButton, SIGNAL(clicked()), this, SLOT(slotSwitch())); + connect(enabledBox, SIGNAL(toggled(bool)), this, SLOT(slotEnable(bool))); + connect(buttonUp, SIGNAL(clicked()), this, SLOT(slotEffectUp())); + connect(buttonDown, SIGNAL(clicked()), this, SLOT(slotEffectDown())); + connect(buttonDel, SIGNAL(clicked()), this, SLOT(slotDeleteEffect())); + +} + +CollapsibleGroup::~CollapsibleGroup() +{ + delete m_menu; +} + +void CollapsibleGroup::slotUnGroup() +{ + emit unGroup(this); +} + +bool CollapsibleGroup::isActive() const +{ + return decoframegroup->property("active").toBool(); +} + +void CollapsibleGroup::setActive(bool activate) +{ + decoframegroup->setProperty("active", activate); + decoframegroup->setStyleSheet(decoframegroup->styleSheet()); +} + +void CollapsibleGroup::mouseDoubleClickEvent ( QMouseEvent * event ) +{ + if (frame->underMouse() && collapseButton->isEnabled()) slotSwitch(); + QWidget::mouseDoubleClickEvent(event); +} + + +void CollapsibleGroup::slotEnable(bool enable) +{ + title->setEnabled(enable); + enabledBox->blockSignals(true); + enabledBox->setChecked(enable); + enabledBox->blockSignals(false); + QVBoxLayout *vbox = static_cast(widgetFrame->layout()); + if (vbox == NULL) return; + for (int i = 0; i < vbox->count(); i++) { + CollapsibleGroup *e = static_cast(vbox->itemAt(i)->widget()); + if (e) e->enabledBox->setChecked(enable);// slotEnable(enable); + } +} + +void CollapsibleGroup::slotDeleteEffect() +{ + emit deleteGroup(groupIndex()); +} + +void CollapsibleGroup::slotEffectUp() +{ + emit changeGroupPosition(groupIndex(), true); +} + +void CollapsibleGroup::slotEffectDown() +{ + emit changeGroupPosition(groupIndex(), false); +} + +void CollapsibleGroup::slotSaveEffect() +{ + QString name = QInputDialog::getText(this, i18n("Save Effect"), i18n("Name for saved effect: ")); + if (name.isEmpty()) return; + QString path = KStandardDirs::locateLocal("appdata", "effects/", true); + path = path + name + ".xml"; + if (QFile::exists(path)) if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", path)) == KMessageBox::No) return; + + /*TODO + QDomDocument doc; + QDomElement effect = m_effect.cloneNode().toElement(); + doc.appendChild(doc.importNode(effect, true)); + effect = doc.firstChild().toElement(); + effect.removeAttribute("kdenlive_ix"); + effect.setAttribute("id", name); + effect.setAttribute("type", "custom"); + QDomElement effectname = effect.firstChildElement("name"); + effect.removeChild(effectname); + effectname = doc.createElement("name"); + QDomText nametext = doc.createTextNode(name); + effectname.appendChild(nametext); + effect.insertBefore(effectname, QDomNode()); + QDomElement effectprops = effect.firstChildElement("properties"); + effectprops.setAttribute("id", name); + effectprops.setAttribute("type", "custom"); + + QFile file(path); + if (file.open(QFile::WriteOnly | QFile::Truncate)) { + QTextStream out(&file); + out << doc.toString(); + } + file.close(); + emit reloadEffects();*/ +} + +void CollapsibleGroup::slotResetEffect() +{ + //TODO: emit resetEffect(effectIndex()); +} + +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.isCollapsed = false; + } + else { + collapseButton->setArrowType(Qt::RightArrow); + m_info.isCollapsed = true; + } + //emit parameterChanged(m_original_effect, m_effect, effectIndex()); +} + +void CollapsibleGroup::updateGroupIndex(int groupIndex) +{ + /*TODO: + m_info.groupIndex = groupIndex; + m_effect.setAttribute("kdenlive_info", m_info.toString()); + emit parameterChanged(m_original_effect, m_effect, effectIndex());*/ +} + +void CollapsibleGroup::addGroupEffect(CollapsibleEffect *effect) +{ + QVBoxLayout *vbox = static_cast(widgetFrame->layout()); + if (vbox == NULL) { + vbox = new QVBoxLayout(); + vbox->setContentsMargins(10, 0, 0, 0); + vbox->setSpacing(2); + widgetFrame->setLayout(vbox); + } + effect->setGroupIndex(groupIndex()); + vbox->addWidget(effect); +} + +QString CollapsibleGroup::infoString() const +{ + return m_info.toString(); +} + +void CollapsibleGroup::removeGroup(int ix, QVBoxLayout *layout) +{ + QVBoxLayout *vbox = static_cast(widgetFrame->layout()); + if (vbox == NULL) return; + + for (int j = vbox->count() - 1; j >= 0; j--) { + QLayoutItem *child = vbox->takeAt(j); + CollapsibleGroup *e = static_cast(child->widget()); + layout->insertWidget(ix, e); + e->updateGroupIndex(-1); + delete child; + } +} + +int CollapsibleGroup::groupIndex() const +{ + return m_index; +} + + + +bool CollapsibleGroup::isGroup() const +{ + return true; +} + +void CollapsibleGroup::updateTimecodeFormat() +{ + QVBoxLayout *vbox = static_cast(widgetFrame->layout()); + if (vbox == NULL) return; + for (int j = vbox->count() - 1; j >= 0; j--) { + CollapsibleEffect *e = static_cast(vbox->itemAt(j)->widget()); + if (e) e->updateTimecodeFormat(); + } +} + +void CollapsibleGroup::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasFormat("kdenlive/effectslist")) { + frame->setProperty("active", true); + frame->setStyleSheet(frame->styleSheet()); + event->acceptProposedAction(); + } +} + +void CollapsibleGroup::dragLeaveEvent(QDragLeaveEvent */*event*/) +{ + frame->setProperty("active", false); + frame->setStyleSheet(frame->styleSheet()); +} + +void CollapsibleGroup::dropEvent(QDropEvent *event) +{ + frame->setProperty("active", false); + frame->setStyleSheet(frame->styleSheet()); + const QString effects = QString::fromUtf8(event->mimeData()->data("kdenlive/effectslist")); + //event->acceptProposedAction(); + QDomDocument doc; + doc.setContent(effects, true); + QDomElement e = doc.documentElement(); + int ix = e.attribute("kdenlive_ix").toInt(); + if (ix == 0) { + // effect dropped from effects list, add it + e.setAttribute("kdenlive_ix", ix); + event->setDropAction(Qt::CopyAction); + event->accept(); + emit addEffect(e); + return; + } + int new_index = -1; + QVBoxLayout *vbox = static_cast(widgetFrame->layout()); + if (vbox == NULL) return; + CollapsibleEffect *effect = static_cast(vbox->itemAt(vbox->count() -1)->widget()); + new_index = effect->effectIndex(); + emit moveEffect(ix, new_index, m_index); + event->setDropAction(Qt::MoveAction); + event->accept(); +} + diff --git a/src/effectstack/collapsiblegroup.h b/src/effectstack/collapsiblegroup.h new file mode 100644 index 00000000..a0972add --- /dev/null +++ b/src/effectstack/collapsiblegroup.h @@ -0,0 +1,99 @@ +/*************************************************************************** + * 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 COLLAPSIBLEGROUP_H +#define COLLAPSIBLEGROUP_H + + +#include "ui_collapsiblegroup_ui.h" + +#include "abstractcollapsiblewidget.h" +#include "collapsibleeffect.h" +#include "timecode.h" +#include "keyframeedit.h" + +#include +#include + +class QFrame; + + +/**) + * @class CollapsibleEffect + * @brief A dialog for editing markers and guides. + * @author Jean-Baptiste Mardelle + */ + +class CollapsibleGroup : public AbstractCollapsibleWidget, public Ui::CollapsibleGroup_UI +{ + Q_OBJECT + +public: + CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, QWidget * parent = 0); + ~CollapsibleGroup(); + void updateTimecodeFormat(); + void setActive(bool activate); + int groupIndex() const; + bool isGroup() const; + QString infoString() const; + bool isActive() const; + void addGroupEffect(CollapsibleEffect *effect); + void removeGroup(int ix, QVBoxLayout *layout); + +public slots: + void slotEnable(bool enable); + +private slots: + void slotSwitch(); + void slotShow(bool show); + void slotDeleteEffect(); + void slotEffectUp(); + void slotEffectDown(); + void slotSaveEffect(); + void slotResetEffect(); + void slotUnGroup(); + +private: + //QList m_subParamWidgets; + QMenu *m_menu; + EffectInfo m_info; + int m_index; + void updateGroupIndex(int groupIndex); + +protected: + virtual void mouseDoubleClickEvent ( QMouseEvent * event ); + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dragLeaveEvent(QDragLeaveEvent *event); + virtual void dropEvent(QDropEvent *event); + +signals: + void syncEffectsPos(int); + void effectStateChanged(bool, int ix = -1); + void deleteGroup(int); + void changeGroupPosition(int, bool); + void activateEffect(int); + void moveEffect(int current_pos, int new_pos, int groupIndex); + void addEffect(QDomElement e); + void unGroup(CollapsibleGroup *); +}; + + +#endif + diff --git a/src/effectstack/effectstackview2.cpp b/src/effectstack/effectstackview2.cpp index 829d2b6d..46b9afa5 100644 --- a/src/effectstack/effectstackview2.cpp +++ b/src/effectstack/effectstackview2.cpp @@ -26,6 +26,8 @@ #include "monitoreditwidget.h" #include "monitorscene.h" #include "kdenlivesettings.h" +#include "collapsibleeffect.h" +#include "collapsiblegroup.h" #include #include @@ -163,13 +165,14 @@ void EffectStackView2::setupListView(int ix) continue; } - CollapsibleEffect *group = NULL; + CollapsibleGroup *group = NULL; EffectInfo effectInfo; effectInfo.fromString(d.attribute("kdenlive_info")); if (effectInfo.groupIndex >= 0) { // effect is in a group - for (int i = 0; i < vbox1->count(); i++) { - CollapsibleEffect *eff = static_cast(vbox1->itemAt(i)->widget()); + + for (int j = 0; j < vbox1->count(); j++) { + CollapsibleGroup *eff = static_cast(vbox1->itemAt(j)->widget()); if (eff->isGroup() && eff->groupIndex() == effectInfo.groupIndex) { group = eff; break; @@ -177,10 +180,10 @@ void EffectStackView2::setupListView(int ix) } if (group == NULL) { - group = new CollapsibleEffect(QDomElement(), QDomElement(), ItemInfo(), effectInfo.groupIndex, &m_effectMetaInfo, false, true, m_ui.container->widget()); + group = new CollapsibleGroup(effectInfo.groupIndex, i == 0, i == m_currentEffectList.count() - 1, m_ui.container->widget()); if (!effectInfo.groupName.isEmpty()) group->title->setText(effectInfo.groupName); - connect(group, SIGNAL(moveEffect(int,int,CollapsibleEffect*)), this, SLOT(slotMoveEffect(int,int,CollapsibleEffect*))); - connect(group, SIGNAL(unGroup(CollapsibleEffect*)), this , SLOT(slotUnGroup(CollapsibleEffect*))); + connect(group, SIGNAL(moveEffect(int,int,int)), this, SLOT(slotMoveEffect(int,int,int))); + connect(group, SIGNAL(unGroup(CollapsibleGroup*)), this , SLOT(slotUnGroup(CollapsibleGroup*))); vbox1->addWidget(group); } if (effectInfo.groupIndex >= m_groupIndex) m_groupIndex = effectInfo.groupIndex + 1; @@ -200,7 +203,7 @@ void EffectStackView2::setupListView(int ix) } else info = m_clipref->info(); - CollapsibleEffect *currentEffect = new CollapsibleEffect(d, m_currentEffectList.at(i), info, i, &m_effectMetaInfo, i == m_currentEffectList.count() - 1, false, view); + CollapsibleEffect *currentEffect = new CollapsibleEffect(d, m_currentEffectList.at(i), info, &m_effectMetaInfo, i == m_currentEffectList.count() - 1, view); m_effects.append(currentEffect); if (group) { group->addGroupEffect(currentEffect); @@ -223,7 +226,7 @@ void EffectStackView2::setupListView(int ix) connect(currentEffect, SIGNAL(checkMonitorPosition(int)), this, SLOT(slotCheckMonitorPosition(int))); connect(currentEffect, SIGNAL(seekTimeline(int)), this , SLOT(slotSeekTimeline(int))); connect(currentEffect, SIGNAL(createGroup(int)), this , SLOT(slotCreateGroup(int))); - connect(currentEffect, SIGNAL(moveEffect(int,int,CollapsibleEffect*)), this , SLOT(slotMoveEffect(int,int,CollapsibleEffect*))); + connect(currentEffect, SIGNAL(moveEffect(int,int,int)), this , SLOT(slotMoveEffect(int,int,int))); connect(currentEffect, SIGNAL(addEffect(QDomElement)), this , SLOT(slotAddEffect(QDomElement))); //ui.title->setPixmap(icon.pixmap(QSize(12, 12))); @@ -540,11 +543,11 @@ void EffectStackView2::slotResetEffect(int ix) info.cropStart = GenTime(0); info.startPos = GenTime(-1); info.track = 0; - m_effects.at(ix)->updateWidget(info, ix, dom, &m_effectMetaInfo); + m_effects.at(ix)->updateWidget(info, dom, &m_effectMetaInfo); emit updateEffect(NULL, m_trackindex, old, dom, ix); } else { m_clipref->initEffect(dom); - m_effects.at(ix)->updateWidget(m_clipref->info(), ix, dom, &m_effectMetaInfo); + m_effects.at(ix)->updateWidget(m_clipref->info(), dom, &m_effectMetaInfo); //m_ui.region_url->setUrl(KUrl(dom.attribute("region"))); emit updateEffect(m_clipref, -1, old, dom, ix); } @@ -593,15 +596,15 @@ void EffectStackView2::slotCreateGroup(int ix) } } - CollapsibleEffect *group = new CollapsibleEffect(QDomElement(), QDomElement(), ItemInfo(), m_groupIndex, &m_effectMetaInfo, false, true, m_ui.container->widget()); + CollapsibleGroup *group = new CollapsibleGroup(m_groupIndex, ix == 1, ix == m_currentEffectList.count() - 2, m_ui.container->widget()); m_groupIndex++; - connect(group, SIGNAL(moveEffect(int,int,CollapsibleEffect*)), this , SLOT(slotMoveEffect(int,int,CollapsibleEffect*))); - connect(group, SIGNAL(unGroup(CollapsibleEffect*)), this , SLOT(slotUnGroup(CollapsibleEffect*))); + connect(group, SIGNAL(moveEffect(int,int,int)), this , SLOT(slotMoveEffect(int,int,int))); + connect(group, SIGNAL(unGroup(CollapsibleGroup*)), this , SLOT(slotUnGroup(CollapsibleGroup*))); l->insertWidget(groupPos, group); group->addGroupEffect(effectToMove); } -void EffectStackView2::slotMoveEffect(int currentIndex, int newIndex, CollapsibleEffect* target) +void EffectStackView2::slotMoveEffect(int currentIndex, int newIndex, int groupIndex) { CollapsibleEffect *effectToMove = getEffectByIndex(currentIndex); if (effectToMove == NULL) return; @@ -611,7 +614,7 @@ void EffectStackView2::slotMoveEffect(int currentIndex, int newIndex, Collapsibl EffectInfo effectinfo; effectinfo.fromString(oldeffect.attribute("kdenlive_info")); - effectinfo.groupIndex = target->groupIndex(); + effectinfo.groupIndex = groupIndex; neweffect.setAttribute("kdenlive_info", effectinfo.toString()); ItemInfo info; @@ -621,9 +624,9 @@ void EffectStackView2::slotMoveEffect(int currentIndex, int newIndex, Collapsibl info.cropStart = GenTime(0); info.startPos = GenTime(-1); info.track = 0; - emit updateEffect(NULL, m_trackindex, oldeffect, neweffect, effectToMove->index()); + emit updateEffect(NULL, m_trackindex, oldeffect, neweffect, effectToMove->effectIndex()); } else { - emit updateEffect(m_clipref, -1, oldeffect, neweffect, effectToMove->index()); + emit updateEffect(m_clipref, -1, oldeffect, neweffect, effectToMove->effectIndex()); } //if (currentIndex == newIndex) return; @@ -636,7 +639,7 @@ void EffectStackView2::slotMoveEffect(int currentIndex, int newIndex, Collapsibl } } -void EffectStackView2::slotUnGroup(CollapsibleEffect* group) +void EffectStackView2::slotUnGroup(CollapsibleGroup* group) { QVBoxLayout *l = static_cast(m_ui.container->widget()->layout()); int ix = l->indexOf(group); diff --git a/src/effectstack/effectstackview2.h b/src/effectstack/effectstackview2.h index a3ab02f0..431af94b 100644 --- a/src/effectstack/effectstackview2.h +++ b/src/effectstack/effectstackview2.h @@ -27,6 +27,7 @@ #include "ui_effectstack2_ui.h" #include "effectstackedit.h" #include "collapsibleeffect.h" +#include "collapsiblegroup.h" class EffectsList; class ClipItem; @@ -157,10 +158,10 @@ private slots: ** @param group the effect on which the effect was dropped ** @param lastEffectIndex the last effect index in the group, effect will be inserted after that index */ - void slotMoveEffect(int currentIndex, int newIndex, CollapsibleEffect* target); + void slotMoveEffect(int currentIndex, int newIndex, int groupIndex); /** @brief Remove effects from a group */ - void slotUnGroup(CollapsibleEffect* group); + void slotUnGroup(CollapsibleGroup* group); /** @brief Add en effect to selected clip */ void slotAddEffect(QDomElement effect); diff --git a/src/effectstackedit.cpp b/src/effectstackedit.cpp index 8f0ec5ec..b56a1a86 100644 --- a/src/effectstackedit.cpp +++ b/src/effectstackedit.cpp @@ -185,7 +185,7 @@ void EffectStackEdit::updateParameter(const QString &name, const QString &value) void EffectStackEdit::transferParamDesc(const QDomElement &d, ItemInfo info, bool /*isEffect*/) { if (m_paramWidget) delete m_paramWidget; - m_paramWidget = new ParameterContainer(d, info, &m_metaInfo, 0, m_baseWidget); + m_paramWidget = new ParameterContainer(d, info, &m_metaInfo, m_baseWidget); connect (m_paramWidget, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)), this, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int))); connect(m_paramWidget, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString)), this, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString))); diff --git a/src/widgets/collapsiblegroup_ui.ui b/src/widgets/collapsiblegroup_ui.ui new file mode 100644 index 00000000..c3b74cd7 --- /dev/null +++ b/src/widgets/collapsiblegroup_ui.ui @@ -0,0 +1,222 @@ + + + CollapsibleGroup_UI + + + + 0 + 0 + 245 + 48 + + + + Form + + + + 0 + + + + + true + + + QFrame::StyledPanel + + + QFrame::Plain + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 0 + + + 2 + + + 0 + + + 2 + + + 0 + + + + + ... + + + true + + + Qt::DownArrow + + + + + + + Qt::Vertical + + + + + + + + + + Return + + + + + + + + + + + + + + false + + + true + + + + + + + Qt::Horizontal + + + + 80 + 20 + + + + + + + + + 22 + 22 + + + + ... + + + QToolButton::InstantPopup + + + true + + + + + + + + 22 + 22 + + + + ... + + + true + + + + + + + + 22 + 22 + + + + ... + + + true + + + + + + + + 22 + 22 + + + + ... + + + true + + + + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + + + + + + + + + KSeparator + QFrame +
kseparator.h
+
+
+ + +
-- 2.39.2