#include "groupclipscommand.h"
#include "splitaudiocommand.h"
#include "changecliptypecommand.h"
+#include "trackdialog.h"
#include <KDebug>
#include <KLocale>
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));
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;
}
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;
AbstractClipItem *clip = static_cast <AbstractClipItem*>(item);
if (m_tool == RAZORTOOL) {
// razor tool over a clip, display current frame in monitor
- if (false && /*!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(), mappedXPos - (clip->startPos() - clip->cropStart()).frames(m_document->fps()));
}
return;
} else {
if (m_visualTip) {
+ scene()->removeItem(m_visualTip);
m_animationTimer->stop();
delete m_animation;
m_animation = NULL;
setCursor(Qt::SplitHCursor);
} else {
if (m_visualTip) {
+ scene()->removeItem(m_visualTip);
m_animationTimer->stop();
delete m_animation;
m_animation = NULL;
// virtual
void CustomTrackView::mousePressEvent(QMouseEvent * event)
{
- //kDebug() << "mousePressEvent STARTED";
setFocus(Qt::MouseFocusReason);
m_menuPosition = QPoint();
}
if (event->modifiers() & Qt::ShiftModifier) {
+ // Rectangle selection
+ setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
setDragMode(QGraphicsView::RubberBandDrag);
if (!(event->modifiers() & Qt::ControlModifier)) {
resetSelectionGroup();
scene()->clearSelection();
}
- QGraphicsView::mousePressEvent(event);
m_blockRefresh = false;
m_operationMode = RUBBERSELECTION;
+ QGraphicsView::mousePressEvent(event);
return;
}
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;
}
ct++;
}
- if (!found) m_dragItem = NULL;
+ 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;
}
groupSelectedItems(true);
m_operationMode = SPACER;
- } else setCursorPos((int)(mapToScene(event->x(), 0).x()));
+ } else {
+ setCursorPos((int)(mapToScene(event->x(), 0).x()));
+ }
QGraphicsView::mousePressEvent(event);
return;
}
return;
}
- if (dragGroup == NULL) updateSnapPoints(m_dragItem);
+ 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) {
+ 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();
+ dragGroup = static_cast <AbstractGroupItem *>(m_dragItem->parentItem());
+ }
+ bool selected = !m_dragItem->isSelected();
+ if (dragGroup) dragGroup->setSelected(selected);
+ else m_dragItem->setSelected(selected);
+
+ groupSelectedItems();
+ ClipItem *clip = static_cast <ClipItem *>(m_dragItem);
+ updateClipTypeActions(dragGroup == NULL ? clip : NULL);
+ m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1);
+ }
+
+ // Update snap points
+ if (m_selectionGroup == NULL) updateSnapPoints(m_dragItem);
else {
QList <GenTime> offsetList;
- QList<QGraphicsItem *> children = dragGroup->childItems();
+ 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));
}
}
- 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) {
- if (event->modifiers() != Qt::ControlModifier) m_scene->clearSelection();
- resetSelectionGroup();
- dragGroup = NULL;
- if (m_dragItem->parentItem() && m_dragItem->parentItem()->type() == GROUPWIDGET) {
- //kDebug()<<"// KLIK FOUND GRP: "<<m_dragItem->sceneBoundingRect();
- dragGroup = static_cast <AbstractGroupItem *>(m_dragItem->parentItem());
- }
- bool selected = !m_dragItem->isSelected();
- if (dragGroup) dragGroup->setSelected(selected);
- else m_dragItem->setSelected(selected);
-
- groupSelectedItems();
- ClipItem *clip = static_cast <ClipItem *>(m_dragItem);
- updateClipTypeActions(dragGroup == NULL ? clip : NULL);
- m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1);
- }
-
if (collisionClip != NULL || m_dragItem == NULL) {
if (m_dragItem && m_dragItem->type() == AVWIDGET && !m_dragItem->isItemLocked()) {
- kDebug() << "//////// CLIP ITEM SELECTED, TRANSMITTING . . . . . . .";
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()));
m_blockRefresh = false;
//kDebug()<<pos;
- //QGraphicsView::mousePressEvent(event);
+ QGraphicsView::mousePressEvent(event);
}
void CustomTrackView::resetSelectionGroup(bool selectItems)
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;
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);
}
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);
- return;
+ 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);
+ 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.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);
- return;
+ 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, 1, false);
+ 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.endPos = info.startPos + clip->duration();
+ info.track = 0;
start += clip->duration();
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
-{
- 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->cropDuration().frames(m_document->fps()) - 0.02, m_tracksHeight - 1);
- kDebug() << " / / INSERT RECT: " << shape;
- path = path.united(QPolygonF(shape));
- }
- }
-
- QList<QGraphicsItem*> collindingItems = scene()->items(path, Qt::IntersectsItemShape);
- if (collindingItems.isEmpty()) return true;
- else {
- for (int i = 0; i < collindingItems.count(); i++) {
- QGraphicsItem *collision = collindingItems.at(i);
- if (collision->type() == AVWIDGET) {
- // Collision
- kDebug() << "// COLLISIION DETECTED";
- return false;
- }
- }
- return true;
- }
+void CustomTrackView::dragEnterEvent(QDragEnterEvent * event)
+{
+ if (insertDropClips(event->mimeData(), event->pos())) {
+ event->acceptProposedAction();
+ } else QGraphicsView::dragEnterEvent(event);
}
-
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);
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);
+ QDomElement effect = insertedEffect.cloneNode().toElement();
if (clip) {
-
// Special case: speed effect
if (effect.attribute("id") == "speed") {
ItemInfo info = clip->info();
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);
setDocumentModified();
} else {
}
}
-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);
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);
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);
}
}
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_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)
{
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;
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;
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);
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);
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;
setDocumentModified();
- m_document->renderer()->doRefresh();
+ if (refresh) m_document->renderer()->doRefresh();
}
void CustomTrackView::deleteSelectedClips()
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) {
m_document->renderer()->mltAddEffect(info.track, info.startPos, item->getEffectArgs(item->effectAt(i)), false);
}
setDocumentModified();
- m_document->renderer()->doRefresh();
+ if (refresh) m_document->renderer()->doRefresh();
m_waitingThumbs.append(item);
m_thumbsTimer.start();
}
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) {
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()), start.track);
// 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);
}
kDebug() << "// GROUP MOV; OFFSET: " << offset.frames(25) << ", TK OFF: " << trackOffset;*/
resetSelectionGroup();
m_scene->clearSelection();
-
+ m_document->renderer()->blockSignals(true);
for (int i = 0; i < startClip.count(); i++) {
if (reverseMove) {
startClip[i].startPos = startClip.at(i).startPos - offset;
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);
}
+ m_document->renderer()->blockSignals(false);
groupSelectedItems(true);
if (m_selectionGroup) {
bool snap = KdenliveSettings::snaptopoints();
} 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) {
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;
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;
m_animation = NULL;
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());
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)
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++) {
}
if (clip->type() == TRANSITIONWIDGET) {
m_commandStack->push(new MoveTransitionCommand(this, startInfo, endInfo, true));
- } else m_commandStack->push(new ResizeClipCommand(this, startInfo, endInfo, true));
+ } else m_commandStack->push(new ResizeClipCommand(this, startInfo, endInfo, true, false));
}
void CustomTrackView::setOutPoint()
if (clip->type() == TRANSITIONWIDGET) {
m_commandStack->push(new MoveTransitionCommand(this, startInfo, endInfo, true));
- } else m_commandStack->push(new ResizeClipCommand(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;
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);
setDocumentModified();
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 {
}
}
- selection = m_scene->items();
new AddTrackCommand(this, ix, trackinfo, false, deleteTrack);
m_commandStack->push(deleteTrack);
}