]> git.sesse.net Git - kdenlive/commitdiff
Introducing timeline edit mode, starting with overwrite mode (allows to move a clip...
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Mon, 26 Oct 2009 09:45:00 +0000 (09:45 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Mon, 26 Oct 2009 09:45:00 +0000 (09:45 +0000)
svn path=/trunk/kdenlive/; revision=4061

14 files changed:
src/abstractgroupitem.cpp
src/clipitem.cpp
src/customtrackscene.cpp
src/customtrackscene.h
src/customtrackview.cpp
src/customtrackview.h
src/kdenliveui.rc
src/mainwindow.cpp
src/mainwindow.h
src/razorclipcommand.cpp
src/razorclipcommand.h
src/renderer.cpp
src/renderer.h
src/transition.cpp

index aed9c10837da7393ee33ca90ba8891723d678511..2f3f564c342d58b0df8bb473f5d4b7cb598eb103 100644 (file)
@@ -196,11 +196,13 @@ QVariant AbstractGroupItem::itemChange(GraphicsItemChange change, const QVariant
         }*/
 
         QPainterPath shape = clipGroupShape(newPos - pos());
-        QList<QGraphicsItem*> collindingItems = scene()->items(shape, Qt::IntersectsItemShape);
-        for (int i = 0; i < children.count(); i++) {
-            collindingItems.removeAll(children.at(i));
+        QList<QGraphicsItem*> collindingItems;
+        if (projectScene()->editMode() == NORMALEDIT) {
+            collindingItems = scene()->items(shape, Qt::IntersectsItemShape);
+            for (int i = 0; i < children.count(); i++) {
+                collindingItems.removeAll(children.at(i));
+            }
         }
-
         if (!collindingItems.isEmpty()) {
             bool forwardMove = xpos > start.x();
             int offset = 0;
index 7abb6815b735cc0871cfd0d00313a5937f1bfd39..f15929af47bb710ae5d9c7b724865d3748b9a6f0 100644 (file)
@@ -1186,7 +1186,9 @@ QVariant ClipItem::itemChange(GraphicsItemChange change, const QVariant &value)
         // Only one clip is moving
         QRectF sceneShape = rect();
         sceneShape.translate(newPos);
-        QList<QGraphicsItem*> items = scene()->items(sceneShape, Qt::IntersectsItemShape);
+        QList<QGraphicsItem*> items;
+        if (projectScene()->editMode() == NORMALEDIT)
+            items = scene()->items(sceneShape, Qt::IntersectsItemShape);
         items.removeAll(this);
         bool forwardMove = newPos.x() > pos().x();
         int offset = 0;
index 1364d22d8e33a96d9daef78770edbfde8cf8b6ee..1f8b40ae2f6de2f45f5e8483aa7c1a149b886aa7 100644 (file)
@@ -25,7 +25,8 @@
 CustomTrackScene::CustomTrackScene(KdenliveDoc *doc, QObject *parent) :
         QGraphicsScene(parent),
         m_document(doc),
-        m_scale(1.0, 1.0)
+        m_scale(1.0, 1.0),
+        m_editMode(NORMALEDIT)
 {
 }
 
@@ -96,4 +97,14 @@ MltVideoProfile CustomTrackScene::profile() const
     return m_document->mltProfile();
 }
 
+void CustomTrackScene::setEditMode(EDITMODE mode)
+{
+    m_editMode = mode;
+}
+
+EDITMODE CustomTrackScene::editMode() const
+{
+    return m_editMode;
+}
+
 #include "customtrackscene.moc"
index 961927dea2d732a333680b083def2935fd919184..d0f37060acbe8d4ccfeb9ad5ed6d320c26430821 100644 (file)
@@ -30,7 +30,9 @@
 class KdenliveDoc;
 class MltVideoProfile;
 
-/** This class holds all properties that need to be used by clip items */
+/** This class holds all scene properties that need to be used by clip items */
+
+enum EDITMODE { NORMALEDIT = 0 , OVERWRITEEDIT = 1 , INSERTEDIT = 2 };
 
 class CustomTrackScene : public QGraphicsScene
 {
@@ -47,11 +49,14 @@ public:
     QPointF scale() const;
     int tracksCount() const;
     MltVideoProfile profile() const;
+    void setEditMode(EDITMODE mode);
+    EDITMODE editMode() const;
 
 private:
     KdenliveDoc *m_document;
     QList <GenTime> m_snapPoints;
     QPointF m_scale;
+    EDITMODE m_editMode;
 };
 
 #endif
index 99fd9666312bbafa54896aa8490d6fdf1ecc79ab..f9759412831fa5c111fd4511458a6d94cdd8bf33 100644 (file)
@@ -19,7 +19,6 @@
 
 
 #include "customtrackview.h"
-#include "customtrackscene.h"
 #include "docclipbase.h"
 #include "clipitem.h"
 #include "definitions.h"
@@ -966,6 +965,7 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event)
         return;
     } else if (m_operationMode == MOVE) {
         setCursor(Qt::ClosedHandCursor);
+        if (m_dragItem) m_dragItem->setZValue(10);
     } else if (m_operationMode == TRANSITIONSTART && event->modifiers() != Qt::ControlModifier) {
         ItemInfo info;
         info.startPos = m_dragItem->startPos();
@@ -1314,6 +1314,7 @@ bool CustomTrackView::insertDropClips(const QMimeData *data, const QPoint pos)
         updateSnapPoints(NULL, offsetList);
         m_selectionGroup->setPos(framePos);
         scene()->addItem(m_selectionGroup);
+        m_selectionGroup->setZValue(10);
         return true;
     } else if (data->hasFormat("kdenlive/producerslist")) {
         m_clipDrag = true;
@@ -1357,6 +1358,7 @@ bool CustomTrackView::insertDropClips(const QMimeData *data, const QPoint pos)
             start += info.cropDuration;
             offsetList.append(start);
             ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, 1, false);
+            item->setZValue(10);
             item->setFlags(QGraphicsItem::ItemIsSelectable);
             m_selectionGroup->addToGroup(item);
             m_waitingThumbs.append(item);
@@ -1365,6 +1367,7 @@ bool CustomTrackView::insertDropClips(const QMimeData *data, const QPoint pos)
         updateSnapPoints(NULL, offsetList);
         m_selectionGroup->setPos(framePos);
         scene()->addItem(m_selectionGroup);
+        m_selectionGroup->setZValue(10);
         m_thumbsTimer.start();
         return true;
 
@@ -1691,7 +1694,7 @@ void CustomTrackView::slotUpdateClipEffect(ClipItem *clip, QDomElement oldeffect
     m_commandStack->push(command);
 }
 
-void CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut)
+ClipItem *CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut, bool execute)
 {
     if (cut) {
         // cut clip
@@ -1700,7 +1703,7 @@ void CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut)
             emit displayMessage(i18n("Cannot find clip to cut"), ErrorMessage);
             kDebug() << "/////////  ERROR CUTTING CLIP : (" << item->startPos().frames(25) << "-" << item->endPos().frames(25) << "), INFO: (" << info.startPos.frames(25) << "-" << info.endPos.frames(25) << ")" << ", CUT: " << cutTime.frames(25);
             m_blockRefresh = false;
-            return;
+            return NULL;
         }
         if (item->parentItem()) {
             // Item is part of a group, reset group
@@ -1708,7 +1711,7 @@ void CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut)
         }
         kDebug() << "/////////  CUTTING CLIP : (" << item->startPos().frames(25) << "-" << item->endPos().frames(25) << "), INFO: (" << info.startPos.frames(25) << "-" << info.endPos.frames(25) << ")" << ", CUT: " << cutTime.frames(25);
 
-        m_document->renderer()->mltCutClip(m_document->tracksCount() - info.track, cutTime);
+        if (execute) m_document->renderer()->mltCutClip(m_document->tracksCount() - info.track, cutTime);
         int cutPos = (int) cutTime.frames(m_document->fps());
         ItemInfo newPos;
         newPos.startPos = cutTime;
@@ -1737,6 +1740,7 @@ void CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut)
         item->baseClip()->addReference();
         m_document->updateClip(item->baseClip()->getId());
         setDocumentModified();
+        return dup;
         //kDebug() << "/////////  CUTTING CLIP RESULT: (" << item->startPos().frames(25) << "-" << item->endPos().frames(25) << "), DUP: (" << dup->startPos().frames(25) << "-" << dup->endPos().frames(25) << ")" << ", CUT: " << cutTime.frames(25);
     } else {
         // uncut clip
@@ -1746,11 +1750,11 @@ void CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut)
         if (!item || !dup || item == dup) {
             emit displayMessage(i18n("Cannot find clip to uncut"), ErrorMessage);
             m_blockRefresh = false;
-            return;
+            return NULL;
         }
         if (m_document->renderer()->mltRemoveClip(m_document->tracksCount() - info.track, cutTime) == false) {
             emit displayMessage(i18n("Error removing clip at %1 on track %2", m_document->timecode().getTimecodeFromFrames(cutTime.frames(m_document->fps())), info.track), ErrorMessage);
-            return;
+            return NULL;
         }
 
         /*kDebug() << "// UNCUTTING CLIPS: ITEM 1 (" << item->startPos().frames(25) << "x" << item->endPos().frames(25) << ")";
@@ -1773,9 +1777,10 @@ void CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut)
             setDocumentModified();
         } else
             emit displayMessage(i18n("Error when resizing clip"), ErrorMessage);
+        return item;
 
     }
-    QTimer::singleShot(3000, this, SLOT(slotEnableRefresh()));
+    //QTimer::singleShot(3000, this, SLOT(slotEnableRefresh()));
 }
 
 void CustomTrackView::slotEnableRefresh()
@@ -1992,8 +1997,9 @@ void CustomTrackView::dropEvent(QDropEvent * event)
                 updateClipTypeActions(NULL);
             }
 
-            new AddTimelineClipCommand(this, item->xml(), item->clipProducer(), item->info(), item->effectList(), false, false, addCommand);
+            //TODO: take care of edit mode for undo
             item->baseClip()->addReference();
+            item->setZValue(2);
             m_document->updateClip(item->baseClip()->getId());
             ItemInfo info = item->info();
 
@@ -2002,9 +2008,58 @@ void CustomTrackView::dropEvent(QDropEvent * event)
             if (isLocked) item->setItemLocked(true);
             ItemInfo clipInfo = info;
             clipInfo.track = m_document->tracksCount() - item->track();
-            if (m_document->renderer()->mltInsertClip(clipInfo, item->xml(), item->baseClip()->producer(item->track())) == -1) {
+            if (m_document->renderer()->mltInsertClip(clipInfo, item->xml(), item->baseClip()->producer(item->track()), m_scene->editMode() == OVERWRITEEDIT, m_scene->editMode() == INSERTEDIT) == -1) {
                 emit displayMessage(i18n("Cannot insert clip in timeline"), ErrorMessage);
             }
+            if (m_scene->editMode() == OVERWRITEEDIT) {
+                // if we are in overwrite or push mode, move clips accordingly
+                QRectF rect(clipInfo.startPos.frames(m_document->fps()), info.track * m_tracksHeight + m_tracksHeight / 2, (clipInfo.endPos - clipInfo.startPos).frames(m_document->fps()) - 1, m_tracksHeight / 2 - 2);
+                QList<QGraphicsItem *> selection = m_scene->items(rect);
+                selection.removeAll(item);
+                for (int i = 0; i < selection.count(); i++) {
+                    if (selection.at(i)->type() == AVWIDGET) {
+                        ClipItem *clip = static_cast<ClipItem *>(selection.at(i));
+                        kDebug() << " - - FOUND COLLIDE CLIP: " << clip->baseClip()->getId();
+                        if (clip->startPos() < item->startPos()) {
+                            if (clip->endPos() > item->endPos()) {
+                                ItemInfo clipInfo = clip->info();
+                                ItemInfo dupInfo = clipInfo;
+                                GenTime diff = item->startPos() - clip->startPos();
+                                dupInfo.startPos = item->startPos();
+                                dupInfo.cropStart += diff + GenTime(1, m_document->fps());
+                                dupInfo.cropDuration += GenTime() - diff;
+                                ItemInfo newdupInfo = dupInfo;
+                                GenTime diff2 = item->endPos() - item->startPos();
+                                newdupInfo.startPos = GenTime(item->endPos().frames(m_document->fps()), m_document->fps());
+                                newdupInfo.cropStart += diff2;
+                                newdupInfo.cropDuration += GenTime() - diff2;
+                                new RazorClipCommand(this, clipInfo, item->startPos(), false, addCommand);
+                                new ResizeClipCommand(this, dupInfo, newdupInfo, false, false, addCommand);
+                                ClipItem *dup = cutClip(clipInfo, item->startPos(), true, false);
+                                if (dup) dup->resizeStart(item->endPos().frames(m_document->fps()));
+
+                            } else {
+                                ItemInfo newclipInfo = clip->info();
+                                newclipInfo.endPos = item->startPos();
+                                new ResizeClipCommand(this, clip->info(), newclipInfo, false, false, addCommand);
+                                clip->resizeEnd(item->startPos().frames(m_document->fps()));
+                            }
+                        } else if (clip->endPos() < item->endPos()) {
+                            new AddTimelineClipCommand(this, clip->xml(), clip->clipProducer(), clip->info(), clip->effectList(), false, true, addCommand);
+                            scene()->removeItem(clip);
+                            delete clip;
+                            clip = NULL;
+                        } else {
+                            ItemInfo newclipInfo = clip->info();
+                            newclipInfo.startPos = item->endPos();
+                            new ResizeClipCommand(this, clip->info(), newclipInfo, false, false, addCommand);
+                            clip->resizeStart(item->endPos().frames(m_document->fps()));
+                        }
+                    }
+                }
+            }
+
+            new AddTimelineClipCommand(this, item->xml(), item->clipProducer(), item->info(), item->effectList(), false, false, addCommand);
 
             if (item->baseClip()->isTransparent() && getTransitionItemAtStart(info.startPos, info.track) == NULL) {
                 // add transparency transition
@@ -2613,7 +2668,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event)
 
     if (m_operationMode == MOVE) {
         setCursor(Qt::OpenHandCursor);
-
+        if (m_dragItem) m_dragItem->setZValue(2);
         if (m_dragItem->parentItem() == 0) {
             // we are moving one clip, easy
             if (m_dragItem->type() == AVWIDGET && (m_dragItemInfo.startPos != info.startPos || m_dragItemInfo.track != info.track)) {
@@ -2622,14 +2677,60 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event)
                 if (item->isAudioOnly()) prod = item->baseClip()->audioProducer(m_dragItemInfo.track);
                 else if (item->isVideoOnly()) prod = item->baseClip()->videoProducer();
                 else prod = item->baseClip()->producer(m_dragItemInfo.track);
-                bool success = m_document->renderer()->mltMoveClip((int)(m_document->tracksCount() - m_dragItemInfo.track), (int)(m_document->tracksCount() - m_dragItem->track()), (int) m_dragItemInfo.startPos.frames(m_document->fps()), (int)(m_dragItem->startPos().frames(m_document->fps())), prod);
+                bool success = m_document->renderer()->mltMoveClip((int)(m_document->tracksCount() - m_dragItemInfo.track), (int)(m_document->tracksCount() - m_dragItem->track()), (int) m_dragItemInfo.startPos.frames(m_document->fps()), (int)(m_dragItem->startPos().frames(m_document->fps())), prod, m_scene->editMode() == OVERWRITEEDIT, m_scene->editMode() == INSERTEDIT);
 
                 if (success) {
+                    QUndoCommand *moveCommand = new QUndoCommand();
+                    moveCommand->setText(i18n("Move clip"));
+
+                    if (m_scene->editMode() == OVERWRITEEDIT) {
+                        // if we are in overwrite or push mode, move clips accordingly
+                        QRectF rect(info.startPos.frames(m_document->fps()), info.track * m_tracksHeight + m_tracksHeight / 2, (info.endPos - info.startPos).frames(m_document->fps()) - 1, m_tracksHeight / 2 - 2);
+                        QList<QGraphicsItem *> selection = m_scene->items(rect);
+                        selection.removeAll(item);
+                        for (int i = 0; i < selection.count(); i++) {
+                            if (selection.at(i)->type() == AVWIDGET) {
+                                ClipItem *clip = static_cast<ClipItem *>(selection.at(i));
+                                if (clip->startPos() < item->startPos()) {
+                                    if (clip->endPos() > item->endPos()) {
+                                        ItemInfo clipInfo = clip->info();
+                                        ItemInfo dupInfo = clipInfo;
+                                        GenTime diff = item->startPos() - clip->startPos();
+                                        dupInfo.startPos = item->startPos();
+                                        dupInfo.cropStart += diff + GenTime(1, m_document->fps());
+                                        dupInfo.cropDuration += GenTime() - diff;
+                                        ItemInfo newdupInfo = dupInfo;
+                                        GenTime diff2 = item->endPos() - item->startPos();
+                                        newdupInfo.startPos = GenTime(item->endPos().frames(m_document->fps()), m_document->fps());
+                                        newdupInfo.cropStart += diff2;
+                                        newdupInfo.cropDuration += GenTime() - diff2;
+                                        new RazorClipCommand(this, clipInfo, item->startPos(), false, moveCommand);
+                                        new ResizeClipCommand(this, dupInfo, newdupInfo, false, false, moveCommand);
+                                        ClipItem *dup = cutClip(clipInfo, item->startPos(), true, false);
+                                        if (dup) dup->resizeStart(item->endPos().frames(m_document->fps()));
+                                    } else {
+                                        ItemInfo newclipInfo = clip->info();
+                                        newclipInfo.endPos = item->startPos();
+                                        new ResizeClipCommand(this, clip->info(), newclipInfo, false, false, moveCommand);
+                                        clip->resizeEnd(item->startPos().frames(m_document->fps()));
+                                    }
+                                } else if (clip->endPos() < item->endPos()) {
+                                    new AddTimelineClipCommand(this, clip->xml(), clip->clipProducer(), clip->info(), clip->effectList(), false, true, moveCommand);
+                                    scene()->removeItem(clip);
+                                    delete clip;
+                                    clip = NULL;
+                                } else {
+                                    ItemInfo newclipInfo = clip->info();
+                                    newclipInfo.startPos = item->endPos();
+                                    new ResizeClipCommand(this, clip->info(), newclipInfo, false, false, moveCommand);
+                                    clip->resizeStart(item->endPos().frames(m_document->fps()));
+                                }
+                            }
+                        }
+                    }
                     int tracknumber = m_document->tracksCount() - item->track() - 1;
                     bool isLocked = m_document->trackInfoAt(tracknumber).isLocked;
                     if (isLocked) item->setItemLocked(true);
-                    QUndoCommand *moveCommand = new QUndoCommand();
-                    moveCommand->setText(i18n("Move clip"));
                     new MoveClipCommand(this, m_dragItemInfo, info, false, moveCommand);
                     // Also move automatic transitions (on lower track)
                     Transition *startTransition = getTransitionItemAtStart(m_dragItemInfo.startPos, m_dragItemInfo.track);
@@ -4326,6 +4427,10 @@ void CustomTrackView::copyClip()
 
 bool CustomTrackView::canBePastedTo(ItemInfo info, int type) const
 {
+    if (m_scene->editMode() != NORMALEDIT) {
+        // If we are in overwrite mode, always allow the move
+        return true;
+    }
     QRectF rect((double) info.startPos.frames(m_document->fps()), (double)(info.track * m_tracksHeight + 1), (double)(info.endPos - info.startPos).frames(m_document->fps()), (double)(m_tracksHeight - 1));
     QList<QGraphicsItem *> collisions = scene()->items(rect, Qt::IntersectsItemBoundingRect);
     for (int i = 0; i < collisions.count(); i++) {
@@ -5286,4 +5391,11 @@ void CustomTrackView::selectTransition(bool add, bool group)
         }
     }
     if (group) groupSelectedItems();
-}
\ No newline at end of file
+}
+
+void CustomTrackView::setEditMode(EDITMODE mode)
+{
+    m_scene->setEditMode(mode);
+}
+
+
index ba7bfa745f5204d0b5d3a9a2019d1b69e3f354b1..d2fe46086babac0d310503da79770dc9e953057a 100644 (file)
 #include "docclipbase.h"
 #include "guide.h"
 #include "effectslist.h"
+#include "customtrackscene.h"
 
 class ClipItem;
 class AbstractClipItem;
 class AbstractGroupItem;
 class Transition;
-class CustomTrackScene;
 
 class CustomTrackView : public QGraphicsView
 {
@@ -84,7 +84,7 @@ public:
     void checkTrackHeight();
     //QList <TrackInfo> tracksList() const;
     void setTool(PROJECTTOOL tool);
-    void cutClip(ItemInfo info, GenTime cutTime, bool cut);
+    ClipItem *cutClip(ItemInfo info, GenTime cutTime, bool cut, bool execute = true);
     void slotSeekToPreviousSnap();
     void slotSeekToNextSnap();
     double getSnapPointForPos(double pos);
@@ -127,6 +127,7 @@ public:
     int selectedTrack() const;
     void selectClip(bool add, bool group = false);
     void selectTransition(bool add, bool group = false);
+    void setEditMode(EDITMODE mode);
 
 public slots:
     void setCursorPos(int pos, bool seek = true);
index 2c4b698d20a67046e7ab39ba123f07a2f07af7d3..91e60ccd383539bd01a07d90dbcdab9cbfebebac 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<gui name="kdenlive" version="48">
+<gui name="kdenlive" version="49">
   <ToolBar name="extraToolBar" >
     <text>Extra Toolbar</text>
        <Action name="project_render" />
     </Menu>
 
     <Menu name="tool" ><text>Tool</text>
+      <Action name="normal_mode" />
+      <Action name="overwrite_mode" />
+      <Action name="insert_mode" />
+      <Separator />
       <Action name="select_tool" />
       <Action name="razor_tool" />
       <Action name="spacer_tool" />
index 5d9b16d9e0bf0f92a25171ed3586b5ecf512ef58..c17d6109cfa0aa023e35beb216bc89f9dd37a425 100644 (file)
@@ -739,10 +739,41 @@ void MainWindow::setupActions()
 
     KToolBar *toolbar = new KToolBar("statusToolBar", this, Qt::BottomToolBarArea);
     toolbar->setMovable(false);
-    m_toolGroup = new QActionGroup(this);
     statusBar()->setStyleSheet(QString("QStatusBar QLabel {font-size:%1pt;} QStatusBar::item { border: 0px; font-size:%1pt;padding:0px; }").arg(statusBar()->font().pointSize()));
     QString style1 = "QToolBar { border: 0px } QToolButton { border-style: inset; border:1px solid #999999;border-radius: 3px;margin: 0px 3px;padding: 0px;} QToolButton:checked { background-color: rgba(224, 224, 0, 100); border-style: inset; border:1px solid #cc6666;border-radius: 3px;}";
+    
+    // create edit mode buttons
+    KAction *normaledit = new KAction(KIcon("kdenlive-normal-edit"), i18n("Normal mode"), this);
+    normaledit->setShortcut(i18nc("Normal editing", "n"));
+    toolbar->addAction(normaledit);
+    normaledit->setCheckable(true);
+    normaledit->setChecked(true);
+    
+    m_overwriteModeTool = new KAction(KIcon("kdenlive-overwrite-edit"), i18n("Overwrite mode"), this);
+    m_overwriteModeTool->setShortcut(i18nc("Overwrite mode shortcut", "o"));
+    toolbar->addAction(m_overwriteModeTool);
+    m_overwriteModeTool->setCheckable(true);
+    m_overwriteModeTool->setChecked(false);
+
+    m_insertModeTool = new KAction(KIcon("kdenlive-insert-edit"), i18n("Insert mode"), this);
+    m_insertModeTool->setShortcut(i18nc("Insert mode shortcut", "i"));
+    toolbar->addAction(m_insertModeTool);
+    m_insertModeTool->setCheckable(true);
+    m_insertModeTool->setChecked(false);
+    // not implemented yet
+    m_insertModeTool->setEnabled(false);
+    
+    QActionGroup *editGroup = new QActionGroup(this);
+    editGroup->addAction(normaledit);
+    editGroup->addAction(m_overwriteModeTool);
+    editGroup->addAction(m_insertModeTool);
+    editGroup->setExclusive(true);
+    connect(editGroup, SIGNAL(triggered(QAction *)), this, SLOT(slotChangeEdit(QAction *)));
+    //connect(m_overwriteModeTool, SIGNAL(toggled(bool)), this, SLOT(slotSetOverwriteMode(bool)));
+    
+    toolbar->addSeparator();
 
+    // create tools buttons
     m_buttonSelectTool = new KAction(KIcon("kdenlive-select-tool"), i18n("Selection tool"), this);
     m_buttonSelectTool->setShortcut(i18nc("Selection tool shortcut", "s"));
     toolbar->addAction(m_buttonSelectTool);
@@ -761,14 +792,27 @@ void MainWindow::setupActions()
     m_buttonSpacerTool->setCheckable(true);
     m_buttonSpacerTool->setChecked(false);
 
-    m_toolGroup->addAction(m_buttonSelectTool);
-    m_toolGroup->addAction(m_buttonRazorTool);
-    m_toolGroup->addAction(m_buttonSpacerTool);
-    m_toolGroup->setExclusive(true);
+    QActionGroup *toolGroup = new QActionGroup(this);
+    toolGroup->addAction(m_buttonSelectTool);
+    toolGroup->addAction(m_buttonRazorTool);
+    toolGroup->addAction(m_buttonSpacerTool);
+    toolGroup->setExclusive(true);
     toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly);
 
     QWidget * actionWidget;
     int max = toolbar->iconSizeDefault() + 2;
+    actionWidget = toolbar->widgetForAction(normaledit);
+    actionWidget->setMaximumWidth(max);
+    actionWidget->setMaximumHeight(max - 4);
+
+    actionWidget = toolbar->widgetForAction(m_insertModeTool);
+    actionWidget->setMaximumWidth(max);
+    actionWidget->setMaximumHeight(max - 4);
+    
+    actionWidget = toolbar->widgetForAction(m_overwriteModeTool);
+    actionWidget->setMaximumWidth(max);
+    actionWidget->setMaximumHeight(max - 4);
+    
     actionWidget = toolbar->widgetForAction(m_buttonSelectTool);
     actionWidget->setMaximumWidth(max);
     actionWidget->setMaximumHeight(max - 4);
@@ -782,7 +826,7 @@ void MainWindow::setupActions()
     actionWidget->setMaximumHeight(max - 4);
 
     toolbar->setStyleSheet(style1);
-    connect(m_toolGroup, SIGNAL(triggered(QAction *)), this, SLOT(slotChangeTool(QAction *)));
+    connect(toolGroup, SIGNAL(triggered(QAction *)), this, SLOT(slotChangeTool(QAction *)));
 
     toolbar->addSeparator();
     m_buttonFitZoom = new KAction(KIcon("zoom-fit-best"), i18n("Fit zoom to project"), this);
@@ -852,6 +896,9 @@ void MainWindow::setupActions()
     statusBar()->addPermanentWidget(m_timecodeFormat);
     //statusBar()->setMaximumHeight(statusBar()->font().pointSize() * 3);
 
+    collection->addAction("normal_mode", normaledit);    
+    collection->addAction("overwrite_mode", m_overwriteModeTool);
+    collection->addAction("insert_mode", m_insertModeTool);
     collection->addAction("select_tool", m_buttonSelectTool);
     collection->addAction("razor_tool", m_buttonRazorTool);
     collection->addAction("spacer_tool", m_buttonSpacerTool);
@@ -2579,6 +2626,14 @@ void MainWindow::slotChangeTool(QAction * action)
     else if (action == m_buttonSpacerTool) slotSetTool(SPACERTOOL);
 }
 
+void MainWindow::slotChangeEdit(QAction * action)
+{
+    if (!m_activeTimeline) return;
+    if (action == m_overwriteModeTool) m_activeTimeline->projectView()->setEditMode(OVERWRITEEDIT);
+    else if (action == m_insertModeTool) m_activeTimeline->projectView()->setEditMode(INSERTEDIT);
+    else m_activeTimeline->projectView()->setEditMode(NORMALEDIT);
+}
+
 void MainWindow::slotSetTool(PROJECTTOOL tool)
 {
     if (m_activeDocument && m_activeTimeline) {
index 781aaa04e691854c5f2bbe8ded5d3e0109265ddd..7cd9bc7c632c6e9b4c4ccf5bbb3afee0bc87fc17 100644 (file)
@@ -166,11 +166,12 @@ private:
     KAction *m_buttonVideoThumbs;
     KAction *m_buttonShowMarkers;
     KAction *m_buttonFitZoom;
+    KAction *m_overwriteModeTool;
+    KAction *m_insertModeTool;
     KAction *m_buttonSelectTool;
     KAction *m_buttonRazorTool;
     KAction *m_buttonSpacerTool;
     KAction *m_buttonSnap;
-    QActionGroup *m_toolGroup;
     KAction *m_saveAction;
     KAction *m_closeAction;
     QSlider *m_zoomSlider;
@@ -266,6 +267,7 @@ private slots:
     void slotActivateEffectStackView();
     void slotActivateTransitionView(Transition *);
     void slotChangeTool(QAction * action);
+    void slotChangeEdit(QAction * action);
     void slotSetTool(PROJECTTOOL tool);
     void slotSnapForward();
     void slotSnapRewind();
index 557d594a9a8a3dc87317b1c23e74bd9b0388ebc5..023f39f8c7ab8d33253aa4d52c80bf012ff3e696 100644 (file)
 
 #include <KLocale>
 
-RazorClipCommand::RazorClipCommand(CustomTrackView *view, const ItemInfo info, const GenTime cutTime, QUndoCommand * parent) :
+RazorClipCommand::RazorClipCommand(CustomTrackView *view, const ItemInfo info, const GenTime cutTime, bool doIt, QUndoCommand * parent) :
         QUndoCommand(parent),
         m_view(view),
         m_info(info),
-        m_cutTime(cutTime)
+        m_cutTime(cutTime),
+        m_doIt(doIt)
 {
     setText(i18n("Razor clip"));
 }
@@ -42,6 +43,7 @@ void RazorClipCommand::undo()
 void RazorClipCommand::redo()
 {
     // kDebug() << "----  redoing action cut: " << m_cutTime.frames(25);
-    m_view->cutClip(m_info, m_cutTime, true);
+    if (m_doIt) m_view->cutClip(m_info, m_cutTime, true);
+    m_doIt = true;
 }
 
index 4bfc9e9378159fa932685344f0132f632e7f27c6..c66a22c041f87e9e85da31e799dc47a89720ce61 100644 (file)
@@ -32,7 +32,7 @@ class CustomTrackView;
 class RazorClipCommand : public QUndoCommand
 {
 public:
-    RazorClipCommand(CustomTrackView *view, const ItemInfo info, const GenTime cutTime, QUndoCommand * parent = 0);
+    RazorClipCommand(CustomTrackView *view, const ItemInfo info, const GenTime cutTime, bool doIt = true, QUndoCommand * parent = 0);
     virtual void undo();
     virtual void redo();
 
@@ -40,6 +40,7 @@ private:
     CustomTrackView *m_view;
     ItemInfo m_info;
     GenTime m_cutTime;
+    bool m_doIt;
 };
 
 #endif
index 4f6f95e28ccbd6d69645488a8db23e658b796c26..349a6a9075f131f052044fd7aa15d889b5ce688c 100644 (file)
@@ -1533,7 +1533,7 @@ void Render::mltCheckLength(Mlt::Tractor *tractor)
     }
 }
 
-int Render::mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *prod)
+int Render::mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *prod, bool overwrite, bool push)
 {
     if (m_mltProducer == NULL) {
         kDebug() << "PLAYLIST NOT INITIALISED //////";
@@ -1561,6 +1561,7 @@ int Render::mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *pro
     }
     mlt_service_lock(service.get_service());
     Mlt::Producer trackProducer(tractor.track(info.track));
+    int trackDuration = trackProducer.get_playtime() - 1;
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
     //kDebug()<<"/// INSERT cLIP: "<<info.cropStart.frames(m_fps)<<", "<<info.startPos.frames(m_fps)<<"-"<<info.endPos.frames(m_fps);
 
@@ -1592,9 +1593,22 @@ int Render::mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *pro
             return -1;
         }
     }
-
-    Mlt::Producer *clip = prod->cut((int) info.cropStart.frames(m_fps), (int)(info.endPos - info.startPos + info.cropStart).frames(m_fps) - 1);
-    int newIndex = trackPlaylist.insert_at((int) info.startPos.frames(m_fps), clip, 1);
+    int cutPos = (int) info.cropStart.frames(m_fps);
+    int insertPos = (int) info.startPos.frames(m_fps);
+    int cutDuration = (int)(info.endPos - info.startPos).frames(m_fps) - 1;
+    Mlt::Producer *clip = prod->cut(cutPos, cutDuration + cutPos);
+    if (overwrite && (insertPos < trackDuration)) {
+        // Replace zone with blanks
+        //trackPlaylist.split_at(insertPos, true);
+        trackPlaylist.remove_region(insertPos, cutDuration + 1);
+        int clipIndex = trackPlaylist.get_clip_index_at(insertPos);
+        trackPlaylist.insert_blank(clipIndex, cutDuration);
+    } else if (push) {
+        trackPlaylist.split_at(insertPos, true);
+        int clipIndex = trackPlaylist.get_clip_index_at(insertPos);
+        trackPlaylist.insert_blank(clipIndex, cutDuration);
+    }
+    int newIndex = trackPlaylist.insert_at(insertPos, clip, 1);
     delete clip;
     /*if (QString(prod->get("transparency")).toInt() == 1)
         mltAddClipTransparency(info, info.track - 1, QString(prod->get("id")).toInt());*/
@@ -2733,9 +2747,9 @@ bool Render::mltResizeClipStart(ItemInfo info, GenTime diff)
     return true;
 }
 
-bool Render::mltMoveClip(int startTrack, int endTrack, GenTime moveStart, GenTime moveEnd, Mlt::Producer *prod)
+bool Render::mltMoveClip(int startTrack, int endTrack, GenTime moveStart, GenTime moveEnd, Mlt::Producer *prod, bool overwrite, bool insert)
 {
-    return mltMoveClip(startTrack, endTrack, (int) moveStart.frames(m_fps), (int) moveEnd.frames(m_fps), prod);
+    return mltMoveClip(startTrack, endTrack, (int) moveStart.frames(m_fps), (int) moveEnd.frames(m_fps), prod, overwrite, insert);
 }
 
 
@@ -2779,7 +2793,7 @@ bool Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod)
     return true;
 }
 
-bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEnd, Mlt::Producer *prod)
+bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEnd, Mlt::Producer *prod, bool overwrite, bool insert)
 {
     m_isBlocked++;
 
@@ -2798,7 +2812,7 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn
     bool checkLength = false;
     if (endTrack == startTrack) {
         Mlt::Producer *clipProducer = trackPlaylist.replace_with_blank(clipIndex);
-        if (!trackPlaylist.is_blank_at(moveEnd) || !clipProducer || clipProducer->is_blank()) {
+        if (!overwrite && (!trackPlaylist.is_blank_at(moveEnd) || !clipProducer || clipProducer->is_blank())) {
             // error, destination is not empty
             if (!trackPlaylist.is_blank_at(moveEnd)) trackPlaylist.insert_at(moveStart, clipProducer, 1);
             if (clipProducer) delete clipProducer;
@@ -2809,6 +2823,11 @@ bool Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEn
             return false;
         } else {
             trackPlaylist.consolidate_blanks(0);
+            if (overwrite) {
+                trackPlaylist.remove_region(moveEnd, clipProducer->get_playtime());
+                int clipIndex = trackPlaylist.get_clip_index_at(moveEnd);
+                trackPlaylist.insert_blank(clipIndex, clipProducer->get_playtime() - 1);
+            }
             int newIndex = trackPlaylist.insert_at(moveEnd, clipProducer, 1);
             delete clipProducer;
             /*if (QString(clipProducer.parent().get("transparency")).toInt() == 1) {
@@ -2908,7 +2927,7 @@ bool Render::mltMoveTransition(QString type, int startTrack, int newTrack, int n
         int currentTrack = transition.get_b_track();
         int currentIn = (int) transition.get_in();
         int currentOut = (int) transition.get_out();
-        
+
         if (resource == type && startTrack == currentTrack && currentIn <= old_pos && currentOut >= old_pos) {
             found = true;
             if (newTrack - startTrack != 0) {
index c7d308ea6a3bc0209a9de497c9d7c83544ef5b98..e1cd584b94fb85dc0a2a0a579cf91c3093ba6ca1 100644 (file)
@@ -169,7 +169,7 @@ Q_OBJECT public:
     double dar() const;
 
     /** Playlist manipulation */
-    int mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *prod);
+    int mltInsertClip(ItemInfo info, QDomElement element, Mlt::Producer *prod, bool overwrite = false, bool push = false);
     bool mltUpdateClip(ItemInfo info, QDomElement element, Mlt::Producer *prod);
     void mltCutClip(int track, GenTime position);
     void mltInsertSpace(QMap <int, int> trackClipStartList, QMap <int, int> trackTransitionStartList, int track, const GenTime duration, const GenTime timeOffset);
@@ -178,8 +178,8 @@ Q_OBJECT public:
     bool mltResizeClipEnd(ItemInfo info, GenTime clipDuration);
     bool mltResizeClipStart(ItemInfo info, GenTime diff);
     bool mltResizeClipCrop(ItemInfo info, GenTime diff);
-    bool mltMoveClip(int startTrack, int endTrack, GenTime pos, GenTime moveStart, Mlt::Producer *prod);
-    bool mltMoveClip(int startTrack, int endTrack, int pos, int moveStart, Mlt::Producer *prod);
+    bool mltMoveClip(int startTrack, int endTrack, GenTime pos, GenTime moveStart, Mlt::Producer *prod, bool overwrite = false, bool insert = false);
+    bool mltMoveClip(int startTrack, int endTrack, int pos, int moveStart, Mlt::Producer *prod, bool overwrite = false, bool insert = false);
     bool mltRemoveClip(int track, GenTime position);
     /** Delete an effect to a clip in MLT's playlist */
     bool mltRemoveEffect(int track, GenTime position, QString index, bool updateIndex, bool doRefresh = true);
index 2c37ffcd13b9cf5c10b4081a7c4c4150b4f551ed..a4700c8b96d01b053858ee2a643fe8499cad0a71 100644 (file)
@@ -207,7 +207,9 @@ QVariant Transition::itemChange(GraphicsItemChange change, const QVariant &value
         // Only one clip is moving
         QRectF sceneShape = rect();
         sceneShape.translate(newPos);
-        QList<QGraphicsItem*> items = scene()->items(sceneShape, Qt::IntersectsItemShape);
+        QList<QGraphicsItem*> items;
+        if (projectScene()->editMode() == NORMALEDIT)
+            items = scene()->items(sceneShape, Qt::IntersectsItemShape);
         items.removeAll(this);
 
         if (!items.isEmpty()) {