#include "groupclipscommand.h"
#include "splitaudiocommand.h"
#include "changecliptypecommand.h"
+#include "trackdialog.h"
#include <KDebug>
#include <KLocale>
#include <QInputDialog>
+bool sortGuidesList(const Guide *g1 , const Guide *g2)
+{
+ return (*g1).position() < (*g2).position();
+}
+
+
//TODO:
// disable animation if user asked it in KDE's global settings
// http://lists.kde.org/?l=kde-commits&m=120398724717624&w=2
m_animation(NULL),
m_clickPoint(),
m_autoScroll(KdenliveSettings::autoscroll()),
- m_changeSpeedAction(NULL),
m_pasteEffectsAction(NULL),
m_ungroupAction(NULL),
m_scrollOffset(0),
else m_commandStack = NULL;
setMouseTracking(true);
setAcceptDrops(true);
+ setFrameShape(QFrame::NoFrame);
+ setLineWidth(0);
+ //setCacheMode(QGraphicsView::CacheBackground);
+ //setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+
KdenliveSettings::setTrackheight(m_tracksHeight);
m_animationTimer = new QTimeLine(800);
m_animationTimer->setFrameRange(0, 5);
m_tipPen.setColor(border);
m_tipPen.setWidth(3);
setContentsMargins(0, 0, 0, 0);
- const int maxWidth = m_tracksHeight * m_document->tracksCount();
- setSceneRect(0, 0, sceneRect().width(), maxWidth);
- verticalScrollBar()->setMaximum(maxWidth);
- m_cursorLine = projectscene->addLine(0, 0, 0, maxWidth);
+ const int maxHeight = m_tracksHeight * m_document->tracksCount();
+ setSceneRect(0, 0, sceneRect().width(), maxHeight);
+ verticalScrollBar()->setMaximum(maxHeight);
+ m_cursorLine = projectscene->addLine(0, 0, 0, maxHeight);
m_cursorLine->setZValue(1000);
+ QPen pen1 = QPen();
+ pen1.setWidth(1);
+ pen1.setColor(Qt::black);
+ m_cursorLine->setPen(pen1);
+ m_cursorLine->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
+
KIcon razorIcon("edit-cut");
m_razorCursor = QCursor(razorIcon.pixmap(22, 22));
m_clipTypeGroup = clipTypeGroup;
QList <QAction *> list = m_timelineContextClipMenu->actions();
for (int i = 0; i < list.count(); i++) {
- if (list.at(i)->data().toString() == "change_speed") m_changeSpeedAction = list.at(i);
- else if (list.at(i)->data().toString() == "paste_effects") m_pasteEffectsAction = list.at(i);
+ if (list.at(i)->data().toString() == "paste_effects") m_pasteEffectsAction = list.at(i);
else if (list.at(i)->data().toString() == "ungroup_clip") m_ungroupAction = list.at(i);
}
{
int pos = event->x();
int mappedXPos = (int)(mapToScene(event->pos()).x() + 0.5);
+ double snappedPos = getSnapPointForPos(mappedXPos);
emit mousePosition(mappedXPos);
if (event->buttons() & Qt::MidButton) return;
- if (m_operationMode == RUBBERSELECTION || (event->modifiers() == Qt::ControlModifier && m_tool != SPACERTOOL)) {
- QGraphicsView::mouseMoveEvent(event);
+ if (dragMode() == QGraphicsView::RubberBandDrag || (event->modifiers() == Qt::ControlModifier && m_tool != SPACERTOOL)) {
+ event->setAccepted(true);
m_moveOpMode = NONE;
+ QGraphicsView::mouseMoveEvent(event);
return;
}
} else if (m_scrollTimer.isActive()) m_scrollTimer.stop();
} else if (m_operationMode == RESIZESTART && move) {
- double snappedPos = getSnapPointForPos(mappedXPos);
m_document->renderer()->pause();
m_dragItem->resizeStart((int)(snappedPos));
} else if (m_operationMode == RESIZEEND && move) {
- double snappedPos = getSnapPointForPos(mappedXPos);
m_document->renderer()->pause();
m_dragItem->resizeEnd((int)(snappedPos));
} else if (m_operationMode == FADEIN && move) {
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;
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;
} else if (m_operationMode == SPACER && move && m_selectionGroup) {
// spacer tool
int mappedClick = (int)(mapToScene(m_clickEvent).x() + 0.5);
- m_selectionGroup->setPos(mappedXPos + (((int) m_selectionGroup->boundingRect().topLeft().x() + 0.5) - mappedClick) , m_selectionGroup->pos().y());
+ if (snappedPos < 0) snappedPos = 0;
+ // Make sure there is no collision
+ QList<QGraphicsItem *> children = m_selectionGroup->childItems();
+ QPainterPath shape = m_selectionGroup->clipGroupShape(QPointF(snappedPos - m_selectionGroup->sceneBoundingRect().left(), 0));
+ QList<QGraphicsItem*> collidingItems = scene()->items(shape, Qt::IntersectsItemShape);
+ collidingItems.removeAll(m_selectionGroup);
+ for (int i = 0; i < children.count(); i++) {
+ collidingItems.removeAll(children.at(i));
+ }
+ bool collision = false;
+ for (int i = 0; i < collidingItems.count(); i++) {
+ if (collidingItems.at(i)->type() == AVWIDGET) {
+ collision = true;
+ break;
+ }
+ }
+ if (!collision) {
+ // Check transitions
+ shape = m_selectionGroup->transitionGroupShape(QPointF(snappedPos - m_selectionGroup->sceneBoundingRect().left(), 0));
+ collidingItems = scene()->items(shape, Qt::IntersectsItemShape);
+ collidingItems.removeAll(m_selectionGroup);
+ for (int i = 0; i < children.count(); i++) {
+ collidingItems.removeAll(children.at(i));
+ }
+ for (int i = 0; i < collidingItems.count(); i++) {
+ if (collidingItems.at(i)->type() == TRANSITIONWIDGET) {
+ collision = true;
+ break;
+ }
+ }
+ }
+
+ if (!collision)
+ m_selectionGroup->translate(snappedPos - m_selectionGroup->sceneBoundingRect().left(), 0);
+ //m_selectionGroup->setPos(mappedXPos + (((int) m_selectionGroup->boundingRect().topLeft().x() + 0.5) - mappedClick) , m_selectionGroup->pos().y());
}
}
AbstractClipItem *clip = static_cast <AbstractClipItem*>(item);
if (m_tool == RAZORTOOL) {
// razor tool over a clip, display current frame in monitor
- if (!m_blockRefresh && item->type() == AVWIDGET) {
+ if (false && !m_blockRefresh && item->type() == AVWIDGET) {
//TODO: solve crash when showing frame when moving razor over clip
- //emit showClipFrame(((ClipItem *) item)->baseClip(), mapToScene(event->pos()).x() / m_scale - (clip->startPos() - clip->cropStart()).frames(m_document->fps()));
+ emit showClipFrame(((ClipItem *) item)->baseClip(), mappedXPos - (clip->startPos() - clip->cropStart()).frames(m_document->fps()));
}
event->accept();
return;
return;
} else {
if (m_visualTip) {
+ scene()->removeItem(m_visualTip);
+ m_animationTimer->stop();
delete m_animation;
m_animation = NULL;
- m_animationTimer->stop();
delete m_visualTip;
m_visualTip = NULL;
}
setCursor(Qt::SplitHCursor);
} else {
if (m_visualTip) {
- delete m_animation;
+ scene()->removeItem(m_visualTip);
m_animationTimer->stop();
+ delete m_animation;
m_animation = NULL;
delete m_visualTip;
m_visualTip = NULL;
// virtual
void CustomTrackView::mousePressEvent(QMouseEvent * event)
{
- //kDebug() << "mousePressEvent STARTED";
setFocus(Qt::MouseFocusReason);
m_menuPosition = QPoint();
return;
}
+ if (event->modifiers() & Qt::ShiftModifier) {
+ // Rectangle selection
+ setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+ setDragMode(QGraphicsView::RubberBandDrag);
+ if (!(event->modifiers() & Qt::ControlModifier)) {
+ resetSelectionGroup();
+ scene()->clearSelection();
+ }
+ m_blockRefresh = false;
+ m_operationMode = RUBBERSELECTION;
+ QGraphicsView::mousePressEvent(event);
+ return;
+ }
+
m_blockRefresh = true;
- m_dragItem = NULL;
m_dragGuide = NULL;
bool collision = false;
QList<QGraphicsItem *> collisionList = items(m_clickEvent);
if (event->modifiers() == Qt::ControlModifier && m_tool != SPACERTOOL && collisionList.count() == 0) {
+ // Pressing Ctrl + left mouse button in an empty area scrolls the timeline
setDragMode(QGraphicsView::ScrollHandDrag);
QGraphicsView::mousePressEvent(event);
m_blockRefresh = false;
return;
}
- if (event->modifiers() & Qt::ShiftModifier && collisionList.count() == 0) {
- setDragMode(QGraphicsView::RubberBandDrag);
- if (!(event->modifiers() & Qt::ControlModifier)) {
- resetSelectionGroup();
- scene()->clearSelection();
- }
- QGraphicsView::mousePressEvent(event);
- m_blockRefresh = false;
- m_operationMode = RUBBERSELECTION;
- return;
- }
-
// if a guide and a clip were pressed, just select the guide
for (int i = 0; i < collisionList.count(); ++i) {
if (collisionList.at(i)->type() == GUIDEITEM) {
// Find first clip, transition or group under mouse (when no guides selected)
int ct = 0;
AbstractGroupItem *dragGroup = NULL;
+ AbstractClipItem *collisionClip = NULL;
+ bool found = false;
while (!m_dragGuide && ct < collisionList.count()) {
if (collisionList.at(ct)->type() == AVWIDGET || collisionList.at(ct)->type() == TRANSITIONWIDGET) {
- m_dragItem = static_cast <AbstractClipItem *>(collisionList.at(ct));
+ collisionClip = static_cast <AbstractClipItem *>(collisionList.at(ct));
+ if (collisionClip == m_dragItem) {
+ collisionClip = NULL;
+ } 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) {
// kDebug()<<"// KLIK FOUND GRP: "<<m_dragItem->sceneBoundingRect();
}
ct++;
}
+ if (!found) {
+ if (m_dragItem) emit clipItemSelected(NULL);
+ m_dragItem = NULL;
+ }
if (m_dragItem && m_dragItem->type() == TRANSITIONWIDGET) {
// update transition menu action
setCursor(Qt::ArrowCursor);
m_scene->clearSelection();
//event->accept();
- emit clipItemSelected(NULL);
updateClipTypeActions(NULL);
if (m_tool == SPACERTOOL) {
QList<QGraphicsItem *> selection;
if (event->modifiers() == Qt::ControlModifier) {
// Ctrl + click, select all items on track after click position
int track = (int)(mapToScene(m_clickEvent).y() / m_tracksHeight);
- selection = items(m_clickEvent.x(), track * m_tracksHeight + m_tracksHeight / 2, mapFromScene(sceneRect().width(), 0).x() - m_clickEvent.x(), m_tracksHeight / 2 - 2);
+ QRectF rect(mapToScene(m_clickEvent).x(), track * m_tracksHeight + m_tracksHeight / 2, sceneRect().width() - mapToScene(m_clickEvent).x(), m_tracksHeight / 2 - 2);
+
+ bool isOk;
+ selection = checkForGroups(rect, isOk);
+ if (!isOk) {
+ // groups found on track, do not allow the move
+ emit displayMessage(i18n("Cannot use spacer in a track with a group"), ErrorMessage);
+ return;
+ }
kDebug() << "SPACER TOOL + CTRL, SELECTING ALL CLIPS ON TRACK " << track << " WITH SELECTION RECT " << m_clickEvent.x() << "/" << track * m_tracksHeight + 1 << "; " << mapFromScene(sceneRect().width(), 0).x() - m_clickEvent.x() << "/" << m_tracksHeight - 2;
} else {
kDebug() << "SELELCTING ELEMENTS WITHIN =" << event->pos().x() << "/" << 1 << ", " << mapFromScene(sceneRect().width(), 0).x() - event->pos().x() << "/" << sceneRect().height();
}
+ // create group to hold selected items
+ m_selectionGroup = new AbstractGroupItem(m_document->fps());
+ scene()->addItem(m_selectionGroup);
+ QList <GenTime> offsetList;
for (int i = 0; i < selection.count(); i++) {
- if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET) {
- selection.at(i)->setSelected(true);
+ if (selection.at(i)->parentItem() == 0 && (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET)) {
+ AbstractClipItem *item = static_cast<AbstractClipItem *>(selection.at(i));
+ offsetList.append(item->startPos());
+ offsetList.append(item->endPos());
+ m_selectionGroup->addToGroup(selection.at(i));
+ selection.at(i)->setFlags(QGraphicsItem::ItemIsSelectable);
+ } else if (selection.at(i)->parentItem() == 0 && selection.at(i)->type() == GROUPWIDGET) {
+ QList<QGraphicsItem *> children = selection.at(i)->childItems();
+ for (int j = 0; j < children.count(); j++) {
+ AbstractClipItem *item = static_cast<AbstractClipItem *>(children.at(j));
+ offsetList.append(item->startPos());
+ offsetList.append(item->endPos());
+ }
+ m_selectionGroup->addToGroup(selection.at(i));
+ selection.at(i)->setFlags(QGraphicsItem::ItemIsSelectable);
+ } else if (selection.at(i)->parentItem()) {
+ m_selectionGroup->addToGroup(selection.at(i)->parentItem());
+ selection.at(i)->parentItem()->setFlags(QGraphicsItem::ItemIsSelectable);
}
}
- groupSelectedItems(true);
+
+ if (!offsetList.isEmpty()) {
+ qSort(offsetList);
+ QList <GenTime> cleandOffsetList;
+ GenTime startOffset = offsetList.takeFirst();
+ for (int k = 0; k < offsetList.size(); k++) {
+ GenTime newoffset = offsetList.at(k) - startOffset;
+ if (newoffset != GenTime() && !cleandOffsetList.contains(newoffset)) {
+ cleandOffsetList.append(newoffset);
+ }
+ }
+ updateSnapPoints(NULL, cleandOffsetList, true);
+ }
m_operationMode = SPACER;
- } else setCursorPos((int)(mapToScene(event->x(), 0).x()));
+ } else {
+ setCursorPos((int)(mapToScene(event->x(), 0).x()));
+ }
QGraphicsView::mousePressEvent(event);
- kDebug() << "END mousePress EVENT ";
return;
}
RazorClipCommand* command = new RazorClipCommand(this, clip->info(), GenTime((int)(mapToScene(event->pos()).x()), m_document->fps()));
m_document->renderer()->pause();
m_commandStack->push(command);
- m_document->setModified(true);
+ setDocumentModified();
m_dragItem = NULL;
event->accept();
return;
}
- if (dragGroup == NULL) updateSnapPoints(m_dragItem);
- else {
- QList <GenTime> offsetList;
- QList<QGraphicsItem *> children = dragGroup->childItems();
- for (int i = 0; i < children.count(); i++) {
- if (children.at(i)->type() == AVWIDGET || children.at(i)->type() == TRANSITIONWIDGET) {
- AbstractClipItem *item = static_cast <AbstractClipItem *>(children.at(i));
- offsetList.append(item->startPos());
- offsetList.append(item->endPos());
- }
- }
- if (!offsetList.isEmpty()) {
- qSort(offsetList);
- GenTime startOffset = offsetList.takeFirst();
- QList <GenTime> cleandOffsetList;
- for (int k = 0; k < offsetList.size(); k++) {
- GenTime newoffset = offsetList.at(k) - startOffset;
- if (newoffset != GenTime() && !cleandOffsetList.contains(newoffset)) {
- cleandOffsetList.append(newoffset);
- }
- }
- updateSnapPoints(NULL, cleandOffsetList, true);
- }
- }
-
- if (m_dragItem->type() == AVWIDGET && !m_dragItem->isItemLocked()) emit clipItemSelected((ClipItem*) m_dragItem);
- else emit clipItemSelected(NULL);
-
bool itemSelected = false;
if (m_dragItem->isSelected()) itemSelected = true;
else if (m_dragItem->parentItem() && m_dragItem->parentItem()->isSelected()) itemSelected = true;
else if (dragGroup && dragGroup->isSelected()) itemSelected = true;
+
if (event->modifiers() == Qt::ControlModifier || itemSelected == false) {
- resetSelectionGroup();
- if (event->modifiers() != Qt::ControlModifier) m_scene->clearSelection();
+ if (event->modifiers() != Qt::ControlModifier) {
+ resetSelectionGroup(false);
+ m_scene->clearSelection();
+ // A refresh seems necessary otherwise in zoomed mode, some clips disappear
+ viewport()->update();
+ } else resetSelectionGroup();
dragGroup = NULL;
if (m_dragItem->parentItem() && m_dragItem->parentItem()->type() == GROUPWIDGET) {
//kDebug()<<"// KLIK FOUND GRP: "<<m_dragItem->sceneBoundingRect();
groupSelectedItems();
ClipItem *clip = static_cast <ClipItem *>(m_dragItem);
updateClipTypeActions(dragGroup == NULL ? clip : NULL);
- m_changeSpeedAction->setEnabled(clip->clipType() == AV || clip->clipType() == VIDEO);
m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1);
}
+ if (collisionClip != NULL || m_dragItem == NULL) {
+ if (m_dragItem && m_dragItem->type() == AVWIDGET && !m_dragItem->isItemLocked()) {
+ ClipItem *selected = static_cast <ClipItem*>(m_dragItem);
+ emit clipItemSelected(selected);
+ } else emit clipItemSelected(NULL);
+ }
+
// If clicked item is selected, allow move
- if (event->modifiers() != Qt::ControlModifier && m_operationMode == NONE/* && (m_dragItem->isSelected() || (dragGroup && dragGroup->isSelected()))*/) QGraphicsView::mousePressEvent(event);
+ if (event->modifiers() != Qt::ControlModifier && m_operationMode == NONE) QGraphicsView::mousePressEvent(event);
m_clickPoint = QPoint((int)(mapToScene(event->pos()).x() - m_dragItem->startPos().frames(m_document->fps())), (int)(event->pos().y() - m_dragItem->pos().y()));
m_operationMode = m_dragItem->operationMode(mapToScene(event->pos()));
+ // Update snap points
+ if (m_selectionGroup == NULL) {
+ if (m_operationMode == RESIZEEND || m_operationMode == RESIZESTART) updateSnapPoints(NULL);
+ else updateSnapPoints(m_dragItem);
+ } else {
+ QList <GenTime> offsetList;
+ QList<QGraphicsItem *> children = m_selectionGroup->childItems();
+ for (int i = 0; i < children.count(); i++) {
+ if (children.at(i)->type() == AVWIDGET || children.at(i)->type() == TRANSITIONWIDGET) {
+ AbstractClipItem *item = static_cast <AbstractClipItem *>(children.at(i));
+ offsetList.append(item->startPos());
+ offsetList.append(item->endPos());
+ }
+ }
+ if (!offsetList.isEmpty()) {
+ qSort(offsetList);
+ GenTime startOffset = offsetList.takeFirst();
+ QList <GenTime> cleandOffsetList;
+ for (int k = 0; k < offsetList.size(); k++) {
+ GenTime newoffset = offsetList.at(k) - startOffset;
+ if (newoffset != GenTime() && !cleandOffsetList.contains(newoffset)) {
+ cleandOffsetList.append(newoffset);
+ }
+ }
+ updateSnapPoints(NULL, cleandOffsetList, true);
+ }
+ }
+
if (m_operationMode == KEYFRAME) {
m_dragItem->updateSelectedKeyFrame();
m_blockRefresh = false;
m_blockRefresh = false;
//kDebug()<<pos;
- //QGraphicsView::mousePressEvent(event);
+ QGraphicsView::mousePressEvent(event);
}
void CustomTrackView::resetSelectionGroup(bool selectItems)
QList<QGraphicsItem *> children = m_selectionGroup->childItems();
scene()->destroyItemGroup(m_selectionGroup);
for (int i = 0; i < children.count(); i++) {
- if (children.at(i)->type() == AVWIDGET || children.at(i)->type() == TRANSITIONWIDGET) {
+ if (children.at(i)->parentItem() == 0 && (children.at(i)->type() == AVWIDGET || children.at(i)->type() == TRANSITIONWIDGET)) {
if (!static_cast <AbstractClipItem *>(children.at(i))->isItemLocked()) {
children.at(i)->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
children.at(i)->setSelected(selectItems);
}
QList<QGraphicsItem *> selection = m_scene->selectedItems();
if (selection.isEmpty()) return;
- QPointF top = selection.at(0)->sceneBoundingRect().topLeft();
+ QRectF rectUnion;
// Find top left position of selection
- for (int i = 1; i < selection.count(); i++) {
- if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET) {
- QPointF currenttop = selection.at(i)->sceneBoundingRect().topLeft();
- if (currenttop.x() < top.x()) top.setX(currenttop.x());
- if (currenttop.y() < top.y()) top.setY(currenttop.y());
+ for (int i = 0; i < selection.count(); i++) {
+ if (selection.at(i)->parentItem() == 0 && (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET)) {
+ rectUnion = rectUnion.united(selection.at(i)->sceneBoundingRect());
+ } else if (selection.at(i)->parentItem()) {
+ rectUnion = rectUnion.united(selection.at(i)->parentItem()->sceneBoundingRect());
}
}
KdenliveSettings::setSnaptopoints(false);
if (createNewGroup) {
AbstractGroupItem *newGroup = m_document->clipManager()->createGroup();
- newGroup->translate(-top.x(), -top.y() + 1);
- newGroup->setPos(top.x(), top.y() - 1);
+ newGroup->setPos(rectUnion.left(), rectUnion.top() - 1);
+ QPointF diff = newGroup->pos();
+ newGroup->translate(-diff.x(), -diff.y());
+ //newGroup->translate((int) -rectUnion.left(), (int) -rectUnion.top() + 1);
+
scene()->addItem(newGroup);
// CHeck if we are trying to include a group in a group
KdenliveSettings::setSnaptopoints(snap);
} else {
m_selectionGroup = new AbstractGroupItem(m_document->fps());
- m_selectionGroup->translate(-top.x(), -top.y() + 1);
- m_selectionGroup->setPos(top.x(), top.y() - 1);
+ m_selectionGroup->setPos(rectUnion.left(), rectUnion.top() - 1);
+ QPointF diff = m_selectionGroup->pos();
+ //m_selectionGroup->translate((int) - rectUnion.left(), (int) -rectUnion.top() + 1);
+ m_selectionGroup->translate(- diff.x(), -diff.y());
+
scene()->addItem(m_selectionGroup);
for (int i = 0; i < selection.count(); i++) {
- if (selection.at(i)->parentItem() == NULL && (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET)) {
+ if (selection.at(i)->parentItem() == 0 && (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET)) {
m_selectionGroup->addToGroup(selection.at(i));
selection.at(i)->setFlags(QGraphicsItem::ItemIsSelectable);
}
void CustomTrackView::mouseDoubleClickEvent(QMouseEvent *event)
{
- kDebug() << "++++++++++++ DBL CLK";
if (m_dragItem && m_dragItem->hasKeyFrames()) {
if (m_moveOpMode == KEYFRAME) {
// user double clicked on a keyframe, open edit dialog
QDialog d(parentWidget());
Ui::KeyFrameDialog_UI view;
view.setupUi(&d);
- view.kfr_position->setText(m_document->timecode().getTimecode(GenTime(m_dragItem->selectedKeyFramePos(), m_document->fps()) - m_dragItem->cropStart(), m_document->fps()));
+ view.kfr_position->setText(m_document->timecode().getTimecode(GenTime(m_dragItem->selectedKeyFramePos(), m_document->fps()) - m_dragItem->cropStart()));
view.kfr_value->setValue(m_dragItem->selectedKeyFrameValue());
view.kfr_value->setFocus();
if (d.exec() == QDialog::Accepted) {
- int pos = m_document->timecode().getFrameCount(view.kfr_position->text(), m_document->fps());
+ int pos = m_document->timecode().getFrameCount(view.kfr_position->text());
m_dragItem->updateKeyFramePos(GenTime(pos, m_document->fps()) + m_dragItem->cropStart(), (double) view.kfr_value->value() * m_dragItem->keyFrameFactor());
- ClipItem *item = (ClipItem *)m_dragItem;
+ ClipItem *item = static_cast <ClipItem *>(m_dragItem);
QString previous = item->keyframes(item->selectedEffectIndex());
item->updateKeyframeEffect();
QString next = item->keyframes(item->selectedEffectIndex());
EditKeyFrameCommand *command = new EditKeyFrameCommand(this, item->track(), item->startPos(), item->selectedEffectIndex(), previous, next, false);
m_commandStack->push(command);
updateEffect(m_document->tracksCount() - item->track(), item->startPos(), item->selectedEffect(), item->selectedEffectIndex());
+ emit clipItemSelected(item, item->selectedEffectIndex());
}
} else {
// add keyframe
GenTime keyFramePos = GenTime((int)(mapToScene(event->pos()).x()), m_document->fps()) - m_dragItem->startPos() + m_dragItem->cropStart();
m_dragItem->addKeyFrame(keyFramePos, mapToScene(event->pos()).toPoint().y());
- ClipItem * item = (ClipItem *) m_dragItem;
+ ClipItem * item = static_cast <ClipItem *>(m_dragItem);
QString previous = item->keyframes(item->selectedEffectIndex());
item->updateKeyframeEffect();
QString next = item->keyframes(item->selectedEffectIndex());
EditKeyFrameCommand *command = new EditKeyFrameCommand(this, m_dragItem->track(), m_dragItem->startPos(), item->selectedEffectIndex(), previous, next, false);
m_commandStack->push(command);
updateEffect(m_document->tracksCount() - item->track(), item->startPos(), item->selectedEffect(), item->selectedEffectIndex());
+ emit clipItemSelected(item, item->selectedEffectIndex());
}
} else if (m_dragItem && !m_dragItem->isItemLocked()) {
ClipDurationDialog d(m_dragItem, m_document->timecode(), this);
QUndoCommand *moveCommand = new QUndoCommand();
moveCommand->setText(i18n("Edit clip"));
ItemInfo clipInfo = m_dragItem->info();
- if (d.duration() < m_dragItem->duration() || d.cropStart() != clipInfo.cropStart) {
+ if (d.duration() < m_dragItem->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, moveCommand);
+ new ResizeClipCommand(this, startInfo, clipInfo, true, false, moveCommand);
}
if (d.startPos() != clipInfo.startPos) {
ItemInfo startInfo = clipInfo;
clipInfo.endPos = m_dragItem->endPos() + (clipInfo.startPos - startInfo.startPos);
new MoveClipCommand(this, startInfo, clipInfo, true, moveCommand);
}
- if (d.duration() > m_dragItem->duration()) {
+ if (d.duration() > m_dragItem->cropDuration()) {
// duration was increased, so process it after move
ItemInfo startInfo = clipInfo;
clipInfo.endPos = clipInfo.startPos + d.duration();
clipInfo.cropStart = d.cropStart();
- new ResizeClipCommand(this, startInfo, clipInfo, true, moveCommand);
+ new ResizeClipCommand(this, startInfo, clipInfo, true, false, moveCommand);
}
m_commandStack->push(moveCommand);
}
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);
+ updateEffect(m_document->tracksCount() - clip->track(), clip->startPos(), clip->effectAt(index), index, false);
} else emit displayMessage(i18n("Cannot find clip with keyframe"), ErrorMessage);
}
m_editGuide->setEnabled(m_dragGuide != NULL);
if (clip == NULL) m_timelineContextMenu->popup(pos);
else if (group != NULL) {
- m_changeSpeedAction->setEnabled(false);
m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1);
m_ungroupAction->setEnabled(true);
updateClipTypeActions(NULL);
if (clip->type() == AVWIDGET) {
ClipItem *item = static_cast <ClipItem*>(clip);
updateClipTypeActions(item);
- m_changeSpeedAction->setEnabled(item->clipType() == AV || item->clipType() == VIDEO);
m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1);
m_timelineContextClipMenu->popup(pos);
} else if (clip->type() == TRANSITIONWIDGET) m_timelineContextTransitionMenu->popup(pos);
emit activateDocumentMonitor();
}
-void CustomTrackView::dragEnterEvent(QDragEnterEvent * event)
+bool CustomTrackView::insertDropClips(const QMimeData *data, const QPoint pos)
{
- if (event->mimeData()->hasFormat("kdenlive/clip")) {
+ if (data->hasFormat("kdenlive/clip")) {
m_clipDrag = true;
resetSelectionGroup();
- QStringList list = QString(event->mimeData()->data("kdenlive/clip")).split(';');
- m_selectionGroup = new AbstractGroupItem(m_document->fps());
- QPoint pos;
+ QStringList list = QString(data->data("kdenlive/clip")).split(';');
DocClipBase *clip = m_document->getBaseClip(list.at(0));
- if (clip == NULL) kDebug() << " WARNING))))))))) CLIP NOT FOUND : " << list.at(0);
+ if (clip == NULL) {
+ kDebug() << " WARNING))))))))) CLIP NOT FOUND : " << list.at(0);
+ return false;
+ }
+ const QPointF framePos = mapToScene(pos);
ItemInfo info;
info.startPos = GenTime();
info.cropStart = GenTime(list.at(1).toInt(), m_document->fps());
info.endPos = GenTime(list.at(2).toInt() - list.at(1).toInt(), m_document->fps());
- info.track = (int)(1 / m_tracksHeight);
- ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0);
+ info.cropDuration = info.endPos - info.startPos;
+ info.originalcropStart = info.cropStart;
+ info.track = 0;
+
+ // Check if clip can be inserted at that position
+ ItemInfo pasteInfo = info;
+ pasteInfo.startPos = GenTime((int)(framePos.x() + 0.5), m_document->fps());
+ pasteInfo.endPos = pasteInfo.startPos + info.endPos;
+ pasteInfo.track = (int)(framePos.y() / m_tracksHeight);
+ if (!canBePastedTo(pasteInfo, AVWIDGET)) {
+ return true;
+ }
+ m_selectionGroup = new AbstractGroupItem(m_document->fps());
+ ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, 1);
m_selectionGroup->addToGroup(item);
item->setFlags(QGraphicsItem::ItemIsSelectable);
- //TODO: check if we do not overlap another clip when first dropping in timeline
- // if (insertPossible(m_selectionGroup, event->pos()))
+
QList <GenTime> offsetList;
offsetList.append(info.endPos);
updateSnapPoints(NULL, offsetList);
+ m_selectionGroup->setPos(framePos);
scene()->addItem(m_selectionGroup);
- event->acceptProposedAction();
- } else if (event->mimeData()->hasFormat("kdenlive/producerslist")) {
+ return true;
+ } else if (data->hasFormat("kdenlive/producerslist")) {
m_clipDrag = true;
- QStringList ids = QString(event->mimeData()->data("kdenlive/producerslist")).split(';');
+ QStringList ids = QString(data->data("kdenlive/producerslist")).split(';');
m_scene->clearSelection();
resetSelectionGroup(false);
- m_selectionGroup = new AbstractGroupItem(m_document->fps());
- QPoint pos;
- GenTime start;
QList <GenTime> offsetList;
+ QList <ItemInfo> infoList;
+ const QPointF framePos = mapToScene(pos);
+ GenTime start = GenTime((int)(framePos.x() + 0.5), m_document->fps());
+ int track = (int)(framePos.y() / m_tracksHeight);
+
+ // Check if clips can be inserted at that position
for (int i = 0; i < ids.size(); ++i) {
DocClipBase *clip = m_document->getBaseClip(ids.at(i));
- if (clip == NULL) kDebug() << " WARNING))))))))) CLIP NOT FOUND : " << ids.at(i);
+ if (clip == NULL) {
+ kDebug() << " WARNING))))))))) CLIP NOT FOUND : " << ids.at(i);
+ return false;
+ }
ItemInfo info;
info.startPos = start;
- info.endPos = info.startPos + clip->duration();
- info.track = (int)(1 / m_tracksHeight);
- ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, false);
+ info.cropDuration = clip->duration();
+ info.endPos = info.startPos + info.cropDuration;
+ info.track = track;
+ infoList.append(info);
start += clip->duration();
+ }
+ if (!canBePastedTo(infoList, AVWIDGET)) {
+ return true;
+ }
+ m_selectionGroup = new AbstractGroupItem(m_document->fps());
+ start = GenTime();
+ for (int i = 0; i < ids.size(); ++i) {
+ DocClipBase *clip = m_document->getBaseClip(ids.at(i));
+ ItemInfo info;
+ info.startPos = start;
+ info.cropDuration = clip->duration();
+ info.endPos = info.startPos + info.cropDuration;
+ info.track = 0;
+ start += info.cropDuration;
offsetList.append(start);
- m_selectionGroup->addToGroup(item);
+ ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, 1, false);
item->setFlags(QGraphicsItem::ItemIsSelectable);
+ m_selectionGroup->addToGroup(item);
m_waitingThumbs.append(item);
}
- //TODO: check if we do not overlap another clip when first dropping in timeline
- //if (insertPossible(m_selectionGroup, event->pos()))
+
updateSnapPoints(NULL, offsetList);
+ m_selectionGroup->setPos(framePos);
scene()->addItem(m_selectionGroup);
m_thumbsTimer.start();
- event->acceptProposedAction();
+ return true;
} else {
// the drag is not a clip (may be effect, ...)
m_clipDrag = false;
- QGraphicsView::dragEnterEvent(event);
+ return false;
}
}
-bool CustomTrackView::insertPossible(AbstractGroupItem *group, const QPoint &pos) const
+
+void CustomTrackView::dragEnterEvent(QDragEnterEvent * event)
{
- QPolygonF path;
- QList<QGraphicsItem *> children = group->childItems();
- for (int i = 0; i < children.count(); i++) {
- if (children.at(i)->type() == AVWIDGET) {
- ClipItem *clip = static_cast <ClipItem *>(children.at(i));
- ItemInfo info = clip->info();
- kDebug() << " / / INSERT : " << pos.x();
- QRectF shape = QRectF(clip->startPos().frames(m_document->fps()), clip->track() * m_tracksHeight + 1, clip->duration().frames(m_document->fps()) - 0.02, m_tracksHeight - 1);
- kDebug() << " / / INSERT RECT: " << shape;
- path = path.united(QPolygonF(shape));
- }
- }
+ if (insertDropClips(event->mimeData(), event->pos())) {
+ event->acceptProposedAction();
+ } else QGraphicsView::dragEnterEvent(event);
+}
- QList<QGraphicsItem*> collindingItems = scene()->items(path, Qt::IntersectsItemShape);
- if (collindingItems.isEmpty()) return true;
+bool CustomTrackView::itemCollision(AbstractClipItem *item, ItemInfo newPos)
+{
+ QRectF shape = QRectF(newPos.startPos.frames(m_document->fps()), newPos.track * m_tracksHeight + 1, (newPos.endPos - newPos.startPos).frames(m_document->fps()) - 0.02, m_tracksHeight - 1);
+ QList<QGraphicsItem*> collindingItems = scene()->items(shape, Qt::IntersectsItemShape);
+ collindingItems.removeAll(item);
+ if (collindingItems.isEmpty()) return false;
else {
for (int i = 0; i < collindingItems.count(); i++) {
QGraphicsItem *collision = collindingItems.at(i);
- if (collision->type() == AVWIDGET) {
+ if (collision->type() == item->type()) {
// Collision
kDebug() << "// COLLISIION DETECTED";
- return false;
+ return true;
}
}
- return true;
+ return false;
}
-
}
void CustomTrackView::slotRefreshEffects(ClipItem *clip)
void CustomTrackView::addEffect(int track, GenTime pos, QDomElement effect)
{
- ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_document->tracksCount() - track);
+ ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()), m_document->tracksCount() - track);
if (clip) {
- if (!m_document->renderer()->mltAddEffect(track, pos, clip->addEffect(effect)))
+ // Special case: speed effect
+ if (effect.attribute("id") == "speed") {
+ if (clip->clipType() != VIDEO && clip->clipType() != AV && clip->clipType() != PLAYLIST) {
+ emit displayMessage(i18n("Problem adding effect to clip"), ErrorMessage);
+ return;
+ }
+ ItemInfo info = clip->info();
+ double speed = EffectsList::parameter(effect, "speed").toDouble() / 100.0;
+ int strobe = EffectsList::parameter(effect, "strobe").toInt();
+ if (strobe == 0) strobe = 1;
+ doChangeClipSpeed(info, speed, 1.0, strobe, clip->baseClip()->getId());
+ EffectsParameterList params = clip->addEffect(effect);
+ m_document->renderer()->mltAddEffect(track, pos, params);
+ if (clip->isSelected()) emit clipItemSelected(clip);
+ return;
+ }
+ EffectsParameterList params = clip->addEffect(effect);
+ if (effect.attribute("disabled") == "1") {
+ // Effect is disabled, don't add it to MLT playlist
+ if (clip->isSelected()) emit clipItemSelected(clip);
+ return;
+ }
+ if (!m_document->renderer()->mltAddEffect(track, pos, params))
emit displayMessage(i18n("Problem adding effect to clip"), ErrorMessage);
- emit clipItemSelected(clip);
+ if (clip->isSelected()) emit clipItemSelected(clip);
} else emit displayMessage(i18n("Cannot find clip to add effect"), ErrorMessage);
}
void CustomTrackView::deleteEffect(int track, GenTime pos, QDomElement effect)
{
QString index = effect.attribute("kdenlive_ix");
+ // Special case: speed effect
+ if (effect.attribute("id") == "speed") {
+ ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()), m_document->tracksCount() - track);
+ if (clip) {
+ ItemInfo info = clip->info();
+ doChangeClipSpeed(info, 1.0, clip->speed(), 1, clip->baseClip()->getId());
+ clip->deleteEffect(index);
+ emit clipItemSelected(clip);
+ m_document->renderer()->mltRemoveEffect(track, pos, index, true);
+ return;
+ }
+ }
if (!m_document->renderer()->mltRemoveEffect(track, pos, index, true) && effect.attribute("disabled") != "1") {
kDebug() << "// ERROR REMOV EFFECT: " << index << ", DISABLE: " << effect.attribute("disabled");
emit displayMessage(i18n("Problem deleting effect"), ErrorMessage);
return;
}
- ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_document->tracksCount() - track);
+ ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()), m_document->tracksCount() - track);
if (clip) {
clip->deleteEffect(index);
emit clipItemSelected(clip);
}
if (count > 0) {
m_commandStack->push(effectCommand);
- m_document->setModified(true);
+ setDocumentModified();
} else delete effectCommand;
}
int count = 0;
if (track == -1) itemList = scene()->selectedItems();
if (itemList.isEmpty()) {
- ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, track);
+ ClipItem *clip = getClipItemAt((int) pos.frames(m_document->fps()), track);
if (clip) itemList.append(clip);
else emit displayMessage(i18n("Select a clip if you want to apply an effect"), ErrorMessage);
}
kDebug() << "// REQUESTING EFFECT ON CLIP: " << pos.frames(25) << ", TRK: " << track << "SELECTED ITEMS: " << itemList.count();
for (int i = 0; i < itemList.count(); i++) {
if (itemList.at(i)->type() == AVWIDGET) {
- ClipItem *item = (ClipItem *)itemList.at(i);
+ ClipItem *item = static_cast <ClipItem *>(itemList.at(i));
if (effect.attribute("type") == "audio") {
// Don't add audio effects on video clips
if (item->isVideoOnly() || (item->clipType() != AUDIO && item->clipType() != AV && item->clipType() != PLAYLIST)) {
}
if (count > 0) {
m_commandStack->push(effectCommand);
- m_document->setModified(true);
+ setDocumentModified();
} else delete effectCommand;
}
{
AddEffectCommand *command = new AddEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), effect, false);
m_commandStack->push(command);
- m_document->setModified(true);
+ setDocumentModified();
}
-void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement effect, int ix, bool triggeredByUser)
+void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement insertedEffect, int ix, bool triggeredByUser)
{
- ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_document->tracksCount() - track);
+ ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()), m_document->tracksCount() - track);
+ QDomElement effect = insertedEffect.cloneNode().toElement();
if (clip) {
+ // Special case: speed effect
+ if (effect.attribute("id") == "speed") {
+ ItemInfo info = clip->info();
+ if (effect.attribute("disabled") == "1") doChangeClipSpeed(info, 1.0, clip->speed(), 1, clip->baseClip()->getId());
+ else {
+ double speed = EffectsList::parameter(effect, "speed").toDouble() / 100.0;
+ int strobe = EffectsList::parameter(effect, "strobe").toInt();
+ if (strobe == 0) strobe = 1;
+ doChangeClipSpeed(info, speed, clip->speed(), strobe, clip->baseClip()->getId());
+ }
+ clip->setEffectAt(ix, effect);
+ if (ix == clip->selectedEffectIndex()) {
+ clip->setSelectedEffect(ix);
+ if (!triggeredByUser) emit clipItemSelected(clip, ix);
+ }
+ return;
+ }
+
EffectsParameterList effectParams = clip->getEffectArgs(effect);
if (effect.attribute("tag") == "ladspa") {
// Update the ladspa affect file
// check if we are trying to reset a keyframe effect
if (effectParams.hasParam("keyframes") && effectParams.paramValue("keyframes").isEmpty()) {
clip->initEffect(effect);
- clip->setEffectAt(ix, effect);
effectParams = clip->getEffectArgs(effect);
}
if (effectParams.paramValue("disabled") == "1") {
}
}
}
- m_document->setModified(true);
+ setDocumentModified();
}
void CustomTrackView::moveEffect(int track, GenTime pos, int oldPos, int newPos)
{
- ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_document->tracksCount() - track);
- if (clip) {
- m_document->renderer()->mltMoveEffect(track, pos, oldPos, newPos);
- QDomElement act = clip->effectAt(newPos - 1).cloneNode().toElement();
- QDomElement before = clip->effectAt(oldPos - 1).cloneNode().toElement();
+ ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()), m_document->tracksCount() - track);
+ if (clip && !clip->effectAt(newPos - 1).isNull() && !clip->effectAt(oldPos - 1).isNull()) {
+ QDomElement act = clip->effectAt(newPos - 1);
+ QDomElement before = clip->effectAt(oldPos - 1);
clip->setEffectAt(oldPos - 1, act);
clip->setEffectAt(newPos - 1, before);
+ // special case: speed effect, which is a pseudo-effect, not appearing in MLT's effects
+ if (act.attribute("id") == "speed") {
+ m_document->renderer()->mltUpdateEffectPosition(track, pos, oldPos, newPos);
+ } else if (before.attribute("id") == "speed") {
+ m_document->renderer()->mltUpdateEffectPosition(track, pos, newPos, oldPos);
+ } else m_document->renderer()->mltMoveEffect(track, pos, oldPos, newPos);
emit clipItemSelected(clip, newPos - 1);
- }
- m_document->setModified(true);
+ setDocumentModified();
+ } else emit displayMessage(i18n("Cannot move effect"), ErrorMessage);
}
void CustomTrackView::slotChangeEffectState(ClipItem *clip, int effectPos, bool disable)
{
QDomElement effect = clip->effectAt(effectPos);
QDomElement oldEffect = effect.cloneNode().toElement();
- effect.setAttribute("disabled", disable);
+
+ effect.setAttribute("disabled", (int) disable);
EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), oldEffect, effect, effectPos, true);
m_commandStack->push(command);
- m_document->setModified(true);
+ setDocumentModified();;
}
void CustomTrackView::slotChangeEffectPosition(ClipItem *clip, int currentPos, int newPos)
{
MoveEffectCommand *command = new MoveEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), currentPos, newPos);
m_commandStack->push(command);
- m_document->setModified(true);
+ setDocumentModified();
}
void CustomTrackView::slotUpdateClipEffect(ClipItem *clip, QDomElement oldeffect, QDomElement effect, int ix)
{
if (cut) {
// cut clip
- ClipItem *item = getClipItemAt((int) info.startPos.frames(m_document->fps()) + 1, info.track);
+ ClipItem *item = getClipItemAt((int) info.startPos.frames(m_document->fps()), info.track);
if (!item || cutTime >= item->endPos() || cutTime <= item->startPos()) {
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_document->renderer()->mltCutClip(m_document->tracksCount() - info.track, cutTime);
int cutPos = (int) cutTime.frames(m_document->fps());
- ItemInfo newPos;
+ ItemInfo newPos = info;
double speed = item->speed();
newPos.startPos = cutTime;
newPos.endPos = info.endPos;
if (dup->checkKeyFrames()) slotRefreshEffects(dup);
item->baseClip()->addReference();
m_document->updateClip(item->baseClip()->getId());
- m_document->setModified(true);
- 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);
- kDebug() << "// CUTTING CLIP dONE";
+ setDocumentModified();
+ //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
ClipItem *item = getClipItemAt((int) info.startPos.frames(m_document->fps()), info.track);
- ClipItem *dup = getClipItemAt((int) cutTime.frames(m_document->fps()) + 1, info.track);
+ ClipItem *dup = getClipItemAt((int) cutTime.frames(m_document->fps()), info.track);
if (!item || !dup || item == dup) {
emit displayMessage(i18n("Cannot find clip to uncut"), ErrorMessage);
m_blockRefresh = false;
return;
}
- kDebug() << "// UNCUTTING CLIPS: ITEM 1 (" << item->startPos().frames(25) << "x" << item->endPos().frames(25) << ")";
+ /*kDebug() << "// UNCUTTING CLIPS: ITEM 1 (" << item->startPos().frames(25) << "x" << item->endPos().frames(25) << ")";
kDebug() << "// UNCUTTING CLIPS: ITEM 2 (" << dup->startPos().frames(25) << "x" << dup->endPos().frames(25) << ")";
- kDebug() << "// UNCUTTING CLIPS, INFO (" << info.startPos.frames(25) << "x" << info.endPos.frames(25) << ") , CUT: " << cutTime.frames(25);;
+ kDebug() << "// UNCUTTING CLIPS, INFO (" << info.startPos.frames(25) << "x" << info.endPos.frames(25) << ") , CUT: " << cutTime.frames(25);;*/
//deleteClip(dup->info());
bool success = m_document->renderer()->mltResizeClipEnd(clipinfo, info.endPos - info.startPos);
if (success) {
item->resizeEnd((int) info.endPos.frames(m_document->fps()));
- m_document->setModified(true);
+ setDocumentModified();
} else
emit displayMessage(i18n("Error when resizing clip"), ErrorMessage);
ClipItem *transitionClip = NULL;
const int transitiontrack = getPreviousVideoTrack(info.track);
GenTime pos = GenTime((int)(mapToScene(m_menuPosition).x()), m_document->fps());
- if (pos < item->startPos() + item->duration() / 2) {
+ if (pos < item->startPos() + item->cropDuration() / 2) {
// add transition to clip start
info.startPos = item->startPos();
if (transitiontrack != 0) transitionClip = getClipItemAt((int) info.startPos.frames(m_document->fps()), m_document->tracksCount() - transitiontrack);
}
AddTransitionCommand* command = new AddTransitionCommand(this, transitionInfo, endTrack, transition, false, true);
m_commandStack->push(command);
- m_document->setModified(true);
+ setDocumentModified();
}
-void CustomTrackView::addTransition(ItemInfo transitionInfo, int endTrack, QDomElement params)
+void CustomTrackView::addTransition(ItemInfo transitionInfo, int endTrack, QDomElement params, bool refresh)
{
Transition *tr = new Transition(transitionInfo, endTrack, m_document->fps(), params, true);
//kDebug() << "---- ADDING transition " << params.attribute("value");
- if (m_document->renderer()->mltAddTransition(tr->transitionTag(), endTrack, m_document->tracksCount() - transitionInfo.track, transitionInfo.startPos, transitionInfo.endPos, tr->toXML())) {
+ if (m_document->renderer()->mltAddTransition(tr->transitionTag(), endTrack, m_document->tracksCount() - transitionInfo.track, transitionInfo.startPos, transitionInfo.endPos, tr->toXML(), refresh)) {
scene()->addItem(tr);
- m_document->setModified(true);
+ setDocumentModified();
} else {
emit displayMessage(i18n("Cannot add transition"), ErrorMessage);
delete tr;
}
}
-void CustomTrackView::deleteTransition(ItemInfo transitionInfo, int endTrack, QDomElement /*params*/)
+void CustomTrackView::deleteTransition(ItemInfo transitionInfo, int endTrack, QDomElement /*params*/, bool refresh)
{
Transition *item = getTransitionItemAt(transitionInfo.startPos, transitionInfo.track);
if (!item) {
emit displayMessage(i18n("Select clip to delete"), ErrorMessage);
return;
}
- m_document->renderer()->mltDeleteTransition(item->transitionTag(), endTrack, m_document->tracksCount() - transitionInfo.track, transitionInfo.startPos, transitionInfo.endPos, item->toXML());
+ m_document->renderer()->mltDeleteTransition(item->transitionTag(), endTrack, m_document->tracksCount() - transitionInfo.track, transitionInfo.startPos, transitionInfo.endPos, item->toXML(), refresh);
if (m_dragItem == item) m_dragItem = NULL;
delete item;
emit transitionItemSelected(NULL);
- m_document->setModified(true);
+ setDocumentModified();
}
void CustomTrackView::slotTransitionUpdated(Transition *tr, QDomElement old)
{
- kDebug() << "TRANS UPDATE, TRACKS: " << old.attribute("transition_btrack") << ", NEW: " << tr->toXML().attribute("transition_btrack");
+ //kDebug() << "TRANS UPDATE, TRACKS: " << old.attribute("transition_btrack") << ", NEW: " << tr->toXML().attribute("transition_btrack");
EditTransitionCommand *command = new EditTransitionCommand(this, tr->track(), tr->startPos(), old, tr->toXML(), false);
m_commandStack->push(command);
- m_document->setModified(true);
+ setDocumentModified();
}
void CustomTrackView::updateTransition(int track, GenTime pos, QDomElement oldTransition, QDomElement transition, bool updateTransitionWidget)
ClipItem *transitionClip = getClipItemAt(info.startPos, info.track);
if (transitionClip && transitionClip->baseClip()) {
QString size = transitionClip->baseClip()->getProperty("frame_size");
- p.setX(size.section('x', 0, 0).toInt());
+ double factor = transitionClip->baseClip()->getProperty("aspect_ratio").toDouble();
+ p.setX((int)(size.section('x', 0, 0).toInt() * factor + 0.5));
p.setY(size.section('x', 1, 1).toInt());
}
emit transitionItemSelected(item, getPreviousVideoTrack(info.track), p, true);
}
- m_document->setModified(true);
+ setDocumentModified();
}
void CustomTrackView::dragMoveEvent(QDragMoveEvent * event)
{
- event->setDropAction(Qt::IgnoreAction);
- const QPointF pos = mapToScene(event->pos());
- if (m_selectionGroup && m_clipDrag) {
- m_selectionGroup->setPos(pos.x(), pos.y());
- emit mousePosition((int)(m_selectionGroup->scenePos().x() + 0.5));
- event->setDropAction(Qt::MoveAction);
- event->acceptProposedAction();
+ if (m_clipDrag) {
+ const QPointF pos = mapToScene(event->pos());
+ if (m_selectionGroup) {
+ m_selectionGroup->setPos(pos);
+ emit mousePosition((int)(m_selectionGroup->scenePos().x() + 0.5));
+ event->acceptProposedAction();
+ } else {
+ // Drag enter was not possible, try again at mouse position
+ insertDropClips(event->mimeData(), event->pos());
+ event->accept();
+ }
} else {
QGraphicsView::dragMoveEvent(event);
}
int tracknumber = m_document->tracksCount() - info.track - 1;
bool isLocked = m_document->trackInfoAt(tracknumber).isLocked;
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) {
+ emit displayMessage(i18n("Cannot insert clip in timeline"), ErrorMessage);
+ }
if (item->baseClip()->isTransparent() && getTransitionItemAtStart(info.startPos, info.track) == NULL) {
// add transparency transition
- new AddTransitionCommand(this, info, getPreviousVideoTrack(info.track), MainWindow::transitions.getEffectByTag("composite", "composite"), false, true, addCommand);
+ QDomElement trans = MainWindow::transitions.getEffectByTag("composite", "composite").cloneNode().toElement();
+ new AddTransitionCommand(this, info, getPreviousVideoTrack(info.track), trans, false, true, addCommand);
}
- info.track = m_document->tracksCount() - item->track();
- m_document->renderer()->mltInsertClip(info, item->xml(), item->baseClip()->producer(item->track()));
item->setSelected(true);
}
m_commandStack->push(addCommand);
- m_document->setModified(true);
- m_changeSpeedAction->setEnabled(hasVideoClip);
+ setDocumentModified();
m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1);
if (items.count() > 1) groupSelectedItems(true);
+ event->setDropAction(Qt::MoveAction);
+ event->accept();
} else QGraphicsView::dropEvent(event);
setFocus();
}
m_selectionGroup = new AbstractGroupItem(m_document->fps());
scene()->addItem(m_selectionGroup);
for (int i = 0; i < selection.count(); i++) {
- if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET)
+ if ((!selection.at(i)->parentItem()) && (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET)) {
m_selectionGroup->addToGroup(selection.at(i));
- selection.at(i)->setFlags(QGraphicsItem::ItemIsSelectable);
+ selection.at(i)->setFlags(QGraphicsItem::ItemIsSelectable);
+ }
}
// Move graphic items
m_selectionGroup->translate(0, m_tracksHeight);
// adjust track number
QList<QGraphicsItem *> children = m_selectionGroup->childItems();
for (int i = 0; i < children.count(); i++) {
+ if (children.at(i)->type() == GROUPWIDGET) {
+ AbstractGroupItem *grp = static_cast<AbstractGroupItem*>(children.at(i));
+ children << grp->childItems();
+ continue;
+ }
AbstractClipItem *item = static_cast <AbstractClipItem *>(children.at(i));
item->updateItem();
ItemInfo clipinfo = item->info();
else if (clip->isVideoOnly()) prod = clip->baseClip()->videoProducer();
else prod = clip->baseClip()->producer(clipinfo.track);
m_document->renderer()->mltUpdateClipProducer((int)(m_document->tracksCount() - clipinfo.track), clipinfo.startPos.frames(m_document->fps()), prod);
- kDebug() << "// UPDATING CLIP TO TRACK PROD: " << clipinfo.track;
}
} else if (item->type() == TRANSITIONWIDGET) {
Transition *tr = static_cast <Transition *>(item);
}
}
resetSelectionGroup(false);
-
}
+
int maxHeight = m_tracksHeight * m_document->tracksCount();
for (int i = 0; i < m_guides.count(); i++) {
QLineF l = m_guides.at(i)->line();
}
m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), maxHeight);
setSceneRect(0, 0, sceneRect().width(), maxHeight);
- QTimer::singleShot(300, this, SIGNAL(trackHeightChanged()));
viewport()->update();
+ emit trackHeightChanged();
+ //QTimer::singleShot(500, this, SIGNAL(trackHeightChanged()));
//setFixedHeight(50 * m_tracksCount);
}
m_selectionGroup = new AbstractGroupItem(m_document->fps());
scene()->addItem(m_selectionGroup);
for (int i = 0; i < selection.count(); i++) {
- if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET) {
+ if ((!selection.at(i)->parentItem()) && (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET)) {
m_selectionGroup->addToGroup(selection.at(i));
selection.at(i)->setFlags(QGraphicsItem::ItemIsSelectable);
}
QList<QGraphicsItem *> children = m_selectionGroup->childItems();
//kDebug() << "// FOUND CLIPS TO MOVE: " << children.count();
for (int i = 0; i < children.count(); i++) {
+ if (children.at(i)->type() == GROUPWIDGET) {
+ AbstractGroupItem *grp = static_cast<AbstractGroupItem*>(children.at(i));
+ children << grp->childItems();
+ continue;
+ }
if (children.at(i)->type() == AVWIDGET) {
ClipItem *clip = static_cast <ClipItem *>(children.at(i));
clip->updateItem();
}
m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), maxHeight);
setSceneRect(0, 0, sceneRect().width(), maxHeight);
- QTimer::singleShot(300, this, SIGNAL(trackHeightChanged()));
viewport()->update();
+ emit trackHeightChanged();
+ //QTimer::singleShot(500, this, SIGNAL(trackHeightChanged()));
}
void CustomTrackView::changeTrack(int ix, TrackInfo type)
m_document->switchTrackAudio(tracknumber, !m_document->trackInfoAt(tracknumber).isMute);
kDebug() << "NEXT TRK STATE: " << m_document->trackInfoAt(tracknumber).isMute << m_document->trackInfoAt(tracknumber).isBlind;
m_document->renderer()->mltChangeTrackState(tracknumber + 1, m_document->trackInfoAt(tracknumber).isMute, m_document->trackInfoAt(tracknumber).isBlind);
- m_document->setModified(true);
+ setDocumentModified();
}
void CustomTrackView::slotSwitchTrackLock(int ix)
}
kDebug() << "NEXT TRK STATE: " << m_document->trackInfoAt(tracknumber).isLocked;
viewport()->update();
- m_document->setModified(true);
+ setDocumentModified();
}
void CustomTrackView::slotSwitchTrackVideo(int ix)
int tracknumber = m_document->tracksCount() - ix;
m_document->switchTrackVideo(tracknumber - 1, !m_document->trackInfoAt(tracknumber - 1).isBlind);
m_document->renderer()->mltChangeTrackState(tracknumber, m_document->trackInfoAt(tracknumber - 1).isMute, m_document->trackInfoAt(tracknumber - 1).isBlind);
- m_document->setModified(true);
+ setDocumentModified();
+}
+
+QList<QGraphicsItem *> CustomTrackView::checkForGroups(const QRectF &rect, bool &ok)
+{
+ // Check there is no group going over several tracks there, or that would result in timeline corruption
+ QList<QGraphicsItem *> selection = scene()->items(rect);
+ int maxHeight = m_tracksHeight * 1.5;
+ for (int i = 0; i < selection.count(); i++) {
+ // Check that we don't try to move a group with clips on other tracks
+ if (selection.at(i)->type() == GROUPWIDGET && (selection.at(i)->boundingRect().height() >= maxHeight)) {
+ ok = false;
+ break;
+ } else if (selection.at(i)->parentItem() && (selection.at(i)->parentItem()->boundingRect().height() >= maxHeight)) {
+ ok = false;
+ break;
+ }
+ }
+ return selection;
}
void CustomTrackView::slotRemoveSpace()
pos = GenTime((int)(mapToScene(m_menuPosition).x()), m_document->fps());
track = (int)(mapToScene(m_menuPosition).y() / m_tracksHeight);
}
+
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);
int length = m_document->renderer()->mltGetSpaceLength(pos, m_document->tracksCount() - track, true);
//kDebug() << "// GOT LENGT; " << length;
if (length <= 0) {
- 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);
+ 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);
return;
}
- QRectF r(pos.frames(m_document->fps()), track * m_tracksHeight + m_tracksHeight / 2, sceneRect().width() - pos.frames(m_document->fps()), m_tracksHeight / 2 - 1);
- QList<QGraphicsItem *> items = m_scene->items(r);
+ // 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<QGraphicsItem *> items = checkForGroups(rect, isOk);
+ if (!isOk) {
+ // groups found on track, do not allow the move
+ emit displayMessage(i18n("Cannot remove space in a track with a group"), ErrorMessage);
+ return;
+ }
QList<ItemInfo> clipsToMove;
QList<ItemInfo> transitionsToMove;
if (d.exec() != QDialog::Accepted) return;
GenTime spaceDuration = d.selectedDuration();
track = d.selectedTrack();
+
ClipItem *item = getClipItemAt(pos, track);
if (item) pos = item->startPos();
- int minh = 0;
- int maxh = sceneRect().height();
- if (track != -1) {
- minh = track * m_tracksHeight + m_tracksHeight / 2;
- maxh = m_tracksHeight / 2 - 1;
+ // 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<QGraphicsItem *> 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;
}
- QRectF r(pos.frames(m_document->fps()), minh, sceneRect().width() - pos.frames(m_document->fps()), maxh);
- QList<QGraphicsItem *> items = m_scene->items(r);
-
QList<ItemInfo> clipsToMove;
QList<ItemInfo> transitionsToMove;
}
if (trackClipStartList.value(m_document->tracksCount() - clipsToMove.at(i).track) == -1 || clipsToMove.at(i).startPos.frames(m_document->fps()) < trackClipStartList.value(m_document->tracksCount() - clipsToMove.at(i).track))
trackClipStartList[m_document->tracksCount() - clipsToMove.at(i).track] = clipsToMove.at(i).startPos.frames(m_document->fps());
- } else emit displayMessage(i18n("Cannot move clip at position %1, track %2", m_document->timecode().getTimecodeFromFrames(clipsToMove.at(i).startPos.frames(m_document->fps())), clipsToMove.at(i).track), ErrorMessage);
- }
+ } else emit {
+ displayMessage(i18n("Cannot move clip at position %1, track %2", m_document->timecode().getTimecodeFromFrames((clipsToMove.at(i).startPos + offset).frames(m_document->fps())), clipsToMove.at(i).track), ErrorMessage);
+ }
+ }
if (!transToMove.isEmpty()) for (int i = 0; i < transToMove.count(); i++) {
transition = getTransitionItemAtStart(transToMove.at(i).startPos + offset, transToMove.at(i).track);
if (transition) {
- if (transition->parentItem()) m_selectionGroup->addToGroup(transition->parentItem());
- m_selectionGroup->addToGroup(transition);
+ if (transition->parentItem()) {
+ m_selectionGroup->addToGroup(transition->parentItem());
+ transition->parentItem()->setFlags(QGraphicsItem::ItemIsSelectable);
+ } else {
+ m_selectionGroup->addToGroup(transition);
+ transition->setFlags(QGraphicsItem::ItemIsSelectable);
+ }
if (trackTransitionStartList.value(m_document->tracksCount() - transToMove.at(i).track) == -1 || transToMove.at(i).startPos.frames(m_document->fps()) < trackTransitionStartList.value(m_document->tracksCount() - transToMove.at(i).track))
trackTransitionStartList[m_document->tracksCount() - transToMove.at(i).track] = transToMove.at(i).startPos.frames(m_document->fps());
- transition->setFlags(QGraphicsItem::ItemIsSelectable);
} else emit displayMessage(i18n("Cannot move transition at position %1, track %2", m_document->timecode().getTimecodeFromFrames(transToMove.at(i).startPos.frames(m_document->fps())), transToMove.at(i).track), ErrorMessage);
}
m_selectionGroup->translate(diff, 0);
// update items coordinates
- QList<QGraphicsItem *> itemList = scene()->selectedItems();
+ QList<QGraphicsItem *> itemList = m_selectionGroup->childItems();
+
for (int i = 0; i < itemList.count(); i++) {
if (itemList.at(i)->type() == AVWIDGET || itemList.at(i)->type() == TRANSITIONWIDGET) {
static_cast < AbstractClipItem *>(itemList.at(i))->updateItem();
} else if (itemList.at(i)->type() == GROUPWIDGET) {
QList<QGraphicsItem *> children = itemList.at(i)->childItems();
for (int j = 0; j < children.count(); j++) {
- static_cast < AbstractClipItem *>(children.at(j))->updateItem();
+ AbstractClipItem * clp = static_cast < AbstractClipItem *>(children.at(j));
+ clp->updateItem();
}
}
}
resetSelectionGroup();
QList<QGraphicsItem *> itemList = items();
QUndoCommand *deleteCommand = new QUndoCommand();
- deleteCommand->setText(i18n("Delete timeline clips"));
int count = 0;
for (int i = 0; i < itemList.count(); i++) {
if (itemList.at(i)->type() == AVWIDGET) {
}
}
}
+ deleteCommand->setText(i18np("Delete timeline clip", "Delete timeline clips", count));
if (count == 0) delete deleteCommand;
else m_commandStack->push(deleteCommand);
}
{
if (m_moveOpMode == SEEK) m_moveOpMode = NONE;
QGraphicsView::mouseReleaseEvent(event);
+ setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
if (m_scrollTimer.isActive()) m_scrollTimer.stop();
if (event->button() == Qt::MidButton) {
return;
EditGuideCommand *command = new EditGuideCommand(this, m_dragGuide->position(), m_dragGuide->label(), newPos, m_dragGuide->label(), false);
m_commandStack->push(command);
m_dragGuide->updateGuide(GenTime(m_dragGuide->pos().x(), m_document->fps()));
+ qSort(m_guides.begin(), m_guides.end(), sortGuidesList);
m_document->syncGuides(m_guides);
}
m_dragGuide = NULL;
// We are moving all tracks
track = -1;
} else track = (int)(mapToScene(m_clickEvent).y() / m_tracksHeight);
- GenTime timeOffset = GenTime(m_selectionGroup->scenePos().x(), m_document->fps()) - m_selectionGroupInfo.startPos;
+ GenTime timeOffset = GenTime((int)(m_selectionGroup->scenePos().x()), m_document->fps()) - m_selectionGroupInfo.startPos;
+
if (timeOffset != GenTime()) {
QList<QGraphicsItem *> items = m_selectionGroup->childItems();
trackTransitionStartList[i] = -1;
}
- int max = items.count();
- for (int i = 0; i < max; i++) {
+ for (int i = 0; i < items.count(); i++) {
if (items.at(i)->type() == GROUPWIDGET)
- items += static_cast <QGraphicsItemGroup *>(items.at(i))->childItems();
+ items += items.at(i)->childItems();
}
for (int i = 0; i < items.count(); i++) {
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);
+
if (success) {
- kDebug() << "// get trans info";
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 *tr = getTransitionItemAtStart(m_dragItemInfo.startPos, m_dragItemInfo.track);
- kDebug() << "// get trans info2";
if (tr && tr->isAutomatic()) {
ItemInfo trInfo = tr->info();
ItemInfo newTrInfo = trInfo;
ItemInfo trInfo = tr->info();
ItemInfo newTrInfo = trInfo;
newTrInfo.endPos = m_dragItem->endPos();
+ kDebug() << "CLIP ENDS AT: " << newTrInfo.endPos.frames(25);
+ kDebug() << "CLIP STARTS AT: " << newTrInfo.startPos.frames(25);
ClipItem * upperClip = getClipItemAt(m_dragItemInfo.startPos, m_dragItemInfo.track - 1);
if (!upperClip || !upperClip->baseClip()->isTransparent()) {
if (!getClipItemAtStart(trInfo.startPos, tr->track())) {
KdenliveSettings::setSnaptopoints(snap);
emit displayMessage(i18n("Cannot move clip to position %1", m_document->timecode().getTimecodeFromFrames(m_dragItemInfo.startPos.frames(m_document->fps()))), ErrorMessage);
}
- m_document->setModified(true);
+ setDocumentModified();
}
if (m_dragItem->type() == TRANSITIONWIDGET && (m_dragItemInfo.startPos != info.startPos || m_dragItemInfo.track != info.track)) {
Transition *transition = static_cast <Transition *>(m_dragItem);
items += items.at(i)->childItems();
}
}
-
+ m_document->renderer()->blockSignals(true);
for (int i = 0; i < items.count(); i++) {
if (items.at(i)->type() != AVWIDGET && items.at(i)->type() != TRANSITIONWIDGET) continue;
AbstractClipItem *item = static_cast <AbstractClipItem *>(items.at(i));
m_document->renderer()->mltDeleteTransition(tr->transitionTag(), tr->transitionEndTrack(), m_document->tracksCount() - info.track, info.startPos, info.endPos, tr->toXML());
}
}
-
+ m_document->renderer()->blockSignals(false);
for (int i = 0; i < items.count(); i++) {
// re-add items in correct place
if (items.at(i)->type() != AVWIDGET && items.at(i)->type() != TRANSITIONWIDGET) continue;
m_selectionGroupInfo.startPos = GenTime(m_selectionGroup->scenePos().x(), m_document->fps());
m_selectionGroupInfo.track = m_selectionGroup->track();
}
- m_document->setModified(true);
+ setDocumentModified();
}
}
m_document->renderer()->doRefresh();
new MoveTransitionCommand(this, trInfo, newTrInfo, true, resizeCommand);
}
}
- updateClipFade(static_cast <ClipItem *>(m_dragItem));
- new ResizeClipCommand(this, m_dragItemInfo, info, false, resizeCommand);
+
+ ClipItem *clip = static_cast < ClipItem * >(m_dragItem);
+ updateClipFade(clip);
+
+ // check keyframes
+ QDomDocument doc;
+ QDomElement root = doc.createElement("list");
+ doc.appendChild(root);
+ QList <int> 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 {
m_dragItem->resizeStart((int) m_dragItemInfo.startPos.frames(m_document->fps()));
}
}
- new ResizeClipCommand(this, m_dragItemInfo, info, false, resizeCommand);
+ // check keyframes
+ ClipItem *clip = static_cast < ClipItem * >(m_dragItem);
+ QDomDocument doc;
+ QDomElement root = doc.createElement("list");
+ doc.appendChild(root);
+ QList <int> 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);
- updateClipFade(static_cast <ClipItem *>(m_dragItem));
+ updateClipFade(clip);
} else {
m_dragItem->resizeEnd((int) m_dragItemInfo.endPos.frames(m_document->fps()));
emit displayMessage(i18n("Error when resizing clip"), ErrorMessage);
//m_document->renderer()->doRefresh();
} else if (m_operationMode == FADEIN) {
// resize fade in effect
- ClipItem * item = (ClipItem *) m_dragItem;
+ ClipItem * item = static_cast <ClipItem *>(m_dragItem);
int ix = item->hasEffect("volume", "fadein");
if (ix != -1) {
QDomElement oldeffect = item->effectAt(ix);
}
} else if (m_operationMode == FADEOUT) {
// resize fade in effect
- ClipItem * item = (ClipItem *) m_dragItem;
+ ClipItem * item = static_cast <ClipItem *>(m_dragItem);
int ix = item->hasEffect("volume", "fadeout");
if (ix != -1) {
QDomElement oldeffect = item->effectAt(ix);
- int end = (item->duration() + item->cropStart()).frames(m_document->fps());
+ int end = (item->cropDuration() + item->cropStart()).frames(m_document->fps());
int start = item->fadeOut();
if (start == 0) {
slotDeleteEffect(item, oldeffect);
ix = item->hasEffect("brightness", "fade_to_black");
if (ix != -1) {
QDomElement oldeffect = item->effectAt(ix);
- int end = (item->duration() + item->cropStart()).frames(m_document->fps());
+ int end = (item->cropDuration() + item->cropStart()).frames(m_document->fps());
int start = item->fadeOut();
if (start == 0) {
slotDeleteEffect(item, oldeffect);
}
} else if (m_operationMode == KEYFRAME) {
// update the MLT effect
- ClipItem * item = (ClipItem *) m_dragItem;
+ ClipItem * item = static_cast <ClipItem *>(m_dragItem);
QString previous = item->keyframes(item->selectedEffectIndex());
item->updateKeyframeEffect();
QString next = item->keyframes(item->selectedEffectIndex());
EditKeyFrameCommand *command = new EditKeyFrameCommand(this, item->track(), item->startPos(), item->selectedEffectIndex(), previous, next, false);
m_commandStack->push(command);
updateEffect(m_document->tracksCount() - item->track(), item->startPos(), item->selectedEffect(), item->selectedEffectIndex());
+ emit clipItemSelected(item, item->selectedEffectIndex());
}
if (m_dragItem && m_dragItem->type() == TRANSITIONWIDGET && m_dragItem->isSelected()) {
// A transition is selected
ClipItem *transitionClip = getClipItemAt(m_dragItemInfo.startPos, m_dragItemInfo.track);
if (transitionClip && transitionClip->baseClip()) {
QString size = transitionClip->baseClip()->getProperty("frame_size");
- p.setX(size.section('x', 0, 0).toInt());
+ double factor = transitionClip->baseClip()->getProperty("aspect_ratio").toDouble();
+ p.setX((int)(size.section('x', 0, 0).toInt() * factor + 0.5));
p.setY(size.section('x', 1, 1).toInt());
}
emit transitionItemSelected(static_cast <Transition *>(m_dragItem), getPreviousVideoTrack(m_dragItem->track()), p);
} else emit transitionItemSelected(NULL);
- if (m_operationMode != NONE && m_operationMode != MOVE) m_document->setModified(true);
+ if (m_operationMode != NONE && m_operationMode != MOVE) setDocumentModified();
m_operationMode = NONE;
}
-void CustomTrackView::deleteClip(ItemInfo info)
+void CustomTrackView::deleteClip(ItemInfo info, bool refresh)
{
ClipItem *item = getClipItemAt((int) info.startPos.frames(m_document->fps()), info.track);
delete tr;
}
}*/
- scene()->removeItem(item);
m_waitingThumbs.removeAll(item);
if (m_dragItem == item) m_dragItem = NULL;
+ scene()->removeItem(item);
delete item;
item = NULL;
- m_document->setModified(true);
- m_document->renderer()->doRefresh();
+ setDocumentModified();
+ if (refresh) m_document->renderer()->doRefresh();
}
void CustomTrackView::deleteSelectedClips()
}
scene()->clearSelection();
QUndoCommand *deleteSelected = new QUndoCommand();
- deleteSelected->setText(i18n("Delete selected items"));
- bool resetGroup = false;
+ bool resetGroup = false;
+ int groupCount = 0;
+ int clipCount = 0;
+ int transitionCount = 0;
// expand & destroy groups
for (int i = 0; i < itemList.count(); i++) {
if (itemList.at(i)->type() == GROUPWIDGET) {
+ groupCount++;
QList<QGraphicsItem *> children = itemList.at(i)->childItems();
itemList += children;
QList <ItemInfo> clipInfos;
for (int i = 0; i < itemList.count(); i++) {
if (itemList.at(i)->type() == AVWIDGET) {
+ clipCount++;
ClipItem *item = static_cast <ClipItem *>(itemList.at(i));
if (item->parentItem()) resetGroup = true;
+ //kDebug()<<"// DELETE CLP AT: "<<item->info().startPos.frames(25);
new AddTimelineClipCommand(this, item->xml(), item->clipProducer(), item->info(), item->effectList(), true, true, deleteSelected);
emit clipItemSelected(NULL);
} else if (itemList.at(i)->type() == TRANSITIONWIDGET) {
+ transitionCount++;
Transition *item = static_cast <Transition *>(itemList.at(i));
+ //kDebug()<<"// DELETE TRANS AT: "<<item->info().startPos.frames(25);
if (item->parentItem()) resetGroup = true;
new AddTransitionCommand(this, item->info(), item->transitionEndTrack(), item->toXML(), true, true, deleteSelected);
emit transitionItemSelected(NULL);
}
}
-
+ if (groupCount > 0 && clipCount == 0 && transitionCount == 0)
+ deleteSelected->setText(i18np("Delete selected group", "Delete selected groups", groupCount));
+ else if (clipCount > 0 && groupCount == 0 && transitionCount == 0)
+ deleteSelected->setText(i18np("Delete selected clip", "Delete selected clips", clipCount));
+ else if (transitionCount > 0 && groupCount == 0 && clipCount == 0)
+ deleteSelected->setText(i18np("Delete selected transition", "Delete selected transitions", transitionCount));
+ else deleteSelected->setText(i18n("Delete selected items"));
m_commandStack->push(deleteSelected);
}
double speed = (double) percent / 100.0;
if (item->speed() != speed && (item->clipType() == VIDEO || item->clipType() == AV)) {
count++;
- new ChangeSpeedCommand(this, info, item->speed(), speed, item->clipProducer(), changeSelected);
+ //new ChangeSpeedCommand(this, info, item->speed(), speed, item->clipProducer(), changeSelected);
}
}
}
else delete changeSelected;
}
-void CustomTrackView::doChangeClipSpeed(ItemInfo info, const double speed, const double oldspeed, const QString &id)
+void CustomTrackView::doChangeClipSpeed(ItemInfo info, const double speed, const double oldspeed, int strobe, const QString &id)
{
DocClipBase *baseclip = m_document->clipManager()->getClipById(id);
ClipItem *item = getClipItemAt((int) info.startPos.frames(m_document->fps()), info.track);
return;
}
info.track = m_document->tracksCount() - item->track();
- int endPos = m_document->renderer()->mltChangeClipSpeed(info, speed, oldspeed, baseclip->producer());
+ int endPos = m_document->renderer()->mltChangeClipSpeed(info, speed, oldspeed, strobe, baseclip->producer());
if (endPos >= 0) {
- item->setSpeed(speed);
+ item->setSpeed(speed, strobe);
item->updateRectGeometry();
if (item->cropDuration().frames(m_document->fps()) > endPos)
item->AbstractClipItem::resizeEnd(info.startPos.frames(m_document->fps()) + endPos, speed);
- m_document->setModified(true);
+ updateClipFade(item);
+ setDocumentModified();
} else emit displayMessage(i18n("Invalid clip"), ErrorMessage);
}
}
tr->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
}
- m_document->setModified(true);
+ setDocumentModified();
return;
}
}
groupSelectedItems(false, true);
- m_document->setModified(true);
+ setDocumentModified();
}
-void CustomTrackView::addClip(QDomElement xml, const QString &clipId, ItemInfo info, EffectsList effects)
+void CustomTrackView::addClip(QDomElement xml, const QString &clipId, ItemInfo info, EffectsList effects, bool refresh)
{
DocClipBase *baseclip = m_document->clipManager()->getClipById(clipId);
if (baseclip == NULL) {
emit displayMessage(i18n("No clip copied"), ErrorMessage);
return;
}
- ClipItem *item = new ClipItem(baseclip, info, m_document->fps(), xml.attribute("speed", "1").toDouble());
+ ClipItem *item = new ClipItem(baseclip, info, m_document->fps(), xml.attribute("speed", "1").toDouble(), xml.attribute("strobe", "1").toInt());
item->setEffectList(effects);
if (xml.hasAttribute("audio_only")) item->setAudioOnly(true);
else if (xml.hasAttribute("video_only")) item->setVideoOnly(true);
for (int i = 0; i < item->effectsCount(); i++) {
m_document->renderer()->mltAddEffect(info.track, info.startPos, item->getEffectArgs(item->effectAt(i)), false);
}
- m_document->setModified(true);
- m_document->renderer()->doRefresh();
+ setDocumentModified();
+ if (refresh) m_document->renderer()->doRefresh();
m_waitingThumbs.append(item);
m_thumbsTimer.start();
}
-void CustomTrackView::slotUpdateClip(const QString &clipId)
+void CustomTrackView::slotUpdateClip(const QString &clipId, bool reload)
{
QList<QGraphicsItem *> list = scene()->items();
ClipItem *clip = NULL;
if (clip->clipProducer() == clipId) {
ItemInfo info = clip->info();
info.track = m_document->tracksCount() - clip->track();
- m_document->renderer()->mltUpdateClip(info, clip->xml(), clip->baseClip()->producer());
+ if (reload) m_document->renderer()->mltUpdateClip(info, clip->xml(), clip->baseClip()->producer());
clip->refreshClip(true);
clip->update();
}
ClipItem *CustomTrackView::getClipItemAt(int pos, int track)
{
- QList<QGraphicsItem *> list = scene()->items(QPointF(pos, track * m_tracksHeight + m_tracksHeight / 2));
+ const QPointF p(pos, track * m_tracksHeight + m_tracksHeight / 2);
+ QList<QGraphicsItem *> list = scene()->items(p);
ClipItem *clip = NULL;
for (int i = 0; i < list.size(); i++) {
if (list.at(i)->type() == AVWIDGET) {
ClipItem *CustomTrackView::getClipItemAt(GenTime pos, int track)
{
- int framepos = (int)(pos.frames(m_document->fps()));
- return getClipItemAt(framepos, track);
+ return getClipItemAt((int) pos.frames(m_document->fps()), track);
}
Transition *CustomTrackView::getTransitionItemAt(int pos, int track)
{
- QList<QGraphicsItem *> list = scene()->items(QPointF(pos, (track + 1) * m_tracksHeight));
+ const QPointF p(pos, (track + 1) * m_tracksHeight);
+ QList<QGraphicsItem *> list = scene()->items(p);
Transition *clip = NULL;
for (int i = 0; i < list.size(); i++) {
if (list.at(i)->type() == TRANSITIONWIDGET) {
Transition *CustomTrackView::getTransitionItemAtEnd(GenTime pos, int track)
{
int framepos = (int)(pos.frames(m_document->fps()));
- QList<QGraphicsItem *> list = scene()->items(QPointF(framepos - 1, (track + 1) * m_tracksHeight));
+ const QPointF p(framepos - 1, (track + 1) * m_tracksHeight);
+ QList<QGraphicsItem *> list = scene()->items(p);
Transition *clip = NULL;
for (int i = 0; i < list.size(); i++) {
if (list.at(i)->type() == TRANSITIONWIDGET) {
Transition *CustomTrackView::getTransitionItemAtStart(GenTime pos, int track)
{
- QList<QGraphicsItem *> list = scene()->items(QPointF(pos.frames(m_document->fps()), (track + 1) * m_tracksHeight));
+ const QPointF p(pos.frames(m_document->fps()), (track + 1) * m_tracksHeight);
+ QList<QGraphicsItem *> list = scene()->items(p);
Transition *clip = NULL;
for (int i = 0; i < list.size(); ++i) {
if (list.at(i)->type() == TRANSITIONWIDGET) {
return clip;
}
-void CustomTrackView::moveClip(const ItemInfo start, const ItemInfo end)
+void CustomTrackView::moveClip(const ItemInfo start, const ItemInfo end, bool refresh)
{
if (m_selectionGroup) resetSelectionGroup(false);
- ClipItem *item = getClipItemAt((int) start.startPos.frames(m_document->fps()) + 1, start.track);
+ ClipItem *item = getClipItemAt((int) start.startPos.frames(m_document->fps()), start.track);
if (!item) {
emit displayMessage(i18n("Cannot move clip at time: %1 on track %2", m_document->timecode().getTimecodeFromFrames(start.startPos.frames(m_document->fps())), start.track), ErrorMessage);
kDebug() << "---------------- ERROR, CANNOT find clip to move at.. ";
}
}
KdenliveSettings::setSnaptopoints(snap);
- m_document->setModified(true);
+ setDocumentModified();
} else {
// undo last move and emit error message
emit displayMessage(i18n("Cannot move clip to position %1", m_document->timecode().getTimecodeFromFrames(end.startPos.frames(m_document->fps()))), ErrorMessage);
}
- m_document->renderer()->doRefresh();
+ if (refresh) m_document->renderer()->doRefresh();
//kDebug() << " // MOVED CLIP TO: " << end.startPos.frames(25) << ", ITEM START: " << item->startPos().frames(25);
}
resetSelectionGroup();
m_scene->clearSelection();
+ m_selectionGroup = new AbstractGroupItem(m_document->fps());
+ scene()->addItem(m_selectionGroup);
+
+ m_document->renderer()->blockSignals(true);
for (int i = 0; i < startClip.count(); i++) {
if (reverseMove) {
startClip[i].startPos = startClip.at(i).startPos - offset;
ClipItem *clip = getClipItemAt(startClip.at(i).startPos, startClip.at(i).track);
if (clip) {
clip->setItemLocked(false);
- if (clip->parentItem()) clip->parentItem()->setSelected(true);
- else clip->setSelected(true);
+ if (clip->parentItem()) {
+ m_selectionGroup->addToGroup(clip->parentItem());
+ clip->parentItem()->setFlags(QGraphicsItem::ItemIsSelectable);
+ } else {
+ m_selectionGroup->addToGroup(clip);
+ clip->setFlags(QGraphicsItem::ItemIsSelectable);
+ }
m_document->renderer()->mltRemoveClip(m_document->tracksCount() - startClip.at(i).track, startClip.at(i).startPos);
} else kDebug() << "//MISSING CLIP AT: " << startClip.at(i).startPos.frames(25);
}
Transition *tr = getTransitionItemAt(startTransition.at(i).startPos, startTransition.at(i).track);
if (tr) {
tr->setItemLocked(false);
- if (tr->parentItem()) tr->parentItem()->setSelected(true);
- else tr->setSelected(true);
+ if (tr->parentItem()) {
+ m_selectionGroup->addToGroup(tr->parentItem());
+ tr->parentItem()->setFlags(QGraphicsItem::ItemIsSelectable);
+ } else {
+ m_selectionGroup->addToGroup(tr);
+ tr->setFlags(QGraphicsItem::ItemIsSelectable);
+ }
m_document->renderer()->mltDeleteTransition(tr->transitionTag(), tr->transitionEndTrack(), m_document->tracksCount() - startTransition.at(i).track, startTransition.at(i).startPos, startTransition.at(i).endPos, tr->toXML());
} else kDebug() << "//MISSING TRANSITION AT: " << startTransition.at(i).startPos.frames(25);
}
- groupSelectedItems(true);
+ m_document->renderer()->blockSignals(false);
+
if (m_selectionGroup) {
bool snap = KdenliveSettings::snaptopoints();
KdenliveSettings::setSnaptopoints(false);
- m_selectionGroup->moveBy(offset.frames(m_document->fps()), trackOffset *(qreal) m_tracksHeight);
-
- kDebug() << "%% GRP NEW POS: " << m_selectionGroup->scenePos().x();
+ m_selectionGroup->translate(offset.frames(m_document->fps()), trackOffset *(qreal) m_tracksHeight);
+ //m_selectionGroup->moveBy(offset.frames(m_document->fps()), trackOffset *(qreal) m_tracksHeight);
QList<QGraphicsItem *> children = m_selectionGroup->childItems();
// Expand groups
for (int i = 0; i < max; i++) {
if (children.at(i)->type() == GROUPWIDGET) {
children += children.at(i)->childItems();
+ AbstractGroupItem *grp = static_cast<AbstractGroupItem *>(children.at(i));
+ //grp->moveBy(offset.frames(m_document->fps()), trackOffset *(qreal) m_tracksHeight);
+ /*m_document->clipManager()->removeGroup(grp);
+ m_scene->destroyItemGroup(grp);*/
+ children.removeAll(children.at(i));
+ i--;
}
}
- kDebug() << "// GRP MOVE; FOUND CHILDREN:" << children.count();
for (int i = 0; i < children.count(); i++) {
// re-add items in correct place
m_document->renderer()->mltAddTransition(tr->transitionTag(), newTrack, m_document->tracksCount() - info.track, info.startPos, info.endPos, tr->toXML());
}
}
+ resetSelectionGroup(false);
KdenliveSettings::setSnaptopoints(snap);
m_document->renderer()->doRefresh();
} else kDebug() << "///////// WARNING; NO GROUP TO MOVE";
}
-void CustomTrackView::moveTransition(const ItemInfo start, const ItemInfo end)
+void CustomTrackView::moveTransition(const ItemInfo start, const ItemInfo end, bool m_refresh)
{
Transition *item = getTransitionItemAt(start.startPos, start.track);
if (!item) {
item->resizeStart((int) end.startPos.frames(m_document->fps()));
} else if (end.startPos == start.startPos) {
// Transition end resize;
+ kDebug() << "// resize END: " << end.endPos.frames(m_document->fps());
item->resizeEnd((int) end.endPos.frames(m_document->fps()));
} else {
// Move & resize
ClipItem *transitionClip = getClipItemAt(item->startPos(), item->track());
if (transitionClip && transitionClip->baseClip()) {
QString size = transitionClip->baseClip()->getProperty("frame_size");
- p.setX(size.section('x', 0, 0).toInt());
+ double factor = transitionClip->baseClip()->getProperty("aspect_ratio").toDouble();
+ p.setX((int)(size.section('x', 0, 0).toInt() * factor + 0.5));
p.setY(size.section('x', 1, 1).toInt());
}
emit transitionItemSelected(item, getPreviousVideoTrack(item->track()), p);
}
- m_document->renderer()->doRefresh();
+ if (m_refresh) m_document->renderer()->doRefresh();
}
-void CustomTrackView::resizeClip(const ItemInfo start, const ItemInfo end)
+void CustomTrackView::resizeClip(const ItemInfo start, const ItemInfo end, bool dontWorry)
{
- bool resizeClipStart = true;
- if (start.startPos == end.startPos) resizeClipStart = false;
- /*if (resizeClipStart) offset = 1;
- else offset = -1;*/
- ClipItem *item = getClipItemAt((int)(start.startPos.frames(m_document->fps())), start.track);
+ bool resizeClipStart = (start.startPos != end.startPos);
+ ClipItem *item = getClipItemAtStart(start.startPos, start.track);
if (!item) {
+ if (dontWorry) return;
emit displayMessage(i18n("Cannot move clip at time: %1 on track %2", m_document->timecode().getTimecodeFromFrames(start.startPos.frames(m_document->fps())), start.track), ErrorMessage);
kDebug() << "---------------- ERROR, CANNOT find clip to resize at... "; // << startPos;
return;
// Item is part of a group, reset group
resetSelectionGroup();
}
+
bool snap = KdenliveSettings::snaptopoints();
KdenliveSettings::setSnaptopoints(false);
- if (resizeClipStart && start.startPos != end.startPos) {
+ if (resizeClipStart) {
ItemInfo clipinfo = item->info();
clipinfo.track = m_document->tracksCount() - clipinfo.track;
- bool success = m_document->renderer()->mltResizeClipStart(clipinfo, end.startPos - item->startPos());
+ bool success = m_document->renderer()->mltResizeClipStart(clipinfo, end.startPos - clipinfo.startPos);
if (success) {
kDebug() << "RESIZE CLP STRAT TO:" << end.startPos.frames(m_document->fps()) << ", OLD ST: " << start.startPos.frames(25);
item->resizeStart((int) end.startPos.frames(m_document->fps()));
updateClipFade(item);
} else emit displayMessage(i18n("Error when resizing clip"), ErrorMessage);
- } else if (!resizeClipStart) {
+ } else {
ItemInfo clipinfo = item->info();
clipinfo.track = m_document->tracksCount() - clipinfo.track;
bool success = m_document->renderer()->mltResizeClipEnd(clipinfo, end.endPos - clipinfo.startPos);
updateClipFade(item);
} else emit displayMessage(i18n("Error when resizing clip"), ErrorMessage);
}
- if (end.cropStart != start.cropStart) {
+ if (!resizeClipStart && end.cropStart != start.cropStart) {
kDebug() << "// RESIZE CROP, DIFF: " << (end.cropStart - start.cropStart).frames(25);
ItemInfo clipinfo = end;
clipinfo.track = m_document->tracksCount() - end.track;
void CustomTrackView::updateSnapPoints(AbstractClipItem *selected, QList <GenTime> offsetList, bool skipSelectedItems)
{
QList <GenTime> snaps;
- if (selected && offsetList.isEmpty()) offsetList.append(selected->duration());
+ if (selected && offsetList.isEmpty()) offsetList.append(selected->cropDuration());
QList<QGraphicsItem *> itemList = items();
for (int i = 0; i < itemList.count(); i++) {
if (itemList.at(i) == selected) continue;
void CustomTrackView::clipStart()
{
- ClipItem *item = getMainActiveClip();
+ AbstractClipItem *item = getMainActiveClip();
if (item != NULL) {
setCursorPos((int) item->startPos().frames(m_document->fps()));
checkScrolling();
void CustomTrackView::clipEnd()
{
- ClipItem *item = getMainActiveClip();
+ AbstractClipItem *item = getMainActiveClip();
if (item != NULL) {
setCursorPos((int) item->endPos().frames(m_document->fps()) - 1);
checkScrolling();
DocClipBase *base = m_document->clipManager()->getClipById(id);
if (!comment.isEmpty()) base->addSnapMarker(pos, comment);
else base->deleteSnapMarker(pos);
- m_document->setModified(true);
+ emit updateClipMarkers(base);
+ setDocumentModified();
viewport()->update();
}
-bool sortGuidesList(const Guide *g1 , const Guide *g2)
-{
- return (*g1).position() < (*g2).position();
-}
-
int CustomTrackView::hasGuide(int pos, int offset)
{
for (int i = 0; i < m_guides.count(); i++) {
return false;
}
}
- Guide *g = new Guide(this, pos, comment, m_document->fps(), m_tracksHeight * m_document->tracksCount());
+ Guide *g = new Guide(this, pos, comment, m_tracksHeight * m_document->tracksCount());
scene()->addItem(g);
m_guides.append(g);
qSort(m_guides.begin(), m_guides.end(), sortGuidesList);
QMatrix matrix;
matrix = matrix.scale(scaleFactor, verticalScale);
m_scene->setScale(scaleFactor, verticalScale);
+ if (m_visualTip) scene()->removeItem(m_visualTip);
m_animationTimer->stop();
delete m_visualTip;
m_visualTip = NULL;
delete m_animation;
m_animation = NULL;
-
- //setSceneRect(0, 0, m_projectDuration + 100 * scaleFactor, sceneRect().height());
+ double verticalPos = mapToScene(QPoint(0, viewport()->height() / 2)).y();
setMatrix(matrix);
+ m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), m_tracksHeight * m_document->tracksCount() * verticalScale);
int diff = sceneRect().width() - m_projectDuration;
if (diff * matrix.m11() < 50) {
if (matrix.m11() < 0.4) setSceneRect(0, 0, (m_projectDuration + 100 / matrix.m11()), sceneRect().height());
else setSceneRect(0, 0, (m_projectDuration + 300), sceneRect().height());
}
-
- centerOn(QPointF(cursorPos(), m_tracksHeight));
- //verticalScrollBar()->setValue(vert);*/
+ centerOn(QPointF(cursorPos(), verticalPos));
}
void CustomTrackView::slotRefreshGuides()
{
if (KdenliveSettings::showmarkers()) {
- kDebug() << "// refresh GUIDES";
for (int i = 0; i < m_guides.count(); i++) {
m_guides.at(i)->update();
}
void CustomTrackView::drawBackground(QPainter * painter, const QRectF &rect)
{
- QRectF r = rect;
- r.setWidth(r.width() + 1);
- painter->setClipRect(r);
- painter->drawLine(r.left(), 0, r.right(), 0);
- uint max = m_document->tracksCount();
+ //kDebug() << "// DRAW BG: " << rect.width();
+ painter->setClipRect(rect);
KColorScheme scheme(palette().currentColorGroup(), KColorScheme::Window);
+ QPen pen1 = painter->pen();
+ pen1.setColor(scheme.shade(KColorScheme::DarkShade));
+ painter->setPen(pen1);
+ double min = rect.left();
+ double max = rect.right();
+ painter->drawLine(QPointF(min, 0), QPointF(max, 0));
+ uint maxTrack = m_document->tracksCount();
QColor lockedColor = scheme.background(KColorScheme::NegativeBackground).color();
QColor audioColor = palette().alternateBase().color();
QColor base = scheme.background(KColorScheme::NormalBackground).color();
- for (uint i = 0; i < max; i++) {
- if (m_document->trackInfoAt(max - i - 1).isLocked == true) painter->fillRect(r.left(), m_tracksHeight * i + 1, r.right() - r.left() + 1, m_tracksHeight - 1, QBrush(lockedColor));
- else if (m_document->trackInfoAt(max - i - 1).type == AUDIOTRACK) painter->fillRect(r.left(), m_tracksHeight * i + 1, r.right() - r.left() + 1, m_tracksHeight - 1, QBrush(audioColor));
- painter->drawLine(r.left(), m_tracksHeight *(i + 1), r.right(), m_tracksHeight *(i + 1));
+ for (uint i = 0; i < maxTrack; i++) {
+ TrackInfo info = m_document->trackInfoAt(maxTrack - i - 1);
+ if (info.isLocked || info.type == AUDIOTRACK) {
+ const QRectF track(min, m_tracksHeight * i + 1, max - min, m_tracksHeight - 1);
+ painter->fillRect(track, info.isLocked ? lockedColor : audioColor);
+ }
+ painter->drawLine(QPointF(min, m_tracksHeight *(i + 1)), QPointF(max, m_tracksHeight *(i + 1)));
+ }
+ int lowerLimit = m_tracksHeight * maxTrack + 1;
+ if (height() > lowerLimit) {
+ const QRectF bg(min, lowerLimit, max - min, height() - lowerLimit);
+ painter->fillRect(bg, base);
}
- int lowerLimit = m_tracksHeight * m_document->tracksCount() + 1;
- if (height() > lowerLimit)
- painter->fillRect(QRectF(r.left(), lowerLimit, r.width(), height() - lowerLimit), QBrush(base));
}
bool CustomTrackView::findString(const QString &text)
}
for (int i = 0; i < itemList.count(); i++) {
if (itemList.at(i)->type() == AVWIDGET) {
- ClipItem *dup = static_cast <ClipItem *>(itemList.at(i));
- m_copiedItems.append(dup->clone(dup->info()));
+ ClipItem *clip = static_cast <ClipItem *>(itemList.at(i));
+ ClipItem *clone = clip->clone(clip->info());
+ m_copiedItems.append(clone);
} else if (itemList.at(i)->type() == TRANSITIONWIDGET) {
Transition *dup = static_cast <Transition *>(itemList.at(i));
m_copiedItems.append(dup->clone());
return true;
}
+bool CustomTrackView::canBePastedTo(QList <ItemInfo> infoList, int type) const
+{
+ QPainterPath path;
+ for (int i = 0; i < infoList.count(); i++) {
+ const QRectF rect((double) infoList.at(i).startPos.frames(m_document->fps()), (double)(infoList.at(i).track * m_tracksHeight + 1), (double)(infoList.at(i).endPos - infoList.at(i).startPos).frames(m_document->fps()), (double)(m_tracksHeight - 1));
+ path.addRect(rect);
+ }
+ QList<QGraphicsItem *> collisions = scene()->items(path);
+ for (int i = 0; i < collisions.count(); i++) {
+ if (collisions.at(i)->type() == type) return false;
+ }
+ return true;
+}
+
bool CustomTrackView::canBePasted(QList<AbstractClipItem *> items, GenTime offset, int trackOffset) const
{
for (int i = 0; i < items.count(); i++) {
// parse all clip names
if (m_copiedItems.at(i) && m_copiedItems.at(i)->type() == AVWIDGET) {
ClipItem *clip = static_cast <ClipItem *>(m_copiedItems.at(i));
- ItemInfo info;
- info.startPos = clip->startPos() + offset;
- info.endPos = clip->endPos() + offset;
- info.cropStart = clip->cropStart();
- info.track = clip->track() + trackOffset;
+ ItemInfo info = clip->info();
+ info.startPos += offset;
+ info.endPos += offset;
+ info.track += trackOffset;
if (canBePastedTo(info, AVWIDGET)) {
new AddTimelineClipCommand(this, clip->xml(), clip->clipProducer(), info, clip->effectList(), true, false, pasteClips);
} else emit displayMessage(i18n("Cannot paste clip to selected place"), ErrorMessage);
return;
}
ClipItem *clip = static_cast < ClipItem *>(m_copiedItems.at(0));
- EffectsList effects = clip->effectList();
QUndoCommand *paste = new QUndoCommand();
paste->setText("Paste effects");
for (int i = 0; i < clips.count(); ++i) {
if (clips.at(i)->type() == AVWIDGET) {
ClipItem *item = static_cast < ClipItem *>(clips.at(i));
- for (int i = 0; i < clip->effectsCount(); i++) {
- new AddEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), clip->effectAt(i), true, paste);
+ for (int j = 0; j < clip->effectsCount(); j++) {
+ new AddEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), clip->effectAt(j), true, paste);
}
}
}
return NULL;
}
-ClipItem *CustomTrackView::getMainActiveClip() const
+AbstractClipItem *CustomTrackView::getMainActiveClip() const
{
QList<QGraphicsItem *> clips = scene()->selectedItems();
if (clips.isEmpty()) {
return getClipUnderCursor();
} else {
- ClipItem *item = NULL;
+ AbstractClipItem *item = NULL;
for (int i = 0; i < clips.count(); ++i) {
- if (clips.at(i)->type() == AVWIDGET)
- item = static_cast < ClipItem *>(clips.at(i));
- if (item->startPos().frames(m_document->fps()) <= m_cursorPos && item->endPos().frames(m_document->fps()) >= m_cursorPos) break;
+ if (clips.count() == 1 || clips.at(i)->type() == AVWIDGET) {
+ item = static_cast < AbstractClipItem *>(clips.at(i));
+ if (clips.count() > 1 && item->startPos().frames(m_document->fps()) <= m_cursorPos && item->endPos().frames(m_document->fps()) >= m_cursorPos) break;
+ }
}
if (item) return item;
}
void CustomTrackView::setInPoint()
{
- ClipItem *clip = getActiveClipUnderCursor(true);
+ AbstractClipItem *clip = getActiveClipUnderCursor(true);
if (clip == NULL) {
- emit displayMessage(i18n("You must select one clip for this action"), ErrorMessage);
- return;
+ if (m_dragItem && m_dragItem->type() == TRANSITIONWIDGET) {
+ clip = m_dragItem;
+ } else {
+ emit displayMessage(i18n("You must select one clip for this action"), ErrorMessage);
+ return;
+ }
}
ItemInfo startInfo = clip->info();
ItemInfo endInfo = startInfo;
return;
} else if (endInfo.startPos < startInfo.startPos) {
int length = m_document->renderer()->mltGetSpaceLength(endInfo.startPos, m_document->tracksCount() - startInfo.track, false);
- if (length < (startInfo.startPos - endInfo.startPos).frames(m_document->fps())) {
+ 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;
}
}
- ResizeClipCommand *command = new ResizeClipCommand(this, startInfo, endInfo, true);
- m_commandStack->push(command);
+ if (clip->type() == TRANSITIONWIDGET) {
+ m_commandStack->push(new MoveTransitionCommand(this, startInfo, endInfo, true));
+ } else m_commandStack->push(new ResizeClipCommand(this, startInfo, endInfo, true, false));
}
void CustomTrackView::setOutPoint()
{
- ClipItem *clip = getActiveClipUnderCursor(true);
+ AbstractClipItem *clip = getActiveClipUnderCursor(true);
if (clip == NULL) {
- emit displayMessage(i18n("You must select one clip for this action"), ErrorMessage);
- return;
+ if (m_dragItem && m_dragItem->type() == TRANSITIONWIDGET) {
+ clip = m_dragItem;
+ } else {
+ emit displayMessage(i18n("You must select one clip for this action"), ErrorMessage);
+ return;
+ }
}
ItemInfo startInfo = clip->info();
ItemInfo endInfo = clip->info();
return;
} else if (endInfo.endPos > startInfo.endPos) {
int length = m_document->renderer()->mltGetSpaceLength(endInfo.endPos, m_document->tracksCount() - startInfo.track, false);
- if (length < (endInfo.endPos - startInfo.endPos).frames(m_document->fps())) {
+ if ((clip->type() == TRANSITIONWIDGET && itemCollision(clip, endInfo) == true) || (clip->type() == AVWIDGET && length < (endInfo.endPos - startInfo.endPos).frames(m_document->fps()))) {
emit displayMessage(i18n("Invalid action"), ErrorMessage);
return;
}
}
-
- ResizeClipCommand *command = new ResizeClipCommand(this, startInfo, endInfo, true);
- m_commandStack->push(command);
+ if (clip->type() == TRANSITIONWIDGET) {
+ m_commandStack->push(new MoveTransitionCommand(this, startInfo, endInfo, true));
+ } else m_commandStack->push(new ResizeClipCommand(this, startInfo, endInfo, true, false));
}
void CustomTrackView::slotUpdateAllThumbs()
void CustomTrackView::slotInsertTrack(int ix)
{
- kDebug() << "// INSERTING TRK: " << ix;
- QDialog d(parentWidget());
- Ui::AddTrack_UI view;
- view.setupUi(&d);
- view.track_nb->setMaximum(m_document->tracksCount() - 1);
- view.track_nb->setValue(ix);
- d.setWindowTitle(i18n("Insert Track"));
+ TrackDialog d(m_document, parentWidget());
+ 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 = view.track_nb->value();
- if (view.before_select->currentIndex() == 1) {
+ ix = d.track_nb->value();
+ if (d.before_select->currentIndex() == 1) {
ix++;
}
TrackInfo info;
- if (view.video_track->isChecked()) {
+ if (d.video_track->isChecked()) {
info.type = VIDEOTRACK;
info.isMute = false;
info.isBlind = false;
}
AddTrackCommand *addTrack = new AddTrackCommand(this, ix, info, true);
m_commandStack->push(addTrack);
- m_document->setModified(true);
+ setDocumentModified();
}
}
void CustomTrackView::slotDeleteTrack(int ix)
{
- bool ok;
- ix = QInputDialog::getInteger(this, i18n("Remove Track"), i18n("Track"), ix, 0, m_document->tracksCount() - 1, 1, &ok);
- if (ok) {
+ TrackDialog d(m_document, parentWidget());
+ 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();
TrackInfo info = m_document->trackInfoAt(m_document->tracksCount() - ix - 1);
deleteTimelineTrack(ix, info);
- m_document->setModified(true);
+ setDocumentModified();
/*AddTrackCommand* command = new AddTrackCommand(this, ix, info, false);
m_commandStack->push(command);*/
}
void CustomTrackView::slotChangeTrack(int ix)
{
- QDialog d(parentWidget());
- Ui::AddTrack_UI view;
- view.setupUi(&d);
- view.label->setText(i18n("Change track"));
- view.before_select->setHidden(true);
- view.track_nb->setMaximum(m_document->tracksCount() - 1);
- view.track_nb->setValue(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"));
if (m_document->trackInfoAt(m_document->tracksCount() - ix - 1).type == VIDEOTRACK)
- view.video_track->setChecked(true);
+ d.video_track->setChecked(true);
else
- view.audio_track->setChecked(true);
+ d.audio_track->setChecked(true);
if (d.exec() == QDialog::Accepted) {
TrackInfo info;
info.isLocked = false;
info.isMute = false;
- ix = view.track_nb->value();
+ ix = d.track_nb->value();
- if (view.video_track->isChecked()) {
+ if (d.video_track->isChecked()) {
info.type = VIDEOTRACK;
info.isBlind = false;
} else {
info.isBlind = true;
}
changeTimelineTrack(ix, info);
- m_document->setModified(true);
+ setDocumentModified();
}
}
}
}
- selection = m_scene->items();
new AddTrackCommand(this, ix, trackinfo, false, deleteTrack);
m_commandStack->push(deleteTrack);
}
kDebug() << "// CHK DOC TRK:" << freetrack << ", DUR:" << m_document->renderer()->mltTrackDuration(freetrack);
if (m_document->trackInfoAt(freetrack - 1).type == AUDIOTRACK) {
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->duration().frames(m_document->fps())) {
+ 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;
break;
}
if (freetrack == 0) {
emit displayMessage(i18n("No empty space to put clip audio"), ErrorMessage);
} else {
- ItemInfo info;
- info.startPos = clip->startPos();
- info.endPos = clip->endPos();
- info.cropStart = clip->cropStart();
+ ItemInfo info = clip->info();
info.track = m_document->tracksCount() - freetrack;
addClip(clip->xml(), clip->clipProducer(), info, clip->effectList());
scene()->clearSelection();
m_document->renderer()->mltUpdateClipProducer(m_document->tracksCount() - track, start, clip->baseClip()->producer(track));
}
clip->update();
- m_document->setModified(true);
+ setDocumentModified();
}
void CustomTrackView::updateClipTypeActions(ClipItem *clip)
emit transitionItemSelected(NULL);
}
-#include "customtrackview.moc"
+double CustomTrackView::fps() const
+{
+ return m_document->fps();
+}
+
+void CustomTrackView::updateProjectFps()
+{
+ // update all clips to the new fps
+ resetSelectionGroup();
+ scene()->clearSelection();
+ m_dragItem = NULL;
+ QList<QGraphicsItem *> itemList = items();
+ for (int i = 0; i < itemList.count(); i++) {
+ // remove all items and re-add them one by one
+ if (itemList.at(i) != m_cursorLine && itemList.at(i)->parentItem() == NULL) m_scene->removeItem(itemList.at(i));
+ }
+ for (int i = 0; i < itemList.count(); i++) {
+ if (itemList.at(i)->parentItem() == 0 && (itemList.at(i)->type() == AVWIDGET || itemList.at(i)->type() == TRANSITIONWIDGET)) {
+ AbstractClipItem *clip = static_cast <AbstractClipItem *>(itemList.at(i));
+ clip->updateFps(m_document->fps());
+ m_scene->addItem(clip);
+ } else if (itemList.at(i)->type() == GROUPWIDGET) {
+ AbstractGroupItem *grp = static_cast <AbstractGroupItem *>(itemList.at(i));
+ QList<QGraphicsItem *> children = grp->childItems();
+ for (int j = 0; j < children.count(); j++) {
+ if (children.at(j)->type() == AVWIDGET || children.at(j)->type() == TRANSITIONWIDGET) {
+ AbstractClipItem *clip = static_cast <AbstractClipItem *>(children.at(j));
+ clip->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
+ clip->updateFps(m_document->fps());
+ }
+ }
+ m_document->clipManager()->removeGroup(grp);
+ m_scene->addItem(grp);
+ scene()->destroyItemGroup(grp);
+ for (int j = 0; j < children.count(); j++) {
+ if (children.at(j)->type() == AVWIDGET || children.at(j)->type() == TRANSITIONWIDGET) {
+ //children.at(j)->setParentItem(0);
+ children.at(j)->setSelected(true);
+ }
+ }
+ groupSelectedItems(true, true);
+ } else if (itemList.at(i)->type() == GUIDEITEM) {
+ Guide *g = static_cast<Guide *>(itemList.at(i));
+ g->updatePos();
+ m_scene->addItem(g);
+ }
+ }
+ viewport()->update();
+}