Commit 82159161 authored by Julius Künzel's avatar Julius Künzel 💬
Browse files

Fixes for Slip and add Ripple (not feature complete yet)

- Ripple: yet disabled on clips with mix compositions
parent 2f7f7c5b
......@@ -393,6 +393,10 @@ void Core::initLocale()
QLocale::setDefault(systemLocale);
}
ToolType::ProjectTool Core::activeTool() {
return m_mainWindow->getCurrentTimeline()->activeTool();
}
std::unique_ptr<Mlt::Repository> &Core::getMltRepository()
{
return MltConnection::self()->getMltRepository();
......
......@@ -124,6 +124,7 @@ public:
bool currentRemap(const QString &clipId);
/** @brief Returns a pointer to the audio mixer. */
MixerManager *mixer();
ToolType::ProjectTool activeTool();
/** @brief Returns a pointer to MLT's repository */
std::unique_ptr<Mlt::Repository> &getMltRepository();
......
......@@ -100,6 +100,7 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include <kns3/knewstuffaction.h>
#include <ktogglefullscreenaction.h>
#include <kwidgetsaddons_version.h>
#include <kcoreaddons_version.h>
#include "kdenlive_debug.h"
#include <QAction>
......@@ -1190,11 +1191,13 @@ void MainWindow::setupActions()
m_buttonSpacerTool->setCheckable(true);
m_buttonSpacerTool->setChecked(false);
/* TODO Implement Ripple
// TODO icon available (and properly working) in KF 5.86
#if KCOREADDONS_VERSION >= QT_VERSION_CHECK(5,86,0)
m_buttonRippleTool = new QAction(QIcon::fromTheme(QStringLiteral("kdenlive-ripple")), i18n("Ripple tool"), this);
#else
m_buttonRippleTool = new QAction(QIcon::fromTheme(QStringLiteral("resizecol")), i18n("Ripple tool"), this);
#endif
m_buttonRippleTool->setCheckable(true);
m_buttonRippleTool->setChecked(false);*/
m_buttonRippleTool->setChecked(false);
/* TODO Implement Roll
// TODO icon available (and properly working) in KF 5.86
......@@ -1203,9 +1206,11 @@ void MainWindow::setupActions()
m_buttonRollTool->setCheckable(true);
m_buttonRollTool->setChecked(false);*/
// TODO icon available (and properly working) in KF 5.86
//m_buttonSlipTool = new QAction(QIcon::fromTheme(QStringLiteral("kdenlive-slip")), i18n("Slip tool"), this);
#if KCOREADDONS_VERSION >= QT_VERSION_CHECK(5,86,0)
m_buttonSlipTool = new QAction(QIcon::fromTheme(QStringLiteral("kdenlive-slip")), i18n("Slip tool"), this);
#else
m_buttonSlipTool = new QAction(QIcon::fromTheme(QStringLiteral("transform-move-horizontal")), i18n("Slip tool"), this);
#endif
m_buttonSlipTool->setCheckable(true);
m_buttonSlipTool->setChecked(false);
......@@ -1223,7 +1228,7 @@ void MainWindow::setupActions()
toolGroup->addAction(m_buttonSelectTool);
toolGroup->addAction(m_buttonRazorTool);
toolGroup->addAction(m_buttonSpacerTool);
//toolGroup->addAction(m_buttonRippleTool);
toolGroup->addAction(m_buttonRippleTool);
//toolGroup->addAction(m_buttonRollTool);
toolGroup->addAction(m_buttonSlipTool);
//toolGroup->addAction(m_buttonSlideTool);
......@@ -1370,7 +1375,7 @@ void MainWindow::setupActions()
addAction(QStringLiteral("select_tool"), m_buttonSelectTool, Qt::Key_S);
addAction(QStringLiteral("razor_tool"), m_buttonRazorTool, Qt::Key_X);
addAction(QStringLiteral("spacer_tool"), m_buttonSpacerTool, Qt::Key_M);
//addAction(QStringLiteral("ripple_tool"), m_buttonRippleTool);
addAction(QStringLiteral("ripple_tool"), m_buttonRippleTool);
//addAction(QStringLiteral("roll_tool"), m_buttonRollTool);
addAction(QStringLiteral("slip_tool"), m_buttonSlipTool);
addAction(QStringLiteral("multicam_tool"), m_buttonMulticamTool);
......@@ -3480,12 +3485,12 @@ QString::number(zone.y()) << "-consumer" << "xml:" + url->url().path());
void MainWindow::slotResizeItemStart()
{
getMainTimeline()->controller()->setInPoint();
getMainTimeline()->controller()->setInPoint(m_activeTool == ToolType::RippleTool);
}
void MainWindow::slotResizeItemEnd()
{
getMainTimeline()->controller()->setOutPoint();
getMainTimeline()->controller()->setOutPoint(m_activeTool == ToolType::RippleTool);
}
int MainWindow::getNewStuff(const QString &configFile)
......
......@@ -468,27 +468,27 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
m_trimmingOffset = new QLabel();
m_trimmingbar->addWidget(m_trimmingOffset);
QAction *fiveLess = new QAction(i18n("-5"), this);
m_trimmingbar->addAction(fiveLess);
connect(fiveLess, &QAction::triggered, this, [&](){
m_fiveLess = new QAction(i18n("-5"), this);
m_trimmingbar->addAction(m_fiveLess);
connect(m_fiveLess, &QAction::triggered, this, [&](){
slotTrimmingPos(-5);
pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(-5, true);
});
QAction *oneLess = new QAction(i18n("-1"), this);
m_trimmingbar->addAction(oneLess);
connect(oneLess, &QAction::triggered, this, [&](){
m_oneLess = new QAction(i18n("-1"), this);
m_trimmingbar->addAction(m_oneLess);
connect(m_oneLess, &QAction::triggered, this, [&](){
slotTrimmingPos(-1);
pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(-1, true);
});
QAction *oneMore = new QAction(i18n("+1"), this);
m_trimmingbar->addAction(oneMore);
connect(oneMore, &QAction::triggered, this, [&](){
m_oneMore = new QAction(i18n("+1"), this);
m_trimmingbar->addAction(m_oneMore);
connect(m_oneMore, &QAction::triggered, this, [&](){
slotTrimmingPos(1);
pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(1, true);
});
QAction *fiveMore = new QAction(i18n("+5"), this);
m_trimmingbar->addAction(fiveMore);
connect(fiveMore, &QAction::triggered, this, [&](){
m_fiveMore = new QAction(i18n("+5"), this);
m_trimmingbar->addAction(m_fiveMore);
connect(m_fiveMore, &QAction::triggered, this, [&](){
slotTrimmingPos(5);
pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(5, true);
});
......@@ -2358,6 +2358,17 @@ void Monitor::slotSwitchTrimming(bool enable)
loadQmlScene(MonitorSceneTrimming);
m_toolbar->setVisible(false);
m_trimmingbar->setVisible(true);
if (pCore->activeTool() == ToolType::RippleTool) {
m_oneLess->setVisible(false);
m_oneMore->setVisible(false);
m_fiveLess->setVisible(false);
m_fiveMore->setVisible(false);
} else {
m_oneLess->setVisible(true);
m_oneMore->setVisible(true);
m_fiveLess->setVisible(true);
m_fiveMore->setVisible(true);
}
m_glMonitor->switchRuler(false);
} else if (m_trimmingbar->isVisible()) {
loadQmlScene(MonitorSceneDefault);
......
......@@ -207,6 +207,10 @@ private:
GenTime getSnapForPos(bool previous);
QToolBar *m_toolbar;
QToolBar *m_trimmingbar;
QAction *m_oneLess;
QAction *m_oneMore;
QAction *m_fiveLess;
QAction *m_fiveMore;
QLabel *m_trimmingOffset;
QSlider *m_audioSlider;
QAction *m_editMarker;
......
......@@ -283,9 +283,11 @@ void MonitorManager::slotForward(double speed)
void MonitorManager::slotRewindOneFrame()
{
if (pCore->window()->getCurrentTimeline()->activeTool() == ToolType::SlipTool) {
if (pCore->activeTool() == ToolType::SlipTool) {
m_projectMonitor->slotTrimmingPos(-1);
pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(-1, true);
} else if (isTrimming()) {
return;
} else {
if (m_activeMonitor == m_clipMonitor) {
m_clipMonitor->slotRewindOneFrame();
......@@ -297,9 +299,11 @@ void MonitorManager::slotRewindOneFrame()
void MonitorManager::slotForwardOneFrame()
{
if (pCore->window()->getCurrentTimeline()->activeTool() == ToolType::SlipTool) {
if (pCore->activeTool() == ToolType::SlipTool) {
m_projectMonitor->slotTrimmingPos(1);
pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(1, true);
} else if (isTrimming()) {
return;
} else {
if (m_activeMonitor == m_clipMonitor) {
m_clipMonitor->slotForwardOneFrame();
......@@ -311,9 +315,11 @@ void MonitorManager::slotForwardOneFrame()
void MonitorManager::slotRewindOneSecond()
{
if (pCore->window()->getCurrentTimeline()->activeTool() == ToolType::SlipTool) {
if (pCore->activeTool() == ToolType::SlipTool) {
m_projectMonitor->slotTrimmingPos(-qRound(pCore->getCurrentFps()));
pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(-qRound(pCore->getCurrentFps()), true);
} else if (isTrimming()) {
return;
} else {
if (m_activeMonitor == m_clipMonitor) {
m_clipMonitor->slotRewindOneFrame(qRound(pCore->getCurrentFps()));
......@@ -325,9 +331,11 @@ void MonitorManager::slotRewindOneSecond()
void MonitorManager::slotForwardOneSecond()
{
if (pCore->window()->getCurrentTimeline()->activeTool() == ToolType::SlipTool) {
if (pCore->activeTool() == ToolType::SlipTool) {
m_projectMonitor->slotTrimmingPos(qRound(pCore->getCurrentFps()));
pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(qRound(pCore->getCurrentFps()), true);
} else if (isTrimming()) {
return;
} else {
if (m_activeMonitor == m_clipMonitor) {
m_clipMonitor->slotForwardOneFrame(qRound(pCore->getCurrentFps()));
......
......@@ -1269,9 +1269,9 @@ int ClipModel::getFakePosition() const
return m_fakePosition;
}
void ClipModel::setFakePosition(int fid)
void ClipModel::setFakePosition(int fpos)
{
m_fakePosition = fid;
m_fakePosition = fpos;
}
QDomElement ClipModel::toXml(QDomDocument &document)
......
......@@ -89,14 +89,14 @@ public:
ClipType::ProducerType clipType() const;
/** @brief Sets the timeline clip status (video / audio only) */
bool setClipState(PlaylistState::ClipState state, Fun &undo, Fun &redo);
/** @brief The fake track is used in insrt/overwrote mode.
/** @brief The fake track is used in insert/overwrite mode.
* in this case, dragging a clip is always accepted, but the change is not applied to the model.
* so we use a 'fake' track id to pass to the qml view
*/
int getFakeTrackId() const;
void setFakeTrackId(int fid);
void setFakePosition(int fpos);
int getFakePosition() const;
void setFakePosition(int fid);
void setMixDuration(int mix, int offset);
void setMixDuration(int mix);
int getMixDuration() const;
......@@ -111,7 +111,7 @@ public:
void allSnaps(std::vector<int> &snaps, int offset = 0);
protected:
// helper functions that creates the lambda
/** @brief helper functions that creates the lambda */
Fun setClipState_lambda(PlaylistState::ClipState state);
public:
......
......@@ -313,7 +313,7 @@ bool TimelineFunctions::requestClipCutAll(std::shared_ptr<TimelineItemModel> tim
return count > 0;
}
int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, int position)
int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, int position, bool ignoreMultiTrackGroups)
{
std::unordered_set<int> clips = timeline->getItemsInRange(trackId, position, -1);
timeline->requestClearSelection();
......@@ -337,6 +337,8 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
int pos = timeline->getItemPosition(l);
if (pos + timeline->getItemPlaytime(l) < position) {
leavesToRemove.insert(l);
} else if (ignoreMultiTrackGroups && trackId > -1 && timeline->getItemTrackId(l) != trackId) {
leavesToRemove.insert(l);
} else {
leavesToKeep.insert(l);
int tid = timeline->getItemTrackId(l);
......@@ -430,7 +432,7 @@ int TimelineFunctions::requestSpacerStartOperation(const std::shared_ptr<Timelin
return -1;
}
bool TimelineFunctions::requestSpacerEndOperation(const std::shared_ptr<TimelineItemModel> &timeline, int itemId, int startPosition, int endPosition, int affectedTrack, bool moveGuides, Fun &undo, Fun &redo)
bool TimelineFunctions::requestSpacerEndOperation(const std::shared_ptr<TimelineItemModel> &timeline, int itemId, int startPosition, int endPosition, int affectedTrack, bool moveGuides, Fun &undo, Fun &redo, bool pushUndo)
{
// Move group back to original position
spacerMinPosition = -1;
......@@ -492,10 +494,12 @@ bool TimelineFunctions::requestSpacerEndOperation(const std::shared_ptr<Timeline
}
timeline->requestClearSelection();
if (final) {
if (startPosition < endPosition) {
pCore->pushUndo(undo, redo, i18n("Insert space"));
} else {
pCore->pushUndo(undo, redo, i18n("Remove space"));
if (pushUndo) {
if (startPosition < endPosition) {
pCore->pushUndo(undo, redo, i18n("Insert space"));
} else {
pCore->pushUndo(undo, redo, i18n("Remove space"));
}
}
// Regroup temporarily ungrouped items
QMapIterator<int, int> i(spacerUngroupedItems);
......
......@@ -71,8 +71,8 @@ struct TimelineFunctions
*/
static bool requestDeleteBlankAt(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, int position, bool affectAllTracks);
static int requestSpacerStartOperation(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, int position);
static bool requestSpacerEndOperation(const std::shared_ptr<TimelineItemModel> &timeline, int itemId, int startPosition, int endPosition, int affectedTrack, bool moveGuides, Fun &undo, Fun &redo);
static int requestSpacerStartOperation(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, int position, bool ignoreMultiTrackGroups = false);
static bool requestSpacerEndOperation(const std::shared_ptr<TimelineItemModel> &timeline, int itemId, int startPosition, int endPosition, int affectedTrack, bool moveGuides, Fun &undo, Fun &redo, bool pushUndo = true);
static bool extractZone(const std::shared_ptr<TimelineItemModel> &timeline, QVector<int> tracks, QPoint zone, bool liftOnly);
static bool liftZone(const std::shared_ptr<TimelineItemModel> &timeline, int trackId, QPoint zone, Fun &undo, Fun &redo);
static bool removeSpace(const std::shared_ptr<TimelineItemModel> &timeline, QPoint zone, Fun &undo, Fun &redo, QVector<int> allowedTracks = QVector<int>(), bool useTargets = true);
......
This diff is collapsed.
......@@ -271,6 +271,11 @@ public:
/** @brief Return the next track of same type as source trackId, or trackId if no track found */
Q_INVOKABLE int getNextTrackId(int trackId);
/** @brief Returns true if the clip has a mix composition at the end
@param clipId Id of the clip to test
*/
Q_INVOKABLE bool hasClipEndMix(int clipId) const;
/** @brief Returns the in cut position of a clip
@param clipId Id of the clip to test
*/
......@@ -496,6 +501,11 @@ public:
/** @brief Same function, but accumulates undo and redo and doesn't deal with snapping*/
bool requestItemResize(int itemId, int size, bool right, bool logUndo, Fun &undo, Fun &redo, bool blockUndo = false);
/** @brief @todo TODO */
Q_INVOKABLE int requestItemRippleResize(int itemId, int size, bool right, bool logUndo = true, int snapDistance = -1, bool allowSingleResize = false);
/** @brief @todo TODO */
bool requestItemRippleResize(int itemId, int size, bool right, bool logUndo, Fun &undo, Fun &redo, bool blockUndo = false);
/** @brief Move ("slip") in and out point of a clip by the given offset
This action is undoable
@param itemId is the ID of the clip
......
......@@ -134,6 +134,10 @@ Rectangle {
}
}
onInPointChanged: useFakeInOut = false;
onOutPointChanged: useFakeInOut = false;
onModelStartChanged: {
x = modelStart * timeScale;
}
......@@ -257,10 +261,10 @@ Rectangle {
}
MouseArea {
id: mouseArea
enabled: root.activeTool === ProjectTool.SelectTool || root.activeTool === ProjectTool.SlipTool
enabled: root.activeTool === ProjectTool.SelectTool || root.activeTool === ProjectTool.SlipTool || root.activeTool === ProjectTool.RippleTool
anchors.fill: clipRoot
acceptedButtons: Qt.RightButton
hoverEnabled: root.activeTool === ProjectTool.SelectTool
hoverEnabled: root.activeTool === ProjectTool.SelectTool || root.activeTool === ProjectTool.RippleTool
cursorShape: (trimInMouseArea.drag.active || trimOutMouseArea.drag.active)? Qt.SizeHorCursor : dragProxyArea.cursorShape
property bool shiftSlip: false
property bool controlSlip: false
......@@ -482,7 +486,9 @@ Rectangle {
id: markerBase
width: 1
height: container.height
x: clipRoot.speed < 0 ? (clipRoot.maxDuration - clipRoot.inPoint) * timeScale + (Math.round(model.frame / clipRoot.speed)) * timeScale - clipRoot.border.width : (Math.round(model.frame / clipRoot.speed) - clipRoot.inPoint) * timeScale - clipRoot.border.width;
x: clipRoot.speed < 0
? (clipRoot.maxDuration - clipRoot.switchedInPoint) * timeScale + (Math.round(model.frame / clipRoot.speed)) * timeScale - clipRoot.border.width
: (Math.round(model.frame / clipRoot.speed) - clipRoot.switchedInPoint) * timeScale - clipRoot.border.width;
color: model.color
}
Rectangle {
......@@ -501,7 +507,9 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onDoubleClicked: timeline.editMarker(clipRoot.clipId, model.frame)
onClicked: proxy.position = clipRoot.modelStart + (clipRoot.speed < 0 ? (clipRoot.maxDuration - clipRoot.inPoint) * timeScale + (Math.round(model.frame / clipRoot.speed)) : (Math.round(model.frame / clipRoot.speed) - clipRoot.inPoint))
onClicked: proxy.position = clipRoot.modelStart + (clipRoot.speed < 0
? (clipRoot.maxDuration - clipRoot.switchedInPoint) * timeScale + (Math.round(model.frame / clipRoot.speed))
: (Math.round(model.frame / clipRoot.speed) - clipRoot.switchedInPoint))
}
}
TextMetrics {
......@@ -529,7 +537,7 @@ Rectangle {
x: -clipRoot.border.width
height: parent.height
width: root.baseUnit / 2
visible: root.activeTool === ProjectTool.SelectTool
visible: root.activeTool === ProjectTool.SelectTool || (root.activeTool === ProjectTool.RippleTool && clipRoot.mixDuration <= 0 && !controller.hasClipEndMix(clipRoot.clipId))
enabled: !isLocked && (pressed || clipRoot.width > 3 * width)
hoverEnabled: true
drag.target: trimInMouseArea
......@@ -548,6 +556,9 @@ Rectangle {
if (!shiftTrim && clipRoot.grouped) {
clipRoot.initGroupTrim(clipRoot)
}
if (root.activeTool === ProjectTool.RippleTool) {
timeline.requestStartTrimmingMode(clipRoot.clipId, false, false);
}
trimIn.opacity = 0
}
onReleased: {
......@@ -556,12 +567,15 @@ Rectangle {
if (sizeChanged) {
clipRoot.trimmedIn(clipRoot, shiftTrim, controlTrim)
sizeChanged = false
if (!controlTrim) {
if (!controlTrim && root.activeTool !== ProjectTool.RippleTool) {
updateDrag()
} else {
endDrag()
}
} else {
if (root.activeTool === ProjectTool.RippleTool) {
timeline.requestEndTrimmingMode();
}
root.groupTrimData = undefined
}
}
......@@ -574,10 +588,15 @@ Rectangle {
var currentClipPos = clipRoot.modelStart
var delta = currentFrame - currentClipPos
if (delta !== 0) {
if (maxDuration > 0 && delta < -inPoint && !(mouse.modifiers & Qt.ControlModifier)) {
delta = -inPoint
var newDuration = 0;
if (root.activeTool === ProjectTool.RippleTool) {
newDuration = clipRoot.originalDuration - delta
} else {
if (maxDuration > 0 && delta < -inPoint && !(mouse.modifiers & Qt.ControlModifier)) {
delta = -inPoint
}
newDuration = clipDuration - delta
}
var newDuration = clipDuration - delta
sizeChanged = true
clipRoot.trimmingIn(clipRoot, newDuration, shiftTrim, controlTrim)
}
......@@ -615,7 +634,7 @@ Rectangle {
opacity: 0
Drag.active: trimInMouseArea.drag.active
Drag.proposedAction: Qt.MoveAction
visible: trimInMouseArea.pressed || (root.activeTool === ProjectTool.SelectTool && !mouseArea.drag.active && parent.enabled)
visible: trimInMouseArea.pressed || ((root.activeTool === ProjectTool.SelectTool || (root.activeTool === ProjectTool.RippleTool && clipRoot.mixDuration <= 0)) && !mouseArea.drag.active && parent.enabled)
/*ToolTip {
visible: trimInMouseArea.containsMouse && !trimInMouseArea.pressed
......@@ -643,7 +662,7 @@ Rectangle {
height: parent.height
width: root.baseUnit / 2
hoverEnabled: true
visible: root.activeTool === ProjectTool.SelectTool
visible: root.activeTool === ProjectTool.SelectTool || (root.activeTool === ProjectTool.RippleTool && clipRoot.mixDuration <= 0)
enabled: !isLocked && (pressed || clipRoot.width > 3 * width)
property bool shiftTrim: false
property bool controlTrim: false
......@@ -662,6 +681,10 @@ Rectangle {
if (!shiftTrim && clipRoot.grouped) {
clipRoot.initGroupTrim(clipRoot)
}
if (root.activeTool === ProjectTool.RippleTool) {
timeline.requestStartTrimmingMode(clipRoot.clipId, false, true);
}
trimOut.opacity = 0
}
onReleased: {
......@@ -670,12 +693,15 @@ Rectangle {
if (sizeChanged) {
clipRoot.trimmedOut(clipRoot, shiftTrim, controlTrim)
sizeChanged = false
if (!controlTrim) {
if (!controlTrim && root.activeTool !== ProjectTool.RippleTool) {
updateDrag()
} else {
endDrag()
}
} else {
if (root.activeTool === ProjectTool.RippleTool) {
timeline.requestEndTrimmingMode();
}
root.groupTrimData = undefined
}
}
......@@ -747,7 +773,7 @@ Rectangle {
opacity: 0
Drag.active: trimOutMouseArea.drag.active
Drag.proposedAction: Qt.MoveAction
visible: trimOutMouseArea.pressed || (root.activeTool === ProjectTool.SelectTool && !mouseArea.drag.active && parent.enabled)
visible: trimOutMouseArea.pressed || ((root.activeTool === ProjectTool.SelectTool || (root.activeTool === ProjectTool.RippleTool && clipRoot.mixDuration <= 0)) && !mouseArea.drag.active && parent.enabled)
}
}
......@@ -1289,7 +1315,7 @@ Rectangle {
height: container.height
width: clipRoot.maxDuration * clipRoot.timeScale
x: - (clipRoot.inPoint - slipOffset) * clipRoot.timeScale
visible: root.activeTool === ProjectTool.SlipTool && selected && !isLocked && clipRoot.maxDuration > 0 // don't show for endless clips
visible: root.activeTool === ProjectTool.SlipTool && selected && clipRoot.maxDuration > 0 // don't show for endless clips
property int inPoint: clipRoot.inPoint
property int outPoint: clipRoot.outPoint
Rectangle {
......
......@@ -33,8 +33,14 @@ Row {
property int startFrame: clipRoot.inPoint
property int endFrame: clipRoot.outPoint
property real imageWidth: Math.max(thumbRow.thumbWidth, container.width / thumbRepeater.count)
property int thumbStartFrame: fixedThumbs ? 0 : (clipRoot.speed >= 0) ? Math.round(clipRoot.inPoint * clipRoot.speed) : Math.round((clipRoot.maxDuration - clipRoot.inPoint) * -clipRoot.speed - 1)
property int thumbEndFrame: fixedThumbs ? 0 : (clipRoot.speed >= 0) ? Math.round(clipRoot.outPoint * clipRoot.speed) : Math.round((clipRoot.maxDuration - clipRoot.outPoint) * -clipRoot.speed - 1)
property int thumbStartFrame: fixedThumbs ? 0 :
(clipRoot.speed >= 0)
? Math.round(clipRoot.inPoint * clipRoot.speed)
: Math.round((clipRoot.maxDuration - clipRoot.inPoint) * -clipRoot.speed - 1)
property int thumbEndFrame: fixedThumbs ? 0 :
(clipRoot.speed >= 0)
? Math.round(clipRoot.outPoint * clipRoot.speed)
: Math.round((clipRoot.maxDuration - clipRoot.outPoint) * -clipRoot.speed - 1)
Image {
width: thumbRepeater.imageWidth
......
......@@ -37,8 +37,28 @@ Item{
delegate: Item {
property var itemModel : model
property bool clipItem: isClip(model.clipType)
// Z order indicates the items that will be drawn on top. Compositions should be top, then clips. Clips with mix should be ordered related to their position so that the right clip of a clip mix is always on top (the mix UI is drawn over the right clip)
z: model.clipType == ProducerType.Composition ? 50000 : model.mixDuration > 0 ? model.start / 25 : root.activeTool === ProjectTool.SlipTool && model.selected ? model.item === timeline.trimmingMainClip ? 2 : 1 : 0
function calculateZIndex() {
// Z order indicates the items that will be drawn on top.
if (model.clipType == ProducerType.Composition) {
// Compositions should be top, then clips
return 50000;
}
if (model.mixDuration > 0) {
// Clips with mix should be ordered related to their position so that the right clip of a clip mix is always on top (the mix UI is drawn over the right clip)
return model.start / 25;
}
if (root.activeTool === ProjectTool.SlipTool && model.selected) {
return model.item === timeline.trimmingMainClip ? 2 : 1;
}
if (root.activeTool === ProjectTool.RippleTool && model.item === timeline.trimmingMainClip) {
return 1;
}
return 0;
}
z: calculateZIndex()
Loader {
id: loader
Binding {
......@@ -305,7 +325,16 @@ Item{
timeline.showToolTip(s)
return
}
var new_duration = controller.requestItemResize(clip.clipId, newDuration, false, false, root.snapping, shiftTrim)
var new_duration = 0;
if (root.activeTool === ProjectTool.RippleTool) {
console.log("In: Request for " + newDuration)
new_duration = controller.requestItemRippleResize(clip.clipId, newDuration, false, false, root.snapping, shiftTrim)
timeline.requestStartTrimmingMode(clip.clipId, false, false);
timeline.ripplePosChanged(new_duration, false);
} else {
new_duration = controller.requestItemResize(clip.clipId, newDuration, false, false, root.snapping, shiftTrim)
}
if (new_duration > 0) {
clip.lastValidDuration = new_duration
clip.originalX = clip.draggedX
......@@ -323,16 +352,26 @@ Item{
onTrimmedIn: {
//bubbleHelp.hide()
timeline.showToolTip();
if (shiftTrim || root.groupTrimData == undefined || controlTrim) {
if (shiftTrim || (root.groupTrimData == undefined/*TODO > */ || root.activeTool === ProjectTool.RippleTool /* < TODO*/) || controlTrim) {
// We only resize one element
controller.requestItemResize(clip.clipId, clip.originalDuration, false, false, 0, shiftTrim)
if (root.activeTool === ProjectTool.RippleTool) {
controller.requestItemRippleResize(clip.clipId, clip.originalDuration, false, false, 0, shiftTrim)
} else {
controller.requestItemResize(clip.clipId, clip.originalDuration, false, false, 0, shiftTrim)
}
if (controlTrim) {
// Update speed
speedController.visible = false
controller.requestClipResizeAndTimeWarp(clip.clipId, speedController.lastValidDuration, false, root.snapping, shiftTrim, clip.originalDuration * speedController.originalSpeed / speedController.lastValidDuration)