Warning, /multimedia/kasts/src/qml/ChapterSlider.qml is written in an unsupported language. File is not indexed.
0001 /** 0002 * SPDX-FileCopyrightText: 2023 Tobias Fella <fella@posteo.de> 0003 * SPDX-FileCopyrightText: 2023 Bart De Vries <bart@mogwai.be> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 import QtQuick 0009 import QtQuick.Controls 0010 import QtQuick.Layouts 0011 0012 import org.kde.kirigami as Kirigami 0013 0014 import org.kde.kasts 0015 0016 Control { 0017 id: root 0018 0019 property alias model: chapters.model 0020 0021 property int value: AudioManager.position 0022 property int duration: AudioManager.duration 0023 0024 Kirigami.Theme.colorSet: Kirigami.Theme.Button 0025 Kirigami.Theme.inherit: false 0026 0027 implicitHeight: handle.height 0028 implicitWidth: 200 0029 0030 // metrics used by the default font 0031 property var fontMetrics: FontMetrics { 0032 property real fullWidthCharWidth: fontMetrics.tightBoundingRect('_').width 0033 } 0034 0035 // align with the Slider implementations in the major styles 0036 readonly property bool desktopStyle: styleName === "org.kde.desktop" 0037 readonly property color inactiveGrooveColor: desktopStyle ? Kirigami.ColorUtils.scaleColor(inactiveGrooveBorderColor, {alpha: -50}) : Kirigami.Theme.backgroundColor 0038 readonly property color activeGrooveColor: desktopStyle ? Kirigami.ColorUtils.scaleColor(activeGrooveBorderColor, {alpha: -50}) : Kirigami.Theme.alternateBackgroundColor 0039 readonly property color inactiveGrooveBorderColor: desktopStyle ? Kirigami.ColorUtils.scaleColor(Kirigami.Theme.textColor, {alpha: -80}) : Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.3) 0040 readonly property color activeGrooveBorderColor: desktopStyle ? Kirigami.Theme.highlightColor : Kirigami.Theme.focusColor 0041 readonly property color handleColor: Kirigami.Theme.backgroundColor 0042 readonly property color handleBorderColor: dragArea.pressed || dragArea.containsMouse ? Kirigami.Theme.focusColor : Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, 0.4) 0043 0044 readonly property int grooveSize: { 0045 if (desktopStyle) { 0046 return 6; 0047 } else { 0048 let h = Math.floor(fontMetrics.height / 3); 0049 h += h % 2; 0050 return h; 0051 } 0052 } 0053 readonly property int handleSize: desktopStyle ? 20 : fontMetrics.height 0054 0055 function setPlaybackPosition(x) { 0056 AudioManager.position = (Math.max(handle.width / 2, Math.min(x, root.width - handle.width / 2)) - handle.width / 2) / (root.width - handle.width) * duration 0057 } 0058 0059 MouseArea { 0060 anchors.fill: parent 0061 onReleased: { 0062 setPlaybackPosition(mouseX) 0063 } 0064 // TODO: handle scrollwheel 0065 } 0066 0067 RowLayout { 0068 id: layout 0069 anchors.fill: parent 0070 anchors.leftMargin: handle.width / 2 0071 anchors.rightMargin: handle.width / 2 0072 spacing: 0 0073 Repeater { 0074 id: chapters 0075 delegate: Rectangle { 0076 // If we're not dragging, use the more precise method using the AudioManager. If we're dragging, this doesn't work because the AudioManager isn't updated while dragging 0077 readonly property bool isCurrent: dragArea.drag.active ? (x - 1.01 <= handle.centerX && handle.centerX < x + width) : (model.start * 1000 <= AudioManager.position && (model.start + model.duration) * 1000 > AudioManager.position) 0078 readonly property bool isPrevious: dragArea.drag.active ? (x + width < handle.centerX) : ((model.start + model.duration) * 1000 < AudioManager.position) 0079 Layout.preferredWidth: model.duration * 1000 / root.duration * (layout.width - chapters.count + 1) 0080 Layout.preferredHeight: grooveSize 0081 Layout.alignment: Qt.AlignVCenter 0082 radius: height / 2 0083 0084 z: 1 0085 color: inactiveGrooveColor 0086 border { 0087 width: 1 0088 color: inactiveGrooveBorderColor 0089 } 0090 MouseArea { 0091 anchors.fill: parent 0092 hoverEnabled: true 0093 z: 0 0094 ToolTip { 0095 text: model.title 0096 visible: parent.containsMouse 0097 } 0098 onReleased: { 0099 setPlaybackPosition(mouseX + parent.x + handle.width / 2) 0100 } 0101 } 0102 Rectangle { 0103 visible: isCurrent || isPrevious 0104 anchors.left: parent.left 0105 anchors.top: parent.top 0106 anchors.bottom: parent.bottom 0107 width: isCurrent ? handle.centerX - parent.x : parent.width 0108 radius: parent.height / 2 0109 color: activeGrooveColor 0110 border { 0111 width: 1 0112 color: activeGrooveBorderColor 0113 } 0114 } 0115 } 0116 } 0117 } 0118 0119 Rectangle { 0120 color: inactiveGrooveColor 0121 visible: chapters.count === 0 0122 border { 0123 width: 1 0124 color: inactiveGrooveBorderColor 0125 } 0126 width: parent.width - handle.width 0127 height: grooveSize 0128 radius: height / 2 0129 anchors.centerIn: parent 0130 Rectangle { 0131 anchors.left: parent.left 0132 anchors.top: parent.top 0133 anchors.bottom: parent.bottom 0134 width: handle.centerX - parent.x 0135 radius: parent.height / 2 0136 color: activeGrooveColor 0137 border { 0138 width: 1 0139 color: activeGrooveBorderColor 0140 } 0141 } 0142 } 0143 0144 Rectangle { 0145 id: handle 0146 0147 property int centerX: x + width / 2 0148 0149 Kirigami.Theme.inherit: false 0150 Kirigami.Theme.colorSet: Kirigami.Theme.Button 0151 0152 height: root.handleSize 0153 width: height 0154 radius: width / 2 0155 anchors.verticalCenter: root.verticalCenter 0156 color: handleColor 0157 border.width: 1 0158 border.color: handleBorderColor 0159 x: dragArea.drag.active ? 0 : root.value / root.duration * (root.width - handle.width) 0160 z: 2 0161 0162 MouseArea { 0163 id: dragArea 0164 anchors.fill: parent 0165 hoverEnabled: true 0166 drag { 0167 target: handle 0168 axis: Drag.XAxis 0169 minimumX: 0 0170 maximumX: root.width - handle.width 0171 threshold: 0 0172 } 0173 onReleased: setPlaybackPosition(handle.x + handle.width / 2) 0174 } 0175 } 0176 }