]> git.sesse.net Git - kdenlive/commitdiff
Fix drag & drop of effects and groups in effect stack:
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Sun, 15 Apr 2012 09:49:00 +0000 (11:49 +0200)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Sun, 15 Apr 2012 09:49:00 +0000 (11:49 +0200)
http://kdenlive.org/mantis/view.php?id=2581

src/commands/moveeffectcommand.cpp
src/commands/moveeffectcommand.h
src/customtrackview.cpp
src/customtrackview.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
src/mainwindow.cpp

index 6600bde780d730c01653baba5abeb87af7fa284e..43d502d7e07eca0e197fd93a65fcf5774afe40ba 100644 (file)
 
 #include <KLocale>
 
-MoveEffectCommand::MoveEffectCommand(CustomTrackView *view, const int track, GenTime pos, int oldPos, int newPos, QUndoCommand * parent) :
+MoveEffectCommand::MoveEffectCommand(CustomTrackView *view, const int track, GenTime pos, QList <int> oldPos, int newPos, QUndoCommand * parent) :
         QUndoCommand(parent),
         m_view(view),
         m_track(track),
         m_oldindex(oldPos),
-        m_newindex(newPos),
         m_pos(pos)
 {
+    for (int i = 0; i < m_oldindex.count(); i++) {
+       m_newindex << newPos + i;
+    }
     /*    QString effectName;
         QDomElement namenode = effect.firstChildElement("name");
         if (!namenode.isNull()) effectName = i18n(namenode.text().toUtf8().data());
index 790390ac2a9f1d8cf80b9335bf97df5ec42782d3..bc1fd30f67305cdd6081e48a69a2ac9c888c1bda 100644 (file)
@@ -31,7 +31,7 @@ class CustomTrackView;
 class MoveEffectCommand : public QUndoCommand
 {
 public:
-    MoveEffectCommand(CustomTrackView *view, const int track, GenTime pos, int oldPos, int newPos, QUndoCommand * parent = 0);
+    MoveEffectCommand(CustomTrackView *view, const int track, GenTime pos, QList <int> oldPos, int newPos, QUndoCommand * parent = 0);
 
     virtual int id() const;
     virtual bool mergeWith(const QUndoCommand * command);
@@ -41,8 +41,8 @@ public:
 private:
     CustomTrackView *m_view;
     int m_track;
-    int m_oldindex;
-    int m_newindex;
+    QList <int> m_oldindex;
+    QList <int> m_newindex;
     GenTime m_pos;
 };
 
index 2712dff794b56fb86d41f9bdac2a201d435c768d..fa4a471a8f4fcdee1c9442f72363f60b65300f6a 100644 (file)
@@ -2010,44 +2010,62 @@ void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement insertedE
     setDocumentModified();
 }
 
-void CustomTrackView::moveEffect(int track, GenTime pos, int oldPos, int newPos)
+void CustomTrackView::moveEffect(int track, GenTime pos, QList <int> oldPos, QList <int> newPos)
 {
     if (pos < GenTime()) {
         // Moving track effect
-        if (newPos > m_document->getTrackEffects(m_document->tracksCount() - track - 1).count()) {
-           newPos = m_document->getTrackEffects(m_document->tracksCount() - track - 1).count();
+        int documentTrack = m_document->tracksCount() - track - 1;
+        int max = m_document->getTrackEffects(documentTrack).count();
+       int new_position = newPos.at(0);
+       if (new_position > max) {
+           new_position = max;
        }
-        QDomElement act = m_document->getTrackEffect(m_document->tracksCount() - track - 1, newPos);
-        QDomElement before = m_document->getTrackEffect(m_document->tracksCount() - track - 1, oldPos);
-        if (!act.isNull() && !before.isNull()) {
-            //m_document->setTrackEffect(m_document->tracksCount() - track - 1, oldPos, act);
-            m_document->setTrackEffect(m_document->tracksCount() - track - 1, newPos, before);
-            m_document->renderer()->mltMoveEffect(m_document->tracksCount() - track, pos, oldPos, newPos);
-            emit showTrackEffects(m_document->tracksCount() - track, m_document->trackInfoAt(m_document->tracksCount() - track - 1));
-        } else emit displayMessage(i18n("Cannot move effect"), ErrorMessage);
+       int old_position = oldPos.at(0);
+       for (int i = 0; i < newPos.count(); i++) {
+           QDomElement act = m_document->getTrackEffect(documentTrack, new_position);
+           if (old_position > new_position) {
+               // Moving up, we need to adjust index
+               old_position = oldPos.at(i);
+               new_position = newPos.at(i);
+           }
+           QDomElement before = m_document->getTrackEffect(documentTrack, old_position);
+           if (!act.isNull() && !before.isNull()) {
+               m_document->setTrackEffect(documentTrack, new_position, before);
+               m_document->renderer()->mltMoveEffect(m_document->tracksCount() - track, pos, old_position, new_position);
+           } else emit displayMessage(i18n("Cannot move effect"), ErrorMessage);
+       }
+       emit showTrackEffects(m_document->tracksCount() - track, m_document->trackInfoAt(documentTrack));
         return;
     }
     ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()), m_document->tracksCount() - track);
-    if (newPos > clip->effectsCount()) {
-       newPos = clip->effectsCount();
-    }
     if (clip) {
-        QDomElement act = clip->effectAt(newPos);
-        QDomElement before = clip->effectAt(oldPos);
-       if (act.isNull() || before.isNull()) {
-           emit displayMessage(i18n("Cannot move effect"), ErrorMessage);
-           return;
+       int new_position = newPos.at(0);
+       if (new_position > clip->effectsCount()) {
+           new_position = clip->effectsCount();
        }
-        //clip->moveEffect(act, oldPos);
-        clip->moveEffect(before, newPos);
-        // special case: speed effect, which is a pseudo-effect, not appearing in MLT's effects
-        if (act.attribute("id") == "speed") {
-            m_document->renderer()->mltUpdateEffectPosition(track, pos, oldPos, newPos);
-        } else if (before.attribute("id") == "speed") {
-            m_document->renderer()->mltUpdateEffectPosition(track, pos, newPos, oldPos);
-        } else m_document->renderer()->mltMoveEffect(track, pos, oldPos, newPos);
-       clip->setSelectedEffect(newPos);
-        emit clipItemSelected(clip);
+       int old_position = oldPos.at(0);
+       for (int i = 0; i < newPos.count(); i++) {
+           QDomElement act = clip->effectAt(new_position);
+           if (old_position > new_position) {
+               // Moving up, we need to adjust index
+               old_position = oldPos.at(i);
+               new_position = newPos.at(i);
+           }
+           QDomElement before = clip->effectAt(old_position);
+           if (act.isNull() || before.isNull()) {
+               emit displayMessage(i18n("Cannot move effect"), ErrorMessage);
+               return;
+           }
+           clip->moveEffect(before, new_position);
+           // special case: speed effect, which is a pseudo-effect, not appearing in MLT's effects
+           if (act.attribute("id") == "speed") {
+               m_document->renderer()->mltUpdateEffectPosition(track, pos, old_position, new_position);
+           } else if (before.attribute("id") == "speed") {
+               m_document->renderer()->mltUpdateEffectPosition(track, pos, new_position, old_position);
+           } else m_document->renderer()->mltMoveEffect(track, pos, old_position, new_position);
+       }
+       clip->setSelectedEffect(newPos.at(0));
+       emit clipItemSelected(clip);
         setDocumentModified();
     } else emit displayMessage(i18n("Cannot move effect"), ErrorMessage);
 }
@@ -2072,7 +2090,7 @@ void CustomTrackView::slotChangeEffectState(ClipItem *clip, int track, int effec
     setDocumentModified();;
 }
 
-void CustomTrackView::slotChangeEffectPosition(ClipItem *clip, int track, int currentPos, int newPos)
+void CustomTrackView::slotChangeEffectPosition(ClipItem *clip, int track, QList <int> currentPos, int newPos)
 {
     MoveEffectCommand *command;
     if (clip == NULL) {
index e419dedfad0cca40a78e06156c4e94d83f9357ed..a5071e90f0f9c026f723dea8f3e27cb8c251e8a8 100644 (file)
@@ -77,7 +77,7 @@ public:
     void addEffect(int track, GenTime pos, QDomElement effect);
     void deleteEffect(int track, GenTime pos, QDomElement effect);
     void updateEffect(int track, GenTime pos, QDomElement insertedEffect, int ix, bool refreshEffectStack = false);
-    void moveEffect(int track, GenTime pos, int oldPos, int newPos);
+    void moveEffect(int track, GenTime pos, QList <int> oldPos, QList <int> newPos);
     void addTransition(ItemInfo transitionInfo, int endTrack, QDomElement params, bool refresh);
     void deleteTransition(ItemInfo transitionInfo, int endTrack, QDomElement params, bool refresh);
     void updateTransition(int track, GenTime pos,  QDomElement oldTransition, QDomElement transition, bool updateTransitionWidget);
@@ -193,7 +193,7 @@ public slots:
     void updateCursorPos();
     void slotDeleteEffect(ClipItem *clip, int track, QDomElement effect, bool affectGroup = true);
     void slotChangeEffectState(ClipItem *clip, int track, int effectPos, bool disable);
-    void slotChangeEffectPosition(ClipItem *clip, int track, int currentPos, int newPos);
+    void slotChangeEffectPosition(ClipItem *clip, int track, QList <int> currentPos, int newPos);
     void slotUpdateClipEffect(ClipItem *clip, int track, QDomElement oldeffect, QDomElement effect, int ix, bool refreshEffectStack = true);
     void slotUpdateClipRegion(ClipItem *clip, int ix, QString region);
     void slotRefreshEffects(ClipItem *clip);
index b6a96ecfb6d8a627576afb2e99d359e3c48e1b94..f8309fcddf9a37b825d8cd56d7f4f2fc7a11c2f5 100644 (file)
@@ -477,11 +477,13 @@ void CollapsibleEffect::updateCollapsedState()
 void CollapsibleEffect::setGroupIndex(int ix)
 {
     m_info.groupIndex = ix;
+    m_effect.setAttribute("kdenlive_info", m_info.toString());
 }
 
 void CollapsibleEffect::setGroupName(const QString &groupName)
 {
     m_info.groupName = groupName;
+    m_effect.setAttribute("kdenlive_info", m_info.toString());
 }
 
 QString CollapsibleEffect::infoString() const
@@ -623,20 +625,56 @@ void CollapsibleEffect::dropEvent(QDropEvent *event)
     doc.setContent(effects, true);
     QDomElement e = doc.documentElement();
     int ix = e.attribute("kdenlive_ix").toInt();
-    if (ix == effectIndex()) {
+    int currentEffectIx = effectIndex();
+    if (ix == currentEffectIx) {
        // effect dropped on itself, reject
        event->ignore();
        return;
     }
-    if (ix == 0) {
+    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 <int> 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(ix, effectIndex(), m_info.groupIndex, m_info.groupName);
+    emit moveEffect(QList <int> () <<ix, currentEffectIx, m_info.groupIndex, m_info.groupName);
     event->setDropAction(Qt::MoveAction);
     event->accept();
 }
index d0215c8690162f6ce3cde0f87c927a6dc4888be6..800f2b56dd1eef39c0902ba761c07c7d3f1269ce 100644 (file)
@@ -208,10 +208,11 @@ 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, QString groupName);
+    void moveEffect(QList <int> current_pos, int new_pos, int groupIndex, QString groupName);
     void unGroup(CollapsibleEffect *);
     void addEffect(QDomElement e);
     void createRegion(int, KUrl);
+    void deleteGroup(QDomDocument);
 };
 
 
index ab1152ea80af1155feed1117eb6e888758a72e65..f414004dfe7865ab3e04829c0d041199ca82b2f1 100644 (file)
@@ -54,17 +54,17 @@ void MyEditableLabel::mouseDoubleClickEvent ( QMouseEvent * e )
 
 
 CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, EffectInfo info, QWidget * parent) :
-        AbstractCollapsibleWidget(parent),
-        m_index(ix)
+        AbstractCollapsibleWidget(parent)
 {
     setupUi(this);
-    
+    m_info.groupIndex = ix;
     m_subWidgets = QList <CollapsibleEffect *> ();
     setFont(KGlobalSettings::smallestReadableFont());
     QHBoxLayout *l = static_cast <QHBoxLayout *>(framegroup->layout());
     m_title = new MyEditableLabel(this);
     l->insertWidget(3, m_title);
     m_title->setText(info.groupName.isEmpty() ? i18n("Effect Group") : info.groupName);
+    m_info.groupName = m_title->text();
     connect(m_title, SIGNAL(editingFinished()), this, SLOT(slotRenameGroup()));
     buttonUp->setIcon(KIcon("kdenlive-up"));
     buttonUp->setToolTip(i18n("Move effect up"));
@@ -265,7 +265,7 @@ void CollapsibleGroup::removeGroup(int ix, QVBoxLayout *layout)
 
 int CollapsibleGroup::groupIndex() const
 {
-    return m_index;
+    return m_info.groupIndex;
 }
 
 bool CollapsibleGroup::isGroup() const
@@ -308,17 +308,60 @@ void CollapsibleGroup::dropEvent(QDropEvent *event)
     doc.setContent(effects, true);
     QDomElement e = doc.documentElement();
     int ix = e.attribute("kdenlive_ix").toInt();
-    if (ix == 0) {
+    if (ix == 0 || e.tagName() == "effectgroup") {
+       if (e.tagName() == "effectgroup") {
+           // dropped a group on another group
+           QDomNodeList pastedEffects = e.elementsByTagName("effect");
+           if (pastedEffects.isEmpty() || m_subWidgets.isEmpty()) {
+               // Buggy groups, should not happen
+               event->ignore();
+               return;
+           }
+           QList <int> pastedEffectIndexes;
+           QList <int> currentEffectIndexes;
+           EffectInfo pasteInfo;
+           pasteInfo.fromString(pastedEffects.at(0).toElement().attribute("kdenlive_info"));
+           if (pasteInfo.groupIndex == -1) {
+               // Group dropped from effects list, add effect
+               e.setAttribute("kdenlive_ix", m_subWidgets.last()->effectIndex());
+               emit addEffect(e);
+               event->setDropAction(Qt::CopyAction);
+               event->accept();
+               return;
+           }
+           // Moving group
+           for (int i = 0; i < pastedEffects.count(); i++) {
+               pastedEffectIndexes << pastedEffects.at(i).toElement().attribute("kdenlive_ix").toInt();
+           }
+           for (int i = 0; i < m_subWidgets.count(); i++) {
+               currentEffectIndexes << m_subWidgets.at(i)->effectIndex();
+           }
+           kDebug()<<"PASTING: "<<pastedEffectIndexes<<" TO "<<currentEffectIndexes;
+           if (pastedEffectIndexes.at(0) < currentEffectIndexes.at(0)) {
+               // Pasting group after current one:
+               emit moveEffect(pastedEffectIndexes, currentEffectIndexes.last(), pasteInfo.groupIndex, pasteInfo.groupName);
+           }
+           else {
+               // Group moved before current one
+               emit moveEffect(pastedEffectIndexes, currentEffectIndexes.first(), pasteInfo.groupIndex, pasteInfo.groupName);
+           }
+           event->setDropAction(Qt::MoveAction);
+           event->accept();
+           return;
+       }
        // effect dropped from effects list, add it
-       e.setAttribute("kdenlive_ix", ix);
+       e.setAttribute("kdenlive_info", m_info.toString());
+       if (!m_subWidgets.isEmpty()) {
+           e.setAttribute("kdenlive_ix", m_subWidgets.at(0)->effectIndex());
+       }
+       emit addEffect(e);
        event->setDropAction(Qt::CopyAction);
        event->accept();
-       emit addEffect(e);
        return;
     }
     if (m_subWidgets.isEmpty()) return;
     int new_index = m_subWidgets.last()->effectIndex();
-    emit moveEffect(ix, new_index, m_index, m_title->text());
+    emit moveEffect(QList <int> () <<ix, new_index, m_info.groupIndex, m_title->text());
     event->setDropAction(Qt::MoveAction);
     event->accept();
 }
@@ -330,6 +373,7 @@ void CollapsibleGroup::slotRenameGroup()
     for (int j = 0; j < m_subWidgets.count(); j++) {
        m_subWidgets.at(j)->setGroupName(m_title->text());
     }
+    m_info.groupName = m_title->text();
     emit groupRenamed(this);
 }
 
index b8e973dfc4143f62d1da5c62bfe797f1ea17de14..9b7ed39f69f673be791a4fc1f64581aa7ac6d64e 100644 (file)
@@ -94,7 +94,6 @@ private:
     QList <CollapsibleEffect *> m_subWidgets;
     QMenu *m_menu;
     EffectInfo m_info;
-    int m_index;
     MyEditableLabel *m_title;
     QMutex m_mutex;
     
@@ -110,7 +109,7 @@ signals:
     void deleteGroup(QDomDocument);
     void changeGroupPosition(int, bool);
     void activateEffect(int);
-    void moveEffect(int current_pos, int new_pos, int groupIndex, QString groupName);
+    void moveEffect(QList <int> current_pos, int new_pos, int groupIndex, QString groupName);
     void addEffect(QDomElement e);
     void unGroup(CollapsibleGroup *);
     void groupRenamed(CollapsibleGroup *);
index 79794738c84995b49371ce3c51801cea9a9200ca..90b6e9f43359c710c71595166f020d2aeb68c626 100644 (file)
@@ -184,11 +184,7 @@ void EffectStackView2::setupListView()
            
            if (group == NULL) {
                group = new CollapsibleGroup(effectInfo.groupIndex, i == 0, i == m_currentEffectList.count() - 1, effectInfo, m_ui.container->widget());
-               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*)));
-                connect(group, SIGNAL(reloadEffects()), this , SIGNAL(reloadEffects()));
-               connect(group, SIGNAL(deleteGroup(QDomDocument)), this , SLOT(slotDeleteGroup(QDomDocument)));
+               connectGroup(group);
                vbox1->addWidget(group);
                group->installEventFilter( this );
            }
@@ -251,9 +247,10 @@ void EffectStackView2::connectEffect(CollapsibleEffect *currentEffect)
     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,QString)), this , SLOT(slotMoveEffect(int,int,int,QString)));
+    connect(currentEffect, SIGNAL(moveEffect(QList<int>,int,int,QString)), this , SLOT(slotMoveEffect(QList<int>,int,int,QString)));
     connect(currentEffect, SIGNAL(addEffect(QDomElement)), this , SLOT(slotAddEffect(QDomElement)));
     connect(currentEffect, SIGNAL(createRegion(int,KUrl)), this, SLOT(slotCreateRegion(int,KUrl)));
+    connect(currentEffect, SIGNAL(deleteGroup(QDomDocument)), this , SLOT(slotDeleteGroup(QDomDocument)));
 }
 
 void EffectStackView2::slotCheckWheelEventFilter()
@@ -566,8 +563,8 @@ void EffectStackView2::slotMoveEffectUp(int index, bool up)
     else {
         endPos =  index + 1;
     }
-    if (m_effectMetaInfo.trackMode) emit changeEffectPosition(NULL, m_trackindex, index, endPos);
-    else emit changeEffectPosition(m_clipref, -1, index, endPos);
+    if (m_effectMetaInfo.trackMode) emit changeEffectPosition(NULL, m_trackindex, QList <int>() <<index, endPos);
+    else emit changeEffectPosition(m_clipref, -1, QList <int>() <<index, endPos);
 }
 
 void EffectStackView2::slotStartFilterJob(const QString&filterName, const QString&filterParams, const QString&finalFilterName, const QString&consumer, const QString&consumerParams, const QString&properties)
@@ -721,51 +718,59 @@ void EffectStackView2::slotCreateGroup(int ix)
     
     CollapsibleGroup *group = new CollapsibleGroup(m_groupIndex, ix == 1, ix == m_currentEffectList.count() - 2, effectinfo, m_ui.container->widget());
     m_groupIndex++;
-    connect(group, SIGNAL(moveEffect(int,int,int,QString)), this , SLOT(slotMoveEffect(int,int,int,QString)));
+    connectGroup(group);
+    l->insertWidget(groupPos, group);
+    group->installEventFilter( this );
+    group->addGroupEffect(effectToMove);
+}
+
+void EffectStackView2::connectGroup(CollapsibleGroup *group)
+{
+    connect(group, SIGNAL(moveEffect(QList<int>,int,int,QString)), this , SLOT(slotMoveEffect(QList<int>,int,int,QString)));
+    connect(group, SIGNAL(addEffect(QDomElement)), this , SLOT(slotAddEffect(QDomElement)));
     connect(group, SIGNAL(unGroup(CollapsibleGroup*)), this , SLOT(slotUnGroup(CollapsibleGroup*)));
     connect(group, SIGNAL(groupRenamed(CollapsibleGroup *)), this , SLOT(slotRenameGroup(CollapsibleGroup*)));
     connect(group, SIGNAL(reloadEffects()), this , SIGNAL(reloadEffects()));
     connect(group, SIGNAL(deleteGroup(QDomDocument)), this , SLOT(slotDeleteGroup(QDomDocument)));
-    l->insertWidget(groupPos, group);
-    group->installEventFilter( this );
-    group->addGroupEffect(effectToMove);
 }
 
-void EffectStackView2::slotMoveEffect(int currentIndex, int newIndex, int groupIndex, QString groupName)
+void EffectStackView2::slotMoveEffect(QList <int> currentIndexes, int newIndex, int groupIndex, QString groupName)
 {
-    CollapsibleEffect *effectToMove = getEffectByIndex(currentIndex);
-    if (effectToMove == NULL) return;
+    if (currentIndexes.count() == 1) {
+       CollapsibleEffect *effectToMove = getEffectByIndex(currentIndexes.at(0));
+       if (effectToMove == NULL) return;
 
-    QDomElement oldeffect = effectToMove->effect();
-    QDomElement neweffect = oldeffect.cloneNode().toElement();
+       QDomElement oldeffect = effectToMove->effect();
+       QDomElement neweffect = oldeffect.cloneNode().toElement();
     
-    EffectInfo effectinfo;
-    effectinfo.fromString(oldeffect.attribute("kdenlive_info"));
-    effectinfo.groupIndex = groupIndex;
-    effectinfo.groupName = groupName;
-    neweffect.setAttribute("kdenlive_info", effectinfo.toString());
+       EffectInfo effectinfo;
+       effectinfo.fromString(oldeffect.attribute("kdenlive_info"));
+       effectinfo.groupIndex = groupIndex;
+       effectinfo.groupName = groupName;
+       neweffect.setAttribute("kdenlive_info", effectinfo.toString());
     
-    if (oldeffect.attribute("kdenlive_info") != effectinfo.toString()) {
-       // effect's group info or collapsed state changed
-       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, effectToMove->effectIndex(),false);
-       } else {
-           emit updateEffect(m_clipref, -1, oldeffect, neweffect, effectToMove->effectIndex(),false);
+       if (oldeffect.attribute("kdenlive_info") != effectinfo.toString()) {
+           // effect's group info or collapsed state changed
+           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, effectToMove->effectIndex(),false);
+           } else {
+               emit updateEffect(m_clipref, -1, oldeffect, neweffect, effectToMove->effectIndex(),false);
+           }
        }
     }
 
     // Update effect index with new position
     if (m_effectMetaInfo.trackMode) {
-       emit changeEffectPosition(NULL, m_trackindex, currentIndex, newIndex);
+       emit changeEffectPosition(NULL, m_trackindex, currentIndexes, newIndex);
     }
     else {
-       emit changeEffectPosition(m_clipref, -1, currentIndex, newIndex);
+       emit changeEffectPosition(m_clipref, -1, currentIndexes, newIndex);
     }
 }
 
@@ -799,13 +804,8 @@ void EffectStackView2::dragEnterEvent(QDragEnterEvent *event)
     }
 }
 
-void EffectStackView2::dropEvent(QDropEvent *event)
+void EffectStackView2::processDroppedEffect(QDomElement e, QDropEvent *event)
 {
-    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 (e.tagName() == "effectgroup") {
        // We are dropping a group, all effects in group should be moved
@@ -817,17 +817,21 @@ void EffectStackView2::dropEvent(QDropEvent *event)
        EffectInfo info;
        info.fromString(effects.at(0).toElement().attribute("kdenlive_info"));
        if (info.groupIndex < 0) {
+           kDebug()<<"// ADDING EFFECT!!!";
            // Adding a new group effect to the stack
            event->setDropAction(Qt::CopyAction);
            event->accept();
            slotAddEffect(e);
            return;
        }
-       // 
-       for (int i = effects.count() - 1; i >= 0; i--) {
-           //TODO: not working because wee need to move all effects in one go
-           slotMoveEffect(effects.at(i).toElement().attribute("kdenlive_ix").toInt(), m_currentEffectList.count(), info.groupIndex, info.groupName);
+       // Moving group: delete all effects and re-add them
+       QList <int> indexes;
+       for (int i = 0; i < effects.count(); i++) {
+           QDomElement effect = effects.at(i).cloneNode().toElement();
+           indexes << effect.attribute("kdenlive_ix").toInt();
        }
+       kDebug()<<"// Moving: "<<indexes<<" TO "<<m_currentEffectList.count();
+       slotMoveEffect(indexes, m_currentEffectList.count(), info.groupIndex, info.groupName);
     }
     else if (ix == 0) {
        // effect dropped from effects list, add it
@@ -839,10 +843,19 @@ void EffectStackView2::dropEvent(QDropEvent *event)
     }
     else {
        // User is moving an effect
-       slotMoveEffect(ix, m_currentEffectList.count() + 1, -1);
+       slotMoveEffect(QList<int> () << ix, m_currentEffectList.count() + 1, -1);
     }
     event->setDropAction(Qt::MoveAction);
     event->accept();
 }
 
+void EffectStackView2::dropEvent(QDropEvent *event)
+{
+    const QString effects = QString::fromUtf8(event->mimeData()->data("kdenlive/effectslist"));
+    //event->acceptProposedAction();
+    QDomDocument doc;
+    doc.setContent(effects, true);
+    processDroppedEffect(doc.documentElement(), event);
+}
+
 #include "effectstackview2.moc"
index 251777276445ba12d11478f139e4b28eea6fa120..3de1b69c676e0848690845c2d71842acc967be00 100644 (file)
@@ -69,6 +69,9 @@ public:
     
     /** @brief Palette was changed, update style. */
     void updatePalette();
+    
+    /** @brief Process dropped xml effect. */
+    void processDroppedEffect(QDomElement e, QDropEvent *event);
 
 protected:
     virtual void mouseMoveEvent(QMouseEvent * event);
@@ -112,6 +115,8 @@ private:
     
     /** @brief Connect an effect to its signals. */
     void connectEffect(CollapsibleEffect *currentEffect);
+    /** @brief Connect a group to its signals. */
+    void connectGroup(CollapsibleGroup *group);
 
 public slots:
     /** @brief Sets the clip whose effect list should be managed.
@@ -168,12 +173,13 @@ private slots:
     /** @brief Create a region effect with ix index. */
     void slotCreateRegion(int ix, KUrl url);
     
-    /** @brief Move an effect into a group.
-      ** @param ix the index of effect to move in stack layout
-      ** @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
+    /** @brief Move an effect.
+      ** @param currentIndexes the list of effect indexes to move in stack layout
+      ** @param newIndex the position where the effects will be moved
+      ** @param groupIndex the index of the group if any (-1 if none)
+      ** @param groupName the name of the group to paste the effect
       */
-    void slotMoveEffect(int currentIndex, int newIndex, int groupIndex, QString groupName = QString());
+    void slotMoveEffect(QList <int> currentIndexes, int newIndex, int groupIndex, QString groupName = QString());
     
     /** @brief Remove effects from a group */
     void slotUnGroup(CollapsibleGroup* group);
@@ -203,7 +209,7 @@ signals:
     /** Enable or disable an effect */
     void changeEffectState(ClipItem*, int, int, bool);
     /** An effect in stack was moved */
-    void changeEffectPosition(ClipItem*, int, int, int);
+    void changeEffectPosition(ClipItem*, int, QList <int>, int);
     /** an effect was saved, reload list */
     void reloadEffects();
     /** An effect with position parameter was changed, seek */
index d03ff48f7dc62cc6cf4a198e2ea3053b3bb489ba..2833c3566a765703f77b1139fab1f6132d9e94b5 100644 (file)
@@ -2486,7 +2486,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
             disconnect(m_effectStack, SIGNAL(removeEffect(ClipItem*, int, QDomElement)), m_activeTimeline->projectView(), SLOT(slotDeleteEffect(ClipItem*, int, QDomElement)));
            disconnect(m_effectStack, SIGNAL(addEffect(ClipItem*, QDomElement)), trackView->projectView(), SLOT(slotAddEffect(ClipItem*, QDomElement)));
             disconnect(m_effectStack, SIGNAL(changeEffectState(ClipItem*, int, int, bool)), m_activeTimeline->projectView(), SLOT(slotChangeEffectState(ClipItem*, int, int, bool)));
-            disconnect(m_effectStack, SIGNAL(changeEffectPosition(ClipItem*, int, int, int)), m_activeTimeline->projectView(), SLOT(slotChangeEffectPosition(ClipItem*, int, int, int)));
+            disconnect(m_effectStack, SIGNAL(changeEffectPosition(ClipItem*, int, QList<int>, int)), m_activeTimeline->projectView(), SLOT(slotChangeEffectPosition(ClipItem*, int, QList <int>, int)));
             disconnect(m_effectStack, SIGNAL(refreshEffectStack(ClipItem*)), m_activeTimeline->projectView(), SLOT(slotRefreshEffects(ClipItem*)));
             disconnect(m_effectStack, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects()));
             disconnect(m_effectStack, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int)));
@@ -2556,18 +2556,21 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
 
     connect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), trackView->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap)));
 
+    // Effect stack signals
     connect(m_effectStack, SIGNAL(updateEffect(ClipItem*, int, QDomElement, QDomElement, int,bool)), trackView->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, int, QDomElement, QDomElement, int,bool)));
     connect(m_effectStack, SIGNAL(updateClipRegion(ClipItem*, int, QString)), trackView->projectView(), SLOT(slotUpdateClipRegion(ClipItem*, int, QString)));
     connect(m_effectStack, SIGNAL(removeEffect(ClipItem*, int, QDomElement)), trackView->projectView(), SLOT(slotDeleteEffect(ClipItem*, int, QDomElement)));
     connect(m_effectStack, SIGNAL(addEffect(ClipItem*, QDomElement)), trackView->projectView(), SLOT(slotAddEffect(ClipItem*, QDomElement)));
     connect(m_effectStack, SIGNAL(changeEffectState(ClipItem*, int, int, bool)), trackView->projectView(), SLOT(slotChangeEffectState(ClipItem*, int, int, bool)));
-    connect(m_effectStack, SIGNAL(changeEffectPosition(ClipItem*, int, int, int)), trackView->projectView(), SLOT(slotChangeEffectPosition(ClipItem*, int, int, int)));
+    connect(m_effectStack, SIGNAL(changeEffectPosition(ClipItem*, int, QList <int>, int)), trackView->projectView(), SLOT(slotChangeEffectPosition(ClipItem*, int, QList <int>, int)));
     connect(m_effectStack, SIGNAL(refreshEffectStack(ClipItem*)), trackView->projectView(), SLOT(slotRefreshEffects(ClipItem*)));
-    connect(m_transitionConfig, SIGNAL(transitionUpdated(Transition *, QDomElement)), trackView->projectView() , SLOT(slotTransitionUpdated(Transition *, QDomElement)));
-    connect(m_transitionConfig, SIGNAL(seekTimeline(int)), trackView->projectView() , SLOT(setCursorPos(int)));
     connect(m_effectStack, SIGNAL(seekTimeline(int)), trackView->projectView() , SLOT(setCursorPos(int)));
     connect(m_effectStack, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects()));
     connect(m_effectStack, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int)));
+    
+    // Transition config signals
+    connect(m_transitionConfig, SIGNAL(transitionUpdated(Transition *, QDomElement)), trackView->projectView() , SLOT(slotTransitionUpdated(Transition *, QDomElement)));
+    connect(m_transitionConfig, SIGNAL(seekTimeline(int)), trackView->projectView() , SLOT(setCursorPos(int)));
 
     connect(trackView->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(slotActivateMonitor()));
     connect(trackView, SIGNAL(zoneMoved(int, int)), this, SLOT(slotZoneMoved(int, int)));