KIcon razorIcon("edit-cut");
m_razorCursor = QCursor(razorIcon.pixmap(22, 22));
+
+ KIcon spacerIcon("kdenlive-spacer-tool");
+ m_spacerCursor = QCursor(spacerIcon.pixmap(22, 22));
verticalScrollBar()->setTracking(true);
connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(slotRefreshGuides()));
connect(&m_scrollTimer, SIGNAL(timeout()), this, SLOT(slotCheckMouseScrolling()));
emit mousePosition(mappedXPos);
if (event->buttons() & Qt::MidButton) return;
if (event->buttons() != Qt::NoButton) {
+ bool move = (event->pos() - m_clickEvent).manhattanLength() >= QApplication::startDragDistance();
if (m_dragItem && m_tool == SELECTTOOL) {
- bool move = (event->pos() - m_clickEvent).manhattanLength() >= QApplication::startDragDistance();
if (m_operationMode == MOVE && move) {
QGraphicsView::mouseMoveEvent(event);
// If mouse is at a border of the view, scroll
m_visualTip = NULL;
QGraphicsView::mouseMoveEvent(event);
return;
+ } else if (m_operationMode == SPACER && move) {
+ // spacer tool
+ int mappedClick = (int)(mapToScene(m_clickEvent).x() + 0.5);
+ if (mappedXPos > mappedClick)
+ m_selectionGroup->setPos(mappedXPos + (m_spacerStart - mappedClick) , m_selectionGroup->pos().y());
}
}
setCursor(m_razorCursor);
//QGraphicsView::mouseMoveEvent(event);
//return;
+ } else if (m_tool == SPACERTOOL) {
+ setCursor(m_spacerCursor);
+ return;
}
QList<QGraphicsItem *> itemList = items(event->pos());
}
// No item under click
- if (m_dragItem == NULL) {
+ if (m_dragItem == NULL || m_tool == SPACERTOOL) {
if (m_selectionGroup) {
scene()->destroyItemGroup(m_selectionGroup);
m_selectionGroup = NULL;
}
setCursor(Qt::ArrowCursor);
m_scene->clearSelection();
- setCursorPos((int)(mapToScene(event->x(), 0).x()));
event->accept();
emit clipItemSelected(NULL);
+ if (m_tool == SPACERTOOL) {
+ // Select all items on track after click position
+ int track = (int)(mapToScene(m_clickEvent).y() / m_tracksHeight);
+ QList<QGraphicsItem *> selection = items(event->pos().x(), track * m_tracksHeight + 1, sceneRect().width() - event->pos().x(), m_tracksHeight - 2);
+ m_selectionGroup = new AbstractGroupItem(m_document->fps());
+ scene()->addItem(m_selectionGroup);
+ m_spacerStart = -1;
+ int itemStart;
+ for (int i = 0; i < selection.count(); i++) {
+ if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET) {
+ m_selectionGroup->addToGroup(selection.at(i));
+ AbstractClipItem *item = static_cast <AbstractClipItem *>(selection.at(i));
+ itemStart = item->startPos().frames(m_document->fps());
+ if (m_spacerStart == -1 || itemStart < m_spacerStart)
+ m_spacerStart = itemStart;
+ }
+ }
+ QPointF top = m_selectionGroup->boundingRect().topLeft();
+ const int width = m_selectionGroup->boundingRect().width();
+ const int height = m_selectionGroup->boundingRect().height();
+ m_selectionGroup->setPos(top);
+ m_selectionGroup->translate(-top.x(), -top.y() + 1);
+ //kDebug()<<"// SPACER START GRP: "<<m_spacerStart;
+ m_operationMode = SPACER;
+ } else setCursorPos((int)(mapToScene(event->x(), 0).x()));
return;
}
QList<QGraphicsItem *> itemList;
if (track == -1) itemList = items();
else itemList = scene()->items(pos.frames(m_document->fps()) , track * m_tracksHeight + m_tracksHeight / 2, sceneRect().width() - pos.frames(m_document->fps()), m_tracksHeight / 4);
+ if (m_selectionGroup) {
+ scene()->destroyItemGroup(m_selectionGroup);
+ m_selectionGroup = NULL;
+ }
+ m_selectionGroup = new AbstractGroupItem(m_document->fps());
+ scene()->addItem(m_selectionGroup);
for (int i = 0; i < itemList.count(); i++) {
- if (itemList.at(i)->type() == AVWIDGET) {
- ClipItem *item = (ClipItem *)itemList.at(i);
- if (item->endPos() > pos) item->moveBy(diff, 0);
- }
+ if (itemList.at(i)->type() == AVWIDGET || itemList.at(i)->type() == TRANSITIONWIDGET) {
+ /*AbstractClipItem *item = static_cast <AbstractClipItem *> (itemList.at(i));
+ if (item->endPos() > pos)*/
+ m_selectionGroup->addToGroup(itemList.at(i));
+ //item->moveBy(diff, 0);
+ }
+ }
+ QPointF top = m_selectionGroup->boundingRect().topLeft();
+ const int width = m_selectionGroup->boundingRect().width();
+ const int height = m_selectionGroup->boundingRect().height();
+ m_selectionGroup->setPos(top);
+ m_selectionGroup->translate(-top.x(), -top.y() + 1);
+ m_selectionGroup->moveBy(diff, 0);
+ if (m_selectionGroup) {
+ scene()->destroyItemGroup(m_selectionGroup);
+ m_selectionGroup = NULL;
}
if (track != -1) track = m_scene->m_tracksList.count() - track;
m_document->renderer()->mltInsertSpace(pos, track, duration, add);
m_dragGuide = NULL;
m_dragItem = NULL;
return;
+ } else if (m_operationMode == SPACER) {
+ int endClick = (int)(mapToScene(event->pos()).x() + 0.5);
+ int mappedClick = (int)(mapToScene(m_clickEvent).x() + 0.5);
+ int diff = endClick - mappedClick;
+ int track = (int)(mapToScene(m_clickEvent).y() / m_tracksHeight);
+ InsertSpaceCommand *command = new InsertSpaceCommand(this, GenTime(mappedClick, m_document->fps()), track, GenTime(diff, m_document->fps()), false);
+ m_commandStack->push(command);
+ track = m_scene->m_tracksList.count() - track;
+ m_document->renderer()->mltInsertSpace(GenTime(mappedClick, m_document->fps()), track, GenTime(diff, m_document->fps()), true);
+ if (m_selectionGroup) {
+ scene()->destroyItemGroup(m_selectionGroup);
+ m_selectionGroup = NULL;
+ }
+ m_operationMode = NONE;
}
+
if (m_dragItem == NULL && m_selectionGroup == NULL) {
emit transitionItemSelected(NULL);
return;
uint m_selectedTrack;
int m_projectDuration;
int m_cursorPos;
+ int m_spacerStart;
KdenliveDoc *m_document;
CustomTrackScene *m_scene;
QGraphicsLineItem *m_cursorLine;
int m_findIndex;
PROJECTTOOL m_tool;
QCursor m_razorCursor;
+ QCursor m_spacerCursor;
/** list containing items currently copied in the timeline */
QList<AbstractClipItem *> m_copiedItems;
/** Used to get the point in timeline where a context menu was opened */
const int FRAME_SIZE = 90;
const int MAXCLIPDURATION = 15000;
-enum OPERATIONTYPE { NONE = 0, MOVE = 1, RESIZESTART = 2, RESIZEEND = 3, FADEIN = 4, FADEOUT = 5, TRANSITIONSTART = 6, TRANSITIONEND = 7, MOVEGUIDE = 8, KEYFRAME = 9, SEEK = 10};
+enum OPERATIONTYPE { NONE = 0, MOVE = 1, RESIZESTART = 2, RESIZEEND = 3, FADEIN = 4, FADEOUT = 5, TRANSITIONSTART = 6, TRANSITIONEND = 7, MOVEGUIDE = 8, KEYFRAME = 9, SEEK = 10, SPACER = 11};
enum CLIPTYPE { UNKNOWN = 0, AUDIO = 1, VIDEO = 2, AV = 3, COLOR = 4, IMAGE = 5, TEXT = 6, SLIDESHOW = 7, VIRTUAL = 8, PLAYLIST = 9, FOLDER = 10};
enum GRAPHICSRECTITEM { AVWIDGET = 70000 , LABELWIDGET , TRANSITIONWIDGET , GROUPWIDGET};
-enum PROJECTTOOL { SELECTTOOL = 0 , RAZORTOOL = 1 };
+enum PROJECTTOOL { SELECTTOOL = 0 , RAZORTOOL = 1 , SPACERTOOL = 2 };
enum TRANSITIONTYPE {
/** TRANSITIONTYPE: between 0-99: video trans, 100-199: video+audio trans, 200-299: audio trans */
<Menu name="tool" ><text>Tool</text>
<Action name="select_tool" />
<Action name="razor_tool" />
+ <Action name="spacer_tool" />
</Menu>
<Menu name="timeline" ><text>Timeline</text>
m_buttonRazorTool->setCheckable(true);
m_buttonRazorTool->setChecked(false);
+ m_buttonSpacerTool = new KAction(KIcon("kdenlive-spacer-tool"), i18n("Spacer tool"), this);
+ toolbar->addAction(m_buttonSpacerTool);
+ m_buttonSpacerTool->setCheckable(true);
+ m_buttonSpacerTool->setChecked(false);
+
m_toolGroup->addAction(m_buttonSelectTool);
m_toolGroup->addAction(m_buttonRazorTool);
+ m_toolGroup->addAction(m_buttonSpacerTool);
m_toolGroup->setExclusive(true);
toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly);
actionWidget->setMaximumWidth(24);
actionWidget->setMinimumHeight(17);
+ actionWidget = toolbar->widgetForAction(m_buttonSpacerTool);
+ actionWidget->setMaximumWidth(24);
+ actionWidget->setMinimumHeight(17);
+
toolbar->setStyleSheet(style1);
connect(m_toolGroup, SIGNAL(triggered(QAction *)), this, SLOT(slotChangeTool(QAction *)));
collection->addAction("select_tool", m_buttonSelectTool);
collection->addAction("razor_tool", m_buttonRazorTool);
+ collection->addAction("spacer_tool", m_buttonSpacerTool);
collection->addAction("show_video_thumbs", m_buttonVideoThumbs);
collection->addAction("show_audio_thumbs", m_buttonAudioThumbs);
void MainWindow::slotChangeTool(QAction * action) {
if (action == m_buttonSelectTool) slotSetTool(SELECTTOOL);
else if (action == m_buttonRazorTool) slotSetTool(RAZORTOOL);
+ else if (action == m_buttonSpacerTool) slotSetTool(SPACERTOOL);
}
void MainWindow::slotSetTool(PROJECTTOOL tool) {
KAction *m_buttonFitZoom;
KAction *m_buttonSelectTool;
KAction *m_buttonRazorTool;
+ KAction *m_buttonSpacerTool;
KAction *m_buttonSnap;
QActionGroup *m_toolGroup;
KAction *m_saveAction;
Mlt::Service service(parentProd.get_service());
Mlt::Tractor tractor(service);
mlt_service_lock(service.get_service());
+ int insertPos = pos.frames(m_fps);
+ int diff = duration.frames(m_fps) - 1;
if (track != -1) {
// insert space in one track only
Mlt::Producer trackProducer(tractor.track(track));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
- int clipIndex = trackPlaylist.get_clip_index_at(pos.frames(m_fps));
+ int clipIndex = trackPlaylist.get_clip_index_at(insertPos);
if (add) trackPlaylist.insert_blank(clipIndex, duration.frames(m_fps) - 1);
else {
int position = trackPlaylist.clip_start(clipIndex);
- trackPlaylist.remove_region(position, duration.frames(m_fps) - 1);
+ trackPlaylist.remove_region(position, diff);
+ }
+ // now move transitions
+ if (!add) diff = -diff;
+ mlt_service serv = m_mltProducer->parent().get_service();
+ mlt_service nextservice = mlt_service_get_producer(serv);
+ mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
+ QString mlt_type = mlt_properties_get(properties, "mlt_type");
+ QString resource = mlt_properties_get(properties, "mlt_service");
+
+ while (mlt_type == "transition") {
+ mlt_transition tr = (mlt_transition) nextservice;
+ int currentTrack = mlt_transition_get_b_track(tr);
+ int currentIn = (int) mlt_transition_get_in(tr);
+ int currentOut = (int) mlt_transition_get_out(tr);
+
+ if (track == currentTrack && currentOut > insertPos && resource != "mix") {
+ mlt_transition_set_in_and_out(tr, currentIn + diff, currentOut + diff);
+ }
+ nextservice = mlt_service_producer(nextservice);
+ if (nextservice == NULL) break;
+ properties = MLT_SERVICE_PROPERTIES(nextservice);
+ mlt_type = mlt_properties_get(properties, "mlt_type");
+ resource = mlt_properties_get(properties, "mlt_service");
}
} else {
int trackNb = tractor.count();
while (trackNb > 1) {
Mlt::Producer trackProducer(tractor.track(trackNb - 1));
Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
- int clipIndex = trackPlaylist.get_clip_index_at(pos.frames(m_fps));
- if (add) trackPlaylist.insert_blank(clipIndex, duration.frames(m_fps) - 1);
+ int clipIndex = trackPlaylist.get_clip_index_at(insertPos);
+ if (add) trackPlaylist.insert_blank(clipIndex, diff);
else {
int position = trackPlaylist.clip_start(clipIndex);
- trackPlaylist.remove_region(position, duration.frames(m_fps) - 1);
+ trackPlaylist.remove_region(position, diff);
}
trackNb--;
}
+ // now move transitions
+ if (!add) diff = -diff;
+ mlt_service serv = m_mltProducer->parent().get_service();
+ mlt_service nextservice = mlt_service_get_producer(serv);
+ mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
+ QString mlt_type = mlt_properties_get(properties, "mlt_type");
+ QString resource = mlt_properties_get(properties, "mlt_service");
+
+ while (mlt_type == "transition") {
+ mlt_transition tr = (mlt_transition) nextservice;
+ int currentIn = (int) mlt_transition_get_in(tr);
+ int currentOut = (int) mlt_transition_get_out(tr);
+
+ if (currentOut > insertPos && resource != "mix") {
+ mlt_transition_set_in_and_out(tr, currentIn + diff, currentOut + diff);
+ }
+ nextservice = mlt_service_producer(nextservice);
+ if (nextservice == NULL) break;
+ properties = MLT_SERVICE_PROPERTIES(nextservice);
+ mlt_type = mlt_properties_get(properties, "mlt_type");
+ resource = mlt_properties_get(properties, "mlt_service");
+ }
}
mlt_service_unlock(service.get_service());
}
}
void Render::mltMoveTransition(QString type, int startTrack, int newTrack, int newTransitionTrack, GenTime oldIn, GenTime oldOut, GenTime newIn, GenTime newOut) {
-
Mlt::Service service(m_mltProducer->parent().get_service());
Mlt::Tractor tractor(service);
Mlt::Field *field = tractor.field();