Skip to content

Commit

Permalink
improve performance of timeline zoom
Browse files Browse the repository at this point in the history
  • Loading branch information
ddennedy committed Oct 24, 2023
1 parent afd6a65 commit ef4bed6
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 24 deletions.
2 changes: 2 additions & 0 deletions src/docks/timelinedock.cpp
Expand Up @@ -198,7 +198,9 @@ TimelineDock::TimelineDock(QWidget *parent) :
});
connect(&m_model, &MultitrackModel::scaleFactorChanged, zoomSlider, [ = ]() {
double value = round(pow(m_model.scaleFactor() - 0.01, 1.0 / 3.0) * 100.0);
zoomSlider->blockSignals(true);
zoomSlider->setValue(value);
zoomSlider->blockSignals(false);
});
toolbar->addWidget(zoomSlider);
toolbar->addAction(Actions["timelineZoomInAction"]);
Expand Down
9 changes: 4 additions & 5 deletions src/qml/views/timeline/Clip.qml
Expand Up @@ -73,7 +73,7 @@ Rectangle {

// This is needed to make the model have the correct count.
// Model as a property expression is not working in all cases.
waveformRepeater.model = Math.ceil(waveform.innerWidth / waveform.maxWidth);
waveformRepeater.model = Math.ceil(clipRoot.width / waveform.maxWidth);
for (var i = 0; i < waveformRepeater.count; i++)
waveformRepeater.itemAt(0).update();
}
Expand Down Expand Up @@ -191,8 +191,7 @@ Rectangle {
Row {
id: waveform

property int maxWidth: Math.max(application.maxTextureSize / 2, 2048)
property int innerWidth: clipRoot.width - clipRoot.border.width * 2
readonly property int maxWidth: Math.max(application.maxTextureSize / 2, 2048)

visible: !elided && !isBlank && settings.timelineShowWaveforms && (parseInt(audioIndex) > -1 || audioIndex === 'all')
height: (isAudio || parent.height <= 20) ? parent.height : parent.height / 2
Expand All @@ -204,7 +203,7 @@ Rectangle {
Repeater {
id: waveformRepeater

model: Math.ceil(waveform.innerWidth / waveform.maxWidth)
model: Math.ceil(clipRoot.width / waveform.maxWidth)

Shotcut.TimelineWaveform {

Expand All @@ -213,7 +212,7 @@ Rectangle {
// bottom edge
property int channels: 2

width: Math.min(waveform.innerWidth, waveform.maxWidth)
width: Math.min(clipRoot.width, waveform.maxWidth)
height: waveform.height
fillColor: getColor()
inPoint: Math.round((clipRoot.inPoint + index * waveform.maxWidth / timeScale) * speed) * channels
Expand Down
35 changes: 25 additions & 10 deletions src/qml/views/timeline/Ruler.qml
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022 Meltytech, LLC
* Copyright (c) 2013-2023 Meltytech, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -22,21 +22,26 @@ Rectangle {
id: rulerTop

property real timeScale: 1
property int adjustment: 0
property real intervalSeconds: ((timeScale > 5) ? 1 : (5 * Math.max(1, Math.floor(1.5 / timeScale)))) + adjustment
readonly property real intervalFrames: profile.fps * ((timeScale > 5) ? 1 : (5 * Math.max(1, Math.floor(1.5 / timeScale))))

signal editMarkerRequested(int index)
signal deleteMarkerRequested(int index)

height: 28
color: activePalette.base

Timer {
id: updateTimer
interval: 100
onTriggered: repeater.model = Math.round(width / intervalFrames / timeScale)
}

SystemPalette {
id: activePalette
}

Repeater {
model: parent.width / (intervalSeconds * profile.fps * timeScale)
id: repeater

Rectangle {

Expand All @@ -45,7 +50,7 @@ Rectangle {
height: 18
width: 1
color: activePalette.windowText
x: index * intervalSeconds * profile.fps * timeScale
x: index * intervalFrames * timeScale
visible: ((x + width) > tracksFlickable.contentX) && (x < tracksFlickable.contentX + tracksFlickable.width) // left edge

Label {
Expand All @@ -54,7 +59,7 @@ Rectangle {
anchors.bottom: parent.bottom
anchors.bottomMargin: 2
color: activePalette.windowText
text: application.timecode(index * intervalSeconds * profile.fps + 2).substr(0, 8)
text: application.timecode(index * intervalFrames + 2).substr(0, 8)
}
}
}
Expand All @@ -74,7 +79,7 @@ Rectangle {
anchors.top: rulerTop.top
anchors.left: parent.left
anchors.right: parent.right
timeScale: root.timeScale ? root.timescale : 1
timeScale: rulerTop.timeScale
model: markers
onExited: bubbleHelp.hide()
onMouseStatusChanged: (mouseX, mouseY, text, start, end) => {
Expand Down Expand Up @@ -124,11 +129,21 @@ Rectangle {

Connections {
function onProfileChanged() {
// Force a repeater model change to update the labels.
++adjustment;
--adjustment;
updateTimer.restart();
}

target: profile
}

Connections {
function onDurationChanged() {
updateTimer.restart();
}

function onScaleFactorChanged() {
updateTimer.restart();
}

target: multitrack
}
}
6 changes: 3 additions & 3 deletions src/qml/views/timeline/TrackHead.qml
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022 Meltytech, LLC
* Copyright (c) 2013-2023 Meltytech, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -94,10 +94,10 @@ Rectangle {
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: {
onClicked: mouse => {
parent.clicked();
nameEdit.focus = false;
if (mouse.button == Qt.RightButton)
if (mouse.button === Qt.RightButton)
root.timelineRightClicked();
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/qml/views/timeline/timeline.qml
Expand Up @@ -41,21 +41,21 @@ Rectangle {
function setZoom(value, targetX) {
if (!targetX)
targetX = tracksFlickable.contentX + tracksFlickable.width / 2;
var offset = targetX - tracksFlickable.contentX;
var before = multitrack.scaleFactor;
let offset = targetX - tracksFlickable.contentX;
let before = multitrack.scaleFactor;
if (isNaN(value))
value = 0;
multitrack.scaleFactor = Math.pow(Math.max(value, 0), 3) + 0.01;
if (settings.timelineScrolling !== Shotcut.Settings.CenterPlayhead && !settings.timelineScrollZoom)
tracksFlickable.contentX = (targetX * multitrack.scaleFactor / before) - offset;
for (var i = 0; i < tracksRepeater.count; i++)
for (let i = 0; i < tracksRepeater.count; i++)
tracksRepeater.itemAt(i).redrawWaveforms(false);
if (settings.timelineScrollZoom && settings.timelineScrolling !== Shotcut.Settings.CenterPlayhead)
scrollZoomTimer.restart();
}

function adjustZoom(by, targetX) {
var value = Math.pow(multitrack.scaleFactor - 0.01, 1 / 3);
let value = Math.pow(multitrack.scaleFactor - 0.01, 1 / 3);
setZoom(value + by, targetX);
}

Expand All @@ -64,7 +64,7 @@ Rectangle {
}

function selectMultitrack() {
for (var i = 0; i < trackHeaderRepeater.count; i++)
for (let i = 0; i < trackHeaderRepeater.count; i++)
trackHeaderRepeater.itemAt(i).selected = false;
cornerstone.selected = true;
}
Expand Down Expand Up @@ -399,7 +399,7 @@ Rectangle {
timeline.position = (tracksFlickable.contentX + mouse.x) / multitrack.scaleFactor;
bubbleHelp.hide();
}
onWheel: Logic.onMouseWheel(wheel)
onWheel: wheel => Logic.onMouseWheel(wheel)
onReleased: skim = false
onExited: skim = false
onPositionChanged: mouse => {
Expand Down

0 comments on commit ef4bed6

Please sign in to comment.