Commit 8b78b8b9 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Rolling edit can now be triggered by selecting a timeline clip

and pressing Ctrl + Arrow key. This will start a rolling edit on the clip end that
is the closest to timeline cursor. Press again Ctrl + Left/Right Arrow to move edit point.
You currently have to press "Escape" or click "Close" in monitor to finish
operation, or kdenlive will be unstable if you try doing another operation
while in rolling mode.
Ref T1953
parent d9d5d95a
......@@ -32,36 +32,20 @@ Item {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.doAcceptRipple(mouseX > width / 2)
}
}
Rectangle {
id: cancel
anchors {
left: root.left
top: info.bottom
}
width: root.width / 2
height: root.height / 2 - info.height
color: "darkRed"
Text {
text: 'Cancel'
color: "white"
anchors.centerIn: parent
root.doAcceptRipple(true)
}
}
Rectangle {
id: accept
anchors {
right: root.right
left: root.left
top: info.bottom
}
width: root.width / 2
width: root.width
height: root.height / 2 - info.height
color: "darkGreen"
Text {
text: 'Accept'
text: 'close'
color: "white"
anchors.centerIn: parent
}
......
......@@ -861,6 +861,8 @@ void ProjectClip::doExtractIntra()
}
prod->seek(pos);
Mlt::Frame *frame = prod->get_frame();
frame->set("deinterlace_method", "onefield");
frame->set("top_field_first", -1 );
if (frame && frame->is_valid()) {
img = KThumb::getFrame(frame, fullWidth, 150);
bin()->cachePixmap(path, img);
......@@ -910,6 +912,8 @@ void ProjectClip::doExtractImage()
}
prod->seek(pos);
Mlt::Frame *frame = prod->get_frame();
frame->set("deinterlace_method", "onefield");
frame->set("top_field_first", -1 );
if (frame && frame->is_valid()) {
img = KThumb::getFrame(frame, frameWidth, 150);
bin()->cachePixmap(path, img);
......
......@@ -42,7 +42,6 @@ bool TreeEventEater::eventFilter(QObject *obj, QEvent *event)
if (((QKeyEvent*)event)->key() == Qt::Key_Escape) {
emit clearSearchLine();
}
return QObject::eventFilter(obj, event);
}
return QObject::eventFilter(obj, event);
}
......
......@@ -612,8 +612,9 @@ void GLWidget::mouseMoveEvent(QMouseEvent* event)
void GLWidget::keyPressEvent(QKeyEvent* event)
{
QQuickView::keyPressEvent(event);
if (event->isAccepted()) return;
emit passKeyEvent(event);
if (!event->isAccepted()) {
emit passKeyEvent(event);
}
}
void GLWidget::createThread(RenderThread **thread, thread_function_t function, void *data)
......
......@@ -73,30 +73,40 @@ QuickEventEater::QuickEventEater(QObject *parent) : QObject(parent)
bool QuickEventEater::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::DragEnter) {
QDragEnterEvent *ev = reinterpret_cast< QDragEnterEvent* >(event);
if (ev->mimeData()->hasFormat(QStringLiteral("kdenlive/effectslist"))) {
ev->acceptProposedAction();
return true;
switch (event->type()) {
case QEvent::DragEnter:
{
QDragEnterEvent *ev = reinterpret_cast< QDragEnterEvent* >(event);
if (ev->mimeData()->hasFormat(QStringLiteral("kdenlive/effectslist"))) {
ev->acceptProposedAction();
return true;
}
break;
}
}
else if (event->type() == QEvent::DragMove) {
QDragEnterEvent *ev = reinterpret_cast< QDragEnterEvent* >(event);
if (ev->mimeData()->hasFormat(QStringLiteral("kdenlive/effectslist"))) {
ev->acceptProposedAction();
return true;
case QEvent::DragMove:
{
QDragEnterEvent *ev = reinterpret_cast< QDragEnterEvent* >(event);
if (ev->mimeData()->hasFormat(QStringLiteral("kdenlive/effectslist"))) {
ev->acceptProposedAction();
return true;
}
break;
}
}
else if (event->type() == QEvent::Drop) {
QDropEvent *ev = static_cast< QDropEvent* >(event);
if (ev) {
const QString effects = QString::fromUtf8(ev->mimeData()->data(QStringLiteral("kdenlive/effectslist")));
QDomDocument doc;
doc.setContent(effects, true);
emit addEffect(doc.documentElement());
ev->accept();
return true;
case QEvent::Drop:
{
QDropEvent *ev = static_cast< QDropEvent* >(event);
if (ev) {
const QString effects = QString::fromUtf8(ev->mimeData()->data(QStringLiteral("kdenlive/effectslist")));
QDomDocument doc;
doc.setContent(effects, true);
emit addEffect(doc.documentElement());
ev->accept();
return true;
}
break;
}
default:
break;
}
return QObject::eventFilter(obj, event);
}
......
......@@ -189,7 +189,9 @@ void AbstractClipItem::updateRectGeometry()
void AbstractClipItem::resizeStart(int posx, bool hasSizeLimit, bool /*emitChange*/)
{
GenTime durationDiff = GenTime(posx, m_fps) - m_info.startPos;
if (durationDiff == GenTime()) return;
if (durationDiff == GenTime()) {
return;
}
if (type() == AVWidget && hasSizeLimit && (cropStart() + durationDiff < GenTime())) {
durationDiff = GenTime() - cropStart();
......@@ -206,7 +208,6 @@ void AbstractClipItem::resizeStart(int posx, bool hasSizeLimit, bool /*emitChang
if (m_info.cropStart < GenTime())
negCropStart = true;
}
m_info.cropDuration -= durationDiff;
setRect(0, 0, cropDuration().frames(m_fps) - 0.02, rect().height());
moveBy(durationDiff.frames(m_fps), 0);
......@@ -220,7 +221,6 @@ void AbstractClipItem::resizeStart(int posx, bool hasSizeLimit, bool /*emitChang
m_info.cropDuration -= diff;
setRect(0, 0, cropDuration().frames(m_fps) - 0.02, rect().height());
}
// set crop from start to 0 (isn't relevant as this only happens for color clips, images)
if (negCropStart)
m_info.cropStart = GenTime();
......
......@@ -209,13 +209,55 @@ void CustomTrackView::initTools()
//virtual
void CustomTrackView::keyPressEvent(QKeyEvent * event)
{
if (event->key() == Qt::Key_Up) {
slotTrackUp();
event->accept();
} else if (event->key() == Qt::Key_Down) {
slotTrackDown();
event->accept();
} else QWidget::keyPressEvent(event);
switch(event->key()) {
case Qt::Key_Up:
slotTrackUp();
event->accept();
break;
case Qt::Key_Down:
slotTrackDown();
event->accept();
break;
case Qt::Key_Left:
case Qt::Key_Right:
if (event->modifiers() == Qt::ControlModifier) {
if (m_dragItem == NULL || m_dragItem->type() != AVWidget) {
QGraphicsView::keyPressEvent(event);
return;
}
// Enter rolling
int diffStart = qAbs(m_cursorPos - m_dragItem->startPos().frames(m_document->fps()));
int diffEnd = qAbs(m_cursorPos - m_dragItem->endPos().frames(m_document->fps()));
TrimManager *mgr = qobject_cast<TrimManager *>(m_toolManagers.value(TrimType));
if (m_moveOpMode == RollingEnd || m_moveOpMode == RollingStart) {
// Already in trim mode, move
mgr->moveRoll(event->key() == Qt::Key_Right);
} else {
// init trim
mgr->enterTrimMode(m_dragItem->info(), diffStart < diffEnd);
}
setFocus();
event->accept();
return;
}
break;
default:
break;
}
QGraphicsView::keyPressEvent(event);
}
bool CustomTrackView::event( QEvent * e )
{
if ((m_moveOpMode == RollingEnd || m_moveOpMode == RollingStart) && e->type() == QEvent::ShortcutOverride) {
if (((QKeyEvent*)e)->key() == Qt::Key_Escape) {
TrimManager *mgr = qobject_cast<TrimManager *>(m_toolManagers.value(TrimType));
mgr->endRoll();
e->accept();
return true;
}
}
return QGraphicsView::event(e);
}
void CustomTrackView::setDocumentModified()
......@@ -2206,10 +2248,11 @@ void CustomTrackView::rippleMode(bool enable)
emit displayMessage(i18n("Select a clip to enter ripple mode"), InformationMessage);
return;
}
if (m_operationMode == ResizeEnd)
if (m_operationMode == ResizeEnd) {
m_moveOpMode = RollingEnd;
else if (m_operationMode == ResizeStart)
} else if (m_operationMode == ResizeStart) {
m_moveOpMode = RollingStart;
}
int ripplePos = m_moveOpMode == RollingStart ? m_dragItem->startPos().frames(m_document->fps()) : m_dragItem->endPos().frames(m_document->fps());
if (m_timeline->createRippleWindow(m_dragItem->track(), ripplePos)) {
emit loadMonitorScene(MonitorSceneRipple, true);
......@@ -8471,8 +8514,11 @@ void CustomTrackView::switchAllTrackLock()
void CustomTrackView::slotAcceptRipple(bool accept)
{
m_timeline->removeSplitOverlay();
QMetaObject::invokeMethod(this, "doRipple", Qt::QueuedConnection, Q_ARG(bool, accept));
if (m_moveOpMode == RollingEnd || m_moveOpMode == RollingStart) {
TrimManager *mgr = qobject_cast<TrimManager *>(m_toolManagers.value(TrimType));
if (mgr)
QMetaObject::invokeMethod(mgr, "endRoll", Qt::QueuedConnection);
}
}
void CustomTrackView::doRipple(bool accept)
......
......@@ -369,8 +369,6 @@ public slots:
/** @brief Shows the configure tracks dialog. */
void slotConfigTracks(int ix);
void clipNameChanged(const QString &id);
void slotTrackUp();
void slotTrackDown();
void slotSelectTrack(int ix, bool switchTarget = false);
int insertZone(TimelineMode::EditMode sceneMode, const QString clipId, QPoint binZone);
......@@ -418,6 +416,7 @@ protected:
virtual void dragEnterEvent(QDragEnterEvent * event);
virtual void dragMoveEvent(QDragMoveEvent * event);
virtual void dragLeaveEvent(QDragLeaveEvent * event);
virtual bool event( QEvent * e );
/** @brief Something has been dropped onto the timeline */
virtual void dropEvent(QDropEvent * event);
virtual void enterEvent(QEvent * event);
......@@ -558,6 +557,8 @@ private:
void updateTimelineSelection();
/** @brief Break groups containing an item in a locked track. */
void breakLockedGroups(QList<ItemInfo> clipsToMove, QList<ItemInfo> transitionsToMove, QUndoCommand *masterCommand, bool doIt = true);
void slotTrackUp();
void slotTrackDown();
private slots:
void slotRefreshGuides();
......
......@@ -37,8 +37,31 @@ TrimManager::TrimManager(CustomTrackView *view, DocUndoStack *commandStack) : Ab
bool TrimManager::mousePress(ItemInfo info, Qt::KeyboardModifiers, QList<QGraphicsItem *>)
{
qDebug()<<"OP MODE: "<<m_view->prepareMode();
if (m_view->prepareMode() == ResizeStart) {
return enterTrimMode(info, m_view->prepareMode() == ResizeStart);
}
void TrimManager::mouseMove(int pos)
{
if (!m_firstInfo.isValid() || !m_secondInfo.isValid())
return;
if (pos < m_firstClip->endPos().frames(m_view->fps())) {
m_firstClip->resizeEnd(pos, false);
m_secondClip->resizeStart(pos, true, false);
} else {
m_secondClip->resizeStart(pos, true, false);
m_firstClip->resizeEnd(pos, false);
}
m_view->seekCursorPos(pos);
}
void TrimManager::mouseRelease(GenTime)
{
endRoll();
}
bool TrimManager::enterTrimMode(ItemInfo info, bool trimStart)
{
if (trimStart) {
m_firstClip = m_view->getClipItemAtEnd(info.startPos, info.track);
m_secondClip = m_view->getClipItemAtStart(info.startPos, info.track);
} else {
......@@ -46,40 +69,47 @@ bool TrimManager::mousePress(ItemInfo info, Qt::KeyboardModifiers, QList<QGraphi
m_secondClip = m_view->getClipItemAtStart(info.endPos, info.track);
}
if (!m_firstClip || !m_secondClip) {
qDebug()<<"/ / / / WARNING, ERROR WITH TRIM CLIPS";
m_view->setOperationMode(None);
m_firstInfo = ItemInfo();
m_secondInfo = ItemInfo();
return false;
}
m_firstInfo = m_firstClip->info();
m_secondInfo = m_secondClip->info();
AbstractClipItem *dragItem = m_view->dragItem();
m_view->rippleMode(true);
m_view->loadMonitorScene(MonitorSceneRipple, true);
AbstractGroupItem *selectionGroup = m_view->selectionGroup();
if (selectionGroup) {
m_view->resetSelectionGroup(false);
dragItem->setSelected(true);
}
m_view->setOperationMode(trimStart ? RollingStart : RollingEnd);
m_firstInfo = m_firstClip->info();
m_secondInfo = m_secondClip->info();
m_view->rippleMode(true);
m_view->loadMonitorScene(MonitorSceneRipple, true);
m_view->seekCursorPos(trimStart ? info.startPos.frames(m_view->fps()) : info.endPos.frames(m_view->fps()));
return true;
}
void TrimManager::mouseMove(int pos)
void TrimManager::moveRoll(bool forward)
{
if (!m_firstInfo.isValid() || !m_secondInfo.isValid())
return;
if (pos < m_firstClip->endPos().frames(m_view->fps())) {
m_firstClip->resizeEnd(pos, false);
int pos = m_firstClip->endPos().frames(m_view->fps());
bool snap = KdenliveSettings::snaptopoints();
KdenliveSettings::setSnaptopoints(false);
if (forward) {
pos++;
m_secondClip->resizeStart(pos, true, false);
m_firstClip->resizeEnd(pos, false);
} else {
m_secondClip->resizeStart(pos, true, false);
pos--;
m_firstClip->resizeEnd(pos, false);
m_secondClip->resizeStart(pos, true, false);
}
m_view->seekCursorPos(pos);
KdenliveSettings::setSnaptopoints(snap);
}
void TrimManager::mouseRelease(GenTime)
void TrimManager::endRoll()
{
if (!m_firstInfo.isValid() || !m_secondInfo.isValid())
return;
......@@ -97,5 +127,3 @@ void TrimManager::mouseRelease(GenTime)
m_firstInfo = ItemInfo();
m_secondInfo = ItemInfo();
}
......@@ -38,6 +38,11 @@ public:
bool mousePress(ItemInfo info = ItemInfo(), Qt::KeyboardModifiers modifiers = Qt::NoModifier, QList<QGraphicsItem *> list = QList<QGraphicsItem *>());
void mouseMove(int pos);
void mouseRelease(GenTime pos = GenTime());
bool enterTrimMode(ItemInfo info, bool trimStart);
void moveRoll(bool forward);
public slots:
void endRoll();
private:
ClipItem *m_firstClip;
......
......@@ -85,6 +85,7 @@ Timeline::Timeline(KdenliveDoc *doc, const QList<QAction *> &actions, const QLis
connect(splitter, &QSplitter::splitterMoved, this, &Timeline::storeHeaderSize);
m_scene = new CustomTrackScene(this);
m_trackview = new CustomTrackView(doc, this, m_scene, parent);
setFocusProxy(m_trackview);
if (m_doc->setSceneList() == -1) *ok = false;
else *ok = true;
Mlt::Service s(m_doc->renderer()->getProducer()->parent().get_service());
......@@ -232,18 +233,6 @@ int Timeline::visibleTracksCount() const
return m_tractor->count() - 1 - m_hasOverlayTrack - m_usePreview;
}
//virtual
void Timeline::keyPressEvent(QKeyEvent * event)
{
if (event->key() == Qt::Key_Up) {
m_trackview->slotTrackUp();
event->accept();
} else if (event->key() == Qt::Key_Down) {
m_trackview->slotTrackDown();
event->accept();
} else QWidget::keyPressEvent(event);
}
int Timeline::duration() const
{
return m_trackview->duration();
......@@ -1735,17 +1724,23 @@ bool Timeline::createRippleWindow(int tk, int startPos)
}
Mlt::Producer *firstClip = playlist.get_clip(clipIndex - 1);
Mlt::Producer *secondClip = playlist.get_clip(clipIndex);
qDebug()<<"** TRIM ON TK: "<<tk<<", POS: "<<startPos;
if (!firstClip || !firstClip->is_valid()) {
m_tractor->unlock();
return false;
}
if (!secondClip || !secondClip->is_valid()) {
m_tractor->unlock();
return false;
}
// Create duplicate of second clip
Clip clp2(secondClip->parent());
Mlt::Producer *cln2 = clp2.clone();
Clip(*cln2).addEffects(*secondClip);
// Create copy of first clip
Mlt::Producer *cln = new Mlt::Producer(firstClip->parent());
cln->set_in_and_out(firstClip->get_in(), -1);
Clip(*cln).addEffects(*firstClip);
int secondStart = playlist.clip_start(clipIndex) - secondClip->get_in();
int rippleStart = playlist.clip_start(clipIndex - 1);
......
......@@ -189,9 +189,6 @@ public:
/** @brief Toggle current project's compositing mode. */
void switchComposite(int mode);
protected:
void keyPressEvent(QKeyEvent * event);
public slots:
void slotDeleteClip(const QString &clipId, QUndoCommand *deleteCommand);
void slotChangeZoom(int horizontal, int vertical = -1);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment