Commit 3be2b286 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Fix timeline focus issues on drag & drop, fix mouse position and project...

Fix timeline focus issues on drag & drop, fix mouse position and project duration in timeline toolbar not consistently updated
parent 18a625dc
Pipeline #156356 passed with stage
in 7 minutes and 8 seconds
......@@ -141,6 +141,7 @@ static QString defaultStyle(const char *fallback = nullptr)
MainWindow::MainWindow(QWidget *parent)
: KXmlGuiWindow(parent)
, m_activeTool(ToolType::SelectTool)
, m_mousePosition(0)
{
// Init all action categories that are used by other parts of the software
// before we call MainWindow::init and therefore can't be initilized there
......@@ -2279,26 +2280,31 @@ void MainWindow::slotCleanProject()
pCore->bin()->cleanupUnused();
}
void MainWindow::slotUpdateMousePosition(int pos)
void MainWindow::slotUpdateMousePosition(int pos, int duration)
{
if (pCore->currentDoc()) {
if (duration < 0) {
duration = getMainTimeline()->controller()->duration() - 1;
}
if (pos >= 0) {
m_mousePosition = pos;
}
switch (m_timeFormatButton->currentItem()) {
case 0:
m_timeFormatButton->setText(pCore->currentDoc()->timecode().getTimecodeFromFrames(pos) + QStringLiteral(" / ") +
pCore->currentDoc()->timecode().getTimecodeFromFrames(getMainTimeline()->controller()->duration() - 1));
m_timeFormatButton->setText(pCore->currentDoc()->timecode().getTimecodeFromFrames(m_mousePosition) + QStringLiteral(" / ") +
pCore->currentDoc()->timecode().getTimecodeFromFrames(duration));
break;
default:
m_timeFormatButton->setText(
QStringLiteral("%1 / %2").arg(pos, 6, 10, QLatin1Char('0')).arg(getMainTimeline()->controller()->duration() - 1, 6, 10, QLatin1Char('0')));
QStringLiteral("%1 / %2").arg(m_mousePosition, 6, 10, QLatin1Char('0')).arg(duration, 6, 10, QLatin1Char('0')));
}
}
}
void MainWindow::slotUpdateProjectDuration(int pos)
void MainWindow::slotUpdateProjectDuration(int duration)
{
Q_UNUSED(pos)
if (pCore->currentDoc()) {
slotUpdateMousePosition(getMainTimeline()->controller()->getMousePos());
slotUpdateMousePosition(-1, duration);
}
}
......
......@@ -282,6 +282,8 @@ private:
QLabel *m_trimLabel;
QActionGroup *m_scaleGroup;
ToolType::ProjectTool m_activeTool;
/** @brief Store latest mouse position in timeline. */
int m_mousePosition;
/** @brief initialize startup values, return true if first run. */
bool readOptions();
......@@ -343,6 +345,8 @@ public slots:
void updateProjectPath(const QString &path);
/** @brief Update compositing action to display current project setting. */
void slotUpdateCompositeAction(int mode);
/** @brief Update duration of projet in timeline toolbar. */
void slotUpdateProjectDuration(int pos);
private slots:
/** @brief Shows the shortcut dialog. */
......@@ -351,8 +355,7 @@ private slots:
/** @brief Reflects setting changes to the GUI. */
void updateConfiguration();
void slotConnectMonitors();
void slotUpdateMousePosition(int pos);
void slotUpdateProjectDuration(int pos);
void slotUpdateMousePosition(int pos, int duration = -1);
void slotEditProjectSettings();
void slotSwitchMarkersComments();
void slotSwitchSnap();
......
......@@ -454,8 +454,6 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
m_timePos = new TimecodeDisplay(pCore->timecode(), this);
if (id == Kdenlive::ProjectMonitor) {
// TODO: reimplement
// connect(render, &Render::durationChanged, this, &Monitor::durationChanged);
connect(m_glMonitor->getControllerProxy(), &MonitorProxy::saveZone, this, &Monitor::zoneUpdated);
connect(m_glMonitor->getControllerProxy(), &MonitorProxy::saveZoneWithUndo, this, &Monitor::zoneUpdatedWithUndo);
} else if (id == Kdenlive::ClipMonitor) {
......@@ -1519,6 +1517,9 @@ void Monitor::adjustRulerSize(int length, const std::shared_ptr<MarkerListModel>
connect(markerModel.get(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), this, SLOT(checkOverlay()));
connect(markerModel.get(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(checkOverlay()));
connect(markerModel.get(), SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(checkOverlay()));
} else {
// Project simply changed length, update display
emit durationChanged(length);
}
}
......
......@@ -1035,6 +1035,7 @@ bool ProjectManager::updateTimeline(int pos, const QString &chunks, const QStrin
pCore->monitorManager()->projectMonitor()->slotActivateMonitor();
pCore->monitorManager()->projectMonitor()->setProducer(m_mainTimelineModel->producer(), pos);
pCore->monitorManager()->projectMonitor()->adjustRulerSize(m_mainTimelineModel->duration() - 1, m_project->getGuideModel());
pCore->window()->slotUpdateProjectDuration(m_mainTimelineModel->duration() - 1);
pCore->window()->getMainTimeline()->controller()->setZone(m_project->zone(), false);
pCore->window()->getMainTimeline()->controller()->setScrollPos(m_project->getDocumentProperty(QStringLiteral("scrollPos")).toInt());
int activeTrackPosition = m_project->getDocumentProperty(QStringLiteral("activeTrack"), QString::number( - 1)).toInt();
......@@ -1056,9 +1057,10 @@ bool ProjectManager::updateTimeline(int pos, const QString &chunks, const QStrin
return true;
}
void ProjectManager::adjustProjectDuration()
void ProjectManager::adjustProjectDuration(int duration)
{
pCore->monitorManager()->projectMonitor()->adjustRulerSize(m_mainTimelineModel->duration() - 1, nullptr);
pCore->monitorManager()->projectMonitor()->adjustRulerSize(duration - 1, nullptr);
}
void ProjectManager::activateAsset(const QVariantMap &effectData)
......
......@@ -170,7 +170,7 @@ public slots:
void setDocumentNotes(const QString &notes);
/** @brief Project's duration changed, adjust monitor, etc. */
void adjustProjectDuration();
void adjustProjectDuration(int duration);
/** @brief Add an asset in timeline (effect, transition). */
void activateAsset(const QVariantMap &effectData);
/** @brief insert current timeline timecode in notes widget and focus widget to allow entering quick note */
......
......@@ -125,6 +125,10 @@ Rectangle {
controller.requestAddToSelection(clipRoot.clipId)
}
function doesContainMouse(pnt) {
return pnt.x > 0.5 && pnt.x < clipRoot.width
}
onClipResourceChanged: {
if (itemType === ProducerType.Color) {
color: Qt.darker(getColor(), 1.5)
......@@ -287,7 +291,7 @@ Rectangle {
//console.log('KFR VIEW VISIBLE: ', effectRow.visible, ', SOURCE: ', effectRow.source, '\n HIDEVIEW:', clipRoot.hideClipViews<<', UNDEFINED: ', (clipRoot.keyframeModel == undefined))
}
onExited: {
endDrag()
root.endDrag()
}
}
MouseArea {
......@@ -356,7 +360,7 @@ Rectangle {
}
onExited: {
endDrag()
root.endDrag()
if (!trimInMouseArea.containsMouse && !trimOutMouseArea.containsMouse && !compInArea.containsMouse && !compOutArea.containsMouse) {
timeline.showToolTip()
}
......@@ -636,7 +640,7 @@ Rectangle {
if (!controlTrim && root.activeTool !== ProjectTool.RippleTool) {
updateDrag()
} else {
endDrag()
root.endDrag()
}
} else {
if (root.activeTool === ProjectTool.RippleTool) {
......@@ -773,7 +777,7 @@ Rectangle {
if (!controlTrim && root.activeTool !== ProjectTool.RippleTool) {
updateDrag()
} else {
endDrag()
root.endDrag()
}
} else {
if (root.activeTool === ProjectTool.RippleTool) {
......
......@@ -102,6 +102,10 @@ Item {
}
}
function doesContainMouse(pnt) {
return pnt.x >= 0 && pnt.x < displayRect.width && (pnt.y > displayRect.y - trackOffset)
}
onTrackIdChanged: {
compositionRoot.parentTrack = Logic.getTrackById(trackId)
compositionRoot.y = compositionRoot.originalTrackId == -1 || trackId == originalTrackId ? 0 : parentTrack.y - Logic.getTrackById(compositionRoot.originalTrackId).y;
......
......@@ -601,7 +601,7 @@ Rectangle {
}
Rectangle {
id: resizer
height: 4
height: Math.round(root.baseUnit/3)
color: 'red'
opacity: 0
Drag.active: trimInMouseArea.drag.active
......
......@@ -324,25 +324,25 @@ Rectangle {
function regainFocus(mousePos) {
var currentMouseTrack = Logic.getTrackIdFromPos(mousePos.y - ruler.height - subtitleTrack.height + scrollView.contentY)
// Try to find correct item
//console.log('checking item on TK: ', currentMouseTrack, ' AT: XPOS', (mousePos.x - trackHeaders.width), ', SCROLL:', scrollView.contentX, ', RES: ', ((mousePos.x - trackHeaders.width + scrollView.contentX) / root.timeScale), ' SCROLL POS: ', (mousePos.y - ruler.height - subtitleTrack.height + scrollView.contentY))
var sourceTrack = Logic.getTrackById(currentMouseTrack)
var mouseYPos = (mousePos.y - ruler.height - subtitleTrack.height + scrollView.contentY) - sourceTrack.y
var mouseYPos = (mousePos.y - ruler.height + scrollView.contentY) - sourceTrack.y
var allowComposition = mouseYPos > sourceTrack.height / 2
var tentativeClip = undefined
root.mousePosChanged(Math.max(0, Math.floor((mousePos.x - trackHeaders.width + scrollView.contentX) / root.timeScale)))
if (allowComposition) {
tentativeClip = getItemAtPos(currentMouseTrack, mousePos.x - trackHeaders.width + scrollView.contentX, true)
tentativeClip = getItemAtPos(currentMouseTrack, (mousePos.x - trackHeaders.width + scrollView.contentX), true)
if (tentativeClip) {
// Ensure mouse is really over the composition
if (mouseYPos < tentativeClip.displayHeight) {
if (!tentativeClip.doesContainMouse(root.mapToItem(tentativeClip, mousePos.x, mousePos.y))) {
tentativeClip = undefined
}
}
}
if (!tentativeClip) {
tentativeClip = getItemAtPos(currentMouseTrack, mousePos.x - trackHeaders.width + scrollView.contentX, false)
tentativeClip = getItemAtPos(currentMouseTrack, (mousePos.x - trackHeaders.width + scrollView.contentX), false)
}
if (tentativeClip && tentativeClip.clipId) {
if (tentativeClip && tentativeClip.clipId && tentativeClip.doesContainMouse(root.mapToItem(tentativeClip, mousePos.x, mousePos.y))) {
dragProxy.draggedItem = tentativeClip.clipId
var tk = controller.getItemTrackId(tentativeClip.clipId)
dragProxy.x = tentativeClip.x
......@@ -569,7 +569,7 @@ Rectangle {
if (clipBeingMovedId == -1) {
var track = Logic.getTrackIdFromPos(drag.y + scrollView.contentY - subtitleTrack.height)
if (track !== -1) {
var frame = Math.round((drag.x + scrollView.contentX) / root.timeScale)
var frame = Math.floor((drag.x + scrollView.contentX) / root.timeScale)
if (clipBeingDroppedId >= 0) {
if (controller.isAudioTrack(track) != isAudioDrag) {
// Don't allow moving composition to an audio track
......@@ -602,6 +602,7 @@ Rectangle {
}
}
}
root.mousePosChanged(Math.max(0, Math.floor((drag.x + scrollView.contentX) / root.timeScale)))
}
onExited:{
if (clipBeingDroppedId != -1) {
......@@ -626,7 +627,7 @@ Rectangle {
}
}
clearDropData()
regainFocus(mapToItem(root, drag.x, drag.y))
regainFocus(clipDropArea.mapToItem(root, drag.x, drag.y))
}
}
DropArea {
......@@ -695,8 +696,11 @@ Rectangle {
}
fakeTrack = -1
fakeFrame = -1
clearDropData()
if (clipDropArea.containsDrag) {
regainFocus(clipDropArea.mapToItem(root, drag.x, drag.y))
}
}
clearDropData()
}
onEntered: {
if (clipBeingDroppedId > -1 && lastDragUuid != drag.getDataAsString('kdenlive/dragid') && timeline.exists(clipBeingDroppedId)) {
......@@ -761,7 +765,7 @@ Rectangle {
if (track >= 0 && track < tracksRepeater.count) {
//timeline.activeTrack = tracksRepeater.itemAt(track).trackInternalId
var targetTrack = tracksRepeater.itemAt(track).trackInternalId
var frame = Math.round((drag.x + scrollView.contentX) / root.timeScale)
var frame = Math.floor((drag.x + scrollView.contentX) / root.timeScale)
if (clipBeingDroppedId > -1) {
var moveData = controller.suggestClipMove(clipBeingDroppedId, targetTrack, frame, root.consumerPosition, root.snapping)
fakeFrame = moveData[0]
......@@ -788,10 +792,10 @@ Rectangle {
}
}
}
root.mousePosChanged(Math.max(0, Math.floor((drag.x + scrollView.contentX) / root.timeScale)))
}
onDropped: {
processDrop()
regainFocus(mapToItem(root, drag.x, drag.y))
}
}
DropArea { //Drop area for urls (direct drop from file manager)
......@@ -838,9 +842,10 @@ Rectangle {
}
}
}
root.mousePosChanged(Math.max(0, Math.floor((drag.x + scrollView.contentX) / root.timeScale)))
}
onDropped: {
var frame = Math.round((drag.x + scrollView.contentX) / root.timeScale)
var frame = Math.floor((drag.x + scrollView.contentX) / root.timeScale)
var track = timeline.activeTrack
//var binIds = clipBeingDroppedData.split(";")
//if (binIds.length == 1) {
......@@ -1161,12 +1166,12 @@ Rectangle {
Column {
id: trackHeadersResizer
spacing: 0
width: root.baseUnit / 2
width: Math.round(root.baseUnit/3)
Rectangle {
id: resizer
height: trackHeaders.height + subtitleTrackHeader.height
width: root.baseUnit / 2
x: root.headerWidth - 2
width: parent.width
x: root.headerWidth - width
color: 'red'
opacity: 0
Drag.active: headerMouseArea.drag.active
......@@ -1378,8 +1383,7 @@ Rectangle {
proxy.position = Math.floor((scrollView.contentX + mouse.x) / root.timeScale)
}
}
var mousePos = Math.max(0, Math.round((mouse.x + scrollView.contentX) / root.timeScale))
root.mousePosChanged(mousePos)
root.mousePosChanged(Math.max(0, Math.floor((mouse.x + scrollView.contentX) / root.timeScale)))
ruler.showZoneLabels = mouse.y < ruler.height
if (shiftPress && mouse.buttons === Qt.LeftButton && (root.activeTool === ProjectTool.SelectTool || root.activeTool === ProjectTool.RippleTool) && !rubberSelect.visible && rubberSelect.y > 0) {
// rubber selection, check if mouse move was enough
......@@ -1796,7 +1800,7 @@ Rectangle {
function moveItem() {
if (dragProxy.draggedItem > -1) {
var mapped = Math.max(0, tracksContainerArea.mapFromItem(dragProxy, dragProxyArea.mouseX, 0).x)
root.mousePosChanged(Math.round(mapped / root.timeScale))
root.mousePosChanged(Math.floor(mapped / root.timeScale))
var posx = Math.round((parent.x)/ root.timeScale)
var posy = Math.min(Math.max(0, dragProxyArea.mouseY + parent.y - dragProxy.verticalOffset), tracksContainerArea.height)
var tId = Logic.getTrackIdFromPos(posy)
......
......@@ -264,7 +264,7 @@ void TimelineController::checkDuration()
int currentLength = m_model->duration();
if (currentLength != m_duration) {
m_duration = currentLength;
emit durationChanged();
emit durationChanged(m_duration);
}
}
......
......@@ -760,7 +760,7 @@ signals:
void scaleFactorChanged();
void audioThumbFormatChanged();
void audioThumbNormalizeChanged();
void durationChanged();
void durationChanged(int duration);
void audioTargetChanged();
void videoTargetChanged();
void hasAudioTargetChanged();
......
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