]> git.sesse.net Git - kdenlive/blobdiff - src/customtrackview.cpp
Trying to fix a bug with the clip move undo command. No success.
[kdenlive] / src / customtrackview.cpp
index 428612df4ece540b243863d1d2098c9e7564fa1b..1a0a8ebb1acdc8c70459fae14ea6e5877b12ad7b 100644 (file)
 #include "docclipbase.h"
 #include "clipitem.h"
 #include "definitions.h"
-#include "moveclipcommand.h"
-#include "movetransitioncommand.h"
-#include "resizeclipcommand.h"
-#include "editguidecommand.h"
-#include "addtimelineclipcommand.h"
-#include "addeffectcommand.h"
-#include "editeffectcommand.h"
-#include "moveeffectcommand.h"
-#include "addtransitioncommand.h"
-#include "edittransitioncommand.h"
-#include "editkeyframecommand.h"
-#include "changespeedcommand.h"
-#include "addmarkercommand.h"
-#include "razorclipcommand.h"
+#include "commands/moveclipcommand.h"
+#include "commands/movetransitioncommand.h"
+#include "commands/resizeclipcommand.h"
+#include "commands/editguidecommand.h"
+#include "commands/addtimelineclipcommand.h"
+#include "commands/addeffectcommand.h"
+#include "commands/editeffectcommand.h"
+#include "commands/moveeffectcommand.h"
+#include "commands/addtransitioncommand.h"
+#include "commands/edittransitioncommand.h"
+#include "commands/editkeyframecommand.h"
+#include "commands/changespeedcommand.h"
+#include "commands/addmarkercommand.h"
+#include "commands/razorclipcommand.h"
 #include "kdenlivesettings.h"
 #include "transition.h"
 #include "clipmanager.h"
 #include "ui_keyframedialog_ui.h"
 #include "clipdurationdialog.h"
 #include "abstractgroupitem.h"
-#include "insertspacecommand.h"
+#include "commands/insertspacecommand.h"
 #include "spacerdialog.h"
-#include "addtrackcommand.h"
-#include "movegroupcommand.h"
+#include "commands/addtrackcommand.h"
+#include "commands/movegroupcommand.h"
 #include "ui_addtrack_ui.h"
 #include "initeffects.h"
-#include "locktrackcommand.h"
-#include "groupclipscommand.h"
-#include "splitaudiocommand.h"
-#include "changecliptypecommand.h"
+#include "commands/locktrackcommand.h"
+#include "commands/groupclipscommand.h"
+#include "commands/splitaudiocommand.h"
+#include "commands/changecliptypecommand.h"
 #include "trackdialog.h"
 #include "tracksconfigdialog.h"
-#include "configtrackscommand.h"
-#include "rebuildgroupcommand.h"
-#include "razorgroupcommand.h"
+#include "commands/configtrackscommand.h"
+#include "commands/rebuildgroupcommand.h"
+#include "commands/razorgroupcommand.h"
 #include "profilesdialog.h"
 
+#include "lib/audio/audioEnvelope.h"
+#include "lib/audio/audioCorrelation.h"
+
 #include <KDebug>
 #include <KLocale>
 #include <KUrl>
@@ -98,38 +101,41 @@ bool sortGuidesList(const Guide *g1 , const Guide *g2)
 // const int duration = animate ? 1500 : 1;
 
 CustomTrackView::CustomTrackView(KdenliveDoc *doc, CustomTrackScene* projectscene, QWidget *parent) :
-        QGraphicsView(projectscene, parent),
-        m_tracksHeight(KdenliveSettings::trackheight()),
-        m_projectDuration(0),
-        m_cursorPos(0),
-        m_document(doc),
-        m_scene(projectscene),
-        m_cursorLine(NULL),
-        m_operationMode(NONE),
-        m_moveOpMode(NONE),
-        m_dragItem(NULL),
-        m_dragGuide(NULL),
-        m_visualTip(NULL),
-        m_animation(NULL),
-        m_clickPoint(),
-        m_autoScroll(KdenliveSettings::autoscroll()),
-        m_pasteEffectsAction(NULL),
-        m_ungroupAction(NULL),
-        m_scrollOffset(0),
-        m_clipDrag(false),
-        m_findIndex(0),
-        m_tool(SELECTTOOL),
-        m_copiedItems(),
-        m_menuPosition(),
-        m_blockRefresh(false),
-        m_selectionGroup(NULL),
-        m_selectedTrack(0),
-        m_controlModifier(false)
-{
-    if (doc)
+    QGraphicsView(projectscene, parent),
+    m_tracksHeight(KdenliveSettings::trackheight()),
+    m_projectDuration(0),
+    m_cursorPos(0),
+    m_document(doc),
+    m_scene(projectscene),
+    m_cursorLine(NULL),
+    m_operationMode(NONE),
+    m_moveOpMode(NONE),
+    m_dragItem(NULL),
+    m_dragGuide(NULL),
+    m_visualTip(NULL),
+    m_animation(NULL),
+    m_clickPoint(),
+    m_autoScroll(KdenliveSettings::autoscroll()),
+    m_pasteEffectsAction(NULL),
+    m_ungroupAction(NULL),
+    m_scrollOffset(0),
+    m_clipDrag(false),
+    m_findIndex(0),
+    m_tool(SELECTTOOL),
+    m_copiedItems(),
+    m_menuPosition(),
+    m_blockRefresh(false),
+    m_selectionGroup(NULL),
+    m_selectedTrack(0),
+    m_audioCorrelator(NULL),
+    m_audioAlignmentReference(NULL),
+    m_controlModifier(false)
+{
+    if (doc) {
         m_commandStack = doc->commandStack();
-    else
+    } else {
         m_commandStack = NULL;
+    }
     m_ct = 0;
     setMouseTracking(true);
     setAcceptDrops(true);
@@ -602,7 +608,7 @@ void CustomTrackView::mouseMoveEvent(QMouseEvent * event)
             // razor tool over a clip, display current frame in monitor
             if (false && !m_blockRefresh && item->type() == AVWIDGET) {
                 //TODO: solve crash when showing frame when moving razor over clip
-                emit showClipFrame(((ClipItem *) item)->baseClip(), QPoint(), mappedXPos - (clip->startPos() - clip->cropStart()).frames(m_document->fps()));
+                emit showClipFrame(((ClipItem *) item)->baseClip(), QPoint(), false, mappedXPos - (clip->startPos() - clip->cropStart()).frames(m_document->fps()));
             }
             event->accept();
             return;
@@ -1641,8 +1647,7 @@ void CustomTrackView::addEffect(int track, GenTime pos, QDomElement effect)
     if (pos < GenTime()) {
         // Add track effect
         if (effect.attribute("id") == "speed") {
-            // TODO: uncomment after 0.8.2 release
-            // emit displayMessage(i18n("Cannot add speed effect to track"));
+            emit displayMessage(i18n("Cannot add speed effect to track"), ErrorMessage);
             return;
         }
         clearSelection();
@@ -1897,7 +1902,7 @@ void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement insertedE
         return;
     }
     QDomElement effect = insertedEffect.cloneNode().toElement();
-    //kDebug() << "// update effect ix: " << effect.attribute("kdenlive_ix")<<", TRACK: "<<track;
+    //kDebug() << "// update effect ix: " << effect.attribute("kdenlive_ix")<<", GAIN: "<<EffectsList::parameter(effect, "gain");
     if (pos < GenTime()) {
         // editing a track effect
         EffectsParameterList effectParams = getEffectArgs(effect);
@@ -1965,6 +1970,7 @@ void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement insertedE
                 emit clipItemSelected(clip, ix);
         }
     }
+    else emit displayMessage(i18n("Cannot find clip to update effect"), ErrorMessage);
     setDocumentModified();
 }
 
@@ -2475,6 +2481,10 @@ void CustomTrackView::dropEvent(QDropEvent * event)
         }
         event->setDropAction(Qt::MoveAction);
         event->accept();
+
+        /// \todo enable when really working
+//        alignAudio();
+
     } else QGraphicsView::dropEvent(event);
     setFocus();
 }
@@ -3777,10 +3787,10 @@ void CustomTrackView::deleteClip(ItemInfo info, bool refresh)
         emit displayMessage(i18n("Error removing clip at %1 on track %2", m_document->timecode().getTimecodeFromFrames(info.startPos.frames(m_document->fps())), info.track), ErrorMessage);
         kDebug()<<"CANNOT REMOVE: "<<info.startPos.frames(m_document->fps())<<", TK: "<<info.track;
         //m_document->renderer()->saveSceneList(QString("/tmp/error%1.mlt").arg(m_ct), QDomElement());
-        exit(1);
         return;
     }
     m_waitingThumbs.removeAll(item);
+    item->stopThumbs();
     if (item->isSelected()) emit clipItemSelected(NULL);
     item->baseClip()->removeReference();
     m_document->updateClip(item->baseClip()->getId());
@@ -3884,34 +3894,6 @@ void CustomTrackView::deleteSelectedClips()
     m_commandStack->push(deleteSelected);
 }
 
-void CustomTrackView::changeClipSpeed()
-{
-  // TODO: remove after string freeze
-    QList<QGraphicsItem *> itemList = scene()->selectedItems();
-    if (itemList.count() == 0) {
-        emit displayMessage(i18n("Select clip to change speed"), ErrorMessage);
-        return;
-    }
-    QUndoCommand *changeSelected = new QUndoCommand();
-    changeSelected->setText("Edit clip speed");
-    int count = 0;
-    int percent = -1;
-    bool ok;
-    for (int i = 0; i < itemList.count(); i++) {
-        if (itemList.at(i)->type() == AVWIDGET) {
-            ClipItem *item = static_cast <ClipItem *>(itemList.at(i));
-            if (percent == -1) percent = QInputDialog::getInteger(this, i18n("Edit Clip Speed"), i18n("New speed (percents)"), item->speed() * 100, 1, 10000, 1, &ok);
-            if (!ok) break;
-            double speed = (double) percent / 100.0;
-            if (item->speed() != speed && (item->clipType() == VIDEO || item->clipType() == AV)) {
-                count++;
-                //new ChangeSpeedCommand(this, info, item->speed(), speed, item->clipProducer(), changeSelected);
-            }
-        }
-    }
-    if (count > 0) m_commandStack->push(changeSelected);
-    else delete changeSelected;
-}
 
 void CustomTrackView::doChangeClipSpeed(ItemInfo info, ItemInfo speedIndependantInfo, const double speed, const double oldspeed, int strobe, const QString &id)
 {
@@ -4133,9 +4115,10 @@ void CustomTrackView::addClip(QDomElement xml, const QString &clipId, ItemInfo i
         emit displayMessage(i18n("Waiting for clip..."), InformationMessage);
         emit forceClipProcessing(clipId);
         qApp->processEvents();
-        for (int i = 0; i < 3; i++) {
+        for (int i = 0; i < 10; i++) {
             if (baseclip->getProducer() == NULL) {
-                m_producerNotReady.wait(&m_mutex, 500 + 500 * i);
+                qApp->processEvents();
+                m_producerNotReady.wait(&m_mutex, 200);
             } else break;
         }
         if (baseclip->getProducer() == NULL) {
@@ -4200,12 +4183,9 @@ void CustomTrackView::slotUpdateClip(const QString &clipId, bool reload)
             }
         }
     }
-    m_document->renderer()->unlockService(tractor);
     for (int i = 0; i < clipList.count(); i++)
         clipList.at(i)->refreshClip(true, true);
-    if (baseClip) {
-        baseClip->cleanupProducers();
-    }
+    m_document->renderer()->unlockService(tractor);
 }
 
 ClipItem *CustomTrackView::getClipItemAtEnd(GenTime pos, int track)
@@ -4261,7 +4241,7 @@ ClipItem *CustomTrackView::getClipItemAt(GenTime pos, int track)
 
 Transition *CustomTrackView::getTransitionItemAt(int pos, int track)
 {
-    const QPointF p(pos, (track + 1) * m_tracksHeight);
+    const QPointF p(pos, track * m_tracksHeight + Transition::itemOffset() + 1);
     QList<QGraphicsItem *> list = scene()->items(p);
     Transition *clip = NULL;
     for (int i = 0; i < list.size(); i++) {
@@ -4282,7 +4262,7 @@ Transition *CustomTrackView::getTransitionItemAt(GenTime pos, int track)
 Transition *CustomTrackView::getTransitionItemAtEnd(GenTime pos, int track)
 {
     int framepos = (int)(pos.frames(m_document->fps()));
-    const QPointF p(framepos - 1, (track + 1) * m_tracksHeight);
+    const QPointF p(framepos - 1, track * m_tracksHeight + Transition::itemOffset() + 1);
     QList<QGraphicsItem *> list = scene()->items(p);
     Transition *clip = NULL;
     for (int i = 0; i < list.size(); i++) {
@@ -4298,7 +4278,7 @@ Transition *CustomTrackView::getTransitionItemAtEnd(GenTime pos, int track)
 
 Transition *CustomTrackView::getTransitionItemAtStart(GenTime pos, int track)
 {
-    const QPointF p(pos.frames(m_document->fps()), (track + 1) * m_tracksHeight);
+    const QPointF p(pos.frames(m_document->fps()), track * m_tracksHeight + Transition::itemOffset() + 1);
     QList<QGraphicsItem *> list = scene()->items(p);
     Transition *clip = NULL;
     for (int i = 0; i < list.size(); ++i) {
@@ -4312,18 +4292,24 @@ Transition *CustomTrackView::getTransitionItemAtStart(GenTime pos, int track)
     return clip;
 }
 
-void CustomTrackView::moveClip(const ItemInfo &start, const ItemInfo &end, bool refresh)
+bool CustomTrackView::moveClip(const ItemInfo &start, const ItemInfo &end, bool refresh, ItemInfo *out_actualEnd)
 {
     if (m_selectionGroup) resetSelectionGroup(false);
     ClipItem *item = getClipItemAt((int) start.startPos.frames(m_document->fps()), start.track);
     if (!item) {
         emit displayMessage(i18n("Cannot move clip at time: %1 on track %2", m_document->timecode().getTimecodeFromFrames(start.startPos.frames(m_document->fps())), start.track), ErrorMessage);
         kDebug() << "----------------  ERROR, CANNOT find clip to move at.. ";
-        return;
+        return false;
     }
     Mlt::Producer *prod = item->getProducer(end.track);
 
-    bool success = m_document->renderer()->mltMoveClip((int)(m_document->tracksCount() - start.track), (int)(m_document->tracksCount() - end.track), (int) start.startPos.frames(m_document->fps()), (int)end.startPos.frames(m_document->fps()), prod);
+    qDebug() << "Moving item " << (long)item << " from .. to:";
+    qDebug().maybeSpace() << item->info();
+    qDebug() << start;
+    qDebug() << end;
+    bool success = m_document->renderer()->mltMoveClip((int)(m_document->tracksCount() - start.track), (int)(m_document->tracksCount() - end.track),
+                                                       (int) start.startPos.frames(m_document->fps()), (int)end.startPos.frames(m_document->fps()),
+                                                       prod);
     if (success) {
         bool snap = KdenliveSettings::snaptopoints();
         KdenliveSettings::setSnaptopoints(false);
@@ -4353,6 +4339,12 @@ void CustomTrackView::moveClip(const ItemInfo &start, const ItemInfo &end, bool
         emit displayMessage(i18n("Cannot move clip to position %1", m_document->timecode().getTimecodeFromFrames(end.startPos.frames(m_document->fps()))), ErrorMessage);
     }
     if (refresh) m_document->renderer()->doRefresh();
+    if (out_actualEnd != NULL) {
+        *out_actualEnd = item->info();
+        qDebug() << "Actual end position updated:" << *out_actualEnd;
+    }
+    qDebug() << item->info();
+    return success;
 }
 
 void CustomTrackView::moveGroup(QList <ItemInfo> startClip, QList <ItemInfo> startTransition, const GenTime &offset, const int trackOffset, bool reverseMove)
@@ -4473,7 +4465,7 @@ void CustomTrackView::moveGroup(QList <ItemInfo> startClip, QList <ItemInfo> sta
     } else kDebug() << "///////// WARNING; NO GROUP TO MOVE";
 }
 
-void CustomTrackView::moveTransition(const ItemInfo &start, const ItemInfo &end, bool m_refresh)
+void CustomTrackView::moveTransition(const ItemInfo &start, const ItemInfo &end, bool refresh)
 {
     Transition *item = getTransitionItemAt(start.startPos, start.track);
     if (!item) {
@@ -4517,7 +4509,7 @@ void CustomTrackView::moveTransition(const ItemInfo &start, const ItemInfo &end,
         }
         emit transitionItemSelected(item, getPreviousVideoTrack(item->track()), p);
     }
-    if (m_refresh) m_document->renderer()->doRefresh();
+    if (refresh) m_document->renderer()->doRefresh();
     setDocumentModified();
 }
 
@@ -5973,6 +5965,97 @@ void CustomTrackView::splitAudio()
     }
 }
 
+void CustomTrackView::setAudioAlignReference()
+{
+    QList<QGraphicsItem *> selection = scene()->selectedItems();
+    if (selection.isEmpty() || selection.size() > 1) {
+        emit displayMessage(i18n("You must select exactly one clip for the audio reference."), ErrorMessage);
+        return;
+    }
+    if (m_audioCorrelator != NULL) {
+        delete m_audioCorrelator;
+    }
+    if (selection.at(0)->type() == AVWIDGET) {
+        ClipItem *clip = static_cast<ClipItem*>(selection.at(0));
+        if (clip->clipType() == AV || clip->clipType() == AUDIO) {
+            m_audioAlignmentReference = clip;
+
+            AudioEnvelope *envelope = new AudioEnvelope(clip->getProducer(clip->track()));
+            m_audioCorrelator = new AudioCorrelation(envelope);
+
+            envelope->drawEnvelope().save("kdenlive-audio-reference-envelope.png");
+            envelope->dumpInfo();
+
+            emit displayMessage(i18n("Audio align reference set."), InformationMessage);
+        }
+        return;
+    }
+    emit displayMessage(i18n("Reference for audio alignment must contain audio data."), ErrorMessage);
+}
+
+void CustomTrackView::alignAudio()
+{
+    bool referenceOK = true;
+    if (m_audioCorrelator == NULL) {
+        referenceOK = false;
+    }
+    if (referenceOK) {
+        if (!scene()->items().contains(m_audioAlignmentReference)) {
+            // The reference item has been deleted from the timeline (or so)
+            referenceOK = false;
+        }
+    }
+    if (!referenceOK) {
+        emit displayMessage(i18n("Audio alignment reference not yet set."), DefaultMessage);
+        return;
+    }
+
+    int counter = 0;
+    QList<QGraphicsItem *> selection = scene()->selectedItems();
+    foreach (QGraphicsItem *item, selection) {
+        if (item->type() == AVWIDGET) {
+            ClipItem *clip = static_cast<ClipItem*>(item);
+            if (clip->clipType() == AV || clip->clipType() == AUDIO) {
+                AudioEnvelope *envelope = new AudioEnvelope(clip->getProducer(clip->track()));
+                int index = m_audioCorrelator->addChild(envelope);
+                int shift = m_audioCorrelator->getShift(index);
+                counter++;
+
+                m_audioCorrelator->info(index)->toImage().save("kdenlive-audio-align-cross-correlation.png");
+                envelope->drawEnvelope().save("kdenlive-audio-align-envelope.png");
+                envelope->dumpInfo();
+
+                int targetPos = m_audioAlignmentReference->startPos().frames(m_document->fps()) + shift;
+                qDebug() << "Reference starts at " << m_audioAlignmentReference->startPos().frames(m_document->fps());
+                qDebug() << "We will start at " << targetPos;
+                qDebug() << "to shift by " << shift;
+                qDebug() << "(eventually)";
+                qDebug() << "(maybe)";
+
+                GenTime add(shift, m_document->fps());
+                ItemInfo start = clip->info();
+                ItemInfo end = clip->info();
+                end.startPos = m_audioAlignmentReference->info().startPos + add;
+                end.endPos = m_audioAlignmentReference->info().startPos + add + clip->info().cropDuration;
+
+                QUndoCommand *moveCommand = new QUndoCommand();
+                moveCommand->setText(i18n("Auto-align clip"));
+                new MoveClipCommand(this, start, end, true, moveCommand);
+//                moveClip(start, end, true);
+                updateTrackDuration(clip->track(), moveCommand);
+                m_commandStack->push(moveCommand);
+
+            }
+        }
+    }
+
+    if (counter == 0) {
+        emit displayMessage(i18n("No audio clips selected."), ErrorMessage);
+    } else {
+        emit displayMessage(i18n("Auto-aligned %1 clips.").arg(counter), InformationMessage);
+    }
+}
+
 void CustomTrackView::doSplitAudio(const GenTime &pos, int track, EffectsList effects, bool split)
 {
     ClipItem *clip = getClipItemAt(pos, track);
@@ -6056,8 +6139,15 @@ void CustomTrackView::doSplitAudio(const GenTime &pos, int track, EffectsList ef
                 deleteClip(clp->info());
                 clip->setVideoOnly(false);
                 Mlt::Tractor *tractor = m_document->renderer()->lockService();
-                if (!m_document->renderer()->mltUpdateClipProducer(tractor, m_document->tracksCount() - info.track, info.startPos.frames(m_document->fps()), clip->baseClip()->getProducer(info.track))) {
-                    emit displayMessage(i18n("Cannot update clip (time: %1, track: %2)", info.startPos.frames(m_document->fps()), info.track), ErrorMessage);
+                if (!m_document->renderer()->mltUpdateClipProducer(
+                            tractor,
+                            m_document->tracksCount() - info.track,
+                            info.startPos.frames(m_document->fps()),
+                            clip->baseClip()->getProducer(info.track))) {
+
+                    emit displayMessage(i18n("Cannot update clip (time: %1, track: %2)",
+                                             info.startPos.frames(m_document->fps()), info.track),
+                                        ErrorMessage);
                 }
                 m_document->renderer()->unlockService(tractor);
 
@@ -6373,6 +6463,33 @@ void CustomTrackView::slotSelectTrack(int ix)
     viewport()->update();
 }
 
+void CustomTrackView::slotSelectClipsInTrack()
+{
+    QRectF rect(0, m_selectedTrack * m_tracksHeight + m_tracksHeight / 2, sceneRect().width(), m_tracksHeight / 2 - 1);
+    QList<QGraphicsItem *> selection = m_scene->items(rect);
+    m_scene->clearSelection();
+    for (int i = 0; i < selection.count(); i++) {
+        if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET) {
+            selection.at(i)->setSelected(true);
+        }
+    }    
+    resetSelectionGroup();
+    groupSelectedItems();
+}
+
+void CustomTrackView::slotSelectAllClips()
+{
+    QList<QGraphicsItem *> selection = m_scene->items();
+    m_scene->clearSelection();
+    for (int i = 0; i < selection.count(); i++) {
+        if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET  || selection.at(i)->type() == GROUPWIDGET) {
+            selection.at(i)->setSelected(true);
+        }
+    }
+    resetSelectionGroup();
+    groupSelectedItems();
+}
+
 void CustomTrackView::selectClip(bool add, bool group, int track, int pos)
 {
     QRectF rect;
@@ -6423,9 +6540,7 @@ QStringList CustomTrackView::extractTransitionsLumas()
             if (!luma.isEmpty()) urls << KUrl(luma).path();
         }
     }
-#if QT_VERSION >= 0x040500
     urls.removeDuplicates();
-#endif
     return urls;
 }
 
@@ -6781,3 +6896,28 @@ void CustomTrackView::adjustEffects(ClipItem* item, ItemInfo oldInfo, QUndoComma
 }
 
 
+void CustomTrackView::slotGotFilterJobResults(const QString &/*id*/, int startPos, int track, const QString &filter, stringMap filterParams)
+{
+    ClipItem *clip = getClipItemAt(GenTime(startPos, m_document->fps()), track);
+    if (clip == NULL) {
+        emit displayMessage(i18n("Cannot find clip for effect update %1.", filter), ErrorMessage);
+        return;
+    }
+    QDomElement newEffect;
+    QDomElement effect = clip->getEffectAt(clip->selectedEffectIndex());
+    if (effect.attribute("id") == filter) {
+        newEffect = effect.cloneNode().toElement();
+        QMap<QString, QString>::const_iterator i = filterParams.constBegin();
+        while (i != filterParams.constEnd()) {
+            EffectsList::setParameter(newEffect, i.key(), i.value());
+            kDebug()<<"// RESULT FILTER: "<<i.key()<<"="<< i.value();
+            ++i;
+        }
+        EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), effect, newEffect, clip->selectedEffectIndex(), true);
+        m_commandStack->push(command);
+        emit clipItemSelected(clip, clip->selectedEffectIndex());
+    }
+    
+}
+
+