From a3c647264b75530ad07b1d3f11cd45c528293d9f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Mon, 26 Mar 2012 11:36:24 +0200 Subject: [PATCH] Implement drag & drop of effects in effect stack --- src/clipitem.cpp | 2 +- src/customtrackview.cpp | 10 +++++-- src/effectstack/collapsibleeffect.cpp | 37 +++++++++++++++-------- src/effectstack/collapsibleeffect.h | 5 ++-- src/effectstack/effectstackview2.cpp | 43 +++++++++++++-------------- src/effectstack/effectstackview2.h | 6 ++-- 6 files changed, 60 insertions(+), 43 deletions(-) diff --git a/src/clipitem.cpp b/src/clipitem.cpp index b934e217..1d0e4c7b 100644 --- a/src/clipitem.cpp +++ b/src/clipitem.cpp @@ -1391,7 +1391,7 @@ bool ClipItem::updateEffect(QDomElement effect) bool ClipItem::moveEffect(QDomElement effect, int ix) { - if (ix < 0 || ix > (m_effectList.count() - 1) || effect.isNull()) { + if (ix <= 0 || ix > (m_effectList.count()) || effect.isNull()) { kDebug() << "Invalid effect index: " << ix; return false; } diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index 94de517a..c6abfabc 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -1999,10 +1999,14 @@ void CustomTrackView::moveEffect(int track, GenTime pos, int oldPos, int newPos) if (newPos > clip->effectsCount()) { newPos = clip->effectsCount(); } - if (clip && !clip->effectAt(newPos ).isNull() && !clip->effectAt(oldPos).isNull()) { + if (clip) { QDomElement act = clip->effectAt(newPos); QDomElement before = clip->effectAt(oldPos); - clip->moveEffect(act, oldPos); + if (act.isNull() || before.isNull()) { + emit displayMessage(i18n("Cannot move effect"), ErrorMessage); + return; + } + //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") { @@ -2010,7 +2014,7 @@ void CustomTrackView::moveEffect(int track, GenTime pos, int oldPos, int newPos) } else if (before.attribute("id") == "speed") { m_document->renderer()->mltUpdateEffectPosition(track, pos, newPos, oldPos); } else m_document->renderer()->mltMoveEffect(track, pos, oldPos, newPos); - emit clipItemSelected(clip, newPos - 1); + emit clipItemSelected(clip, newPos); setDocumentModified(); } else emit displayMessage(i18n("Cannot move effect"), ErrorMessage); } diff --git a/src/effectstack/collapsibleeffect.cpp b/src/effectstack/collapsibleeffect.cpp index 4f1e3cc4..49e303aa 100644 --- a/src/effectstack/collapsibleeffect.cpp +++ b/src/effectstack/collapsibleeffect.cpp @@ -170,12 +170,11 @@ CollapsibleEffect::CollapsibleEffect(QDomElement effect, QDomElement original_ef setupWidget(info, ix, metaInfo); } else { - setAcceptDrops(true); title->setText(i18n("Effect Group")); title->setIcon(KIcon("folder")); m_menu->addAction(KIcon("list-remove"), i18n("Ungroup"), this, SLOT(slotUnGroup())); } - + setAcceptDrops(true); title->setMenu(m_menu); if (m_effect.attribute("disable") == "1") { @@ -275,11 +274,13 @@ QDomElement CollapsibleEffect::effect() const return m_effect; } -void CollapsibleEffect::setActive(bool activate) +void CollapsibleEffect::setActive(bool activate, bool focused) { m_active = activate; - frame->setBackgroundRole(m_active ? QPalette::Mid : QPalette::Midlight); - frame->setAutoFillBackground(activate); + if (focused) { + frame->setBackgroundRole(QPalette::Highlight); + } + else frame->setBackgroundRole(m_active ? QPalette::Mid : QPalette::Midlight); } void CollapsibleEffect::mouseDoubleClickEvent ( QMouseEvent * event ) @@ -299,8 +300,6 @@ void CollapsibleEffect::enterEvent ( QEvent * event ) if (m_paramWidget == NULL || m_paramWidget->index() > 0) buttonUp->setVisible(true); if (!m_lastEffect) buttonDown->setVisible(true); buttonDel->setVisible(true); - if (!m_active) frame->setBackgroundRole(QPalette::Midlight); - frame->setAutoFillBackground(true); QWidget::enterEvent(event); } @@ -309,7 +308,6 @@ void CollapsibleEffect::leaveEvent ( QEvent * event ) buttonUp->setVisible(false); buttonDown->setVisible(false); buttonDel->setVisible(false); - if (!m_active) frame->setAutoFillBackground(false); QWidget::leaveEvent(event); } @@ -546,8 +544,15 @@ void CollapsibleEffect::slotSyncEffectsPos(int pos) void CollapsibleEffect::dragEnterEvent(QDragEnterEvent *event) { - if (event->mimeData()->hasFormat("kdenlive/effectslist")) + if (event->mimeData()->hasFormat("kdenlive/effectslist")) { + setActive(m_active, true); event->acceptProposedAction(); + } +} + +void CollapsibleEffect::dragLeaveEvent(QDragLeaveEvent */*event*/) +{ + setActive(m_active, false); } void CollapsibleEffect::dropEvent(QDropEvent *event) @@ -558,14 +563,22 @@ void CollapsibleEffect::dropEvent(QDropEvent *event) doc.setContent(effects, true); const QDomElement e = doc.documentElement(); int ix = e.attribute("kdenlive_ix").toInt(); - int last_index = -1; + if (ix == effectIndex()) { + // effect dropped on itself, reject + event->ignore(); + return; + } + int new_index = -1; if (m_isGroup) { QVBoxLayout *vbox = static_cast(widgetFrame->layout()); if (vbox == NULL) return; CollapsibleEffect *e = static_cast(vbox->itemAt(vbox->count() -1)->widget()); - last_index = e->effectIndex(); + new_index = e->effectIndex() + 1; + } + else { + new_index = effectIndex(); } - emit moveEffect(ix, this, last_index); + emit moveEffect(ix, new_index, this); event->setDropAction(Qt::MoveAction); event->accept(); } diff --git a/src/effectstack/collapsibleeffect.h b/src/effectstack/collapsibleeffect.h index 0a282629..c4112d32 100644 --- a/src/effectstack/collapsibleeffect.h +++ b/src/effectstack/collapsibleeffect.h @@ -119,7 +119,7 @@ public: static QMap iconCache; void setupWidget(ItemInfo info, int index, EffectMetaInfo *metaInfo); void updateTimecodeFormat(); - void setActive(bool activate); + void setActive(bool activate, bool focused = false); virtual bool eventFilter( QObject * o, QEvent * e ); /** @brief Update effect GUI to reflect parameted changes. */ void updateWidget(ItemInfo info, int index, QDomElement effect, EffectMetaInfo *metaInfo); @@ -171,6 +171,7 @@ protected: virtual void enterEvent( QEvent * event ); virtual void leaveEvent( QEvent * event ); virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dragLeaveEvent(QDragLeaveEvent *event); virtual void dropEvent(QDropEvent *event); signals: @@ -190,7 +191,7 @@ signals: void resetEffect(int ix); /** @brief Ask for creation of a group. */ void createGroup(int ix); - void moveEffect(int ix, CollapsibleEffect *group, int lastEffectIndex); + void moveEffect(int current_pos, int new_pos, CollapsibleEffect *target); void unGroup(CollapsibleEffect *); }; diff --git a/src/effectstack/effectstackview2.cpp b/src/effectstack/effectstackview2.cpp index 26131529..d9104828 100644 --- a/src/effectstack/effectstackview2.cpp +++ b/src/effectstack/effectstackview2.cpp @@ -125,14 +125,7 @@ void EffectStackView2::slotClipItemSelected(ClipItem* c, int ix) //TODO: clear list, reset paramdesc and info //ItemInfo info; //m_effectedit->transferParamDesc(QDomElement(), info); - m_effects.clear(); - QWidget *view = m_ui.container->takeWidget(); - if (view) { - delete view; - } - m_ui.checkAll->setToolTip(QString()); - m_ui.checkAll->setText(QString()); - setEnabled(false); + clear(); return; } setEnabled(true); @@ -198,7 +191,7 @@ void EffectStackView2::setupListView(int ix) if (group == NULL) { group = new CollapsibleEffect(QDomElement(), QDomElement(), ItemInfo(), effectInfo.groupIndex, &m_effectMetaInfo, false, true, m_ui.container->widget()); if (!effectInfo.groupName.isEmpty()) group->title->setText(effectInfo.groupName); - connect(group, SIGNAL(moveEffect(int,CollapsibleEffect*,int)), this , SLOT(slotMoveEffectToGroup(int,CollapsibleEffect*,int))); + connect(group, SIGNAL(moveEffect(int,int,CollapsibleEffect*)), this, SLOT(slotMoveEffect(int,int,CollapsibleEffect*))); connect(group, SIGNAL(unGroup(CollapsibleEffect*)), this , SLOT(slotUnGroup(CollapsibleEffect*))); vbox1->addWidget(group); } @@ -235,13 +228,13 @@ void EffectStackView2::setupListView(int ix) connect(currentEffect, SIGNAL(deleteEffect(const QDomElement)), this , SLOT(slotDeleteEffect(const QDomElement))); connect(currentEffect, SIGNAL(reloadEffects()), this , SIGNAL(reloadEffects())); connect(currentEffect, SIGNAL(resetEffect(int)), this , SLOT(slotResetEffect(int))); - connect(currentEffect, SIGNAL(changeEffectPosition(int,bool)), this , SLOT(slotMoveEffect(int , bool))); + connect(currentEffect, SIGNAL(changeEffectPosition(int,bool)), this , SLOT(slotMoveEffectUp(int , bool))); connect(currentEffect, SIGNAL(effectStateChanged(bool, int)), this, SLOT(slotUpdateEffectState(bool, int))); connect(currentEffect, SIGNAL(activateEffect(int)), this, SLOT(slotSetCurrentEffect(int))); connect(currentEffect, SIGNAL(checkMonitorPosition(int)), this, SLOT(slotCheckMonitorPosition(int))); connect(currentEffect, SIGNAL(seekTimeline(int)), this , SLOT(slotSeekTimeline(int))); connect(currentEffect, SIGNAL(createGroup(int)), this , SLOT(slotCreateGroup(int))); - connect(currentEffect, SIGNAL(moveEffect(int,CollapsibleEffect*,int)), this , SLOT(slotMoveEffectToGroup(int,CollapsibleEffect*,int))); + connect(currentEffect, SIGNAL(moveEffect(int,int,CollapsibleEffect*)), this , SLOT(slotMoveEffect(int,int,CollapsibleEffect*))); //ui.title->setPixmap(icon.pixmap(QSize(12, 12))); } @@ -365,6 +358,14 @@ int EffectStackView2::isTrackMode(bool *ok) const void EffectStackView2::clear() { + m_effects.clear(); + QWidget *view = m_ui.container->takeWidget(); + if (view) { + delete view; + } + m_ui.checkAll->setToolTip(QString()); + m_ui.checkAll->setText(QString()); + setEnabled(false); } void EffectStackView2::updateProjectFormat(MltVideoProfile profile, Timecode t) @@ -422,7 +423,7 @@ void EffectStackView2::slotDeleteEffect(const QDomElement effect) emit removeEffect(m_clipref, -1, effect); } -void EffectStackView2::slotMoveEffect(int index, bool up) +void EffectStackView2::slotMoveEffectUp(int index, bool up) { if (up && index <= 1) return; if (!up && index >= m_currentEffectList.count()) return; @@ -521,26 +522,24 @@ void EffectStackView2::slotCreateGroup(int ix) CollapsibleEffect *group = new CollapsibleEffect(QDomElement(), QDomElement(), ItemInfo(), m_groupIndex, &m_effectMetaInfo, false, true, m_ui.container->widget()); m_groupIndex++; - connect(group, SIGNAL(moveEffect(int,CollapsibleEffect*,int)), this , SLOT(slotMoveEffectToGroup(int,CollapsibleEffect*,int))); + connect(group, SIGNAL(moveEffect(int,int,CollapsibleEffect*)), this , SLOT(slotMoveEffect(int,int,CollapsibleEffect*))); connect(group, SIGNAL(unGroup(CollapsibleEffect*)), this , SLOT(slotUnGroup(CollapsibleEffect*))); l->insertWidget(groupPos, group); group->addGroupEffect(effectToMove); } -void EffectStackView2::slotMoveEffectToGroup(int effectIndex, CollapsibleEffect* group, int lastEffectIndex) +void EffectStackView2::slotMoveEffect(int currentIndex, int newIndex, CollapsibleEffect* target) { QVBoxLayout *l = static_cast(m_ui.container->widget()->layout()); - CollapsibleEffect *effectToMove = getEffectByIndex(effectIndex); + CollapsibleEffect *effectToMove = getEffectByIndex(currentIndex); if (effectToMove == NULL) return; - l->removeWidget(effectToMove); - group->addGroupEffect(effectToMove); - + QDomElement oldeffect = effectToMove->effect(); QDomElement neweffect = oldeffect.cloneNode().toElement(); EffectInfo effectinfo; effectinfo.fromString(oldeffect.attribute("kdenlive_info")); - effectinfo.groupIndex = group->groupIndex(); + effectinfo.groupIndex = target->groupIndex(); neweffect.setAttribute("kdenlive_info", effectinfo.toString()); ItemInfo info; @@ -555,13 +554,13 @@ void EffectStackView2::slotMoveEffectToGroup(int effectIndex, CollapsibleEffect* emit updateEffect(m_clipref, -1, oldeffect, neweffect, effectToMove->index()); } - if (effectToMove->effectIndex() == lastEffectIndex) return; + if (currentIndex == newIndex) return; // Update effect index with new position if (m_effectMetaInfo.trackMode) { - emit changeEffectPosition(NULL, m_trackindex, effectToMove->effectIndex(), lastEffectIndex + 1); + emit changeEffectPosition(NULL, m_trackindex, currentIndex, newIndex); } else { - emit changeEffectPosition(m_clipref, -1, effectToMove->effectIndex(), lastEffectIndex + 1); + emit changeEffectPosition(m_clipref, -1, currentIndex, newIndex); } } diff --git a/src/effectstack/effectstackview2.h b/src/effectstack/effectstackview2.h index d1692853..1ab3f1b7 100644 --- a/src/effectstack/effectstackview2.h +++ b/src/effectstack/effectstackview2.h @@ -130,7 +130,7 @@ private slots: /** @brief Move an effect in the stack. * @param index The effect index in the stack * @param up true if we want to move effect up, false for down */ - void slotMoveEffect(int index, bool up); + void slotMoveEffectUp(int index, bool up); /** @brief Delete an effect in the stack. */ void slotDeleteEffect(const QDomElement effect); @@ -154,10 +154,10 @@ private slots: /** @brief Move an effect into a group. ** @param ix the index of effect to move in stack layout - ** @param group the effect group where the effect is moved + ** @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 slotMoveEffectToGroup(int effectIndex, CollapsibleEffect *group, int lastEffectIndex); + void slotMoveEffect(int currentIndex, int newIndex, CollapsibleEffect* target); /** @brief Remove effects from a group */ void slotUnGroup(CollapsibleEffect* group); -- 2.39.2