]> git.sesse.net Git - kdenlive/commitdiff
Merge branch 'master' into audioAlign
authorSimon A. Eugster <simon.eu@gmail.com>
Thu, 19 Apr 2012 09:33:54 +0000 (11:33 +0200)
committerSimon A. Eugster <simon.eu@gmail.com>
Thu, 19 Apr 2012 09:33:54 +0000 (11:33 +0200)
14 files changed:
src/commands/moveeffectcommand.cpp
src/commands/moveeffectcommand.h
src/customtrackview.cpp
src/customtrackview.h
src/definitions.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/effectstackedit.cpp
src/effectstackedit.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 1af5532e65805319006ad32ba0236e4d90a21129..37d1bcc88d09d165de918441c813e7a365f79d01 100644 (file)
@@ -2018,44 +2018,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);
 }
@@ -2080,7 +2098,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 acb980376bdf6e86f7804ce78a0053aa51eb658c..3590495a03050ad52c6f93c99bd81fc3bd80e437 100644 (file)
@@ -84,7 +84,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);
@@ -206,7 +206,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 f370573f804e6fb93659389074b21b2f18fc1143..e3e5c443ec0bf5f09e144493a31904241b239602 100644 (file)
@@ -148,19 +148,25 @@ struct MltVideoProfile {
 class EffectInfo
 {
 public:
-    EffectInfo() {isCollapsed = false; groupIndex = -1;}
+    EffectInfo() {isCollapsed = false; groupIndex = -1; groupIsCollapsed = false;}
     bool isCollapsed;
+    bool groupIsCollapsed;
     int groupIndex;
     QString groupName;
     QString toString() const {
         QStringList data;
-       data << QString::number(isCollapsed) << QString::number(groupIndex) << groupName;
+       // effect collapsed state: 0 = effect not collapsed, 1 = effect collapsed, 
+       // 2 = group collapsed - effect not, 3 = group and effect collapsed
+       int collapsedState = (int) isCollapsed;
+       if (groupIsCollapsed) collapsedState += 2;
+       data << QString::number(collapsedState) << QString::number(groupIndex) << groupName;
        return data.join("/");
     }
     void fromString(QString value) {
        if (value.isEmpty()) return;
        QStringList data = value.split("/");
-       isCollapsed = data.at(0).toInt();
+       isCollapsed = data.at(0).toInt() == 1 || data.at(0).toInt() == 3;
+       groupIsCollapsed = data.at(0).toInt() == 3;
        if (data.count() > 1) groupIndex = data.at(1).toInt();
        if (data.count() > 2) groupName = data.at(2);
     }
index 0bf2bb2e0bf6b4f961713714e7b4d349901e1523..f8309fcddf9a37b825d8cd56d7f4f2fc7a11c2f5 100644 (file)
@@ -456,18 +456,34 @@ void CollapsibleEffect::slotShow(bool show)
         collapseButton->setArrowType(Qt::RightArrow);
         m_info.isCollapsed = true;
     }
-    m_effect.setAttribute("kdenlive_info", m_info.toString());
-    emit parameterChanged(m_original_effect, m_effect, effectIndex());   
+    updateCollapsedState();
+}
+
+void CollapsibleEffect::groupStateChanged(bool collapsed)
+{
+    m_info.groupIsCollapsed = collapsed;
+    updateCollapsedState();
+}
+
+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());   
+    }
 }
 
 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
@@ -609,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();
 }
@@ -1334,6 +1386,11 @@ QString ParameterContainer::getWipeString(wipeInfo info)
     return QString(start + ";-1=" + end);
 }
 
+void ParameterContainer::updateParameter(const QString &key, const QString &value)
+{
+    m_effect.setAttribute(key, value);
+}
+
 void ParameterContainer::slotStartFilterJobAction()
 {
     QDomNodeList namenode = m_effect.elementsByTagName("parameter");
index 07132f1a131ada748aa1f2f9bf7d878062169cbb..800f2b56dd1eef39c0902ba761c07c7d3f1269ce 100644 (file)
@@ -73,6 +73,7 @@ public:
     ~ParameterContainer();
     void updateTimecodeFormat();
     void updateProjectFormat(MltVideoProfile profile, Timecode t);
+    void updateParameter(const QString &key, const QString &value);
 
 private slots:
     void slotCollectAllParameters();
@@ -143,9 +144,10 @@ public:
     bool isActive() const;
     /** @brief Should the wheel event be sent to parent widget for scrolling. */
     bool filterWheelEvent;
-    
     /** @brief Return the stylesheet required for effect parameters. */
     static const QString getStyleSheet();
+    /** @brief Parent group was collapsed, update. */
+    void groupStateChanged(bool collapsed);
 
 public slots:
     void slotSyncEffectsPos(int pos);
@@ -179,6 +181,8 @@ private:
     EffectInfo m_info;
     /** @brief True if this is a region effect, which behaves in a special way, like a group. */
     bool m_regionEffect;
+    /** @brief Check if collapsed state changed and inform MLT. */
+    void updateCollapsedState();
     
 protected:
     virtual void mouseDoubleClickEvent ( QMouseEvent * event );
@@ -204,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 7f89038f89503ba310603da0034bdef02b516da3..f414004dfe7865ab3e04829c0d041199ca82b2f1 100644 (file)
@@ -53,17 +53,18 @@ void MyEditableLabel::mouseDoubleClickEvent ( QMouseEvent * e )
 }
 
 
-CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, QString groupName, QWidget * parent) :
-        AbstractCollapsibleWidget(parent),
-        m_index(ix)
+CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, EffectInfo info, QWidget * parent) :
+        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(groupName.isEmpty() ? i18n("Effect Group") : groupName);
+    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"));
@@ -85,6 +86,10 @@ CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, QStr
     
     enabledButton->setChecked(false);
     enabledButton->setIcon(KIcon("visible"));
+    
+    if (info.groupIsCollapsed) {
+       slotShow(false);
+    }
 
     connect(collapseButton, SIGNAL(clicked()), this, SLOT(slotSwitch()));
     connect(enabledButton, SIGNAL(toggled(bool)), this, SLOT(slotEnable(bool)));
@@ -208,13 +213,13 @@ void CollapsibleGroup::slotShow(bool show)
     widgetFrame->setVisible(show);
     if (show) {
         collapseButton->setArrowType(Qt::DownArrow);
-       m_info.isCollapsed = false;
+       m_info.groupIsCollapsed = false;
     }
     else {
         collapseButton->setArrowType(Qt::RightArrow);
-       m_info.isCollapsed = true;
+       m_info.groupIsCollapsed = true;
     }
-    //emit parameterChanged(m_original_effect, m_effect, effectIndex());   
+    if (!m_subWidgets.isEmpty()) m_subWidgets.at(0)->groupStateChanged(m_info.groupIsCollapsed);
 }
 
 QWidget *CollapsibleGroup::title() const
@@ -260,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
@@ -303,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();
 }
@@ -325,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 bab2fe611e7c5f5581bea035993fe9d8c5eb94e5..9b7ed39f69f673be791a4fc1f64581aa7ac6d64e 100644 (file)
@@ -59,7 +59,7 @@ class CollapsibleGroup : public AbstractCollapsibleWidget, public Ui::Collapsibl
     Q_OBJECT
 
 public:
-    CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, QString groupName = QString(), QWidget * parent = 0);
+    CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, EffectInfo info, QWidget * parent = 0);
     ~CollapsibleGroup();
     void updateTimecodeFormat();
     void setActive(bool activate);
@@ -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 27f77f42722e6bd7bd9551b30cc9ad9871640ed6..90b6e9f43359c710c71595166f020d2aeb68c626 100644 (file)
@@ -54,6 +54,7 @@ EffectStackView2::EffectStackView2(Monitor *monitor, QWidget *parent) :
     m_effectMetaInfo.trackMode = false;
     m_effectMetaInfo.monitor = monitor;
     m_effects = QList <CollapsibleEffect*>();
+    setAcceptDrops(true);
 
     m_ui.setupUi(this);
     setFont(KGlobalSettings::smallestReadableFont());
@@ -182,12 +183,8 @@ void EffectStackView2::setupListView()
            }
            
            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,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)));
+               group = new CollapsibleGroup(effectInfo.groupIndex, i == 0, i == m_currentEffectList.count() - 1, effectInfo, m_ui.container->widget());
+               connectGroup(group);
                vbox1->addWidget(group);
                group->installEventFilter( this );
            }
@@ -250,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()
@@ -565,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)
@@ -718,50 +716,61 @@ void EffectStackView2::slotCreateGroup(int ix)
        }
     }
     
-    CollapsibleGroup *group = new CollapsibleGroup(m_groupIndex, ix == 1, ix == m_currentEffectList.count() - 2, QString(), m_ui.container->widget());
+    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());
-
-    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);
+       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 (currentIndex == newIndex) return;
+
     // 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);
     }
 }
 
@@ -788,4 +797,65 @@ void EffectStackView2::slotRenameGroup(CollapsibleGroup *group)
     }
 }
 
+void EffectStackView2::dragEnterEvent(QDragEnterEvent *event)
+{
+    if (event->mimeData()->hasFormat("kdenlive/effectslist")) {
+       event->acceptProposedAction();
+    }
+}
+
+void EffectStackView2::processDroppedEffect(QDomElement e, QDropEvent *event)
+{
+    int ix = e.attribute("kdenlive_ix").toInt();
+    if (e.tagName() == "effectgroup") {
+       // We are dropping a group, all effects in group should be moved
+       QDomNodeList effects = e.elementsByTagName("effect");
+       if (effects.count() == 0) {
+           event->ignore();
+           return;
+       }
+       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;
+       }
+       // 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
+       e.setAttribute("kdenlive_ix", m_currentEffectList.count() + 1);
+       event->setDropAction(Qt::CopyAction);
+       event->accept();
+       slotAddEffect(e);
+       return;
+    }
+    else {
+       // User is moving an effect
+       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 2a1da03202313c1d52e09b9c1cb96df650cdd437..3de1b69c676e0848690845c2d71842acc967be00 100644 (file)
@@ -69,11 +69,16 @@ 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);
     virtual void mouseReleaseEvent(QMouseEvent * event);
     virtual void resizeEvent ( QResizeEvent * event );
+    virtual void dragEnterEvent(QDragEnterEvent *event);
+    virtual void dropEvent(QDropEvent *event);
   
 private:
     Ui::EffectStack2_UI m_ui;
@@ -110,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.
@@ -166,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);
@@ -201,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 8ec639f43889f63e0c1c59df571032e8fbcd6af3..85a526f12e5d5431a2f137ed36ef5662191f0569 100644 (file)
@@ -174,7 +174,7 @@ void EffectStackEdit::meetDependency(const QString& name, QString type, QString
 
 void EffectStackEdit::updateParameter(const QString &name, const QString &value)
 {
-    m_params.setAttribute(name, value);
+    m_paramWidget->updateParameter(name, value);
 
     if (name == "disable") {
         // if effect is disabled, disable parameters widget
@@ -855,18 +855,5 @@ void EffectStackEdit::slotSyncEffectsPos(int pos)
     emit syncEffectsPos(pos);
 }
 
-void EffectStackEdit::slotStartFilterJobAction()
-{
-    QDomNodeList namenode = m_params.elementsByTagName("parameter");
-    for (int i = 0; i < namenode.count() ; i++) {
-        QDomElement pa = namenode.item(i).toElement();
-        QString type = pa.attribute("type");
-        if (type == "filterjob") {
-            emit startFilterJob(pa.attribute("filtertag"), pa.attribute("filterparams"), pa.attribute("finalfilter"), pa.attribute("consumer"), pa.attribute("consumerparams"), pa.attribute("wantedproperties"));
-            kDebug()<<" - - -PROPS:\n"<<pa.attribute("filtertag")<<"-"<< pa.attribute("filterparams")<<"-"<< pa.attribute("consumer")<<"-"<< pa.attribute("consumerparams")<<"-"<< pa.attribute("wantedproperties");
-            break;
-        }
-    }
-}
 
 
index 257dfb157564b819af41f385c948aa630f45aea5..3697e2140fa20a1ebcddf73758029e7f31673259 100644 (file)
@@ -66,7 +66,6 @@ private:
 
     QVBoxLayout *m_vbox;
     QList<QWidget*> m_uiItems;
-    QDomElement m_params;
     QMap<QString, QWidget*> m_valueItems;
     int m_in;
     int m_out;
@@ -88,9 +87,6 @@ public slots:
 
     /** @brief Pass position changes of the timeline cursor to the effects to keep their local timelines in sync. */
     void slotSyncEffectsPos(int pos);
-    
-private slots:
-    void slotStartFilterJobAction();
 
 signals:
     void parameterChanged(const QDomElement, const QDomElement, int);
index d34aab8d6f1145fb3b248fc1a8aa3defa9794f16..409f76a3a2c15135cfc85b1b80a2eb84a3cc5871 100644 (file)
@@ -2496,7 +2496,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)));
@@ -2566,18 +2566,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)));