X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fcustomtrackview.cpp;h=17c3f0f45eccf348ebae08c7f971398ac9536832;hb=bb32a23e9e4ed5b55320c7074b3eca686ef8c0c5;hp=1b924a12840581e852d666ddd7f35000b2769ae0;hpb=240da3a525c622798814dae4633a93da4fabca22;p=kdenlive diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index 1b924a12..17c3f0f4 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -48,7 +48,6 @@ #include "insertspacecommand.h" #include "spacerdialog.h" #include "addtrackcommand.h" -#include "changetrackcommand.h" #include "movegroupcommand.h" #include "ui_addtrack_ui.h" #include "initeffects.h" @@ -57,6 +56,8 @@ #include "splitaudiocommand.h" #include "changecliptypecommand.h" #include "trackdialog.h" +#include "tracksconfigdialog.h" +#include "configtrackscommand.h" #include #include @@ -130,7 +131,9 @@ CustomTrackView::CustomTrackView(KdenliveDoc *doc, CustomTrackScene* projectscen setLineWidth(0); //setCacheMode(QGraphicsView::CacheBackground); //setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); + pixmapCache = new KPixmapCache("kdenlive-thumbs"); KdenliveSettings::setTrackheight(m_tracksHeight); m_animationTimer = new QTimeLine(800); m_animationTimer->setFrameRange(0, 5); @@ -403,24 +406,10 @@ void CustomTrackView::mouseMoveEvent(QMouseEvent * event) pos = (br.bottom() - pos) * maxh; m_dragItem->updateKeyFramePos(keyFramePos, pos); } - if (m_visualTip) { - scene()->removeItem(m_visualTip); - m_animationTimer->stop(); - delete m_animation; - m_animation = NULL; - delete m_visualTip; - m_visualTip = NULL; - } + removeTipAnimation(); return; } else if (m_operationMode == MOVEGUIDE) { - if (m_visualTip) { - scene()->removeItem(m_visualTip); - m_animationTimer->stop(); - delete m_animation; - m_animation = NULL; - delete m_visualTip; - m_visualTip = NULL; - } + removeTipAnimation(); QGraphicsView::mouseMoveEvent(event); return; } else if (m_operationMode == SPACER && move && m_selectionGroup) { @@ -436,9 +425,8 @@ void CustomTrackView::mouseMoveEvent(QMouseEvent * event) for (int i = 0; i < children.count(); i++) { if (children.at(i)->type() == GROUPWIDGET) { QList subchildren = children.at(i)->childItems(); - for (int j = 0; j < subchildren.count(); j++) { + for (int j = 0; j < subchildren.count(); j++) collidingItems.removeAll(subchildren.at(j)); - } } collidingItems.removeAll(children.at(i)); } @@ -463,9 +451,8 @@ void CustomTrackView::mouseMoveEvent(QMouseEvent * event) for (int i = 0; i < children.count(); i++) { if (children.at(i)->type() == GROUPWIDGET) { QList subchildren = children.at(i)->childItems(); - for (int j = 0; j < subchildren.count(); j++) { + for (int j = 0; j < subchildren.count(); j++) collidingItems.removeAll(subchildren.at(j)); - } } collidingItems.removeAll(children.at(i)); } @@ -487,9 +474,8 @@ void CustomTrackView::mouseMoveEvent(QMouseEvent * event) for (int i = 0; i < children.count(); i++) { if (children.at(i)->type() == GROUPWIDGET) { QList subchildren = children.at(i)->childItems(); - for (int j = 0; j < subchildren.count(); j++) { + for (int j = 0; j < subchildren.count(); j++) collidingItems.removeAll(subchildren.at(j)); - } } collidingItems.removeAll(children.at(i)); } @@ -514,9 +500,8 @@ void CustomTrackView::mouseMoveEvent(QMouseEvent * event) for (int i = 0; i < children.count(); i++) { if (children.at(i)->type() == GROUPWIDGET) { QList subchildren = children.at(i)->childItems(); - for (int j = 0; j < subchildren.count(); j++) { + for (int j = 0; j < subchildren.count(); j++) collidingItems.removeAll(subchildren.at(j)); - } } collidingItems.removeAll(children.at(i)); } @@ -573,154 +558,25 @@ void CustomTrackView::mouseMoveEvent(QMouseEvent * event) QGraphicsView::mouseMoveEvent(event); return; } else { - if (m_visualTip) { - scene()->removeItem(m_visualTip); - m_animationTimer->stop(); - delete m_animation; - m_animation = NULL; - delete m_visualTip; - m_visualTip = NULL; - } + removeTipAnimation(); } m_moveOpMode = opMode; - if (opMode == MOVE) { + setTipAnimation(clip, opMode, size); + if (opMode == MOVE) setCursor(Qt::OpenHandCursor); - } else if (opMode == RESIZESTART) { + else if (opMode == RESIZESTART) setCursor(KCursor("left_side", Qt::SizeHorCursor)); - if (m_visualTip == NULL) { - QRectF rect = clip->sceneBoundingRect(); - QPolygon polygon; - polygon << QPoint(0, - size * 2); - polygon << QPoint(size * 2, 0); - polygon << QPoint(0, size * 2); - polygon << QPoint(0, - size * 2); - - m_visualTip = new QGraphicsPolygonItem(polygon); - ((QGraphicsPolygonItem*) m_visualTip)->setBrush(m_tipColor); - ((QGraphicsPolygonItem*) m_visualTip)->setPen(m_tipPen); - m_visualTip->setPos(rect.x(), rect.y() + rect.height() / 2); - m_visualTip->setFlags(QGraphicsItem::ItemIgnoresTransformations); - m_visualTip->setZValue(100); - m_animation = new QGraphicsItemAnimation; - m_animation->setItem(m_visualTip); - m_animation->setTimeLine(m_animationTimer); - m_animation->setScaleAt(.5, 2, 1); - m_animation->setScaleAt(1, 1, 1); - scene()->addItem(m_visualTip); - m_animationTimer->start(); - } - } else if (opMode == RESIZEEND) { + else if (opMode == RESIZEEND) setCursor(KCursor("right_side", Qt::SizeHorCursor)); - if (m_visualTip == NULL) { - QRectF rect = clip->sceneBoundingRect(); - QPolygon polygon; - polygon << QPoint(0, - size * 2); - polygon << QPoint(- size * 2, 0); - polygon << QPoint(0, size * 2); - polygon << QPoint(0, - size * 2); - - m_visualTip = new QGraphicsPolygonItem(polygon); - ((QGraphicsPolygonItem*) m_visualTip)->setBrush(m_tipColor); - ((QGraphicsPolygonItem*) m_visualTip)->setPen(m_tipPen); - m_visualTip->setFlags(QGraphicsItem::ItemIgnoresTransformations); - m_visualTip->setPos(rect.right(), rect.y() + rect.height() / 2); - m_visualTip->setZValue(100); - m_animation = new QGraphicsItemAnimation; - m_animation->setItem(m_visualTip); - m_animation->setTimeLine(m_animationTimer); - m_animation->setScaleAt(.5, 2, 1); - m_animation->setScaleAt(1, 1, 1); - scene()->addItem(m_visualTip); - m_animationTimer->start(); - } - } else if (opMode == FADEIN) { - if (m_visualTip == NULL) { - ClipItem *item = (ClipItem *) clip; - QRectF rect = clip->sceneBoundingRect(); - m_visualTip = new QGraphicsEllipseItem(-size, -size, size * 2, size * 2); - ((QGraphicsEllipseItem*) m_visualTip)->setBrush(m_tipColor); - ((QGraphicsEllipseItem*) m_visualTip)->setPen(m_tipPen); - m_visualTip->setPos(rect.x() + item->fadeIn(), rect.y()); - m_visualTip->setFlags(QGraphicsItem::ItemIgnoresTransformations); - m_visualTip->setZValue(100); - m_animation = new QGraphicsItemAnimation; - m_animation->setItem(m_visualTip); - m_animation->setTimeLine(m_animationTimer); - m_animation->setScaleAt(.5, 2, 2); - m_animation->setScaleAt(1, 1, 1); - scene()->addItem(m_visualTip); - m_animationTimer->start(); - } - setCursor(Qt::PointingHandCursor); - } else if (opMode == FADEOUT) { - if (m_visualTip == NULL) { - ClipItem *item = (ClipItem *) clip; - QRectF rect = clip->sceneBoundingRect(); - m_visualTip = new QGraphicsEllipseItem(-size, -size, size * 2, size * 2); - ((QGraphicsEllipseItem*) m_visualTip)->setBrush(m_tipColor); - ((QGraphicsEllipseItem*) m_visualTip)->setPen(m_tipPen); - m_visualTip->setPos(rect.right() - item->fadeOut(), rect.y()); - m_visualTip->setFlags(QGraphicsItem::ItemIgnoresTransformations); - m_visualTip->setZValue(100); - m_animation = new QGraphicsItemAnimation; - m_animation->setItem(m_visualTip); - m_animation->setTimeLine(m_animationTimer); - m_animation->setScaleAt(.5, 2, 2); - m_animation->setScaleAt(1, 1, 1); - scene()->addItem(m_visualTip); - m_animationTimer->start(); - } + else if (opMode == FADEIN || opMode == FADEOUT) { setCursor(Qt::PointingHandCursor); - } else if (opMode == TRANSITIONSTART) { - if (m_visualTip == NULL) { - QRectF rect = clip->sceneBoundingRect(); - QPolygon polygon; - polygon << QPoint(0, - size * 2); - polygon << QPoint(size * 2, 0); - polygon << QPoint(0, 0); - polygon << QPoint(0, - size * 2); - - m_visualTip = new QGraphicsPolygonItem(polygon); - ((QGraphicsPolygonItem*) m_visualTip)->setBrush(m_tipColor); - ((QGraphicsPolygonItem*) m_visualTip)->setPen(m_tipPen); - m_visualTip->setPos(rect.x(), rect.bottom()); - m_visualTip->setFlags(QGraphicsItem::ItemIgnoresTransformations); - m_visualTip->setZValue(100); - m_animation = new QGraphicsItemAnimation; - m_animation->setItem(m_visualTip); - m_animation->setTimeLine(m_animationTimer); - m_animation->setScaleAt(.5, 2, 2); - m_animation->setScaleAt(1, 1, 1); - scene()->addItem(m_visualTip); - m_animationTimer->start(); - } - setCursor(Qt::PointingHandCursor); - } else if (opMode == TRANSITIONEND) { - if (m_visualTip == NULL) { - QRectF rect = clip->sceneBoundingRect(); - QPolygon polygon; - polygon << QPoint(0, - size * 2); - polygon << QPoint(- size * 2, 0); - polygon << QPoint(0, 0); - polygon << QPoint(0, - size * 2); - - m_visualTip = new QGraphicsPolygonItem(polygon); - ((QGraphicsPolygonItem*) m_visualTip)->setBrush(m_tipColor); - ((QGraphicsPolygonItem*) m_visualTip)->setPen(m_tipPen); - m_visualTip->setPos(rect.right(), rect.bottom()); - m_visualTip->setFlags(QGraphicsItem::ItemIgnoresTransformations); - m_visualTip->setZValue(100); - m_animation = new QGraphicsItemAnimation; - m_animation->setItem(m_visualTip); - m_animation->setTimeLine(m_animationTimer); - m_animation->setScaleAt(.5, 2, 2); - m_animation->setScaleAt(1, 1, 1); - scene()->addItem(m_visualTip); - m_animationTimer->start(); - } + emit displayMessage(i18n("Drag to add or resize a fade effect."), InformationMessage); + } else if (opMode == TRANSITIONSTART || opMode == TRANSITIONEND) { setCursor(Qt::PointingHandCursor); + emit displayMessage(i18n("Click to add a transition."), InformationMessage); } else if (opMode == KEYFRAME) { setCursor(Qt::PointingHandCursor); + emit displayMessage(i18n("Move keyframe above or below clip to remove it, double click to add a new one."), InformationMessage); } } // no clip under mouse else if (m_tool == RAZORTOOL) { @@ -730,15 +586,7 @@ void CustomTrackView::mouseMoveEvent(QMouseEvent * event) m_moveOpMode = opMode; setCursor(Qt::SplitHCursor); } else { - if (m_visualTip) { - scene()->removeItem(m_visualTip); - m_animationTimer->stop(); - delete m_animation; - m_animation = NULL; - delete m_visualTip; - m_visualTip = NULL; - - } + removeTipAnimation(); setCursor(Qt::ArrowCursor); if (event->buttons() != Qt::NoButton && event->modifiers() == Qt::NoModifier) { QGraphicsView::mouseMoveEvent(event); @@ -830,9 +678,12 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) while (!m_dragGuide && ct < collisionList.count()) { if (collisionList.at(ct)->type() == AVWIDGET || collisionList.at(ct)->type() == TRANSITIONWIDGET) { collisionClip = static_cast (collisionList.at(ct)); - if (collisionClip == m_dragItem) { + if (collisionClip->isItemLocked()) + break; + if (collisionClip == m_dragItem) collisionClip = NULL; - } else m_dragItem = collisionClip; + else + m_dragItem = collisionClip; found = true; m_dragItemInfo = m_dragItem->info(); if (m_dragItem->parentItem() && m_dragItem->parentItem()->type() == GROUPWIDGET && m_dragItem->parentItem() != m_selectionGroup) { @@ -849,7 +700,7 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) } #if QT_VERSION >= 0x040600 // Add shadow to dragged item, currently disabled because of painting artifacts - //TODO: re-enable when fixed + //TODO: re-enable when fixed /*QGraphicsDropShadowEffect *eff = new QGraphicsDropShadowEffect(); eff->setBlurRadius(5); eff->setOffset(3, 3); @@ -1152,6 +1003,18 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) QGraphicsView::mousePressEvent(event); } +void CustomTrackView::rebuildGroup(AbstractGroupItem* group) +{ + if (group) { + QList children = group->childItems(); + m_document->clipManager()->removeGroup(group); + scene()->destroyItemGroup(group); + for (int i = 0; i < children.count(); i++) + children.at(i)->setSelected(true); + groupSelectedItems(false, true); + } +} + void CustomTrackView::resetSelectionGroup(bool selectItems) { if (m_selectionGroup) { @@ -1207,12 +1070,13 @@ void CustomTrackView::groupSelectedItems(bool force, bool createNewGroup) scene()->addItem(newGroup); - // CHeck if we are trying to include a group in a group + // Check if we are trying to include a group in a group QList groups; for (int i = 0; i < selection.count(); i++) { - if (selection.at(i)->type() == GROUPWIDGET && !groups.contains(static_cast(selection.at(i)))) { + if (selection.at(i)->type() == GROUPWIDGET && !groups.contains(static_cast(selection.at(i)))) groups.append(static_cast(selection.at(i))); - } else if (selection.at(i)->parentItem() && !groups.contains(static_cast(selection.at(i)->parentItem()))) groups.append(static_cast(selection.at(i)->parentItem())); + else if (selection.at(i)->parentItem() && !groups.contains(static_cast(selection.at(i)->parentItem()))) + groups.append(static_cast(selection.at(i)->parentItem())); } if (!groups.isEmpty()) { // ungroup previous groups @@ -1259,7 +1123,7 @@ void CustomTrackView::mouseDoubleClickEvent(QMouseEvent *event) if (m_dragItem && m_dragItem->hasKeyFrames()) { /*if (m_moveOpMode == KEYFRAME) { // user double clicked on a keyframe, open edit dialog - //TODO: update for effects with several values per keyframe + //TODO: update for effects with several values per keyframe QDialog d(parentWidget()); Ui::KeyFrameDialog_UI view; view.setupUi(&d); @@ -1316,59 +1180,62 @@ void CustomTrackView::editItemDuration() if (m_scene->selectedItems().count() == 1) { item = static_cast (m_scene->selectedItems().at(0)); } else { - if (m_scene->selectedItems().empty()) { + if (m_scene->selectedItems().empty()) emit displayMessage(i18n("Cannot find clip to edit"), ErrorMessage); - } else { + else emit displayMessage(i18n("Cannot edit the duration of multiple items"), ErrorMessage); - } return; } } + if (!item) { + emit displayMessage(i18n("Cannot find clip to edit"), ErrorMessage); + return; + } + + if (item->type() == GROUPWIDGET || (item->parentItem() && item->parentItem()->type() == GROUPWIDGET)) { + emit displayMessage(i18n("Cannot edit an item in a group"), ErrorMessage); + return; + } + if (!item->isItemLocked()) { GenTime minimum; GenTime maximum; - if (item->type() == TRANSITIONWIDGET) { + if (item->type() == TRANSITIONWIDGET) getTransitionAvailableSpace(item, minimum, maximum); - } else { + else getClipAvailableSpace(item, minimum, maximum); - } //kDebug()<<"// GOT MOVE POS: "<timecode(), minimum, maximum, this); if (d.exec() == QDialog::Accepted) { + ItemInfo clipInfo = item->info(); + ItemInfo startInfo = clipInfo; if (item->type() == TRANSITIONWIDGET) { // move & resize transition - ItemInfo startInfo; - startInfo.startPos = item->startPos(); - startInfo.endPos = item->endPos(); - startInfo.track = item->track(); - ItemInfo endInfo; - endInfo.startPos = d.startPos(); - endInfo.endPos = endInfo.startPos + d.duration(); - endInfo.track = item->track(); - MoveTransitionCommand *command = new MoveTransitionCommand(this, startInfo, endInfo, true); + clipInfo.startPos = d.startPos(); + clipInfo.endPos = clipInfo.startPos + d.duration(); + clipInfo.track = item->track(); + MoveTransitionCommand *command = new MoveTransitionCommand(this, startInfo, clipInfo, true); m_commandStack->push(command); } else { // move and resize clip QUndoCommand *moveCommand = new QUndoCommand(); moveCommand->setText(i18n("Edit clip")); - ItemInfo clipInfo = item->info(); if (d.duration() < item->cropDuration() || d.cropStart() != clipInfo.cropStart) { // duration was reduced, so process it first - ItemInfo startInfo = clipInfo; clipInfo.endPos = clipInfo.startPos + d.duration(); clipInfo.cropStart = d.cropStart(); new ResizeClipCommand(this, startInfo, clipInfo, true, false, moveCommand); } if (d.startPos() != clipInfo.startPos) { - ItemInfo startInfo = clipInfo; + startInfo = clipInfo; clipInfo.startPos = d.startPos(); clipInfo.endPos = item->endPos() + (clipInfo.startPos - startInfo.startPos); new MoveClipCommand(this, startInfo, clipInfo, true, moveCommand); } if (d.duration() > item->cropDuration()) { // duration was increased, so process it after move - ItemInfo startInfo = clipInfo; + startInfo = clipInfo; clipInfo.endPos = clipInfo.startPos + d.duration(); clipInfo.cropStart = d.cropStart(); new ResizeClipCommand(this, startInfo, clipInfo, true, false, moveCommand); @@ -1376,16 +1243,18 @@ void CustomTrackView::editItemDuration() m_commandStack->push(moveCommand); } } - } else emit displayMessage(i18n("Item is locked"), ErrorMessage); + } else { + emit displayMessage(i18n("Item is locked"), ErrorMessage); + } } -void CustomTrackView::editKeyFrame(const GenTime pos, const int track, const int index, const QString keyframes) +void CustomTrackView::editKeyFrame(const GenTime /*pos*/, const int /*track*/, const int /*index*/, const QString /*keyframes*/) { - ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()), track); + /*ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()), track); if (clip) { clip->setKeyframes(index, keyframes); updateEffect(m_document->tracksCount() - clip->track(), clip->startPos(), clip->effectAt(index), index, false); - } else emit displayMessage(i18n("Cannot find clip with keyframe"), ErrorMessage); + } else emit displayMessage(i18n("Cannot find clip with keyframe"), ErrorMessage);*/ } @@ -1456,6 +1325,11 @@ void CustomTrackView::insertClipCut(DocClipBase *clip, int in, int out) AddTimelineClipCommand *command = new AddTimelineClipCommand(this, clip->toXML(), clip->getId(), pasteInfo, EffectsList(), m_scene->editMode() == OVERWRITEEDIT, m_scene->editMode() == INSERTEDIT, true, false); m_commandStack->push(command); + + selectClip(true, false); + // Automatic audio split + if (KdenliveSettings::splitaudio()) + splitAudio(); } bool CustomTrackView::insertDropClips(const QMimeData *data, const QPoint pos) @@ -1913,6 +1787,15 @@ void CustomTrackView::slotUpdateClipEffect(ClipItem *clip, QDomElement oldeffect m_commandStack->push(command); } +void CustomTrackView::slotUpdateClipRegion(ClipItem *clip, int ix, QString region) +{ + QDomElement effect = clip->getEffectAt(ix); + QDomElement oldeffect = effect.cloneNode().toElement(); + effect.setAttribute("region", region); + EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), oldeffect, effect, ix, true); + m_commandStack->push(command); +} + ClipItem *CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut, bool execute) { if (cut) { @@ -2249,7 +2132,9 @@ 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()), m_scene->editMode() == OVERWRITEEDIT, m_scene->editMode() == INSERTEDIT) == -1) { + + int worked = m_document->renderer()->mltInsertClip(clipInfo, item->xml(), item->baseClip()->producer(item->track()), m_scene->editMode() == OVERWRITEEDIT, m_scene->editMode() == INSERTEDIT); + if (worked == -1) { emit displayMessage(i18n("Cannot insert clip in timeline"), ErrorMessage); brokenClips.append(item); continue; @@ -2269,10 +2154,14 @@ void CustomTrackView::dropEvent(QDropEvent * event) brokenClips.clear(); if (addCommand->childCount() > 0) m_commandStack->push(addCommand); else delete addCommand; + + // Automatic audio split + if (KdenliveSettings::splitaudio()) + splitAudio(); setDocumentModified(); /* - // debug info + // debug info QRectF rect(0, 1 * m_tracksHeight + m_tracksHeight / 2, sceneRect().width(), 2); QList selection = m_scene->items(rect); QStringList timelineList; @@ -2604,16 +2493,17 @@ void CustomTrackView::removeTrack(int ix) //QTimer::singleShot(500, this, SIGNAL(trackHeightChanged())); } -void CustomTrackView::changeTrack(int ix, TrackInfo type) +void CustomTrackView::configTracks(QList < TrackInfo > trackInfos) { - int tracknumber = m_document->tracksCount() - ix; - m_document->setTrackType(tracknumber - 1, type); - m_document->renderer()->mltChangeTrackState(tracknumber, m_document->trackInfoAt(tracknumber - 1).isMute, m_document->trackInfoAt(tracknumber - 1).isBlind); + for (int i = 0; i < trackInfos.count(); ++i) { + m_document->setTrackType(i, trackInfos.at(i)); + m_document->renderer()->mltChangeTrackState(i + 1, m_document->trackInfoAt(i).isMute, m_document->trackInfoAt(i).isBlind); + } + QTimer::singleShot(300, this, SIGNAL(trackHeightChanged())); viewport()->update(); } - void CustomTrackView::slotSwitchTrackAudio(int ix) { /*for (int i = 0; i < m_document->tracksCount(); i++) @@ -2638,6 +2528,7 @@ void CustomTrackView::lockTrack(int ix, bool lock) int tracknumber = m_document->tracksCount() - ix - 1; m_document->switchTrackLock(tracknumber, lock); emit doTrackLock(ix, lock); + AbstractClipItem *clip = NULL; QList selection = m_scene->items(0, ix * m_tracksHeight + m_tracksHeight / 2, sceneRect().width(), m_tracksHeight / 2 - 2); for (int i = 0; i < selection.count(); i++) { @@ -2646,7 +2537,10 @@ void CustomTrackView::lockTrack(int ix, bool lock) if (selection.at(i)->type() == AVWIDGET) emit clipItemSelected(NULL); else emit transitionItemSelected(NULL); } - static_cast (selection.at(i))->setItemLocked(lock); + clip = static_cast (selection.at(i)); + clip->setItemLocked(lock); + if (clip == m_dragItem) + m_dragItem = NULL; } kDebug() << "NEXT TRK STATE: " << m_document->trackInfoAt(tracknumber).isLocked; viewport()->update(); @@ -2694,6 +2588,11 @@ void CustomTrackView::slotRemoveSpace() track = (int)(mapToScene(m_menuPosition).y() / m_tracksHeight); } + if (m_document->isTrackLocked(m_document->tracksCount() - track - 1)) { + emit displayMessage(i18n("Cannot remove space in a locked track"), ErrorMessage); + return; + } + ClipItem *item = getClipItemAt(pos, track); if (item) { emit displayMessage(i18n("You must be in an empty space to remove space (time: %1, track: %2)", m_document->timecode().getTimecodeFromFrames(mapToScene(m_menuPosition).x()), track), ErrorMessage); @@ -2746,22 +2645,33 @@ void CustomTrackView::slotInsertSpace() pos = GenTime((int)(mapToScene(m_menuPosition).x()), m_document->fps()); track = (int)(mapToScene(m_menuPosition).y() / m_tracksHeight) + 1; } - SpacerDialog d(GenTime(65, m_document->fps()), m_document->timecode(), track, m_document->tracksCount() + 1, this); + SpacerDialog d(GenTime(65, m_document->fps()), m_document->timecode(), track, m_document->tracksList(), this); if (d.exec() != QDialog::Accepted) return; GenTime spaceDuration = d.selectedDuration(); track = d.selectedTrack(); - ClipItem *item = getClipItemAt(pos, track); - if (item) pos = item->startPos(); + QList items; + if (track > 0) { + if (m_document->isTrackLocked(m_document->tracksCount() - track - 1)) { + emit displayMessage(i18n("Cannot insert space in a locked track"), ErrorMessage); + return; + } - // Make sure there is no group in the way - QRectF rect(pos.frames(m_document->fps()), track * m_tracksHeight + m_tracksHeight / 2, sceneRect().width() - pos.frames(m_document->fps()), m_tracksHeight / 2 - 2); - bool isOk; - QList items = checkForGroups(rect, &isOk); - if (!isOk) { - // groups found on track, do not allow the move - emit displayMessage(i18n("Cannot insert space in a track with a group"), ErrorMessage); - return; + ClipItem *item = getClipItemAt(pos, track); + if (item) pos = item->startPos(); + + // Make sure there is no group in the way + QRectF rect(pos.frames(m_document->fps()), track * m_tracksHeight + m_tracksHeight / 2, sceneRect().width() - pos.frames(m_document->fps()), m_tracksHeight / 2 - 2); + bool isOk; + items = checkForGroups(rect, &isOk); + if (!isOk) { + // groups found on track, do not allow the move + emit displayMessage(i18n("Cannot insert space in a track with a group"), ErrorMessage); + return; + } + } else { + QRectF rect(pos.frames(m_document->fps()), 0, sceneRect().width() - pos.frames(m_document->fps()), m_document->tracksCount() * m_tracksHeight); + items = scene()->items(rect); } QList clipsToMove; @@ -2771,16 +2681,17 @@ void CustomTrackView::slotInsertSpace() if (items.at(i)->type() == AVWIDGET || items.at(i)->type() == TRANSITIONWIDGET) { AbstractClipItem *item = static_cast (items.at(i)); ItemInfo info = item->info(); - if (item->type() == AVWIDGET) { + if (item->type() == AVWIDGET) clipsToMove.append(info); - } else if (item->type() == TRANSITIONWIDGET) { + else if (item->type() == TRANSITIONWIDGET) transitionsToMove.append(info); - } } } - InsertSpaceCommand *command = new InsertSpaceCommand(this, clipsToMove, transitionsToMove, track, spaceDuration, true); - m_commandStack->push(command); + if (!clipsToMove.isEmpty() || !transitionsToMove.isEmpty()) { + InsertSpaceCommand *command = new InsertSpaceCommand(this, clipsToMove, transitionsToMove, track, spaceDuration, true); + m_commandStack->push(command); + } } void CustomTrackView::insertSpace(QList clipsToMove, QList transToMove, int track, const GenTime duration, const GenTime offset) @@ -2848,7 +2759,8 @@ void CustomTrackView::insertSpace(QList clipsToMove, QList t } } resetSelectionGroup(false); - if (track != -1) track = m_document->tracksCount() - track; + if (track != -1) + track = m_document->tracksCount() - track; m_document->renderer()->mltInsertSpace(trackClipStartList, trackTransitionStartList, track, duration, offset); } @@ -3259,194 +3171,10 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) m_document->renderer()->doRefresh(); } else if (m_operationMode == RESIZESTART && m_dragItem->startPos() != m_dragItemInfo.startPos) { // resize start - if (m_dragItem->type() == AVWIDGET) { - ItemInfo resizeinfo = m_dragItemInfo; - resizeinfo.track = m_document->tracksCount() - resizeinfo.track; - bool success = m_document->renderer()->mltResizeClipStart(resizeinfo, m_dragItem->startPos() - m_dragItemInfo.startPos); - if (success) { - QUndoCommand *resizeCommand = new QUndoCommand(); - resizeCommand->setText(i18n("Resize clip")); - - // Check if there is an automatic transition on that clip (lower track) - Transition *transition = getTransitionItemAtStart(m_dragItemInfo.startPos, m_dragItemInfo.track); - if (transition && transition->isAutomatic()) { - ItemInfo trInfo = transition->info(); - ItemInfo newTrInfo = trInfo; - newTrInfo.startPos = m_dragItem->startPos(); - if (newTrInfo.startPos < newTrInfo.endPos) - new MoveTransitionCommand(this, trInfo, newTrInfo, true, resizeCommand); - } - // Check if there is an automatic transition on that clip (upper track) - transition = getTransitionItemAtStart(m_dragItemInfo.startPos, m_dragItemInfo.track - 1); - if (transition && transition->isAutomatic() && (m_document->tracksCount() - transition->transitionEndTrack()) == m_dragItemInfo.track) { - ItemInfo trInfo = transition->info(); - ItemInfo newTrInfo = trInfo; - newTrInfo.startPos = m_dragItem->startPos(); - ClipItem * upperClip = getClipItemAt(m_dragItemInfo.startPos, m_dragItemInfo.track - 1); - if ((!upperClip || !upperClip->baseClip()->isTransparent()) && newTrInfo.startPos < newTrInfo.endPos) { - new MoveTransitionCommand(this, trInfo, newTrInfo, true, resizeCommand); - } - } - - ClipItem *clip = static_cast < ClipItem * >(m_dragItem); - updatePositionEffects(clip, m_dragItemInfo); - - // check keyframes - QDomDocument doc; - QDomElement root = doc.createElement("list"); - doc.appendChild(root); - QList indexes; - for (int i = 0; i < clip->effectsCount(); i++) { - QDomElement effect = clip->effectAt(i); - if (EffectsList::hasKeyFrames(effect)) { - doc.appendChild(doc.importNode(effect, true)); - indexes.append(i); - } - } - - if (clip->checkEffectsKeyframesPos(m_dragItemInfo.cropStart.frames(m_document->fps()), clip->cropStart().frames(m_document->fps()), true)) { - // Keyframes were modified, updateClip - QDomNodeList effs = doc.elementsByTagName("effect"); - // Hack: - // Since we must always resize clip before updating the keyframes, we - // put a resize command before & after checking keyframes so that - // we are sure the resize is performed before whenever we do or undo the action - - new ResizeClipCommand(this, m_dragItemInfo, info, false, true, resizeCommand); - for (int i = 0; i < indexes.count(); i++) { - new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), effs.at(i).cloneNode().toElement(), clip->effectAt(indexes.at(i)), indexes.at(i), false, resizeCommand); - updateEffect(m_document->tracksCount() - clip->track(), clip->startPos(), clip->effectAt(indexes.at(i)), indexes.at(i)); - } - new ResizeClipCommand(this, m_dragItemInfo, info, false, true, resizeCommand); - emit clipItemSelected(clip); - } else new ResizeClipCommand(this, m_dragItemInfo, info, false, false, resizeCommand); - - m_commandStack->push(resizeCommand); - } else { - bool snap = KdenliveSettings::snaptopoints(); - KdenliveSettings::setSnaptopoints(false); - m_dragItem->resizeStart((int) m_dragItemInfo.startPos.frames(m_document->fps())); - KdenliveSettings::setSnaptopoints(snap); - emit displayMessage(i18n("Error when resizing clip"), ErrorMessage); - } - } else if (m_dragItem->type() == TRANSITIONWIDGET) { - Transition *transition = static_cast (m_dragItem); - if (!m_document->renderer()->mltMoveTransition(transition->transitionTag(), (int)(m_document->tracksCount() - m_dragItemInfo.track), (int)(m_document->tracksCount() - m_dragItemInfo.track), transition->transitionEndTrack(), m_dragItemInfo.startPos, m_dragItemInfo.endPos, info.startPos, info.endPos)) { - // Cannot resize transition - bool snap = KdenliveSettings::snaptopoints(); - KdenliveSettings::setSnaptopoints(false); - transition->resizeStart((int) m_dragItemInfo.startPos.frames(m_document->fps())); - KdenliveSettings::setSnaptopoints(snap); - emit displayMessage(i18n("Cannot resize transition"), ErrorMessage); - } else { - MoveTransitionCommand *command = new MoveTransitionCommand(this, m_dragItemInfo, info, false); - m_commandStack->push(command); - } - - } - if (m_dragItem->parentItem() && m_dragItem->parentItem() != m_selectionGroup) { - // Item was resized, rebuild group; - AbstractGroupItem *group = static_cast (m_dragItem->parentItem()); - QList children = group->childItems(); - m_document->clipManager()->removeGroup(group); - scene()->destroyItemGroup(group); - for (int i = 0; i < children.count(); i++) { - children.at(i)->setSelected(true); - } - groupSelectedItems(false, true); - } - //m_document->renderer()->doRefresh(); + prepareResizeClipStart(m_dragItem, m_dragItemInfo, m_dragItem->startPos().frames(m_document->fps())); } else if (m_operationMode == RESIZEEND && m_dragItem->endPos() != m_dragItemInfo.endPos) { // resize end - if (m_dragItem->type() == AVWIDGET) { - ItemInfo resizeinfo = info; - resizeinfo.track = m_document->tracksCount() - resizeinfo.track; - bool success = m_document->renderer()->mltResizeClipEnd(resizeinfo, resizeinfo.endPos - resizeinfo.startPos); - if (success) { - QUndoCommand *resizeCommand = new QUndoCommand(); - resizeCommand->setText(i18n("Resize clip")); - - // Check if there is an automatic transition on that clip (lower track) - Transition *tr = getTransitionItemAtEnd(m_dragItemInfo.endPos, m_dragItemInfo.track); - if (tr && tr->isAutomatic()) { - ItemInfo trInfo = tr->info(); - ItemInfo newTrInfo = trInfo; - newTrInfo.endPos = m_dragItem->endPos(); - if (newTrInfo.endPos > newTrInfo.startPos) new MoveTransitionCommand(this, trInfo, newTrInfo, true, resizeCommand); - } - - // Check if there is an automatic transition on that clip (upper track) - tr = getTransitionItemAtEnd(m_dragItemInfo.endPos, m_dragItemInfo.track - 1); - if (tr && tr->isAutomatic() && (m_document->tracksCount() - tr->transitionEndTrack()) == m_dragItemInfo.track) { - ItemInfo trInfo = tr->info(); - ItemInfo newTrInfo = trInfo; - newTrInfo.endPos = m_dragItem->endPos(); - ClipItem * upperClip = getClipItemAtEnd(m_dragItemInfo.endPos, m_dragItemInfo.track - 1); - if ((!upperClip || !upperClip->baseClip()->isTransparent()) && newTrInfo.endPos > newTrInfo.startPos) { - new MoveTransitionCommand(this, trInfo, newTrInfo, true, resizeCommand); - } - } - - // check keyframes - ClipItem *clip = static_cast < ClipItem * >(m_dragItem); - QDomDocument doc; - QDomElement root = doc.createElement("list"); - doc.appendChild(root); - QList indexes; - for (int i = 0; i < clip->effectsCount(); i++) { - QDomElement effect = clip->effectAt(i); - if (EffectsList::hasKeyFrames(effect)) { - doc.appendChild(doc.importNode(effect, true)); - indexes.append(i); - } - } - - if (clip->checkEffectsKeyframesPos((m_dragItemInfo.cropStart + m_dragItemInfo.endPos - m_dragItemInfo.startPos).frames(m_document->fps()) - 1, (clip->cropStart() + clip->cropDuration()).frames(m_document->fps()) - 1, false)) { - // Keyframes were modified, updateClip - QDomNodeList effs = doc.elementsByTagName("effect"); - // Hack: - // Since we must always resize clip before updating the keyframes, we - // put a resize command before & after checking keyframes so that - // we are sure the resize is performed before whenever we do or undo the action - - new ResizeClipCommand(this, m_dragItemInfo, info, false, true, resizeCommand); - for (int i = 0; i < indexes.count(); i++) { - new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), effs.at(i).cloneNode().toElement(), clip->effectAt(indexes.at(i)), indexes.at(i), false, resizeCommand); - updateEffect(m_document->tracksCount() - clip->track(), clip->startPos(), clip->effectAt(indexes.at(i)), indexes.at(i)); - } - new ResizeClipCommand(this, m_dragItemInfo, info, false, true, resizeCommand); - emit clipItemSelected(clip); - } else new ResizeClipCommand(this, m_dragItemInfo, info, false, false, resizeCommand); - - m_commandStack->push(resizeCommand); - updatePositionEffects(clip, m_dragItemInfo); - } else { - m_dragItem->resizeEnd((int) m_dragItemInfo.endPos.frames(m_document->fps())); - emit displayMessage(i18n("Error when resizing clip"), ErrorMessage); - } - } else if (m_dragItem->type() == TRANSITIONWIDGET) { - Transition *transition = static_cast (m_dragItem); - if (!m_document->renderer()->mltMoveTransition(transition->transitionTag(), (int)(m_document->tracksCount() - m_dragItemInfo.track), (int)(m_document->tracksCount() - m_dragItemInfo.track), transition->transitionEndTrack(), m_dragItemInfo.startPos, m_dragItemInfo.endPos, info.startPos, info.endPos)) { - // Cannot resize transition - transition->resizeEnd((int) m_dragItemInfo.endPos.frames(m_document->fps())); - emit displayMessage(i18n("Cannot resize transition"), ErrorMessage); - } else { - MoveTransitionCommand *command = new MoveTransitionCommand(this, m_dragItemInfo, info, false); - m_commandStack->push(command); - } - } - if (m_dragItem->parentItem() && m_dragItem->parentItem() != m_selectionGroup) { - // Item was resized, rebuild group; - AbstractGroupItem *group = static_cast (m_dragItem->parentItem()); - QList children = group->childItems(); - m_document->clipManager()->removeGroup(group); - scene()->destroyItemGroup(group); - for (int i = 0; i < children.count(); i++) { - children.at(i)->setSelected(true); - } - groupSelectedItems(false, true); - } - //m_document->renderer()->doRefresh(); + prepareResizeClipEnd(m_dragItem, m_dragItemInfo, m_dragItem->endPos().frames(m_document->fps())); } else if (m_operationMode == FADEIN) { // resize fade in effect ClipItem * item = static_cast (m_dragItem); @@ -3548,11 +3276,14 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) val = (br.bottom() - val) * maxh; int start = item->cropStart().frames(m_document->fps()); int end = (item->cropStart() + item->cropDuration()).frames(m_document->fps()) - 1; + if ((val < -50 || val > 150) && item->editedKeyFramePos() != start && item->editedKeyFramePos() != end) { //delete keyframe - kDebug() << "// DELETE KFR: " << item->editedKeyFramePos(); item->movedKeyframe(item->getEffectAt(item->selectedEffectIndex()), item->selectedKeyFramePos(), -1, 0); - } else item->movedKeyframe(item->getEffectAt(item->selectedEffectIndex()), item->selectedKeyFramePos(), item->editedKeyFramePos(), item->editedKeyFrameValue()); + } else { + item->movedKeyframe(item->getEffectAt(item->selectedEffectIndex()), item->selectedKeyFramePos(), item->editedKeyFramePos(), item->editedKeyFrameValue()); + } + QDomElement newEffect = item->selectedEffect().cloneNode().toElement(); //item->updateKeyframeEffect(); //QString next = item->keyframes(item->selectedEffectIndex()); @@ -3642,7 +3373,6 @@ void CustomTrackView::deleteSelectedClips() if (itemList.at(i)->type() == GROUPWIDGET) { groupCount++; QList children = itemList.at(i)->childItems(); - itemList += children; QList clipInfos; QList transitionInfos; GenTime currentPos = GenTime(m_cursorPos, m_document->fps()); @@ -3654,11 +3384,17 @@ void CustomTrackView::deleteSelectedClips() AbstractClipItem *clip = static_cast (children.at(j)); if (!clip->isItemLocked()) transitionInfos.append(clip->info()); } + if (itemList.contains(children.at(j))) { + children.removeAt(j); + j--; + } } - if (clipInfos.count() > 0) { + itemList += children; + if (clipInfos.count() > 0) new GroupClipsCommand(this, clipInfos, transitionInfos, false, deleteSelected); - } - } + + } else if (itemList.at(i)->parentItem() && itemList.at(i)->parentItem()->type() == GROUPWIDGET) + itemList.insert(i + 1, itemList.at(i)->parentItem()); } for (int i = 0; i < itemList.count(); i++) { @@ -4249,6 +3985,216 @@ void CustomTrackView::resizeClip(const ItemInfo start, const ItemInfo end, bool setDocumentModified(); } +void CustomTrackView::prepareResizeClipStart(AbstractClipItem* item, ItemInfo oldInfo, int pos, bool check) +{ + if (pos == oldInfo.startPos.frames(m_document->fps())) + return; + bool snap = KdenliveSettings::snaptopoints(); + if (check) { + KdenliveSettings::setSnaptopoints(false); + item->resizeStart(pos); + if (item->startPos().frames(m_document->fps()) != pos) { + item->resizeStart(oldInfo.startPos.frames(m_document->fps())); + emit displayMessage(i18n("Not possible to resize"), ErrorMessage); + KdenliveSettings::setSnaptopoints(snap); + return; + } + KdenliveSettings::setSnaptopoints(snap); + } + ItemInfo info = item->info(); + if (item->type() == AVWIDGET) { + ItemInfo resizeinfo = oldInfo; + resizeinfo.track = m_document->tracksCount() - resizeinfo.track; + bool success = m_document->renderer()->mltResizeClipStart(resizeinfo, item->startPos() - oldInfo.startPos); + if (success) { + QUndoCommand *resizeCommand = new QUndoCommand(); + resizeCommand->setText(i18n("Resize clip")); + + // Check if there is an automatic transition on that clip (lower track) + Transition *transition = getTransitionItemAtStart(oldInfo.startPos, oldInfo.track); + if (transition && transition->isAutomatic()) { + ItemInfo trInfo = transition->info(); + ItemInfo newTrInfo = trInfo; + newTrInfo.startPos = item->startPos(); + if (newTrInfo.startPos < newTrInfo.endPos) + new MoveTransitionCommand(this, trInfo, newTrInfo, true, resizeCommand); + } + // Check if there is an automatic transition on that clip (upper track) + transition = getTransitionItemAtStart(oldInfo.startPos, oldInfo.track - 1); + if (transition && transition->isAutomatic() && (m_document->tracksCount() - transition->transitionEndTrack()) == oldInfo.track) { + ItemInfo trInfo = transition->info(); + ItemInfo newTrInfo = trInfo; + newTrInfo.startPos = item->startPos(); + ClipItem * upperClip = getClipItemAt(oldInfo.startPos, oldInfo.track - 1); + if ((!upperClip || !upperClip->baseClip()->isTransparent()) && newTrInfo.startPos < newTrInfo.endPos) + new MoveTransitionCommand(this, trInfo, newTrInfo, true, resizeCommand); + } + + ClipItem *clip = static_cast < ClipItem * >(item); + updatePositionEffects(clip, oldInfo); + + // check keyframes + QDomDocument doc; + QDomElement root = doc.createElement("list"); + doc.appendChild(root); + QList indexes; + for (int i = 0; i < clip->effectsCount(); i++) { + QDomElement effect = clip->effectAt(i); + if (EffectsList::hasKeyFrames(effect)) { + doc.appendChild(doc.importNode(effect, true)); + indexes.append(i); + } + } + + if (clip->checkEffectsKeyframesPos(oldInfo.cropStart.frames(m_document->fps()), clip->cropStart().frames(m_document->fps()), true)) { + // Keyframes were modified, updateClip + QDomNodeList effs = doc.elementsByTagName("effect"); + // Hack: + // Since we must always resize clip before updating the keyframes, we + // put a resize command before & after checking keyframes so that + // we are sure the resize is performed before whenever we do or undo the action + + new ResizeClipCommand(this, oldInfo, info, false, true, resizeCommand); + for (int i = 0; i < indexes.count(); i++) { + new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), effs.at(i).cloneNode().toElement(), clip->effectAt(indexes.at(i)), indexes.at(i), false, resizeCommand); + updateEffect(m_document->tracksCount() - clip->track(), clip->startPos(), clip->effectAt(indexes.at(i)), indexes.at(i)); + } + new ResizeClipCommand(this, oldInfo, info, false, true, resizeCommand); + emit clipItemSelected(clip); + } else { + new ResizeClipCommand(this, oldInfo, info, false, false, resizeCommand); + } + + m_commandStack->push(resizeCommand); + } else { + KdenliveSettings::setSnaptopoints(false); + item->resizeStart((int) oldInfo.startPos.frames(m_document->fps())); + KdenliveSettings::setSnaptopoints(snap); + emit displayMessage(i18n("Error when resizing clip"), ErrorMessage); + } + } else if (item->type() == TRANSITIONWIDGET) { + Transition *transition = static_cast (item); + if (!m_document->renderer()->mltMoveTransition(transition->transitionTag(), (int)(m_document->tracksCount() - oldInfo.track), (int)(m_document->tracksCount() - oldInfo.track), transition->transitionEndTrack(), oldInfo.startPos, oldInfo.endPos, info.startPos, info.endPos)) { + // Cannot resize transition + KdenliveSettings::setSnaptopoints(false); + transition->resizeStart((int) oldInfo.startPos.frames(m_document->fps())); + KdenliveSettings::setSnaptopoints(snap); + emit displayMessage(i18n("Cannot resize transition"), ErrorMessage); + } else { + MoveTransitionCommand *command = new MoveTransitionCommand(this, oldInfo, info, false); + m_commandStack->push(command); + } + + } + if (item->parentItem() && item->parentItem() != m_selectionGroup) + rebuildGroup(static_cast (item->parentItem())); +} + +void CustomTrackView::prepareResizeClipEnd(AbstractClipItem* item, ItemInfo oldInfo, int pos, bool check) +{ + if (pos == oldInfo.endPos.frames(m_document->fps())) + return; + bool snap = KdenliveSettings::snaptopoints(); + if (check) { + KdenliveSettings::setSnaptopoints(false); + item->resizeEnd(pos); + if (item->endPos().frames(m_document->fps()) != pos) { + item->resizeEnd(oldInfo.endPos.frames(m_document->fps())); + emit displayMessage(i18n("Not possible to resize"), ErrorMessage); + KdenliveSettings::setSnaptopoints(snap); + return; + } + KdenliveSettings::setSnaptopoints(snap); + } + ItemInfo info = item->info(); + if (item->type() == AVWIDGET) { + ItemInfo resizeinfo = info; + resizeinfo.track = m_document->tracksCount() - resizeinfo.track; + bool success = m_document->renderer()->mltResizeClipEnd(resizeinfo, resizeinfo.endPos - resizeinfo.startPos); + if (success) { + QUndoCommand *resizeCommand = new QUndoCommand(); + resizeCommand->setText(i18n("Resize clip")); + + // Check if there is an automatic transition on that clip (lower track) + Transition *tr = getTransitionItemAtEnd(oldInfo.endPos, oldInfo.track); + if (tr && tr->isAutomatic()) { + ItemInfo trInfo = tr->info(); + ItemInfo newTrInfo = trInfo; + newTrInfo.endPos = item->endPos(); + if (newTrInfo.endPos > newTrInfo.startPos) + new MoveTransitionCommand(this, trInfo, newTrInfo, true, resizeCommand); + } + + // Check if there is an automatic transition on that clip (upper track) + tr = getTransitionItemAtEnd(oldInfo.endPos, oldInfo.track - 1); + if (tr && tr->isAutomatic() && (m_document->tracksCount() - tr->transitionEndTrack()) == oldInfo.track) { + ItemInfo trInfo = tr->info(); + ItemInfo newTrInfo = trInfo; + newTrInfo.endPos = item->endPos(); + ClipItem * upperClip = getClipItemAtEnd(oldInfo.endPos, oldInfo.track - 1); + if ((!upperClip || !upperClip->baseClip()->isTransparent()) && newTrInfo.endPos > newTrInfo.startPos) + new MoveTransitionCommand(this, trInfo, newTrInfo, true, resizeCommand); + + } + + // check keyframes + ClipItem *clip = static_cast < ClipItem * >(item); + QDomDocument doc; + QDomElement root = doc.createElement("list"); + doc.appendChild(root); + QList indexes; + for (int i = 0; i < clip->effectsCount(); i++) { + QDomElement effect = clip->effectAt(i); + if (EffectsList::hasKeyFrames(effect)) { + doc.appendChild(doc.importNode(effect, true)); + indexes.append(i); + } + } + + if (clip->checkEffectsKeyframesPos((oldInfo.cropStart + oldInfo.endPos - oldInfo.startPos).frames(m_document->fps()) - 1, (clip->cropStart() + clip->cropDuration()).frames(m_document->fps()) - 1, false)) { + // Keyframes were modified, updateClip + QDomNodeList effs = doc.elementsByTagName("effect"); + // Hack: + // Since we must always resize clip before updating the keyframes, we + // put a resize command before & after checking keyframes so that + // we are sure the resize is performed before whenever we do or undo the action + + new ResizeClipCommand(this, oldInfo, info, false, true, resizeCommand); + for (int i = 0; i < indexes.count(); i++) { + new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), effs.at(i).cloneNode().toElement(), clip->effectAt(indexes.at(i)), indexes.at(i), false, resizeCommand); + updateEffect(m_document->tracksCount() - clip->track(), clip->startPos(), clip->effectAt(indexes.at(i)), indexes.at(i)); + } + new ResizeClipCommand(this, oldInfo, info, false, true, resizeCommand); + emit clipItemSelected(clip); + } else { + new ResizeClipCommand(this, oldInfo, info, false, false, resizeCommand); + } + + m_commandStack->push(resizeCommand); + updatePositionEffects(clip, oldInfo); + } else { + KdenliveSettings::setSnaptopoints(false); + item->resizeEnd((int) oldInfo.endPos.frames(m_document->fps())); + KdenliveSettings::setSnaptopoints(true); + emit displayMessage(i18n("Error when resizing clip"), ErrorMessage); + } + } else if (item->type() == TRANSITIONWIDGET) { + Transition *transition = static_cast (item); + if (!m_document->renderer()->mltMoveTransition(transition->transitionTag(), (int)(m_document->tracksCount() - oldInfo.track), (int)(m_document->tracksCount() - oldInfo.track), transition->transitionEndTrack(), oldInfo.startPos, oldInfo.endPos, info.startPos, info.endPos)) { + // Cannot resize transition + KdenliveSettings::setSnaptopoints(false); + transition->resizeEnd((int) oldInfo.endPos.frames(m_document->fps())); + KdenliveSettings::setSnaptopoints(true); + emit displayMessage(i18n("Cannot resize transition"), ErrorMessage); + } else { + MoveTransitionCommand *command = new MoveTransitionCommand(this, oldInfo, info, false); + m_commandStack->push(command); + } + } + if (item->parentItem() && item->parentItem() != m_selectionGroup) + rebuildGroup(static_cast (item->parentItem())); +} + void CustomTrackView::updatePositionEffects(ClipItem * item, ItemInfo info) { int end = item->fadeIn(); @@ -4345,6 +4291,23 @@ void CustomTrackView::updatePositionEffects(ClipItem * item, ItemInfo info) } } } + + effectPos = item->hasEffect("affine", "pan_zoom"); + if (effectPos != -1) { + QDomElement oldeffect = item->effectAt(effectPos); + int start = item->cropStart().frames(m_document->fps()); + int max = start + item->cropDuration().frames(m_document->fps()); + if (start < 0) { + max -= start; + start = 0; + } + oldeffect.setAttribute("in", start); + oldeffect.setAttribute("out", max); + if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - item->track(), item->startPos(), item->getEffectArgs(oldeffect))) + emit displayMessage(i18n("Problem editing effect"), ErrorMessage); + // if effect is displayed, update the effect edit widget with new clip duration + if (item->isSelected() && effectPos == item->selectedEffectIndex()) emit clipItemSelected(item, effectPos); + } } double CustomTrackView::getSnapPointForPos(double pos) @@ -4658,14 +4621,7 @@ void CustomTrackView::setScale(double scaleFactor, double verticalScale) QMatrix newmatrix; newmatrix = newmatrix.scale(scaleFactor, verticalScale); m_scene->setScale(scaleFactor, verticalScale); - if (m_visualTip) { - scene()->removeItem(m_visualTip); - m_animationTimer->stop(); - delete m_animation; - m_animation = NULL; - delete m_visualTip; - m_visualTip = NULL; - } + removeTipAnimation(); double verticalPos = mapToScene(QPoint(0, viewport()->height() / 2)).y(); bool adjust = false; if (verticalScale != matrix().m22()) adjust = true; @@ -4683,8 +4639,10 @@ void CustomTrackView::setScale(double scaleFactor, double verticalScale) int diff = sceneRect().width() - m_projectDuration; if (diff * newmatrix.m11() < 50) { - if (newmatrix.m11() < 0.4) setSceneRect(0, 0, (m_projectDuration + 100 / newmatrix.m11()), sceneRect().height()); - else setSceneRect(0, 0, (m_projectDuration + 300), sceneRect().height()); + if (newmatrix.m11() < 0.4) + setSceneRect(0, 0, (m_projectDuration + 100 / newmatrix.m11()), sceneRect().height()); + else + setSceneRect(0, 0, (m_projectDuration + 300), sceneRect().height()); } centerOn(QPointF(cursorPos(), verticalPos)); } @@ -4692,9 +4650,8 @@ void CustomTrackView::setScale(double scaleFactor, double verticalScale) void CustomTrackView::slotRefreshGuides() { if (KdenliveSettings::showmarkers()) { - for (int i = 0; i < m_guides.count(); i++) { + for (int i = 0; i < m_guides.count(); i++) m_guides.at(i)->update(); - } } } @@ -4717,8 +4674,10 @@ void CustomTrackView::drawBackground(QPainter * painter, const QRectF &rect) TrackInfo info = m_document->trackInfoAt(maxTrack - i - 1); if (info.isLocked || info.type == AUDIOTRACK || i == m_selectedTrack) { const QRectF track(min, m_tracksHeight * i + 1, max - min, m_tracksHeight - 1); - if (i == m_selectedTrack) painter->fillRect(track, scheme.background(KColorScheme::ActiveBackground).color()); - else painter->fillRect(track, info.isLocked ? lockedColor : audioColor); + if (i == m_selectedTrack) + painter->fillRect(track, scheme.background(KColorScheme::ActiveBackground).color()); + else + painter->fillRect(track, info.isLocked ? lockedColor : audioColor); } painter->drawLine(QPointF(min, m_tracksHeight *(i + 1)), QPointF(max, m_tracksHeight *(i + 1))); } @@ -4792,9 +4751,8 @@ void CustomTrackView::initSearchStrings() } // add guides - for (int i = 0; i < m_guides.count(); i++) { + for (int i = 0; i < m_guides.count(); i++) m_searchPoints.append(m_guides.at(i)->info()); - } qSort(m_searchPoints); } @@ -4812,9 +4770,8 @@ QList CustomTrackView::findId(const QString &clipId) for (int i = 0; i < itemList.count(); i++) { if (itemList.at(i)->type() == AVWIDGET) { ClipItem *item = (ClipItem *)itemList.at(i); - if (item->clipProducer() == clipId) { + if (item->clipProducer() == clipId) matchingInfo << item->info(); - } } } return matchingInfo; @@ -5122,24 +5079,7 @@ void CustomTrackView::setInPoint() return; } } - ItemInfo startInfo = clip->info(); - ItemInfo endInfo = startInfo; - endInfo.startPos = GenTime(m_cursorPos, m_document->fps()); - if (endInfo.startPos >= startInfo.endPos || endInfo.startPos < startInfo.startPos - startInfo.cropStart) { - // Check for invalid resize - emit displayMessage(i18n("Invalid action"), ErrorMessage); - return; - } else if (endInfo.startPos < startInfo.startPos) { - int length = m_document->renderer()->mltGetSpaceLength(endInfo.startPos, m_document->tracksCount() - startInfo.track, false); - if ((clip->type() == TRANSITIONWIDGET && itemCollision(clip, endInfo) == true) || ( - (clip->type() == AVWIDGET) && length < (startInfo.startPos - endInfo.startPos).frames(m_document->fps()))) { - emit displayMessage(i18n("Invalid action"), ErrorMessage); - return; - } - } - if (clip->type() == TRANSITIONWIDGET) { - m_commandStack->push(new MoveTransitionCommand(this, startInfo, endInfo, true)); - } else m_commandStack->push(new ResizeClipCommand(this, startInfo, endInfo, true, false)); + prepareResizeClipStart(clip, clip->info(), m_cursorPos, true); } void CustomTrackView::setOutPoint() @@ -5153,27 +5093,7 @@ void CustomTrackView::setOutPoint() return; } } - ItemInfo startInfo = clip->info(); - ItemInfo endInfo = clip->info(); - endInfo.endPos = GenTime(m_cursorPos, m_document->fps()); - CLIPTYPE type = (CLIPTYPE) static_cast (clip)->clipType(); - if (endInfo.endPos <= startInfo.startPos || (type != IMAGE && type != COLOR && type != TEXT && endInfo.endPos > startInfo.startPos + clip->maxDuration() - startInfo.cropStart)) { - // Check for invalid resize - emit displayMessage(i18n("Invalid action"), ErrorMessage); - return; - } else if (endInfo.endPos > startInfo.endPos) { - int length = m_document->renderer()->mltGetSpaceLength(startInfo.endPos, m_document->tracksCount() - startInfo.track, false); - if ((clip->type() == TRANSITIONWIDGET && itemCollision(clip, endInfo) == true) || (clip->type() == AVWIDGET && length != -1 && length < (endInfo.endPos - startInfo.endPos).frames(m_document->fps()))) { - kDebug() << " RESIZE ERROR, BLNK: " << length << ", RESIZE: " << (endInfo.endPos - startInfo.endPos).frames(m_document->fps()); - emit displayMessage(i18n("Invalid action"), ErrorMessage); - return; - } - } - - - if (clip->type() == TRANSITIONWIDGET) { - m_commandStack->push(new MoveTransitionCommand(this, startInfo, endInfo, true)); - } else m_commandStack->push(new ResizeClipCommand(this, startInfo, endInfo, true, false)); + prepareResizeClipEnd(clip, clip->info(), m_cursorPos, true); } void CustomTrackView::slotUpdateAllThumbs() @@ -5258,28 +5178,23 @@ void CustomTrackView::saveThumbnails() void CustomTrackView::slotInsertTrack(int ix) { TrackDialog d(m_document, parentWidget()); + d.comboTracks->setCurrentIndex(ix); d.label->setText(i18n("Insert track")); - d.track_nb->setMaximum(m_document->tracksCount() - 1); - d.track_nb->setValue(ix); d.setWindowTitle(i18n("Insert New Track")); - d.slotUpdateName(ix); if (d.exec() == QDialog::Accepted) { - ix = d.track_nb->value(); - if (d.before_select->currentIndex() == 1) { + ix = d.comboTracks->currentIndex(); + if (d.before_select->currentIndex() == 1) ix++; - } TrackInfo info; + info.isMute = false; + info.isLocked = false; if (d.video_track->isChecked()) { info.type = VIDEOTRACK; - info.isMute = false; info.isBlind = false; - info.isLocked = false; } else { info.type = AUDIOTRACK; - info.isMute = false; info.isBlind = true; - info.isLocked = false; } AddTrackCommand *addTrack = new AddTrackCommand(this, ix, info, true); m_commandStack->push(addTrack); @@ -5289,17 +5204,16 @@ void CustomTrackView::slotInsertTrack(int ix) void CustomTrackView::slotDeleteTrack(int ix) { + if (m_document->tracksCount() < 2) return; TrackDialog d(m_document, parentWidget()); + d.comboTracks->setCurrentIndex(ix); d.label->setText(i18n("Delete track")); d.before_select->setHidden(true); - d.track_nb->setMaximum(m_document->tracksCount() - 1); - d.track_nb->setValue(ix); - d.slotUpdateName(ix); d.setWindowTitle(i18n("Delete Track")); d.video_track->setHidden(true); d.audio_track->setHidden(true); if (d.exec() == QDialog::Accepted) { - ix = d.track_nb->value(); + ix = d.comboTracks->currentIndex(); TrackInfo info = m_document->trackInfoAt(m_document->tracksCount() - ix - 1); deleteTimelineTrack(ix, info); setDocumentModified(); @@ -5308,44 +5222,24 @@ void CustomTrackView::slotDeleteTrack(int ix) } } -void CustomTrackView::slotChangeTrack(int ix) +void CustomTrackView::slotConfigTracks(int ix) { - TrackDialog d(m_document, parentWidget()); - d.label->setText(i18n("Change track")); - d.before_select->setHidden(true); - d.track_nb->setMaximum(m_document->tracksCount() - 1); - d.track_nb->setValue(ix); - d.slotUpdateName(ix); - d.setWindowTitle(i18n("Change Track Type")); - - TrackInfo oldInfo = m_document->trackInfoAt(m_document->tracksCount() - ix - 1); - if (oldInfo.type == VIDEOTRACK) - d.video_track->setChecked(true); - else - d.audio_track->setChecked(true); - + TracksConfigDialog d(m_document, ix, parentWidget()); if (d.exec() == QDialog::Accepted) { - TrackInfo info; - info.isLocked = false; - info.isMute = false; - info.trackName = oldInfo.trackName; - ix = d.track_nb->value(); - - if (d.video_track->isChecked()) { - info.type = VIDEOTRACK; - info.isBlind = false; - } else { - info.type = AUDIOTRACK; - info.isBlind = true; + ConfigTracksCommand *configTracks = new ConfigTracksCommand(this, m_document->tracksList(), d.tracksList()); + m_commandStack->push(configTracks); + QList toDelete = d.deletedTracks(); + for (int i = 0; i < toDelete.count(); ++i) { + TrackInfo info = m_document->trackInfoAt(m_document->tracksCount() - toDelete.at(i) + i - 1); + deleteTimelineTrack(toDelete.at(i) - i, info); } - changeTimelineTrack(ix, info); setDocumentModified(); } } - void CustomTrackView::deleteTimelineTrack(int ix, TrackInfo trackinfo) { + if (m_document->tracksCount() < 2) return; double startY = ix * m_tracksHeight + 1 + m_tracksHeight / 2; QRectF r(0, startY, sceneRect().width(), m_tracksHeight / 2 - 1); QList selection = m_scene->items(r); @@ -5373,13 +5267,6 @@ void CustomTrackView::deleteTimelineTrack(int ix, TrackInfo trackinfo) m_commandStack->push(deleteTrack); } -void CustomTrackView::changeTimelineTrack(int ix, TrackInfo trackinfo) -{ - TrackInfo oldinfo = m_document->trackInfoAt(m_document->tracksCount() - ix - 1); - ChangeTrackCommand *changeTrack = new ChangeTrackCommand(this, ix, oldinfo, trackinfo); - m_commandStack->push(changeTrack); -} - void CustomTrackView::autoTransition() { QList itemList = scene()->selectedItems(); @@ -5460,7 +5347,6 @@ void CustomTrackView::getTransitionAvailableSpace(AbstractClipItem *item, GenTim } } - void CustomTrackView::loadGroups(const QDomNodeList groups) { for (int i = 0; i < groups.count(); i++) { @@ -5488,7 +5374,7 @@ void CustomTrackView::splitAudio() resetSelectionGroup(); QList selection = scene()->selectedItems(); if (selection.isEmpty()) { - emit displayMessage(i18n("You must select one clip for this action"), ErrorMessage); + emit displayMessage(i18n("You must select at least one clip for this action"), ErrorMessage); return; } QUndoCommand *splitCommand = new QUndoCommand(); @@ -5505,7 +5391,8 @@ void CustomTrackView::splitAudio() } } } - m_commandStack->push(splitCommand); + if (splitCommand->childCount() > 0) + m_commandStack->push(splitCommand); } void CustomTrackView::doSplitAudio(const GenTime &pos, int track, bool split) @@ -5520,7 +5407,7 @@ void CustomTrackView::doSplitAudio(const GenTime &pos, int track, bool split) int freetrack = m_document->tracksCount() - track - 1; for (; freetrack > 0; freetrack--) { kDebug() << "// CHK DOC TRK:" << freetrack << ", DUR:" << m_document->renderer()->mltTrackDuration(freetrack); - if (m_document->trackInfoAt(freetrack - 1).type == AUDIOTRACK) { + if (m_document->trackInfoAt(freetrack - 1).type == AUDIOTRACK && !m_document->trackInfoAt(freetrack - 1).isLocked) { kDebug() << "// CHK DOC TRK:" << freetrack << ", DUR:" << m_document->renderer()->mltTrackDuration(freetrack); if (m_document->renderer()->mltTrackDuration(freetrack) < start || m_document->renderer()->mltGetSpaceLength(pos, freetrack, false) >= clip->cropDuration().frames(m_document->fps())) { kDebug() << "FOUND SPACE ON TRK: " << freetrack; @@ -5874,9 +5761,13 @@ void CustomTrackView::slotSelectTrack(int ix) viewport()->update(); } -void CustomTrackView::selectClip(bool add, bool group) +void CustomTrackView::selectClip(bool add, bool group, int track, int pos) { - QRectF rect(m_cursorPos, m_selectedTrack * m_tracksHeight + m_tracksHeight / 2, 1, 1); + QRectF rect; + if (track != -1 && pos != -1) + rect = QRectF(pos, track * m_tracksHeight + m_tracksHeight / 2, 1, 1); + else + rect = QRectF(m_cursorPos, m_selectedTrack * m_tracksHeight + m_tracksHeight / 2, 1, 1); QList selection = m_scene->items(rect); resetSelectionGroup(group); if (!group) m_scene->clearSelection(); @@ -5963,6 +5854,11 @@ void CustomTrackView::insertZoneOverwrite(QStringList data, int in) adjustTimelineClips(OVERWRITEEDIT, NULL, info, addCommand); new AddTimelineClipCommand(this, clip->toXML(), clip->getId(), info, EffectsList(), true, false, true, false, addCommand); m_commandStack->push(addCommand); + + selectClip(true, false, m_selectedTrack, in); + // Automatic audio split + if (KdenliveSettings::splitaudio()) + splitAudio(); } void CustomTrackView::clearSelection() @@ -5973,3 +5869,98 @@ void CustomTrackView::clearSelection() emit clipItemSelected(NULL); } +void CustomTrackView::updatePalette() +{ + if (m_cursorLine) { + QPen pen1 = QPen(); + pen1.setWidth(1); + pen1.setColor(palette().text().color()); + m_cursorLine->setPen(pen1); + } +} + +void CustomTrackView::removeTipAnimation() +{ + if (m_visualTip) { + scene()->removeItem(m_visualTip); + m_animationTimer->stop(); + delete m_animation; + m_animation = NULL; + delete m_visualTip; + m_visualTip = NULL; + } +} + +void CustomTrackView::setTipAnimation(AbstractClipItem *clip, OPERATIONTYPE mode, const double size) +{ + if (m_visualTip == NULL) { + QRectF rect = clip->sceneBoundingRect(); + m_animation = new QGraphicsItemAnimation; + m_animation->setTimeLine(m_animationTimer); + m_animation->setScaleAt(1, 1, 1); + QPolygon polygon; + switch (mode) { + case FADEIN: + case FADEOUT: + m_visualTip = new QGraphicsEllipseItem(-size, -size, size * 2, size * 2); + ((QGraphicsEllipseItem*) m_visualTip)->setBrush(m_tipColor); + ((QGraphicsEllipseItem*) m_visualTip)->setPen(m_tipPen); + if (mode == FADEIN) + m_visualTip->setPos(rect.x() + ((ClipItem *) clip)->fadeIn(), rect.y()); + else + m_visualTip->setPos(rect.right() - ((ClipItem *) clip)->fadeOut(), rect.y()); + + m_animation->setScaleAt(.5, 2, 2); + break; + case RESIZESTART: + case RESIZEEND: + polygon << QPoint(0, - size * 2); + if (mode == RESIZESTART) + polygon << QPoint(size * 2, 0); + else + polygon << QPoint(- size * 2, 0); + polygon << QPoint(0, size * 2); + polygon << QPoint(0, - size * 2); + + m_visualTip = new QGraphicsPolygonItem(polygon); + ((QGraphicsPolygonItem*) m_visualTip)->setBrush(m_tipColor); + ((QGraphicsPolygonItem*) m_visualTip)->setPen(m_tipPen); + if (mode == RESIZESTART) + m_visualTip->setPos(rect.x(), rect.y() + rect.height() / 2); + else + m_visualTip->setPos(rect.right(), rect.y() + rect.height() / 2); + + m_animation->setScaleAt(.5, 2, 1); + break; + case TRANSITIONSTART: + case TRANSITIONEND: + polygon << QPoint(0, - size * 2); + if (mode == TRANSITIONSTART) + polygon << QPoint(size * 2, 0); + else + polygon << QPoint(- size * 2, 0); + polygon << QPoint(0, 0); + polygon << QPoint(0, - size * 2); + + m_visualTip = new QGraphicsPolygonItem(polygon); + ((QGraphicsPolygonItem*) m_visualTip)->setBrush(m_tipColor); + ((QGraphicsPolygonItem*) m_visualTip)->setPen(m_tipPen); + if (mode == TRANSITIONSTART) + m_visualTip->setPos(rect.x(), rect.bottom()); + else + m_visualTip->setPos(rect.right(), rect.bottom()); + + m_animation->setScaleAt(.5, 2, 2); + break; + default: + delete m_animation; + return; + } + + m_visualTip->setFlags(QGraphicsItem::ItemIgnoresTransformations); + m_visualTip->setZValue(100); + scene()->addItem(m_visualTip); + m_animation->setItem(m_visualTip); + m_animationTimer->start(); + } +}