X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Feffectstack%2Fcollapsibleeffect.cpp;h=c2a59f7a41e2d30ef667f956649f4aeaaf80d2e5;hb=c3302003093710ee247ad84c0fe2ef3c579d417f;hp=0fe942b14a16a8cce8b1ce2fcdf7a40fa0c61cf9;hpb=c3deed6356f5456096f600d1a6e2d82ebe2e1fff;p=kdenlive diff --git a/src/effectstack/collapsibleeffect.cpp b/src/effectstack/collapsibleeffect.cpp index 0fe942b1..c2a59f7a 100644 --- a/src/effectstack/collapsibleeffect.cpp +++ b/src/effectstack/collapsibleeffect.cpp @@ -19,120 +19,39 @@ #include "collapsibleeffect.h" - -#include "ui_listval_ui.h" -#include "ui_boolval_ui.h" -#include "ui_wipeval_ui.h" -#include "ui_urlval_ui.h" -#include "ui_keywordval_ui.h" -#include "ui_fontval_ui.h" -#include "complexparameter.h" -#include "geometryval.h" -#include "positionedit.h" -#include "projectlist.h" #include "effectslist.h" #include "kdenlivesettings.h" -#include "profilesdialog.h" -#include "kis_curve_widget.h" -#include "kis_cubic_curve.h" -#include "choosecolorwidget.h" -#include "geometrywidget.h" -#include "colortools.h" -#include "doubleparameterwidget.h" -#include "cornerswidget.h" -#include "dragvalue.h" -#include "beziercurve/beziersplinewidget.h" -#ifdef USE_QJSON -#include "rotoscoping/rotowidget.h" -#endif +#include "projectlist.h" #include #include #include #include +#include +#include +#include #include +#include #include #include #include #include #include -#include -#include -#include #include -class Boolval: public QWidget, public Ui::Boolval_UI -{ -}; - -class Listval: public QWidget, public Ui::Listval_UI -{ -}; - -class Wipeval: public QWidget, public Ui::Wipeval_UI -{ -}; - -class Urlval: public QWidget, public Ui::Urlval_UI -{ -}; - -class Keywordval: public QWidget, public Ui::Keywordval_UI -{ -}; -class Fontval: public QWidget, public Ui::Fontval_UI -{ -}; - -QMap CollapsibleEffect::iconCache; - -void clearLayout(QLayout *layout) -{ - QLayoutItem *item; - while((item = layout->takeAt(0))) { - if (item->layout()) { - clearLayout(item->layout()); - delete item->layout(); - } - if (item->widget()) { - delete item->widget(); - } - delete item; - } -} - -MySpinBox::MySpinBox(QWidget * parent): - QSpinBox(parent) -{ - setFocusPolicy(Qt::StrongFocus); -} - -void MySpinBox::focusInEvent(QFocusEvent *e) -{ - setFocusPolicy(Qt::WheelFocus); - e->accept(); -} - -void MySpinBox::focusOutEvent(QFocusEvent *e) -{ - setFocusPolicy(Qt::StrongFocus); - e->accept(); -} - - -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_regionEffect(false) +CollapsibleEffect::CollapsibleEffect(const QDomElement &effect, const QDomElement &original_effect, const 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_regionEffect(false) { if (m_effect.attribute("tag") == "region") { - m_regionEffect = true; - decoframe->setObjectName("decoframegroup"); + m_regionEffect = true; + decoframe->setObjectName("decoframegroup"); } filterWheelEvent = true; m_info.fromString(effect.attribute("kdenlive_info")); @@ -156,19 +75,24 @@ CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_ef //buttonShowComments->setIcon(KIcon("help-about")); //buttonShowComments->setToolTip(i18n("Show additional information for the parameters")); m_menu = new QMenu; - if (m_regionEffect) m_menu->addAction(KIcon("document-new"), i18n("Change Region"), this, SLOT(slotResetEffect())); m_menu->addAction(KIcon("view-refresh"), i18n("Reset Effect"), this, SLOT(slotResetEffect())); m_menu->addAction(KIcon("document-save"), i18n("Save Effect"), this, SLOT(slotSaveEffect())); - QDomElement namenode = m_effect.firstChildElement("name"); - if (namenode.isNull()) return; - QString effectname = i18n(namenode.text().toUtf8().data()); - if (m_regionEffect) effectname.append(":" + KUrl(EffectsList::parameter(m_effect, "resource")).fileName()); - QHBoxLayout *l = static_cast (frame->layout()); title = new QLabel(this); l->insertWidget(2, title); + m_groupAction = new QAction(KIcon("folder-new"), i18n("Create Group"), this); + connect(m_groupAction, SIGNAL(triggered(bool)), this, SLOT(slotCreateGroup())); + + QDomElement namenode = m_effect.firstChildElement("name"); + if (namenode.isNull()) { + // Warning, broken effect? + kDebug()<<"// Could not create effect"; + return; + } + QString effectname = i18n(namenode.text().toUtf8().data()); + if (m_regionEffect) effectname.append(':' + KUrl(EffectsList::parameter(m_effect, "resource")).fileName()); title->setText(effectname); /* * Do not show icon, makes too much visual noise @@ -179,10 +103,10 @@ CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_ef else if (type == "custom") icon = KIcon("kdenlive-custom-effect"); else icon = KIcon("kdenlive-show-video"); effecticon->setPixmap(icon.pixmap(16,16));*/ - + if (!m_regionEffect) { - m_menu->addAction(KIcon("folder-new"), i18n("Create Group"), this, SLOT(slotCreateGroup())); - m_menu->addAction(KIcon("folder-new"), i18n("Create Region"), this, SLOT(slotCreateRegion())); + if (m_info.groupIndex == -1) m_menu->addAction(m_groupAction); + m_menu->addAction(KIcon("folder-new"), i18n("Create Region"), this, SLOT(slotCreateRegion())); } setupWidget(info, metaInfo); setAcceptDrops(true); @@ -191,16 +115,16 @@ CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_ef if (m_effect.attribute("disable") == "1") { title->setEnabled(false); - enabledButton->setChecked(true); - enabledButton->setIcon(KIcon("novisible")); + enabledButton->setChecked(true); + enabledButton->setIcon(KIcon("novisible")); } else { enabledButton->setChecked(false); - enabledButton->setIcon(KIcon("visible")); + enabledButton->setIcon(KIcon("visible")); } connect(collapseButton, SIGNAL(clicked()), this, SLOT(slotSwitch())); - connect(enabledButton, SIGNAL(toggled(bool)), this, SLOT(slotEnable(bool))); + connect(enabledButton, SIGNAL(toggled(bool)), this, SLOT(slotDisable(bool))); connect(buttonUp, SIGNAL(clicked()), this, SLOT(slotEffectUp())); connect(buttonDown, SIGNAL(clicked()), this, SLOT(slotEffectDown())); connect(buttonDel, SIGNAL(clicked()), this, SLOT(slotDeleteEffect())); @@ -210,63 +134,21 @@ CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_ef sp->setFocusPolicy( Qt::StrongFocus ); } Q_FOREACH( KComboBox * cb, findChildren() ) { - cb->installEventFilter( this ); + cb->installEventFilter( this ); cb->setFocusPolicy( Qt::StrongFocus ); } Q_FOREACH( QProgressBar * cb, findChildren() ) { - cb->installEventFilter( this ); + cb->installEventFilter( this ); cb->setFocusPolicy( Qt::StrongFocus ); } } CollapsibleEffect::~CollapsibleEffect() { - if (m_paramWidget) delete m_paramWidget; + delete m_paramWidget; delete m_menu; } -//static -const QString CollapsibleEffect::getStyleSheet() -{ - KColorScheme scheme(QApplication::palette().currentColorGroup(), KColorScheme::View, KSharedConfig::openConfig(KdenliveSettings::colortheme())); - QColor selected_bg = scheme.decoration(KColorScheme::FocusColor).color(); - QColor hgh = KColorUtils::mix(QApplication::palette().window().color(), selected_bg, 0.2); - QColor hover_bg = scheme.decoration(KColorScheme::HoverColor).color(); - QColor light_bg = scheme.shade(KColorScheme::LightShade); - QColor alt_bg = scheme.background(KColorScheme::NormalBackground).color(); - - QString stylesheet; - - // effect background - stylesheet.append(QString("QFrame#decoframe {border-top-left-radius:5px;border-top-right-radius:5px;border-bottom:2px solid palette(mid);border-top:1px solid palette(light);} QFrame#decoframe[active=\"true\"] {background: %1;}").arg(hgh.name())); - - // effect in group background - stylesheet.append(QString("QFrame#decoframesub {border-top:1px solid palette(light);} QFrame#decoframesub[active=\"true\"] {background: %1;}").arg(hgh.name())); - - // group background - stylesheet.append(QString("QFrame#decoframegroup {border-top-left-radius:5px;border-top-right-radius:5px;border:2px solid palette(dark);margin:0px;margin-top:2px;} ")); - - // effect title bar - stylesheet.append(QString("QFrame#frame {margin-bottom:2px;border-top-left-radius:5px;border-top-right-radius:5px;} QFrame#frame[target=\"true\"] {background: palette(highlight);}")); - - // group effect title bar - stylesheet.append(QString("QFrame#framegroup {border-top-left-radius:2px;border-top-right-radius:2px;background: palette(dark);} QFrame#framegroup[target=\"true\"] {background: palette(highlight);} ")); - - // draggable effect bar content - stylesheet.append(QString("QProgressBar::chunk:horizontal {background: palette(button);border-top-left-radius: 4px;border-bottom-left-radius: 4px;} QProgressBar::chunk:horizontal#dragOnly {background: %1;border-top-left-radius: 4px;border-bottom-left-radius: 4px;} QProgressBar::chunk:horizontal:hover {background: %2;}").arg(alt_bg.name()).arg(selected_bg.name())); - - // draggable effect bar - stylesheet.append(QString("QProgressBar:horizontal {border: 1px solid palette(dark);border-top-left-radius: 4px;border-bottom-left-radius: 4px;border-right:0px;background:%3;padding: 0px;text-align:left center} QProgressBar:horizontal:disabled {border: 1px solid palette(button)} QProgressBar:horizontal#dragOnly {background: %3} QProgressBar:horizontal[inTimeline=\"true\"] { border: 1px solid %1;border-right: 0px;background: %2;padding: 0px;text-align:left center } QProgressBar::chunk:horizontal[inTimeline=\"true\"] {background: %1;}").arg(hover_bg.name()).arg(light_bg.name()).arg(alt_bg.name())); - - // spin box for draggable widget - stylesheet.append(QString("QAbstractSpinBox#dragBox {border: 1px solid palette(dark);border-top-right-radius: 4px;border-bottom-right-radius: 4px;padding-right:0px;} QAbstractSpinBox::down-button#dragBox {width:0px;padding:0px;} QAbstractSpinBox:disabled#dragBox {border: 1px solid palette(button);} QAbstractSpinBox::up-button#dragBox {width:0px;padding:0px;} QAbstractSpinBox[inTimeline=\"true\"]#dragBox { border: 1px solid %1;} QAbstractSpinBox:hover#dragBox {border: 1px solid %2;} ").arg(hover_bg.name()).arg(selected_bg.name())); - - // group editable labels - stylesheet.append(QString("MyEditableLabel { background-color: transparent; color: palette(bright-text); border-radius: 2px;border: 1px solid transparent;} MyEditableLabel:hover {border: 1px solid palette(highlight);} ")); - - return stylesheet; -} - void CollapsibleEffect::slotCreateGroup() { emit createGroup(effectIndex()); @@ -276,12 +158,12 @@ void CollapsibleEffect::slotCreateRegion() { QString allExtensions = ProjectList::getExtensions(); const QString dialogFilter = allExtensions + ' ' + QLatin1Char('|') + i18n("All Supported Files") + "\n* " + QLatin1Char('|') + i18n("All Files"); - KFileDialog *d = new KFileDialog(KUrl("kfiledialog:///clipfolder"), dialogFilter, kapp->activeWindow()); + QPointer d = new KFileDialog(KUrl("kfiledialog:///clipfolder"), dialogFilter, kapp->activeWindow()); d->setOperationMode(KFileDialog::Opening); d->setMode(KFile::File); if (d->exec() == QDialog::Accepted) { - KUrl url = d->selectedUrl(); - if (!url.isEmpty()) emit createRegion(effectIndex(), url); + KUrl url = d->selectedUrl(); + if (!url.isEmpty()) emit createRegion(effectIndex(), url); } delete d; } @@ -294,52 +176,52 @@ void CollapsibleEffect::slotUnGroup() bool CollapsibleEffect::eventFilter( QObject * o, QEvent * e ) { if (e->type() == QEvent::Enter) { - frame->setProperty("mouseover", true); - frame->setStyleSheet(frame->styleSheet()); - return QWidget::eventFilter(o, e); + frame->setProperty("mouseover", true); + frame->setStyleSheet(frame->styleSheet()); + return QWidget::eventFilter(o, e); } if (e->type() == QEvent::Wheel) { - QWheelEvent *we = static_cast(e); - if (!filterWheelEvent || we->modifiers() != Qt::NoModifier) { - e->accept(); - return false; - } - if (qobject_cast(o)) { - if(qobject_cast(o)->focusPolicy() == Qt::WheelFocus) - { - e->accept(); - return false; - } - else - { - e->ignore(); - return true; - } - } - if (qobject_cast(o)) { - if(qobject_cast(o)->focusPolicy() == Qt::WheelFocus) - { - e->accept(); - return false; - } - else - { - e->ignore(); - return true; - } - } - if (qobject_cast(o)) { - if(qobject_cast(o)->focusPolicy() == Qt::WheelFocus) - { - e->accept(); - return false; - } - else - { - e->ignore(); - return true; - } - } + QWheelEvent *we = static_cast(e); + if (!filterWheelEvent || we->modifiers() != Qt::NoModifier) { + e->accept(); + return false; + } + if (qobject_cast(o)) { + if(qobject_cast(o)->focusPolicy() == Qt::WheelFocus) + { + e->accept(); + return false; + } + else + { + e->ignore(); + return true; + } + } + if (qobject_cast(o)) { + if(qobject_cast(o)->focusPolicy() == Qt::WheelFocus) + { + e->accept(); + return false; + } + else + { + e->ignore(); + return true; + } + } + if (qobject_cast(o)) { + if(qobject_cast(o)->focusPolicy() == Qt::WheelFocus) + { + e->accept(); + return false; + } + else + { + e->ignore(); + return true; + } + } } return QWidget::eventFilter(o, e); } @@ -371,11 +253,11 @@ void CollapsibleEffect::mouseDoubleClickEvent ( QMouseEvent * event ) void CollapsibleEffect::mouseReleaseEvent( QMouseEvent *event ) { - if (!decoframe->property("active").toBool()) emit activateEffect(effectIndex()); - QWidget::mouseReleaseEvent(event); + if (!decoframe->property("active").toBool()) emit activateEffect(effectIndex()); + QWidget::mouseReleaseEvent(event); } -void CollapsibleEffect::slotEnable(bool disable, bool updateMainStatus) +void CollapsibleEffect::slotDisable(bool disable, bool emitInfo) { title->setEnabled(!disable); enabledButton->blockSignals(true); @@ -386,7 +268,7 @@ void CollapsibleEffect::slotEnable(bool disable, bool updateMainStatus) if (!disable || KdenliveSettings::disable_effect_parameters()) { widgetFrame->setEnabled(!disable); } - emit effectStateChanged(disable, effectIndex(), updateMainStatus); + if (emitInfo) emit effectStateChanged(disable, effectIndex(), isActive() && needsMonitorEffectScene()); } void CollapsibleEffect::slotDeleteEffect() @@ -455,8 +337,7 @@ void CollapsibleEffect::slotShow(bool show) if (show) { collapseButton->setArrowType(Qt::DownArrow); m_info.isCollapsed = false; - } - else { + } else { collapseButton->setArrowType(Qt::RightArrow); m_info.isCollapsed = true; } @@ -473,13 +354,19 @@ void CollapsibleEffect::updateCollapsedState() { QString info = m_info.toString(); if (info != m_effect.attribute("kdenlive_info")) { - m_effect.setAttribute("kdenlive_info", info); - emit parameterChanged(m_original_effect, m_effect, effectIndex()); + m_effect.setAttribute("kdenlive_info", info); + emit parameterChanged(m_original_effect, m_effect, effectIndex()); } } void CollapsibleEffect::setGroupIndex(int ix) { + if (m_info.groupIndex == -1 && ix != -1) { + m_menu->removeAction(m_groupAction); + } + else if (m_info.groupIndex != -1 && ix == -1) { + m_menu->addAction(m_groupAction); + } m_info.groupIndex = ix; m_effect.setAttribute("kdenlive_info", m_info.toString()); } @@ -497,6 +384,9 @@ QString CollapsibleEffect::infoString() const void CollapsibleEffect::removeFromGroup() { + if (m_info.groupIndex != -1) { + m_menu->addAction(m_groupAction); + } m_info.groupIndex = -1; m_info.groupName.clear(); m_effect.setAttribute("kdenlive_info", m_info.toString()); @@ -514,38 +404,35 @@ int CollapsibleEffect::effectIndex() const return m_effect.attribute("kdenlive_ix").toInt(); } -void CollapsibleEffect::updateWidget(ItemInfo info, QDomElement effect, EffectMetaInfo *metaInfo) +void CollapsibleEffect::updateWidget(const ItemInfo &info, const QDomElement &effect, EffectMetaInfo *metaInfo) { - if (m_paramWidget) { - // cleanup - delete m_paramWidget; - m_paramWidget = NULL; - } + // cleanup + delete m_paramWidget; + m_paramWidget = NULL; m_effect = effect; setupWidget(info, metaInfo); } -void CollapsibleEffect::setupWidget(ItemInfo info, EffectMetaInfo *metaInfo) +void CollapsibleEffect::setupWidget(const ItemInfo &info, EffectMetaInfo *metaInfo) { if (m_effect.isNull()) { -// kDebug() << "// EMPTY EFFECT STACK"; + // kDebug() << "// EMPTY EFFECT STACK"; return; } if (m_effect.attribute("tag") == "region") { - m_regionEffect = true; - QVBoxLayout *vbox = new QVBoxLayout(widgetFrame); - vbox->setContentsMargins(0, 0, 0, 0); - vbox->setSpacing(2); + m_regionEffect = true; QDomNodeList effects = m_effect.elementsByTagName("effect"); QDomNodeList origin_effects = m_original_effect.elementsByTagName("effect"); + m_paramWidget = new ParameterContainer(m_effect, info, metaInfo, widgetFrame); QWidget *container = new QWidget(widgetFrame); + QVBoxLayout *vbox = static_cast (widgetFrame->layout()); vbox->addWidget(container); - // m_paramWidget = new ParameterContainer(m_effect.toElement(), info, metaInfo, container); - for (int i = 0; i < effects.count(); i++) { + // 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, metaInfo, container); m_subParamWidgets.append(coll); - connect(coll, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)), this , SLOT(slotUpdateRegionEffectParams(const QDomElement, const QDomElement, int))); + connect(coll, SIGNAL(parameterChanged(QDomElement,QDomElement,int)), this , SLOT(slotUpdateRegionEffectParams(QDomElement,QDomElement,int))); //container = new QWidget(widgetFrame); vbox->addWidget(coll); //p = new ParameterContainer(effects.at(i).toElement(), info, isEffect, container); @@ -554,30 +441,42 @@ void CollapsibleEffect::setupWidget(ItemInfo info, EffectMetaInfo *metaInfo) } else { m_paramWidget = new ParameterContainer(m_effect, info, metaInfo, widgetFrame); + connect(m_paramWidget, SIGNAL(disableCurrentFilter(bool)), this, SLOT(slotDisableEffect(bool))); if (m_effect.firstChildElement("parameter").isNull()) { // Effect has no parameter, don't allow expand collapseButton->setEnabled(false); - collapseButton->setVisible(false); - widgetFrame->setVisible(false); + collapseButton->setVisible(false); + widgetFrame->setVisible(false); } } if (collapseButton->isEnabled() && m_info.isCollapsed) { - widgetFrame->setVisible(false); - collapseButton->setArrowType(Qt::RightArrow); - + widgetFrame->setVisible(false); + collapseButton->setArrowType(Qt::RightArrow); + } - connect (m_paramWidget, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)), this, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int))); + connect (m_paramWidget, SIGNAL(parameterChanged(QDomElement,QDomElement,int)), this, SIGNAL(parameterChanged(QDomElement,QDomElement,int))); - connect(m_paramWidget, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString)), this, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString))); + connect(m_paramWidget, SIGNAL(startFilterJob(QString,QString,QString,QString,QMap)), this, SIGNAL(startFilterJob(QString,QString,QString,QString,QMap))); connect (this, SIGNAL(syncEffectsPos(int)), m_paramWidget, SIGNAL(syncEffectsPos(int))); - connect (this, SIGNAL(effectStateChanged(bool)), m_paramWidget, SIGNAL(effectStateChanged(bool))); connect (m_paramWidget, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int))); connect (m_paramWidget, SIGNAL(seekTimeline(int)), this, SIGNAL(seekTimeline(int))); + connect(m_paramWidget, SIGNAL(importClipKeyframes()), this, SIGNAL(importClipKeyframes())); } +void CollapsibleEffect::slotDisableEffect(bool disable) +{ + title->setEnabled(!disable); + enabledButton->blockSignals(true); + enabledButton->setChecked(disable); + enabledButton->blockSignals(false); + enabledButton->setIcon(disable ? KIcon("novisible") : KIcon("visible")); + m_effect.setAttribute("disable", disable ? 1 : 0); + emit effectStateChanged(disable, effectIndex(), isActive() && needsMonitorEffectScene()); +} + bool CollapsibleEffect::isGroup() const { return false; @@ -588,7 +487,7 @@ void CollapsibleEffect::updateTimecodeFormat() m_paramWidget->updateTimecodeFormat(); if (!m_subParamWidgets.isEmpty()) { // we have a group - for (int i = 0; i < m_subParamWidgets.count(); i++) + for (int i = 0; i < m_subParamWidgets.count(); ++i) m_subParamWidgets.at(i)->updateTimecodeFormat(); } } @@ -607,9 +506,9 @@ void CollapsibleEffect::slotSyncEffectsPos(int pos) void CollapsibleEffect::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("kdenlive/effectslist")) { - frame->setProperty("target", true); - frame->setStyleSheet(frame->styleSheet()); - event->acceptProposedAction(); + frame->setProperty("target", true); + frame->setStyleSheet(frame->styleSheet()); + event->acceptProposedAction(); } } @@ -631,780 +530,79 @@ void CollapsibleEffect::dropEvent(QDropEvent *event) int ix = e.attribute("kdenlive_ix").toInt(); int currentEffectIx = effectIndex(); if (ix == currentEffectIx) { - // effect dropped on itself, reject - event->ignore(); - return; + // effect dropped on itself, reject + event->ignore(); + return; } if (ix == 0 || e.tagName() == "effectgroup") { - if (e.tagName() == "effectgroup") { - // moving a group - QDomNodeList subeffects = e.elementsByTagName("effect"); - if (subeffects.isEmpty()) { - event->ignore(); - return; - } - EffectInfo info; - info.fromString(subeffects.at(0).toElement().attribute("kdenlive_info")); - event->setDropAction(Qt::MoveAction); - event->accept(); - if (info.groupIndex >= 0) { - // Moving group - QList effectsIds; - // Collect moved effects ids - for (int i = 0; i < subeffects.count(); i++) { - QDomElement effect = subeffects.at(i).toElement(); - effectsIds << effect.attribute("kdenlive_ix").toInt(); - } - emit moveEffect(effectsIds, currentEffectIx, info.groupIndex, info.groupName); - } - else { - // group effect dropped from effect list - if (m_info.groupIndex > -1) { - // TODO: Should we merge groups?? - - } - emit addEffect(e); - } - return; - } - // effect dropped from effects list, add it - e.setAttribute("kdenlive_ix", ix); - if (m_info.groupIndex > -1) { - // Dropped on a group - e.setAttribute("kdenlive_info", m_info.toString()); - } - event->setDropAction(Qt::CopyAction); - event->accept(); - emit addEffect(e); - return; - } - emit moveEffect(QList () <setDropAction(Qt::MoveAction); - event->accept(); -} - -ParameterContainer::ParameterContainer(QDomElement effect, ItemInfo info, EffectMetaInfo *metaInfo, QWidget * parent) : - m_keyframeEditor(NULL), - m_geometryWidget(NULL), - m_metaInfo(metaInfo), - m_effect(effect) -{ - m_in = info.cropStart.frames(KdenliveSettings::project_fps()); - m_out = (info.cropStart + info.cropDuration).frames(KdenliveSettings::project_fps()) - 1; - - QDomNodeList namenode = effect.childNodes(); //elementsByTagName("parameter"); - - QDomElement e = effect.toElement(); - int minFrame = e.attribute("start").toInt(); - int maxFrame = e.attribute("end").toInt(); - // In transitions, maxFrame is in fact one frame after the end of transition - if (maxFrame > 0) maxFrame --; - - bool disable = effect.attribute("disable") == "1" && KdenliveSettings::disable_effect_parameters(); - parent->setEnabled(!disable); - - bool stretch = true; - m_vbox = new QVBoxLayout(parent); - m_vbox->setContentsMargins(4, 0, 4, 0); - m_vbox->setSpacing(2); - - for (int i = 0; i < namenode.count() ; i++) { - QDomElement pa = namenode.item(i).toElement(); - if (pa.tagName() != "parameter") continue; - QDomElement na = pa.firstChildElement("name"); - QDomElement commentElem = pa.firstChildElement("comment"); - QString type = pa.attribute("type"); - QString paramName = na.isNull() ? pa.attribute("name") : i18n(na.text().toUtf8().data()); - QString comment; - if (!commentElem.isNull()) - comment = i18n(commentElem.text().toUtf8().data()); - QWidget * toFillin = new QWidget(parent); - QString value = pa.attribute("value").isNull() ? - pa.attribute("default") : pa.attribute("value"); - - - /** See effects/README for info on the different types */ - - if (type == "double" || type == "constant") { - double min; - double max; - if (pa.attribute("min").contains('%')) - min = ProfilesDialog::getStringEval(m_metaInfo->profile, pa.attribute("min"), m_metaInfo->frameSize); - else - min = pa.attribute("min").toDouble(); - if (pa.attribute("max").contains('%')) - max = ProfilesDialog::getStringEval(m_metaInfo->profile, pa.attribute("max"), m_metaInfo->frameSize); - else - max = pa.attribute("max").toDouble(); - - DoubleParameterWidget *doubleparam = new DoubleParameterWidget(paramName, value.toDouble(), min, max, - pa.attribute("default").toDouble(), comment, -1, pa.attribute("suffix"), pa.attribute("decimals").toInt(), parent); - doubleparam->setFocusPolicy(Qt::StrongFocus); - m_vbox->addWidget(doubleparam); - m_valueItems[paramName] = doubleparam; - connect(doubleparam, SIGNAL(valueChanged(double)), this, SLOT(slotCollectAllParameters())); - connect(this, SIGNAL(showComments(bool)), doubleparam, SLOT(slotShowComment(bool))); - } else if (type == "list") { - Listval *lsval = new Listval; - lsval->setupUi(toFillin); - lsval->list->setFocusPolicy(Qt::StrongFocus); - QStringList listitems = pa.attribute("paramlist").split(';'); - if (listitems.count() == 1) { - // probably custom effect created before change to ';' as separator - listitems = pa.attribute("paramlist").split(","); + if (e.tagName() == "effectgroup") { + // moving a group + QDomNodeList subeffects = e.elementsByTagName("effect"); + if (subeffects.isEmpty()) { + event->ignore(); + return; } - QDomElement list = pa.firstChildElement("paramlistdisplay"); - QStringList listitemsdisplay; - if (!list.isNull()) { - listitemsdisplay = i18n(list.text().toUtf8().data()).split(','); - } else { - listitemsdisplay = i18n(pa.attribute("paramlistdisplay").toUtf8().data()).split(','); - } - if (listitemsdisplay.count() != listitems.count()) - listitemsdisplay = listitems; - lsval->list->setIconSize(QSize(30, 30)); - for (int i = 0; i < listitems.count(); i++) { - lsval->list->addItem(listitemsdisplay.at(i), listitems.at(i)); - QString entry = listitems.at(i); - if (!entry.isEmpty() && (entry.endsWith(".png") || entry.endsWith(".pgm"))) { - if (!CollapsibleEffect::iconCache.contains(entry)) { - QImage pix(entry); - CollapsibleEffect::iconCache[entry] = pix.scaled(30, 30); - } - lsval->list->setItemIcon(i, QPixmap::fromImage(CollapsibleEffect::iconCache[entry])); + EffectInfo info; + info.fromString(subeffects.at(0).toElement().attribute("kdenlive_info")); + event->setDropAction(Qt::MoveAction); + event->accept(); + if (info.groupIndex >= 0) { + // Moving group + QList effectsIds; + // Collect moved effects ids + for (int i = 0; i < subeffects.count(); ++i) { + QDomElement effect = subeffects.at(i).toElement(); + effectsIds << effect.attribute("kdenlive_ix").toInt(); } + emit moveEffect(effectsIds, currentEffectIx, info.groupIndex, info.groupName); } - if (!value.isEmpty()) lsval->list->setCurrentIndex(listitems.indexOf(value)); - lsval->name->setText(paramName); - lsval->labelComment->setText(comment); - lsval->widgetComment->setHidden(true); - m_valueItems[paramName] = lsval; - connect(lsval->list, SIGNAL(currentIndexChanged(int)) , this, SLOT(slotCollectAllParameters())); - if (!comment.isEmpty()) - connect(this, SIGNAL(showComments(bool)), lsval->widgetComment, SLOT(setVisible(bool))); - m_uiItems.append(lsval); - } else if (type == "bool") { - Boolval *bval = new Boolval; - bval->setupUi(toFillin); - bval->checkBox->setCheckState(value == "0" ? Qt::Unchecked : Qt::Checked); - bval->name->setText(paramName); - bval->labelComment->setText(comment); - bval->widgetComment->setHidden(true); - m_valueItems[paramName] = bval; - connect(bval->checkBox, SIGNAL(stateChanged(int)) , this, SLOT(slotCollectAllParameters())); - if (!comment.isEmpty()) - connect(this, SIGNAL(showComments(bool)), bval->widgetComment, SLOT(setVisible(bool))); - m_uiItems.append(bval); - } else if (type == "complex") { - ComplexParameter *pl = new ComplexParameter; - pl->setupParam(effect, pa.attribute("name"), 0, 100); - m_vbox->addWidget(pl); - m_valueItems[paramName+"complex"] = pl; - connect(pl, SIGNAL(parameterChanged()), this, SLOT(slotCollectAllParameters())); - } else if (type == "geometry") { - if (KdenliveSettings::on_monitor_effects()) { - m_geometryWidget = new GeometryWidget(m_metaInfo->monitor, m_metaInfo->timecode, 0, true, effect.hasAttribute("showrotation"), parent); - m_geometryWidget->setFrameSize(m_metaInfo->frameSize); - m_geometryWidget->slotShowScene(!disable); - // connect this before setupParam to make sure the monitor scene shows up at startup - connect(m_geometryWidget, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int))); - connect(m_geometryWidget, SIGNAL(parameterChanged()), this, SLOT(slotCollectAllParameters())); - if (minFrame == maxFrame) - m_geometryWidget->setupParam(pa, m_in, m_out); - else - m_geometryWidget->setupParam(pa, minFrame, maxFrame); - m_vbox->addWidget(m_geometryWidget); - m_valueItems[paramName+"geometry"] = m_geometryWidget; - connect(m_geometryWidget, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int))); - connect(this, SIGNAL(syncEffectsPos(int)), m_geometryWidget, SLOT(slotSyncPosition(int))); - connect(this, SIGNAL(effectStateChanged(bool)), m_geometryWidget, SLOT(slotShowScene(bool))); - } else { - Geometryval *geo = new Geometryval(m_metaInfo->profile, m_metaInfo->timecode, m_metaInfo->frameSize, 0); - if (minFrame == maxFrame) - geo->setupParam(pa, m_in, m_out); - else - geo->setupParam(pa, minFrame, maxFrame); - m_vbox->addWidget(geo); - m_valueItems[paramName+"geometry"] = geo; - connect(geo, SIGNAL(parameterChanged()), this, SLOT(slotCollectAllParameters())); - connect(geo, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int))); - connect(this, SIGNAL(syncEffectsPos(int)), geo, SLOT(slotSyncPosition(int))); - } - } else if (type == "addedgeometry") { - // this is a parameter that should be linked to the geometry widget, for example rotation, shear, ... - if (m_geometryWidget) m_geometryWidget->addParameter(pa); - } else if (type == "keyframe" || type == "simplekeyframe") { - // keyframe editor widget - if (m_keyframeEditor == NULL) { - KeyframeEdit *geo; - if (pa.attribute("widget") == "corners") { - // we want a corners-keyframe-widget - CornersWidget *corners = new CornersWidget(m_metaInfo->monitor, pa, m_in, m_out, m_metaInfo->timecode, e.attribute("active_keyframe", "-1").toInt(), parent); - corners->slotShowScene(!disable); - connect(corners, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int))); - connect(this, SIGNAL(effectStateChanged(bool)), corners, SLOT(slotShowScene(bool))); - connect(this, SIGNAL(syncEffectsPos(int)), corners, SLOT(slotSyncPosition(int))); - geo = static_cast(corners); - } else { - geo = new KeyframeEdit(pa, m_in, m_out, m_metaInfo->timecode, e.attribute("active_keyframe", "-1").toInt()); - } - m_vbox->addWidget(geo); - m_valueItems[paramName+"keyframe"] = geo; - m_keyframeEditor = geo; - connect(geo, SIGNAL(parameterChanged()), this, SLOT(slotCollectAllParameters())); - connect(geo, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int))); - connect(this, SIGNAL(showComments(bool)), geo, SIGNAL(showComments(bool))); - } else { - // we already have a keyframe editor, so just add another column for the new param - m_keyframeEditor->addParameter(pa); - } - } else if (type == "color") { - if (pa.hasAttribute("paramprefix")) value.remove(0, pa.attribute("paramprefix").size()); - if (value.startsWith('#')) - value = value.replace('#', "0x"); - ChooseColorWidget *choosecolor = new ChooseColorWidget(paramName, value, parent); - choosecolor->setAlphaChannelEnabled(true); - m_vbox->addWidget(choosecolor); - m_valueItems[paramName] = choosecolor; - connect(choosecolor, SIGNAL(displayMessage(const QString&, int)), this, SIGNAL(displayMessage(const QString&, int))); - connect(choosecolor, SIGNAL(modified()) , this, SLOT(slotCollectAllParameters())); - } else if (type == "position") { - int pos = value.toInt(); - if (effect.attribute("id") == "fadein" || effect.attribute("id") == "fade_from_black") { - pos = pos - m_in; - } else if (effect.attribute("id") == "fadeout" || effect.attribute("id") == "fade_to_black") { - // fadeout position starts from clip end - pos = m_out - pos; - } - PositionEdit *posedit = new PositionEdit(paramName, pos, 0, m_out - m_in, m_metaInfo->timecode); - m_vbox->addWidget(posedit); - m_valueItems[paramName+"position"] = posedit; - connect(posedit, SIGNAL(parameterChanged()), this, SLOT(slotCollectAllParameters())); - } else if (type == "curve") { - KisCurveWidget *curve = new KisCurveWidget(parent); - curve->setMaxPoints(pa.attribute("max").toInt()); - QList points; - int number; - if (e.attribute("version").toDouble() > 0.2) { - // Rounding gives really weird results. (int) (10 * 0.3) gives 2! So for now, add 0.5 to get correct result - number = EffectsList::parameter(e, pa.attribute("number")).toDouble() * 10 + 0.5; - } else { - number = EffectsList::parameter(e, pa.attribute("number")).toInt(); - } - QString inName = pa.attribute("inpoints"); - QString outName = pa.attribute("outpoints"); - int start = pa.attribute("min").toInt(); - for (int j = start; j <= number; j++) { - QString in = inName; - in.replace("%i", QString::number(j)); - QString out = outName; - out.replace("%i", QString::number(j)); - points << QPointF(EffectsList::parameter(e, in).toDouble(), EffectsList::parameter(e, out).toDouble()); - } - if (!points.isEmpty()) - curve->setCurve(KisCubicCurve(points)); - MySpinBox *spinin = new MySpinBox(); - spinin->setRange(0, 1000); - MySpinBox *spinout = new MySpinBox(); - spinout->setRange(0, 1000); - curve->setupInOutControls(spinin, spinout, 0, 1000); - m_vbox->addWidget(curve); - m_vbox->addWidget(spinin); - m_vbox->addWidget(spinout); - - connect(curve, SIGNAL(modified()), this, SLOT(slotCollectAllParameters())); - m_valueItems[paramName] = curve; + else { + // group effect dropped from effect list + if (m_info.groupIndex > -1) { + // TODO: Should we merge groups?? - QString depends = pa.attribute("depends"); - if (!depends.isEmpty()) - meetDependency(paramName, type, EffectsList::parameter(e, depends)); - } else if (type == "bezier_spline") { - BezierSplineWidget *widget = new BezierSplineWidget(value, parent); - stretch = false; - m_vbox->addWidget(widget); - m_valueItems[paramName] = widget; - connect(widget, SIGNAL(modified()), this, SLOT(slotCollectAllParameters())); - QString depends = pa.attribute("depends"); - if (!depends.isEmpty()) - meetDependency(paramName, type, EffectsList::parameter(e, depends)); -#ifdef USE_QJSON - } else if (type == "roto-spline") { - RotoWidget *roto = new RotoWidget(value, m_metaInfo->monitor, info, m_metaInfo->timecode, parent); - roto->slotShowScene(!disable); - connect(roto, SIGNAL(valueChanged()), this, SLOT(slotCollectAllParameters())); - connect(roto, SIGNAL(checkMonitorPosition(int)), this, SIGNAL(checkMonitorPosition(int))); - connect(roto, SIGNAL(seekToPos(int)), this, SIGNAL(seekTimeline(int))); - connect(this, SIGNAL(syncEffectsPos(int)), roto, SLOT(slotSyncPosition(int))); - connect(this, SIGNAL(effectStateChanged(bool)), roto, SLOT(slotShowScene(bool))); - m_vbox->addWidget(roto); - m_valueItems[paramName] = roto; -#endif - } else if (type == "wipe") { - Wipeval *wpval = new Wipeval; - wpval->setupUi(toFillin); - wipeInfo w = getWipeInfo(value); - switch (w.start) { - case UP: - wpval->start_up->setChecked(true); - break; - case DOWN: - wpval->start_down->setChecked(true); - break; - case RIGHT: - wpval->start_right->setChecked(true); - break; - case LEFT: - wpval->start_left->setChecked(true); - break; - default: - wpval->start_center->setChecked(true); - break; - } - switch (w.end) { - case UP: - wpval->end_up->setChecked(true); - break; - case DOWN: - wpval->end_down->setChecked(true); - break; - case RIGHT: - wpval->end_right->setChecked(true); - break; - case LEFT: - wpval->end_left->setChecked(true); - break; - default: - wpval->end_center->setChecked(true); - break; - } - wpval->start_transp->setValue(w.startTransparency); - wpval->end_transp->setValue(w.endTransparency); - m_valueItems[paramName] = wpval; - connect(wpval->end_up, SIGNAL(clicked()), this, SLOT(slotCollectAllParameters())); - connect(wpval->end_down, SIGNAL(clicked()), this, SLOT(slotCollectAllParameters())); - connect(wpval->end_left, SIGNAL(clicked()), this, SLOT(slotCollectAllParameters())); - connect(wpval->end_right, SIGNAL(clicked()), this, SLOT(slotCollectAllParameters())); - connect(wpval->end_center, SIGNAL(clicked()), this, SLOT(slotCollectAllParameters())); - connect(wpval->start_up, SIGNAL(clicked()), this, SLOT(slotCollectAllParameters())); - connect(wpval->start_down, SIGNAL(clicked()), this, SLOT(slotCollectAllParameters())); - connect(wpval->start_left, SIGNAL(clicked()), this, SLOT(slotCollectAllParameters())); - connect(wpval->start_right, SIGNAL(clicked()), this, SLOT(slotCollectAllParameters())); - connect(wpval->start_center, SIGNAL(clicked()), this, SLOT(slotCollectAllParameters())); - connect(wpval->start_transp, SIGNAL(valueChanged(int)), this, SLOT(slotCollectAllParameters())); - connect(wpval->end_transp, SIGNAL(valueChanged(int)), this, SLOT(slotCollectAllParameters())); - //wpval->title->setTitle(na.toElement().text()); - m_uiItems.append(wpval); - } else if (type == "url") { - Urlval *cval = new Urlval; - cval->setupUi(toFillin); - cval->label->setText(paramName); - cval->urlwidget->fileDialog()->setFilter(ProjectList::getExtensions()); - m_valueItems[paramName] = cval; - cval->urlwidget->setUrl(KUrl(value)); - connect(cval->urlwidget, SIGNAL(returnPressed()) , this, SLOT(slotCollectAllParameters())); - connect(cval->urlwidget, SIGNAL(urlSelected(const KUrl&)) , this, SLOT(slotCollectAllParameters())); - m_uiItems.append(cval); - } else if (type == "keywords") { - Keywordval* kval = new Keywordval; - kval->setupUi(toFillin); - kval->label->setText(paramName); - kval->lineeditwidget->setText(value); - QDomElement klistelem = pa.firstChildElement("keywords"); - QDomElement kdisplaylistelem = pa.firstChildElement("keywordsdisplay"); - QStringList keywordlist; - QStringList keyworddisplaylist; - if (!klistelem.isNull()) { - keywordlist = klistelem.text().split(';'); - keyworddisplaylist = i18n(kdisplaylistelem.text().toUtf8().data()).split(';'); - } - if (keyworddisplaylist.count() != keywordlist.count()) { - keyworddisplaylist = keywordlist; - } - for (int i = 0; i < keywordlist.count(); i++) { - kval->comboboxwidget->addItem(keyworddisplaylist.at(i), keywordlist.at(i)); + } + emit addEffect(e); } - // Add disabled user prompt at index 0 - kval->comboboxwidget->insertItem(0, i18n("