]> git.sesse.net Git - kdenlive/commitdiff
Effect groups can now be dropped onto another clip
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Thu, 29 Mar 2012 00:44:34 +0000 (02:44 +0200)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Thu, 29 Mar 2012 00:44:34 +0000 (02:44 +0200)
12 files changed:
src/clipitem.cpp
src/clipitem.h
src/customtrackview.cpp
src/customtrackview.h
src/effectslist.cpp
src/effectslist.h
src/effectstack/collapsibleeffect.cpp
src/effectstack/collapsibleeffect.h
src/effectstack/collapsiblegroup.cpp
src/effectstack/collapsiblegroup.h
src/effectstack/effectstackview2.cpp
src/effectstack/effectstackview2.h

index 1d0e4c7b58a694f25f2ee6ea4ead9a2e6620306a..f1de5698f9aed2ed02f2a287451de6e9c860e071 100644 (file)
@@ -230,8 +230,6 @@ void ClipItem::initEffect(QDomElement effect, int diff)
 {
     // the kdenlive_ix int is used to identify an effect in mlt's playlist, should
     // not be changed
-    if (effect.attribute("kdenlive_ix").toInt() == 0)
-        effect.setAttribute("kdenlive_ix", QString::number(effectsCounter()));
 
     if (effect.attribute("id") == "freeze" && diff > 0) {
         EffectsList::setParameter(effect, "frame", QString::number(diff));
@@ -1410,31 +1408,36 @@ bool ClipItem::moveEffect(QDomElement effect, int ix)
     return true;
 }
 
-EffectsParameterList ClipItem::addEffect(const QDomElement effect, bool /*animate*/)
+EffectsParameterList ClipItem::addEffect(QDomElement effect, bool /*animate*/)
 {
     bool needRepaint = false;
     QLocale locale;
     int ix;
+    QDomElement insertedEffect;
     if (!effect.hasAttribute("kdenlive_ix")) {
         ix = effectsCounter();
     } else ix = effect.attribute("kdenlive_ix").toInt();
     if (!m_effectList.isEmpty() && ix <= m_effectList.count()) {
         needRepaint = true;
-        m_effectList.insert(effect);
-    } else m_effectList.append(effect);
+        insertedEffect = m_effectList.insert(effect);
+    } else insertedEffect = m_effectList.append(effect);
+    
+    // Update index to the real one
+    effect.setAttribute("kdenlive_ix", insertedEffect.attribute("kdenlive_ix"));
+    
     EffectsParameterList parameters;
-    parameters.addParam("tag", effect.attribute("tag"));
-    parameters.addParam("kdenlive_ix", effect.attribute("kdenlive_ix"));
-    if (effect.hasAttribute("src")) parameters.addParam("src", effect.attribute("src"));
-    if (effect.hasAttribute("disable")) parameters.addParam("disable", effect.attribute("disable"));
+    parameters.addParam("tag", insertedEffect.attribute("tag"));
+    parameters.addParam("kdenlive_ix", insertedEffect.attribute("kdenlive_ix"));
+    if (insertedEffect.hasAttribute("src")) parameters.addParam("src", insertedEffect.attribute("src"));
+    if (insertedEffect.hasAttribute("disable")) parameters.addParam("disable", insertedEffect.attribute("disable"));
 
-    QString effectId = effect.attribute("id");
-    if (effectId.isEmpty()) effectId = effect.attribute("tag");
+    QString effectId = insertedEffect.attribute("id");
+    if (effectId.isEmpty()) effectId = insertedEffect.attribute("tag");
     parameters.addParam("id", effectId);
 
     // special case: the affine effect needs in / out points
 
-    QDomNodeList params = effect.elementsByTagName("parameter");
+    QDomNodeList params = insertedEffect.elementsByTagName("parameter");
     int fade = 0;
     bool needInOutSync = false;
     for (int i = 0; i < params.count(); i++) {
@@ -1635,7 +1638,16 @@ void ClipItem::dropEvent(QGraphicsSceneDragDropEvent * event)
        QDomDocument doc;
        doc.setContent(effects, true);
        QDomElement e = doc.documentElement();
-       e.setAttribute("kdenlive_ix", 0);
+       if (e.tagName() == "list") {
+           // dropped an effect group
+           QDomNodeList effectlist = e.elementsByTagName("effect");
+           for (int i = 0; i < effectlist.count(); i++) {
+               effectlist.at(i).toElement().removeAttribute("kdenlive_ix");
+           }
+       } else {
+           // single effect dropped
+           e.removeAttribute("kdenlive_ix");
+       }
         CustomTrackView *view = (CustomTrackView *) scene()->views()[0];
         if (view) view->slotAddEffect(e, m_info.startPos, track());
     }
index 6457dbcb956f45689672fae882af9bc6145cc81f..f5c8a5b8f8cc682dacbca10ae84fa5831d50c7ba 100644 (file)
@@ -75,7 +75,7 @@ public:
 
     /** @brief Adds an effect to the clip.
     * @return The parameters that will be passed to Mlt */
-    EffectsParameterList addEffect(const QDomElement effect, bool animate = true);
+    EffectsParameterList addEffect(QDomElement effect, bool animate = true);
 
     /** @brief Deletes the effect with id @param index. */
     void deleteEffect(QString index);
index 61fb07b85694fa73b4b7b8c53b9edf1bb360708d..66daef02ddd0dec4abf0f16a01dab5641eb4fb9a 100644 (file)
@@ -1727,32 +1727,21 @@ void CustomTrackView::slotAddGroupEffect(QDomElement effect, AbstractGroupItem *
     if (!namenode.isNull()) effectName = i18n(namenode.text().toUtf8().data());
     else effectName = i18n("effect");
     effectCommand->setText(i18n("Add %1", effectName));
-    int count = 0;
     for (int i = 0; i < itemList.count(); i++) {
         if (itemList.at(i)->type() == AVWIDGET) {
             ClipItem *item = static_cast <ClipItem *>(itemList.at(i));
-            if (effect.attribute("type") == "audio") {
-                // Don't add audio effects on video clips
-                if (item->isVideoOnly() || (item->clipType() != AUDIO && item->clipType() != AV && item->clipType() != PLAYLIST)) continue;
-            } else if (effect.hasAttribute("type") == false) {
-                // Don't add video effect on audio clips
-                if (item->isAudioOnly() || item->clipType() == AUDIO) continue;
-            }
-
-            if (effect.attribute("unique", "0") != "0" && item->hasEffect(effect.attribute("tag"), effect.attribute("id")) != -1) {
-                emit displayMessage(i18n("Effect already present in clip"), ErrorMessage);
-                continue;
-            }
-            if (item->isItemLocked()) {
-                continue;
-            }
-            item->initEffect(effect);
-
-            new AddEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), effect, true, effectCommand);
-            count++;
+            if (effect.tagName() == "list") {
+               QDomNodeList effectlist = effect.elementsByTagName("effect");
+               for (int j = 0; j < effectlist.count(); j++) {
+                   processEffect(item, effectlist.at(j).toElement(), effectCommand);
+               }
+           }
+            else {
+               processEffect(item, effect, effectCommand);
+           }
         }
     }
-    if (count > 0) {
+    if (effectCommand->childCount() > 0) {
         m_commandStack->push(effectCommand);
         setDocumentModified();
     } else delete effectCommand;
@@ -1768,9 +1757,13 @@ void CustomTrackView::slotAddEffect(QDomElement effect, GenTime pos, int track)
     QList<QGraphicsItem *> itemList;
     QUndoCommand *effectCommand = new QUndoCommand();
     QString effectName;
-    QDomElement namenode = effect.firstChildElement("name");
-    if (!namenode.isNull()) effectName = i18n(namenode.text().toUtf8().data());
-    else effectName = i18n("effect");
+    if (effect.tagName() == "list") {
+       effectName = effect.attribute("name");
+    } else {
+       QDomElement namenode = effect.firstChildElement("name");
+       if (!namenode.isNull()) effectName = i18n(namenode.text().toUtf8().data());
+       else effectName = i18n("effect");
+    }
     effectCommand->setText(i18n("Add %1", effectName));
 
     if (track == -1) itemList = scene()->selectedItems();
@@ -1793,40 +1786,13 @@ void CustomTrackView::slotAddEffect(QDomElement effect, GenTime pos, int track)
     for (int i = 0; i < itemList.count(); i++) {
         if (itemList.at(i)->type() == AVWIDGET) {
             ClipItem *item = static_cast <ClipItem *>(itemList.at(i));
-            if (effect.attribute("type") == "audio") {
-                // Don't add audio effects on video clips
-                if (item->isVideoOnly() || (item->clipType() != AUDIO && item->clipType() != AV && item->clipType() != PLAYLIST)) {
-                    /* do not show error message when item is part of a group as the user probably knows what he does then
-                     * and the message is annoying when working with the split audio feature */
-                    if (!item->parentItem() || item->parentItem() == m_selectionGroup)
-                        emit displayMessage(i18n("Cannot add an audio effect to this clip"), ErrorMessage);
-                    continue;
-                }
-            } else if (effect.attribute("type") == "video" || !effect.hasAttribute("type")) {
-                // Don't add video effect on audio clips
-                if (item->isAudioOnly() || item->clipType() == AUDIO) {
-                    /* do not show error message when item is part of a group as the user probably knows what he does then
-                     * and the message is annoying when working with the split audio feature */
-                    if (!item->parentItem() || item->parentItem() == m_selectionGroup)
-                        emit displayMessage(i18n("Cannot add a video effect to this clip"), ErrorMessage);
-                    continue;
-                }
-            }
-            if (item->hasEffect(effect.attribute("tag"), effect.attribute("id")) != -1 && effect.attribute("unique", "0") != "0") {
-                emit displayMessage(i18n("Effect already present in clip"), ErrorMessage);
-                continue;
-            }
-            if (item->isItemLocked()) {
-                continue;
-            }
-
-            if (effect.attribute("id") == "freeze" && m_cursorPos > item->startPos().frames(m_document->fps()) && m_cursorPos < item->endPos().frames(m_document->fps())) {
-                item->initEffect(effect, m_cursorPos - item->startPos().frames(m_document->fps()));
-            } else {
-               kDebug()<<"PREIT 0: "<<effect.attribute("kdenlive_ix");
-                item->initEffect(effect);
-            }
-            new AddEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), effect, true, effectCommand);
+           if (effect.tagName() == "list") {
+               QDomNodeList effectlist = effect.elementsByTagName("effect");
+               for (int j = 0; j < effectlist.count(); j++) {
+                   processEffect(item, effectlist.at(j).toElement(), effectCommand);
+               }
+           }
+            else processEffect(item, effect, effectCommand);
         }
     }
     if (effectCommand->childCount() > 0) {
@@ -1850,6 +1816,43 @@ void CustomTrackView::slotAddEffect(QDomElement effect, GenTime pos, int track)
     } else delete effectCommand;
 }
 
+void CustomTrackView::processEffect(ClipItem *item, QDomElement effect, QUndoCommand *effectCommand)
+{
+    if (effect.attribute("type") == "audio") {
+       // Don't add audio effects on video clips
+        if (item->isVideoOnly() || (item->clipType() != AUDIO && item->clipType() != AV && item->clipType() != PLAYLIST)) {
+           /* do not show error message when item is part of a group as the user probably knows what he does then
+            * and the message is annoying when working with the split audio feature */
+            if (!item->parentItem() || item->parentItem() == m_selectionGroup)
+               emit displayMessage(i18n("Cannot add an audio effect to this clip"), ErrorMessage);
+            return;
+        }
+    } else if (effect.attribute("type") == "video" || !effect.hasAttribute("type")) {
+       // Don't add video effect on audio clips
+        if (item->isAudioOnly() || item->clipType() == AUDIO) {
+           /* do not show error message when item is part of a group as the user probably knows what he does then
+            * and the message is annoying when working with the split audio feature */
+            if (!item->parentItem() || item->parentItem() == m_selectionGroup)
+               emit displayMessage(i18n("Cannot add a video effect to this clip"), ErrorMessage);
+            return;
+        }
+    }
+    if (item->hasEffect(effect.attribute("tag"), effect.attribute("id")) != -1 && effect.attribute("unique", "0") != "0") {
+       emit displayMessage(i18n("Effect already present in clip"), ErrorMessage);
+        return;
+    }
+    if (item->isItemLocked()) {
+       return;
+    }
+
+    if (effect.attribute("id") == "freeze" && m_cursorPos > item->startPos().frames(m_document->fps()) && m_cursorPos < item->endPos().frames(m_document->fps())) {
+       item->initEffect(effect, m_cursorPos - item->startPos().frames(m_document->fps()));
+    } else {
+       item->initEffect(effect);
+    }
+    new AddEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), effect, true, effectCommand);
+}
+
 void CustomTrackView::slotDeleteEffect(ClipItem *clip, int track, QDomElement effect, bool affectGroup)
 {
     if (clip == NULL) {
index 015a2fe15089b13bff84ec405a79ac9d9c1c08ba..6a66ae68c253e59b88a21b98c571e0f49753011d 100644 (file)
@@ -441,6 +441,9 @@ private:
      * @param fromStart false = resize from end
      * @param command Used as a parent for EditEffectCommand */
     void adjustEffects(ClipItem *item, ItemInfo oldInfo, QUndoCommand *command);
+    
+    /** @brief Prepare an add clip command for an effect */
+    void processEffect(ClipItem *item, QDomElement effect, QUndoCommand *effectCommand);
 
 private slots:
     void slotRefreshGuides();
index 77c1f41e1f235a335182480d7e813364e46009f9..276c748d0915f69482919d1988778555a2f81502 100644 (file)
@@ -297,12 +297,16 @@ void EffectsList::removeMetaProperties(QDomElement producer)
     }
 }
 
-void EffectsList::append(QDomElement e)
+QDomElement EffectsList::append(QDomElement e)
 {
+    QDomElement result;
     if (!e.isNull()) {
-       m_baseElement.appendChild(importNode(e, true));
-       if (m_useIndex) updateIndexes(m_baseElement.childNodes());
+       result = m_baseElement.appendChild(importNode(e, true)).toElement();
+       if (m_useIndex) {
+           updateIndexes(m_baseElement.childNodes());
+       }
     }
+    return result;
 }
 
 int EffectsList::count() const
@@ -337,16 +341,18 @@ QDomElement EffectsList::itemFromIndex(int ix) const
     return effects.at(ix - 1).toElement();
 }
 
-void EffectsList::insert(QDomElement effect)
+QDomElement EffectsList::insert(QDomElement effect)
 {
     QDomNodeList effects = m_baseElement.childNodes();
     int ix = effect.attribute("kdenlive_ix").toInt();
-    if (ix > effects.count()) m_baseElement.appendChild(importNode(effect, true));
+    QDomElement result;
+    if (effect.hasAttribute("kdenlive_ix") && ix > effects.count()) result = m_baseElement.appendChild(importNode(effect, true)).toElement();
     else {
         QDomElement listeffect =  effects.at(ix - 1).toElement();
-       m_baseElement.insertBefore(importNode(effect, true), listeffect);
+       result = m_baseElement.insertBefore(importNode(effect, true), listeffect).toElement();
     }
     if (m_useIndex) updateIndexes(effects);
+    return result;
 }
 
 void EffectsList::updateIndexes(QDomNodeList effects)
index 0e26b05f5abd1cd2512044dd886113d4a205f719..e338b2bf1bc8abcad5134a66827ad4eb59bb54d1 100644 (file)
@@ -60,13 +60,13 @@ public:
     QString getInfoFromIndex(const int ix) const;
     QString getEffectInfo(const QDomElement effect) const;
     void clone(const EffectsList &original);
-    void append(QDomElement e);
+    QDomElement append(QDomElement e);
     bool isEmpty() const;
     int count() const;
     const QDomElement at(int ix) const;
     void removeAt(int ix);
     QDomElement itemFromIndex(int ix) const;
-    void insert(QDomElement effect);
+    QDomElement insert(QDomElement effect);
     void updateEffect(QDomElement effect);
     static bool hasKeyFrames(QDomElement effect);
     static bool hasSimpleKeyFrames(QDomElement effect);
index 6ab1eb8cdfef4221e1a29976a0d99d6ea7babb9c..47f39de4e2b6eaf8bd116c3aa01b4d9562ca41c4 100644 (file)
@@ -428,6 +428,7 @@ void CollapsibleEffect::slotShow(bool show)
 void CollapsibleEffect::updateGroupIndex(int groupIndex)
 {
     m_info.groupIndex = groupIndex;
+    if (groupIndex == -1) m_info.groupName.clear();
     m_effect.setAttribute("kdenlive_info", m_info.toString());
     emit parameterChanged(m_original_effect, m_effect, effectIndex());
 }
@@ -592,7 +593,7 @@ void CollapsibleEffect::dropEvent(QDropEvent *event)
        emit addEffect(e);
        return;
     }
-    emit moveEffect(ix, effectIndex(), groupIndex());
+    emit moveEffect(ix, effectIndex(), m_info.groupIndex, m_info.groupName);
     event->setDropAction(Qt::MoveAction);
     event->accept();
 }
index 29682d39964494314a1b3335a0eb92c82789ae1f..38d893e76450efbdb9ec163fb69e698b0bbc973e 100644 (file)
@@ -199,7 +199,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, int groupIndex);
+    void moveEffect(int current_pos, int new_pos, int groupIndex, QString groupName);
     void unGroup(CollapsibleEffect *);
     void addEffect(QDomElement e);
 };
index 5b19a1f3dd9f94851f05e0ca1d8cc83e4b4b5b6b..de38ff5dfe5a97aa49cd7b98e50635f2f7a156bf 100644 (file)
@@ -42,6 +42,7 @@ MyEditableLabel::MyEditableLabel(QWidget * parent):
 {
     setFrame(false);
     setReadOnly(true);
+    setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
 }
 
 void MyEditableLabel::mouseDoubleClickEvent ( QMouseEvent * e )
@@ -56,6 +57,7 @@ CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, QStr
         m_index(ix)
 {
     setupUi(this);
+    m_subWidgets = QList <CollapsibleEffect *> ();
     setFont(KGlobalSettings::smallestReadableFont());
     QHBoxLayout *l = static_cast <QHBoxLayout *>(framegroup->layout());
     m_title = new MyEditableLabel(this);
@@ -208,12 +210,9 @@ void CollapsibleGroup::slotShow(bool show)
     //emit parameterChanged(m_original_effect, m_effect, effectIndex());   
 }
 
-void CollapsibleGroup::updateGroupIndex(int groupIndex)
+QWidget *CollapsibleGroup::title() const
 {
-  /*TODO:
-    m_info.groupIndex = groupIndex;
-    m_effect.setAttribute("kdenlive_info", m_info.toString());
-    emit parameterChanged(m_original_effect, m_effect, effectIndex());*/
+    return m_title;
 }
 
 void CollapsibleGroup::addGroupEffect(CollapsibleEffect *effect)
@@ -226,6 +225,8 @@ void CollapsibleGroup::addGroupEffect(CollapsibleEffect *effect)
        widgetFrame->setLayout(vbox);
     }
     effect->setGroupIndex(groupIndex());
+    effect->setGroupName(m_title->text());
+    m_subWidgets.append(effect);
     vbox->addWidget(effect);
 }
 
@@ -238,14 +239,11 @@ void CollapsibleGroup::removeGroup(int ix, QVBoxLayout *layout)
 {
     QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
     if (vbox == NULL) return;
-    
-    for (int j = vbox->count() - 1; j >= 0; j--) {
-       QLayoutItem *child = vbox->takeAt(j);
-       CollapsibleGroup *e = static_cast<CollapsibleGroup *>(child->widget());
-       layout->insertWidget(ix, e);
-       e->updateGroupIndex(-1);
-       delete child;
+    for (int i = m_subWidgets.count() - 1; i >= 0 ; i--) {
+       vbox->removeWidget(m_subWidgets.at(i));
+       layout->insertWidget(ix, m_subWidgets.at(i));
     }
+    m_subWidgets.clear();
 }
 
 int CollapsibleGroup::groupIndex() const
@@ -253,8 +251,6 @@ int CollapsibleGroup::groupIndex() const
     return m_index;
 }
 
-
-
 bool CollapsibleGroup::isGroup() const
 {
     return true;
@@ -303,12 +299,9 @@ void CollapsibleGroup::dropEvent(QDropEvent *event)
        emit addEffect(e);
        return;
     }
-    int new_index = -1;
-    QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
-    if (vbox == NULL) return;
-    CollapsibleEffect *effect = static_cast<CollapsibleEffect *>(vbox->itemAt(vbox->count() -1)->widget());
-    new_index = effect->effectIndex();
-    emit moveEffect(ix, new_index, m_index);
+    if (m_subWidgets.isEmpty()) return;
+    int new_index = m_subWidgets.at(m_subWidgets.count() - 1)->effectIndex();
+    emit moveEffect(ix, new_index, m_index, m_title->text());
     event->setDropAction(Qt::MoveAction);
     event->accept();
 }
@@ -317,17 +310,26 @@ void CollapsibleGroup::slotRenameGroup()
 {
     m_title->setReadOnly(true);
     if (m_title->text().isEmpty()) m_title->setText(i18n("Effect Group"));
-    QList <CollapsibleEffect*> effects = findChildren<CollapsibleEffect*>();
-    for (int j = 0; j < effects.count(); j++) {
-       effects.at(j)->setGroupName(m_title->text());
+    for (int j = 0; j < m_subWidgets.count(); j++) {
+       m_subWidgets.at(j)->setGroupName(m_title->text());
     }
     emit groupRenamed(this);
 }
 
 QList <CollapsibleEffect*> CollapsibleGroup::effects()
 {
-    QList <CollapsibleEffect*> result = findChildren<CollapsibleEffect*>();
-    return result;
+    return m_subWidgets;
 }
 
+QDomDocument CollapsibleGroup::effectsData()
+{
+    QDomDocument doc;
+    QDomElement list = doc.createElement("list");
+    list.setAttribute("name", m_title->text());
+    doc.appendChild(list);
+    for (int j = 0; j < m_subWidgets.count(); j++) {
+       list.appendChild(doc.importNode(m_subWidgets.at(j)->effect(), true));
+    }
+    return doc;
+}
 
index ee3b8f3dda1e89a6ed6d8063a0420f995ec37472..79e7a5cc10b330f5adfecde21557772074e80477 100644 (file)
@@ -68,7 +68,12 @@ public:
     bool isActive() const;
     void addGroupEffect(CollapsibleEffect *effect);
     void removeGroup(int ix, QVBoxLayout *layout);
+    /** @brief Return all effects in group. */
     QList <CollapsibleEffect*> effects();
+    /** @brief Return the editable title widget. */
+    QWidget *title() const;
+    /** @brief Return the XML data describing all effects in group. */
+    QDomDocument effectsData();
 
 public slots:
     void slotEnable(bool enable);
@@ -85,11 +90,10 @@ private slots:
     void slotRenameGroup();
 
 private:
-    //QList <CollapsibleEffect *> m_subParamWidgets;
+    QList <CollapsibleEffect *> m_subWidgets;
     QMenu *m_menu;
     EffectInfo m_info;
     int m_index;
-    void updateGroupIndex(int groupIndex);
     MyEditableLabel *m_title;
     
 protected:
@@ -104,7 +108,7 @@ signals:
     void deleteGroup(int);
     void changeGroupPosition(int, bool);
     void activateEffect(int);
-    void moveEffect(int current_pos, int new_pos, int groupIndex);
+    void moveEffect(int current_pos, int new_pos, int groupIndex, QString groupName);
     void addEffect(QDomElement e);
     void unGroup(CollapsibleGroup *);
     void groupRenamed(CollapsibleGroup *);
index eb9a3b8f31e0c7219ac9acf61d8c60fab7f7829b..55827ded1217aa29e96fbc49994e564bd5eac0a1 100644 (file)
@@ -48,6 +48,7 @@ EffectStackView2::EffectStackView2(Monitor *monitor, QWidget *parent) :
         m_clipref(NULL),
         m_trackindex(-1),
         m_draggedEffect(NULL),
+        m_draggedGroup(NULL),
         m_groupIndex(0)
 {
     m_effectMetaInfo.trackMode = false;
@@ -141,6 +142,7 @@ void EffectStackView2::setupListView(int ix)
 {
     blockSignals(true);
     m_draggedEffect = NULL;
+    m_draggedGroup = NULL;
     disconnect(m_effectMetaInfo.monitor, SIGNAL(renderPosition(int)), this, SLOT(slotRenderPos(int)));
     m_effects.clear();
     m_groupIndex = 0;
@@ -181,10 +183,11 @@ void EffectStackView2::setupListView(int ix)
            
            if (group == NULL) {
                group = new CollapsibleGroup(effectInfo.groupIndex, i == 0, i == m_currentEffectList.count() - 1, effectInfo.groupName, m_ui.container->widget());
-               connect(group, SIGNAL(moveEffect(int,int,int)), this, SLOT(slotMoveEffect(int,int,int)));
+               connect(group, SIGNAL(moveEffect(int,int,int,QString)), this, SLOT(slotMoveEffect(int,int,int,QString)));
                connect(group, SIGNAL(unGroup(CollapsibleGroup*)), this , SLOT(slotUnGroup(CollapsibleGroup*)));
                connect(group, SIGNAL(groupRenamed(CollapsibleGroup *)), this, SLOT(slotRenameGroup(CollapsibleGroup*)));
                vbox1->addWidget(group);
+               group->installEventFilter( this );
            }
            if (effectInfo.groupIndex >= m_groupIndex) m_groupIndex = effectInfo.groupIndex + 1;
        }
@@ -226,7 +229,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,int)), this , SLOT(slotMoveEffect(int,int,int)));
+       connect(currentEffect, SIGNAL(moveEffect(int,int,int,QString)), this , SLOT(slotMoveEffect(int,int,int,QString)));
        connect(currentEffect, SIGNAL(addEffect(QDomElement)), this , SLOT(slotAddEffect(QDomElement)));
        
         //ui.title->setPixmap(icon.pixmap(QSize(12, 12)));
@@ -276,6 +279,18 @@ bool EffectStackView2::eventFilter( QObject * o, QEvent * e )
            e->accept();
            return false;
        }
+       m_draggedGroup = qobject_cast<CollapsibleGroup*>(o);
+       if (m_draggedGroup) {
+           QMouseEvent *me = static_cast<QMouseEvent *>(e);
+           if (me->button() == Qt::LeftButton && (m_draggedGroup->framegroup->underMouse() || m_draggedGroup->title()->underMouse()))
+               m_clickPoint = me->globalPos();
+           else {
+               m_clickPoint = QPoint();
+               m_draggedGroup = NULL;
+           }
+           e->accept();
+           return false;
+       }
     }  
     if (e->type() == QEvent::MouseMove)  {
        if (qobject_cast<CollapsibleEffect*>(o)) {
@@ -295,26 +310,37 @@ bool EffectStackView2::eventFilter( QObject * o, QEvent * e )
 
 void EffectStackView2::mouseMoveEvent(QMouseEvent * event)
 {
-    if (m_draggedEffect && (event->buttons() & Qt::LeftButton) && (m_clickPoint != QPoint()) && ((event->globalPos() - m_clickPoint).manhattanLength() >= QApplication::startDragDistance())) {
-       startDrag();
+    if (m_draggedEffect || m_draggedGroup) {
+       if ((event->buttons() & Qt::LeftButton) && (m_clickPoint != QPoint()) && ((event->globalPos() - m_clickPoint).manhattanLength() >= QApplication::startDragDistance())) {
+           startDrag();
+       }
     }
 }
 
 void EffectStackView2::mouseReleaseEvent(QMouseEvent * event)
 {
     m_draggedEffect = NULL;
+    m_draggedGroup = NULL;
     QWidget::mouseReleaseEvent(event);
 }
 
 void EffectStackView2::startDrag()
 {
-    QDrag *drag = new QDrag(this);
     // The data to be transferred by the drag and drop operation is contained in a QMimeData object
-    QDomElement effect = m_draggedEffect->effect().cloneNode().toElement();
-    QPixmap pixmap = QPixmap::grabWidget(m_draggedEffect->title);
-    drag->setPixmap(pixmap);
     QDomDocument doc;
-    doc.appendChild(doc.importNode(effect, true));
+    QPixmap pixmap;
+    if (m_draggedEffect) {
+       QDomElement effect = m_draggedEffect->effect().cloneNode().toElement();
+       doc.appendChild(doc.importNode(effect, true));
+       pixmap = QPixmap::grabWidget(m_draggedEffect->title);
+    }
+    else if (m_draggedGroup) {
+       doc = m_draggedGroup->effectsData();
+       pixmap = QPixmap::grabWidget(m_draggedGroup->title());
+    }
+    else return;
+    QDrag *drag = new QDrag(this);
+    drag->setPixmap(pixmap);
     QMimeData *mime = new QMimeData;
     QByteArray data;
     data.append(doc.toString().toUtf8());
@@ -598,14 +624,15 @@ void EffectStackView2::slotCreateGroup(int ix)
     
     CollapsibleGroup *group = new CollapsibleGroup(m_groupIndex, ix == 1, ix == m_currentEffectList.count() - 2, QString(), m_ui.container->widget());
     m_groupIndex++;
-    connect(group, SIGNAL(moveEffect(int,int,int)), this , SLOT(slotMoveEffect(int,int,int)));
+    connect(group, SIGNAL(moveEffect(int,int,int,QString)), this , SLOT(slotMoveEffect(int,int,int,QString)));
     connect(group, SIGNAL(unGroup(CollapsibleGroup*)), this , SLOT(slotUnGroup(CollapsibleGroup*)));
     connect(group, SIGNAL(groupRenamed(CollapsibleGroup *)), this , SLOT(slotRenameGroup(CollapsibleGroup*)));
     l->insertWidget(groupPos, group);
+    group->installEventFilter( this );
     group->addGroupEffect(effectToMove);
 }
 
-void EffectStackView2::slotMoveEffect(int currentIndex, int newIndex, int groupIndex)
+void EffectStackView2::slotMoveEffect(int currentIndex, int newIndex, int groupIndex, QString groupName)
 {
     CollapsibleEffect *effectToMove = getEffectByIndex(currentIndex);
     if (effectToMove == NULL) return;
@@ -616,6 +643,7 @@ void EffectStackView2::slotMoveEffect(int currentIndex, int newIndex, int groupI
     EffectInfo effectinfo;
     effectinfo.fromString(oldeffect.attribute("kdenlive_info"));
     effectinfo.groupIndex = groupIndex;
+    effectinfo.groupName = groupName;
     neweffect.setAttribute("kdenlive_info", effectinfo.toString());
 
     ItemInfo info;
index a23a4001b1a8719269b98373dbbcebdf64b8d807..ffcebec6e118d676f38ba55c5da7a238406da8fe 100644 (file)
@@ -93,6 +93,9 @@ private:
     /** @brief The effect currently being dragged, NULL if no drag happening. */
     CollapsibleEffect *m_draggedEffect;
     
+    /** @brief The effect currently being dragged, NULL if no drag happening. */
+    CollapsibleGroup *m_draggedGroup;
+    
     /** @brief The current number of groups. */
     int m_groupIndex;
 
@@ -158,7 +161,7 @@ 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, int groupIndex);
+    void slotMoveEffect(int currentIndex, int newIndex, int groupIndex, QString groupName = QString());
     
     /** @brief Remove effects from a group */
     void slotUnGroup(CollapsibleGroup* group);