]> git.sesse.net Git - kdenlive/commitdiff
Start work on effect groups
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 24 Mar 2012 10:44:36 +0000 (11:44 +0100)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 24 Mar 2012 10:44:36 +0000 (11:44 +0100)
src/abstractgroupitem.cpp
src/clipitem.cpp
src/customtrackview.cpp
src/effectslist.cpp
src/effectstack/collapsibleeffect.cpp
src/effectstack/collapsibleeffect.h
src/effectstack/effectstackview2.cpp
src/effectstack/effectstackview2.h

index 79364deb60109700e0b875eacbbcf532c33f4fbd..d94cfbca995663a70922d622ae625aee17987115 100644 (file)
@@ -359,6 +359,7 @@ void AbstractGroupItem::dropEvent(QGraphicsSceneDragDropEvent * event)
     QDomDocument doc;
     doc.setContent(effects, true);
     QDomElement e = doc.documentElement();
+    e.setAttribute("kdenlive_ix", 0);
     CustomTrackView *view = (CustomTrackView *) scene()->views()[0];
     if (view) view->slotAddGroupEffect(e, this);
 }
index 38706c3a754d42811b6de437a772dca7eeb45a17..02a73c2ffbaf48d510a923129ccb3c4b4331b0ed 100644 (file)
@@ -1626,7 +1626,8 @@ void ClipItem::dropEvent(QGraphicsSceneDragDropEvent * event)
        event->acceptProposedAction();
        QDomDocument doc;
        doc.setContent(effects, true);
-       const QDomElement e = doc.documentElement();
+       QDomElement e = doc.documentElement();
+       e.setAttribute("kdenlive_ix", 0);
         CustomTrackView *view = (CustomTrackView *) scene()->views()[0];
         if (view) view->slotAddEffect(e, m_info.startPos, track());
     }
index 67dbbf860386f956aa99f988d0d9a77eeafbefbf..488baef4540755ff7edfa38e61ff6b51669a88df 100644 (file)
@@ -2043,6 +2043,7 @@ void CustomTrackView::slotUpdateClipEffect(ClipItem *clip, int track, QDomElemen
     if (clip) command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), oldeffect, effect, ix, true);
     else command = new EditEffectCommand(this, m_document->tracksCount() - track, GenTime(-1), oldeffect, effect, ix, true);
     m_commandStack->push(command);
+    kDebug()<<"// UPDATE EFFECT, "<<EffectsList::property(effect, "kdenlive_ix")<<" / "<<EffectsList::property(effect, "kdenlive_group");
 }
 
 void CustomTrackView::slotUpdateClipRegion(ClipItem *clip, int ix, QString region)
index 5b435cbedc1c9ef0461ad79ef4dba3b3040f04e7..cb6184251349018430403f80e16b403156c4d9e1 100644 (file)
@@ -224,13 +224,24 @@ void EffectsList::setProperty(QDomElement effect, const QString &name, const QSt
 {
     QDomNodeList params = effect.elementsByTagName("property");
     // Update property if it already exists
+    bool found = false;
     for (int i = 0; i < params.count(); i++) {
         QDomElement e = params.item(i).toElement();
         if (e.attribute("name") == name) {
             e.firstChild().setNodeValue(value);
+           found = true;
             break;
         }
     }
+    if (!found) {
+       // create property
+       QDomDocument doc = effect.ownerDocument();
+       QDomElement e = doc.createElement("property");
+       e.setAttribute("name", name);
+       QDomText val = doc.createTextNode(value);
+       e.appendChild(val);
+       effect.appendChild(e);
+    }
 }
 
 // static
index ace7e2843e578fee1574e7fb8a27d323f8d73450..c23a9e36b1c01037497097dddd3fc684a4687cb4 100644 (file)
@@ -116,12 +116,13 @@ void MySpinBox::focusOutEvent(QFocusEvent*)
 }
 
 
-CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_effect, ItemInfo info, int ix, EffectMetaInfo *metaInfo, bool lastEffect, QWidget * parent) :
+CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_effect, ItemInfo info, int ix, EffectMetaInfo *metaInfo, bool lastEffect, bool isGroup, QWidget * parent) :
         QWidget(parent),
         m_paramWidget(NULL),
         m_effect(effect),
         m_original_effect(original_effect),
         m_lastEffect(lastEffect),
+        m_isGroup(isGroup),
         m_active(false)
 {
     //setMouseTracking(true);
@@ -148,20 +149,30 @@ CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_ef
     //checkAll->setToolTip(i18n("Enable/Disable all effects"));
     //buttonShowComments->setIcon(KIcon("help-about"));
     //buttonShowComments->setToolTip(i18n("Show additional information for the parameters"));
-    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");
-    title->setIcon(icon);
-            
     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()));
+    
+    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");
+       title->setIcon(icon);
+       m_menu->addAction(KIcon("folder-new"), i18n("Create Group"), this, SLOT(slotCreateGroup()));
+       setupWidget(info, ix, metaInfo);
+    }
+    else {
+       setAcceptDrops(true);
+       title->setText(i18n("Effect Group"));
+       title->setIcon(KIcon("folder"));
+    }
+    
     title->setMenu(m_menu);
     
     if (m_effect.attribute("disable") == "1") {
@@ -178,7 +189,6 @@ CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_ef
     connect(buttonDown, SIGNAL(clicked()), this, SLOT(slotEffectDown()));
     connect(buttonDel, SIGNAL(clicked()), this, SLOT(slotDeleteEffect()));
 
-    setupWidget(info, ix, metaInfo);
     Q_FOREACH( QSpinBox * sp, findChildren<QSpinBox*>() ) {
         sp->installEventFilter( this );
         sp->setFocusPolicy( Qt::StrongFocus );
@@ -199,6 +209,11 @@ CollapsibleEffect::~CollapsibleEffect()
     delete m_menu;
 }
 
+void CollapsibleEffect::slotCreateGroup()
+{
+    emit createGroup(m_paramWidget->index());
+}
+
 bool CollapsibleEffect::eventFilter( QObject * o, QEvent * e ) 
 {
     if (e->type() == QEvent::Wheel) {
@@ -273,7 +288,7 @@ void CollapsibleEffect::mousePressEvent ( QMouseEvent *event )
 
 void CollapsibleEffect::enterEvent ( QEvent * event )
 {
-    if (m_paramWidget->index() > 0) buttonUp->setVisible(true);
+    if (m_paramWidget == NULL || m_paramWidget->index() > 0) buttonUp->setVisible(true);
     if (!m_lastEffect) buttonDown->setVisible(true);
     buttonDel->setVisible(true);
     if (!m_active) frame->setBackgroundRole(QPalette::Midlight);
@@ -373,6 +388,30 @@ void CollapsibleEffect::slotShow(bool show)
     }
 }
 
+void CollapsibleEffect::addGroupEffect(CollapsibleEffect *effect)
+{
+    QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
+    if (vbox == NULL) {
+       vbox = new QVBoxLayout();
+       vbox->setContentsMargins(10, 0, 0, 0);
+       vbox->setSpacing(2);
+       widgetFrame->setLayout(vbox);
+    }
+    vbox->addWidget(effect);
+}
+
+int CollapsibleEffect::index() const
+{
+    if (m_paramWidget) return m_paramWidget->index();
+    return 0;
+}
+
+int CollapsibleEffect::effectIndex() const
+{
+    if (m_effect.isNull()) return -1;
+    return m_effect.attribute("kdenlive_ix").toInt();
+}
+
 void CollapsibleEffect::updateWidget(ItemInfo info, int index, QDomElement effect, EffectMetaInfo *metaInfo)
 {
     if (m_paramWidget) {
@@ -445,7 +484,24 @@ void CollapsibleEffect::slotSyncEffectsPos(int pos)
     emit syncEffectsPos(pos);
 }
 
+void CollapsibleEffect::dragEnterEvent(QDragEnterEvent *event)
+{
+    if (event->mimeData()->hasFormat("kdenlive/effectslist"))
+       event->acceptProposedAction();
+}
 
+void CollapsibleEffect::dropEvent(QDropEvent *event)
+{
+    const QString effects = QString::fromUtf8(event->mimeData()->data("kdenlive/effectslist"));
+    //event->acceptProposedAction();
+    QDomDocument doc;
+    doc.setContent(effects, true);
+    const QDomElement e = doc.documentElement();
+    int ix = e.attribute("kdenlive_ix").toInt();
+    emit moveEffect(ix, this);
+    event->setDropAction(Qt::MoveAction);
+    event->accept();
+}
 
 ParameterContainer::ParameterContainer(QDomElement effect, ItemInfo info, EffectMetaInfo *metaInfo, int index, QWidget * parent) :
        m_index(index),
@@ -1142,7 +1198,7 @@ QString ParameterContainer::getWipeString(wipeInfo info)
     return QString(start + ";-1=" + end);
 }
 
-int ParameterContainer::index()
+int ParameterContainer::index() const
 {
     return m_index;
 }
@@ -1160,3 +1216,4 @@ void ParameterContainer::slotStartFilterJobAction()
         }
     }
 }
+
index ef614f1f79137f61a69b9c633a9287f34aed9d1b..b9bbaebea13aebbc21ee6c6074040eee4299b980 100644 (file)
@@ -64,7 +64,7 @@ public:
     ~ParameterContainer();
     void updateTimecodeFormat();
     void updateProjectFormat(MltVideoProfile profile, Timecode t);
-    int index();
+    int index() const;
 
 private slots:
     void slotCollectAllParameters();
@@ -114,7 +114,7 @@ class CollapsibleEffect : public QWidget, public Ui::CollapsibleWidget_UI
     Q_OBJECT
 
 public:
-    CollapsibleEffect(QDomElement effect, QDomElement original_effect, ItemInfo info, int ix, EffectMetaInfo *metaInfo, bool lastEffect, QWidget * parent = 0);
+    CollapsibleEffect(QDomElement effect, QDomElement original_effect, ItemInfo info, int ix, EffectMetaInfo *metaInfo, bool lastEffect, bool isGroup = false, QWidget * parent = 0);
     ~CollapsibleEffect();
     static QMap<QString, QImage> iconCache;
     void setupWidget(ItemInfo info, int index, EffectMetaInfo *metaInfo);
@@ -124,6 +124,9 @@ public:
     /** @brief Update effect GUI to reflect parameted changes. */
     void updateWidget(ItemInfo info, int index, QDomElement effect, EffectMetaInfo *metaInfo);
     QDomElement effect() const;
+    void addGroupEffect(CollapsibleEffect *effect);
+    int index() const;
+    int effectIndex() const;
 
 public slots:
     void slotSyncEffectsPos(int pos);
@@ -137,6 +140,7 @@ private slots:
     void slotEffectDown();
     void slotSaveEffect();
     void slotResetEffect();
+    void slotCreateGroup();
 
 private:
     ParameterContainer *m_paramWidget;
@@ -147,6 +151,7 @@ private:
     bool m_lastEffect;    
     int m_in;
     int m_out;
+    bool m_isGroup;
     bool m_active;
     QMenu *m_menu;
     QPoint m_clickPoint;
@@ -156,6 +161,8 @@ protected:
     virtual void mousePressEvent ( QMouseEvent * event );
     virtual void enterEvent( QEvent * event );
     virtual void leaveEvent( QEvent * event );
+    virtual void dragEnterEvent(QDragEnterEvent *event);
+    virtual void dropEvent(QDropEvent *event);
     
 signals:
     void parameterChanged(const QDomElement, const QDomElement, int);
@@ -170,7 +177,11 @@ signals:
     void startFilterJob(QString filterName, QString filterParams, QString finalFilterName, QString consumer, QString consumerParams, QString properties);
     /** @brief An effect was saved, trigger effect list reload. */
     void reloadEffects();
+    /** @brief An effect was reset, trigger param reload. */
     void resetEffect(int ix);
+    /** @brief Ask for creation of a group. */
+    void createGroup(int ix);
+    void moveEffect(int ix, CollapsibleEffect*);
 };
 
 
index 279f42ff2bf2710ebb6f13ff439b33fcd69614b1..a707ec0639dba7a5520e113842c2fd7ce94e0c2a 100644 (file)
@@ -44,7 +44,8 @@ EffectStackView2::EffectStackView2(Monitor *monitor, QWidget *parent) :
         QWidget(parent),
         m_clipref(NULL),
         m_trackindex(-1),
-        m_draggedEffect(NULL)
+        m_draggedEffect(NULL),
+        m_groupIndex(0)
 {
     m_effectMetaInfo.trackMode = false;
     m_effectMetaInfo.monitor = monitor;
@@ -161,6 +162,7 @@ void EffectStackView2::setupListView(int ix)
     m_draggedEffect = NULL;
     disconnect(m_effectMetaInfo.monitor, SIGNAL(renderPosition(int)), this, SLOT(slotRenderPos(int)));
     m_effects.clear();
+    m_groupIndex = 0;
     QWidget *view = m_ui.container->takeWidget();
     if (view) {
        delete view;
@@ -180,6 +182,15 @@ void EffectStackView2::setupListView(int ix)
             kDebug() << " . . . . WARNING, NULL EFFECT IN STACK!!!!!!!!!";
             continue;
         }
+        
+        CollapsibleEffect *group = NULL;
+        QString groupName = EffectsList::property(d, "kdenlive_group");
+       if (!groupName.isEmpty()) {
+           kDebug()<<"// CREATING EWFFECT GRP: "<<groupName;
+           group = new CollapsibleEffect(QDomElement(), QDomElement(), ItemInfo(), groupName.toInt(), &m_effectMetaInfo, false, true, m_ui.container->widget());
+           connect(group, SIGNAL(moveEffect(int, CollapsibleEffect*)), this , SLOT(slotMoveEffectToGroup(int, CollapsibleEffect*)));
+           vbox1->addWidget(group);
+       }
 
         /*QDomDocument doc;
         doc.appendChild(doc.importNode(d, true));
@@ -195,9 +206,13 @@ 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, view);
+        CollapsibleEffect *currentEffect = new CollapsibleEffect(d, m_currentEffectList.at(i), info, i, &m_effectMetaInfo, i == m_currentEffectList.count() - 1, false, view);
         m_effects.append(currentEffect);
-        vbox1->addWidget(currentEffect);
+        if (group) {
+           group->addGroupEffect(currentEffect);
+       } else {
+           vbox1->addWidget(currentEffect);
+       }
 
        // Check drag & drop
        currentEffect->installEventFilter( this );
@@ -212,7 +227,10 @@ void EffectStackView2::setupListView(int ix)
         connect(currentEffect, SIGNAL(activateEffect(int)), this, SLOT(slotSetCurrentEffect(int)));
         connect(currentEffect, SIGNAL(checkMonitorPosition(int)), this, SLOT(slotCheckMonitorPosition(int)));
         connect(currentEffect, SIGNAL(seekTimeline(int)), this , SLOT(slotSeekTimeline(int)));
-            //ui.title->setPixmap(icon.pixmap(QSize(12, 12)));
+       connect(currentEffect, SIGNAL(createGroup(int)), this , SLOT(slotCreateGroup(int)));
+       connect(currentEffect, SIGNAL(moveEffect(int, CollapsibleEffect*)), this , SLOT(slotMoveEffectToGroup(int, CollapsibleEffect*)));
+       
+        //ui.title->setPixmap(icon.pixmap(QSize(12, 12)));
     }
     vbox1->addStretch(10);
     connect(m_effectMetaInfo.monitor, SIGNAL(renderPosition(int)), this, SLOT(slotRenderPos(int)));
@@ -271,7 +289,6 @@ void EffectStackView2::startDrag()
     QDomElement effect = m_draggedEffect->effect().cloneNode().toElement();
     QPixmap pixmap = QPixmap::grabWidget(m_draggedEffect->title);
     drag->setPixmap(pixmap);
-    effect.setAttribute("kdenlive_ix", 0);
     QDomDocument doc;
     doc.appendChild(doc.importNode(effect, true));
     QMimeData *mime = new QMimeData;
@@ -282,7 +299,7 @@ void EffectStackView2::startDrag()
     // Assign ownership of the QMimeData object to the QDrag object.
     drag->setMimeData(mime);
     // Start the drag and drop operation
-    drag->exec(Qt::CopyAction);// | Qt::MoveAction);
+    drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
 }
 
 
@@ -354,6 +371,16 @@ void EffectStackView2::updateTimecodeFormat()
         m_effects.at(i)->updateTimecodeFormat();
 }
 
+CollapsibleEffect *EffectStackView2::getEffectByIndex(int ix)
+{
+    for (int i = 0; i< m_effects.count(); i++) {
+        if (m_effects.at(i)->effectIndex() == ix) {
+           return m_effects.at(i);
+       }
+    }
+    return NULL;
+}
+
 void EffectStackView2::slotUpdateEffectParams(const QDomElement old, const QDomElement e, int ix)
 {
     if (m_effectMetaInfo.trackMode)
@@ -423,7 +450,6 @@ void EffectStackView2::slotResetEffect(int ix)
     }
     if (!dom.isNull()) {
         dom.setAttribute("kdenlive_ix", old.attribute("kdenlive_ix"));
-       //TODO: Track mode
         if (m_effectMetaInfo.trackMode) {
             EffectsList::setParameter(dom, "in", QString::number(0));
             EffectsList::setParameter(dom, "out", QString::number(m_trackInfo.duration));
@@ -438,7 +464,6 @@ void EffectStackView2::slotResetEffect(int ix)
         } else {
             m_clipref->initEffect(dom);
            m_effects.at(ix)->updateWidget(m_clipref->info(), ix, dom, &m_effectMetaInfo);
-            //m_effectedit->transferParamDesc(dom, m_clipref->info());
             //m_ui.region_url->setUrl(KUrl(dom.attribute("region")));
             emit updateEffect(m_clipref, -1, old, dom, ix);
         }
@@ -448,4 +473,44 @@ void EffectStackView2::slotResetEffect(int ix)
     m_ui.labelComment->setHidden(!m_ui.buttonShowComments->isChecked() || !m_ui.labelComment->text().count());*/
 }
 
+
+void EffectStackView2::slotCreateGroup(int ix)
+{
+    QDomElement oldeffect = m_currentEffectList.at(ix);
+    QDomElement neweffect = oldeffect.cloneNode().toElement();
+    QString groupName = QString::number(m_groupIndex);
+    m_groupIndex++;
+    EffectsList::setProperty(neweffect, "kdenlive_group", groupName);
+
+    ItemInfo info;
+    if (m_effectMetaInfo.trackMode) { 
+       info.track = m_trackInfo.type;
+        info.cropDuration = GenTime(m_trackInfo.duration, KdenliveSettings::project_fps());
+        info.cropStart = GenTime(0);
+        info.startPos = GenTime(-1);
+        info.track = 0;
+       emit updateEffect(NULL, m_trackindex, oldeffect, neweffect, ix);
+    } else {
+       emit updateEffect(m_clipref, -1, oldeffect, neweffect, ix);
+    }
+    
+    QVBoxLayout *l = static_cast<QVBoxLayout *>(m_ui.container->widget()->layout());
+    int groupPos = l->indexOf(m_effects.at(ix));
+    
+    CollapsibleEffect *group = new CollapsibleEffect(QDomElement(), QDomElement(), ItemInfo(), m_groupIndex, &m_effectMetaInfo, false, true, m_ui.container->widget());
+    connect(group, SIGNAL(moveEffect(int, CollapsibleEffect*)), this , SLOT(slotMoveEffectToGroup(int, CollapsibleEffect*)));
+    CollapsibleEffect *w = static_cast<CollapsibleEffect*>(l->takeAt(groupPos)->widget());
+    l->insertWidget(groupPos, group);
+    group->addGroupEffect(w);
+}
+
+void EffectStackView2::slotMoveEffectToGroup(int ix, CollapsibleEffect* group)
+{
+    QVBoxLayout *l = static_cast<QVBoxLayout *>(m_ui.container->widget()->layout());
+    CollapsibleEffect *effectToMove = getEffectByIndex(ix);
+    if (effectToMove == NULL) return;
+    l->removeWidget(effectToMove);
+    group->addGroupEffect(effectToMove);
+}
+
 #include "effectstackview2.moc"
index f042fa642c4ab9e55f794df7c076d3a311d165a8..adae1bbe61882ecd6d76bf7df478568ade1a773f 100644 (file)
@@ -64,6 +64,8 @@ public:
     
     /** @brief Used to trigger drag effects. */
     virtual bool eventFilter( QObject * o, QEvent * e );
+    
+    CollapsibleEffect *getEffectByIndex(int ix);
 
 protected:
     virtual void mouseMoveEvent(QMouseEvent * event);
@@ -89,6 +91,9 @@ private:
     
     /** @brief The effect currently being dragged, NULL if no drag happening. */
     CollapsibleEffect *m_draggedEffect;
+    
+    /** @brief The current number of groups. */
+    int m_groupIndex;
 
     /** @brief Sets the list of effects according to the clip's effect list.
     * @param ix Number of the effect to preselect */
@@ -143,6 +148,12 @@ private slots:
     
     /** @brief Reset an effect to its default values. */
     void slotResetEffect(int ix);
+    
+    /** @brief Create a group containing effect with ix index. */
+    void slotCreateGroup(int ix);
+    
+    /** @brief Move an effect into a group. */
+    void slotMoveEffectToGroup(int, CollapsibleEffect*);
 
 
 signals: