feature: a much nicer qml rangedslider
In order to make start and end time setting far more efficient, I decided to create my own RangeSlider called RangedSlider. This has a moved signal for each handle and a released signal for each handle. This allows us to change the video playback but not set the value until released. Meaning only one access to the database.
This commit is contained in:
parent
8b231de32b
commit
81ea712c6b
2 changed files with 131 additions and 124 deletions
|
@ -14,13 +14,18 @@ Rectangle {
|
|||
|
||||
property real firstValue
|
||||
property real secondValue
|
||||
property real firstInitialValue
|
||||
property real secondInitialValue
|
||||
property real firstVisualPosition
|
||||
property real secondVisualPosition
|
||||
|
||||
signal firstReleased()
|
||||
signal secondReleased()
|
||||
signal firstMoved()
|
||||
signal secondMoved()
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Button
|
||||
Kirigami.Theme.inherit: false
|
||||
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
border.width: 0
|
||||
|
@ -28,31 +33,32 @@ Rectangle {
|
|||
|
||||
height: 6
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: range
|
||||
color: Kirigami.Theme.hoverColor
|
||||
height: root.height
|
||||
radius: width / 2
|
||||
border.width: 0
|
||||
anchors.right: second.right
|
||||
anchors.left: first.left
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: first
|
||||
x: firstVisualPosition
|
||||
x: firstInitialValue / (to - from) * (root.width - width)
|
||||
y: -6
|
||||
implicitWidth: 18
|
||||
implicitHeight: 18
|
||||
color: firstMouse.containsMouse ? Kirigami.Theme.hoverColor : Kirigami.Theme.alternateBackgroundColor
|
||||
border.width: firstMouse.containsMouse ? 2 : 1
|
||||
border.color: firstMouse.containsMouse ? Kirigami.Theme.hoverColor : Kirigami.Theme.backgroundColor
|
||||
color: firstMouse.containsMouse || firstMouse.drag.active ? Kirigami.Theme.hoverColor : Kirigami.Theme.alternateBackgroundColor
|
||||
border.width: firstMouse.containsMouse || firstMouse.drag.active ? 2 : 1
|
||||
border.color: firstMouse.containsMouse || firstMouse.drag.active ? Kirigami.Theme.hoverColor : Kirigami.Theme.backgroundColor
|
||||
radius: width / 2
|
||||
|
||||
Drag.active: firstMouse.drag.active
|
||||
Drag.hotSpot.x: width / 2
|
||||
Drag.hotSpot.y: height / 2
|
||||
|
||||
/* states: State { */
|
||||
/* name: "dragged" */
|
||||
/* when: first.Drag.active */
|
||||
/* PropertyChanges { */
|
||||
/* target: first */
|
||||
/* x: x */
|
||||
/* width: width */
|
||||
/* height: height */
|
||||
/* } */
|
||||
/* } */
|
||||
MouseArea {
|
||||
id: firstMouse
|
||||
anchors.fill: parent
|
||||
|
@ -60,41 +66,38 @@ Rectangle {
|
|||
drag {
|
||||
target: first
|
||||
axis: Drag.XAxis
|
||||
maximumX: root.right
|
||||
minimumX: root.left
|
||||
maximumX: Math.min((root.width - first.width / 2), second.x)
|
||||
minimumX: 0 + first.width / 2
|
||||
}
|
||||
onReleased: {
|
||||
firstValue = mouseX;
|
||||
firstValue = (to - from) / (root.width - first.width) * (first.x - first.width / 2) + from;
|
||||
firstVisualPosition = firstValue;
|
||||
firstReleased();
|
||||
}
|
||||
onPositionChanged: {
|
||||
if (drag.active) {
|
||||
firstVisualPosition = (to - from) / (root.width - first.width) * (first.x - first.width / 2) + from;
|
||||
firstMoved()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: second
|
||||
x: secondVisualPosition
|
||||
x: secondInitialValue / (to - from) * (root.width - width)
|
||||
y: -6
|
||||
implicitWidth: 18
|
||||
implicitHeight: 18
|
||||
color: secondMouse.containsMouse ? Kirigami.Theme.hoverColor : Kirigami.Theme.alternateBackgroundColor
|
||||
border.width: secondMouse.containsMouse ? 2 : 1
|
||||
border.color: secondMouse.containsMouse ? Kirigami.Theme.hoverColor : Kirigami.Theme.backgroundColor
|
||||
color: secondMouse.containsMouse || secondMouse.drag.active ? Kirigami.Theme.hoverColor : Kirigami.Theme.alternateBackgroundColor
|
||||
border.width: secondMouse.containsMouse || secondMouse.drag.active ? 2 : 1
|
||||
border.color: secondMouse.containsMouse || secondMouse.drag.active ? Kirigami.Theme.hoverColor : Kirigami.Theme.backgroundColor
|
||||
radius: width / 2
|
||||
|
||||
Drag.active: secondMouse.drag.active
|
||||
Drag.hotSpot.x: width / 2
|
||||
Drag.hotSpot.y: height / 2
|
||||
|
||||
/* states: State { */
|
||||
/* name: "dragged" */
|
||||
/* when: second.Drag.active */
|
||||
/* PropertyChanges { */
|
||||
/* target: second */
|
||||
/* x: x */
|
||||
/* width: width */
|
||||
/* height: height */
|
||||
/* } */
|
||||
/* } */
|
||||
MouseArea {
|
||||
id: secondMouse
|
||||
anchors.fill: parent
|
||||
|
@ -102,19 +105,25 @@ Rectangle {
|
|||
drag {
|
||||
target: second
|
||||
axis: Drag.XAxis
|
||||
maximumX: root.width
|
||||
minimumX: 0
|
||||
maximumX: root.width - second.width / 2
|
||||
minimumX: Math.max((0 + second.width / 2), first.x)
|
||||
}
|
||||
onReleased: {
|
||||
secondValue = second.x;
|
||||
secondValue = (to - from) / (root.width - second.width) * (second.x - second.width / 2) + from;
|
||||
secondVisualPosition = secondValue;
|
||||
secondReleased();
|
||||
}
|
||||
onPositionChanged: {
|
||||
if (drag.active) {
|
||||
secondVisualPosition = (to - from) / (root.width - second.width) * (second.x - second.width / 2) + from;
|
||||
secondMoved()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: range
|
||||
color: Kirigami.Theme.hoverColor
|
||||
radius: width / 2
|
||||
}
|
||||
/* function setValues(first, second) { */
|
||||
/* first.x = first */
|
||||
/* second.x = second */
|
||||
/* } */
|
||||
}
|
||||
|
|
|
@ -80,10 +80,12 @@ Item {
|
|||
|
||||
Item {
|
||||
Layout.columnSpan: 2
|
||||
Layout.preferredWidth: root.width - 50
|
||||
Layout.preferredHeight: Layout.preferredWidth / 16 * 9
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: width / 16 * 9
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.topMargin: 10
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
|
||||
MpvObject {
|
||||
id: videoPreview
|
||||
|
@ -100,16 +102,10 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: videoBg
|
||||
color: Kirigami.Theme.alternateBackgroundColor
|
||||
|
||||
anchors.top: videoPreview.bottom
|
||||
width: parent.width
|
||||
height: videoTitleField.height
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.top: videoPreview.bottom
|
||||
width: videoPreview.width
|
||||
height: videoTitleField.height
|
||||
spacing: 2
|
||||
Kirigami.Icon {
|
||||
source: videoPreview.isPlaying ? "media-pause" : "media-play"
|
||||
|
@ -137,75 +133,85 @@ Item {
|
|||
text: new Date(videoPreview.position * 1000).toISOString().slice(11, 19);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: videoRangeBox
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.leftMargin: 25
|
||||
Layout.rightMargin: 25
|
||||
Layout.topMargin: 40
|
||||
visible: editingRange
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing * 3
|
||||
Layout.bottomMargin: Kirigami.Units.largeSpacing * 3
|
||||
/* visible: editingRange */
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
|
||||
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
border.width: 1
|
||||
border.color: Kirigami.Theme.disabledTextColor
|
||||
radius: 6
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Controls.RangeSlider {
|
||||
id: videoLengthSlider
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.leftMargin: 25
|
||||
Layout.rightMargin: 25
|
||||
|
||||
to: videoPreview.duration
|
||||
from: 0
|
||||
stepSize: 0.1
|
||||
snapMode: Controls.RangeSlider.SnapAlways
|
||||
|
||||
first.value: video.startTime
|
||||
second.value: video.endTime
|
||||
|
||||
first.onMoved: updateStartTime(first.value)
|
||||
second.onMoved: updateEndTime(second.value)
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
topMargin: 5
|
||||
bottomMargin: 5
|
||||
leftMargin: 5
|
||||
rightMargin: 5
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
text: "Adjust start and end times:"
|
||||
Rectangle {
|
||||
anchors.top: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
implicitHeight: Kirigami.Units.smallSpacing / 3
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
}
|
||||
}
|
||||
|
||||
Presenter.RangedSlider {
|
||||
id: videoLengthSlider
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.leftMargin: 25
|
||||
Layout.rightMargin: 25
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing * 3
|
||||
/* Layout.leftMargin: 25 */
|
||||
/* Layout.rightMargin: 25 */
|
||||
|
||||
onFirstReleased: showPassiveNotification("first")
|
||||
onSecondReleased: showPassiveNotification("Second")
|
||||
from: 0
|
||||
to: videoPreview.duration
|
||||
|
||||
firstInitialValue: video.startTime
|
||||
secondInitialValue: video.endTime
|
||||
|
||||
onFirstMoved: videoPreview.seek(firstVisualPosition)
|
||||
onSecondMoved: videoPreview.seek(secondVisualPosition)
|
||||
|
||||
onFirstReleased: updateStartTime(firstValue)
|
||||
onSecondReleased: updateEndTime(secondValue)
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
Layout.leftMargin: 25
|
||||
Layout.rightMargin: 25
|
||||
|
||||
Controls.Label {
|
||||
Controls.TextField {
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
text: "Start Time: " + new Date(videoLengthSlider.first.value * 1000).toISOString().slice(11, 19);
|
||||
text: "Start Time: " + new Date(videoLengthSlider.firstVisualPosition * 1000).toISOString().slice(11, 19);
|
||||
horizontalAlignment: TextInput.AlignHCenter
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
Controls.TextField {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
text: "End Time: " + new Date(videoLengthSlider.second.value * 1000).toISOString().slice(11, 19);
|
||||
text: "End Time: " + new Date(videoLengthSlider.secondVisualPosition * 1000).toISOString().slice(11, 19);
|
||||
horizontalAlignment: TextInput.AlignHCenter
|
||||
}
|
||||
|
||||
}
|
||||
Controls.ToolButton {
|
||||
text: "FIX"
|
||||
onClicked: videoLengthSlider.setValues(video.startTime, video.endTime)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,8 +242,6 @@ Item {
|
|||
interval: 100
|
||||
onTriggered: {
|
||||
videoPreview.loadFile(video.filePath.toString());
|
||||
videoLengthSlider.setValues(video.startTime, video.endTime);
|
||||
/* showPassiveNotification(video[0]); */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,7 +251,6 @@ Item {
|
|||
console.log(video.startTime);
|
||||
console.log(video.endTime);
|
||||
mpvLoadingTimer.restart();
|
||||
videoLengthSlider.setValues(vid.startTime, vid.endTime);
|
||||
footerLeftString = "File path: " + video.filePath
|
||||
}
|
||||
|
||||
|
@ -258,18 +261,13 @@ Item {
|
|||
}
|
||||
|
||||
function updateEndTime(value) {
|
||||
videoPreview.seek(value);
|
||||
videoProxyModel.updateEndTime(video.id, value);
|
||||
videoProxyModel.updateEndTime(video.id, Math.min(value, videoPreview.duration));
|
||||
video.endTime = value;
|
||||
/* showPassiveNotification(video.endTime); */
|
||||
}
|
||||
|
||||
function updateStartTime(value) {
|
||||
/* changeStartTime(value, false); */
|
||||
videoPreview.seek(value);
|
||||
videoProxyModel.updateStartTime(video.id, value);
|
||||
videoProxyModel.updateStartTime(video.id, Math.max(value, 0));
|
||||
video.startTime = value;
|
||||
/* showPassiveNotification(value); */
|
||||
}
|
||||
|
||||
function updateTitle(text) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue