feat: rebuild the interface after Haruna
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
54ad4eecf3
commit
614a31db1b
45 files changed
+3818
-798
No files matched your search
@@ -0,0 +1,196 @@
|
||||
// SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2026 Tri Vo Khac
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import org.kde.ki18n
|
||||
import org.kde.kirigami as Kirigami
|
||||
|
||||
// The video, with Haruna's default mouse bindings and drag and drop.
|
||||
MpvItem {
|
||||
id: root
|
||||
|
||||
required property Actions actions
|
||||
property bool fullscreen: false
|
||||
|
||||
signal pointerMoved(x: real, y: real)
|
||||
signal pointerLeft()
|
||||
// Files dropped on the top part are queued; on the bottom part they play now.
|
||||
signal filesDropped(urls: list<url>, append: bool)
|
||||
signal subtitleDropped(url: url)
|
||||
|
||||
function isSubtitleFile(url: url): bool {
|
||||
return /\.(srt|ass|ssa|vtt|sub|sup)$/i.test(url.toString())
|
||||
}
|
||||
|
||||
// Plain-text and translated subtitles; styled ASS subtitles keep their own fonts.
|
||||
function applySubtitleStyle() {
|
||||
setPropertyAsync("sub-font-size", QtPotatoSettings.subtitleFontSize)
|
||||
setPropertyAsync("sub-outline-size", QtPotatoSettings.subtitleOutlineSize)
|
||||
}
|
||||
|
||||
loadUserConfig: QtPotatoSettings.loadMpvConfig
|
||||
|
||||
// Set once the saved volume is applied; mpv reports its default volume before that.
|
||||
property bool volumeRestored: false
|
||||
|
||||
// QtPotato's own settings win over mpv.conf.
|
||||
onUserConfigApplied: {
|
||||
applySubtitleStyle()
|
||||
volume = QtPotatoSettings.volume
|
||||
volumeRestored = true
|
||||
}
|
||||
|
||||
onVolumeChanged: {
|
||||
if (volumeRestored) {
|
||||
QtPotatoSettings.volume = volume
|
||||
}
|
||||
}
|
||||
|
||||
readonly property int subtitleFontSize: QtPotatoSettings.subtitleFontSize
|
||||
onSubtitleFontSizeChanged: applySubtitleStyle()
|
||||
readonly property int subtitleOutlineSize: QtPotatoSettings.subtitleOutlineSize
|
||||
onSubtitleOutlineSizeChanged: applySubtitleStyle()
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "black"
|
||||
visible: !root.fileLoaded
|
||||
z: -1
|
||||
}
|
||||
|
||||
Kirigami.PlaceholderMessage {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - Kirigami.Units.gridUnit * 4
|
||||
visible: !root.fileLoaded && !dropArea.containsDrag
|
||||
icon.name: "video-symbolic"
|
||||
text: KI18n.i18nc("@info:placeholder", "No video open")
|
||||
explanation: KI18n.i18nc("@info:placeholder", "Open a file or drop one here")
|
||||
helpfulAction: root.actions.openFile
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: hideCursorTimer
|
||||
running: root.fullscreen && mouseArea.containsMouse
|
||||
repeat: true
|
||||
interval: 2000
|
||||
onTriggered: mouseArea.hideCursor = true
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
property bool hideCursor: false
|
||||
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton | Qt.ForwardButton | Qt.BackButton
|
||||
hoverEnabled: true
|
||||
cursorShape: hideCursor && root.fullscreen ? Qt.BlankCursor : Qt.ArrowCursor
|
||||
|
||||
onPositionChanged: mouse => {
|
||||
hideCursor = false
|
||||
hideCursorTimer.restart()
|
||||
root.pointerMoved(mouse.x, mouse.y)
|
||||
}
|
||||
onExited: root.pointerLeft()
|
||||
|
||||
onPressed: mouse => {
|
||||
switch (mouse.button) {
|
||||
case Qt.LeftButton:
|
||||
root.actions.playPause.trigger()
|
||||
break
|
||||
case Qt.MiddleButton:
|
||||
root.actions.mute.trigger()
|
||||
break
|
||||
case Qt.RightButton:
|
||||
root.actions.openContextMenu.trigger()
|
||||
break
|
||||
case Qt.ForwardButton:
|
||||
root.actions.seekForwardSmall.trigger()
|
||||
break
|
||||
case Qt.BackButton:
|
||||
root.actions.seekBackwardSmall.trigger()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
onDoubleClicked: mouse => {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
// Both presses of the double click toggled playback, so it is unchanged.
|
||||
root.actions.toggleFullscreen.trigger()
|
||||
} else if (mouse.button === Qt.MiddleButton) {
|
||||
root.actions.configure.trigger()
|
||||
}
|
||||
}
|
||||
|
||||
onWheel: wheel => {
|
||||
if (wheel.angleDelta.y > 0) {
|
||||
root.actions.volumeUp.trigger()
|
||||
} else if (wheel.angleDelta.y < 0) {
|
||||
root.actions.volumeDown.trigger()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropArea {
|
||||
id: dropArea
|
||||
|
||||
readonly property bool onTopPart: containsDrag && drag.y <= height * 0.25
|
||||
property bool onlySubtitles: false
|
||||
|
||||
anchors.fill: parent
|
||||
keys: ["text/uri-list"]
|
||||
|
||||
onEntered: drag => {
|
||||
onlySubtitles = drag.urls.length > 0 && drag.urls.every(url => root.isSubtitleFile(url))
|
||||
}
|
||||
|
||||
onDropped: drop => {
|
||||
if (!drop.hasUrls) {
|
||||
return
|
||||
}
|
||||
if (onlySubtitles) {
|
||||
root.subtitleDropped(drop.urls[0])
|
||||
} else {
|
||||
root.filesDropped(drop.urls, onTopPart)
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: dropArea.containsDrag && !dropArea.onlySubtitles ? 2 : 0
|
||||
delegate: Rectangle {
|
||||
id: dropZone
|
||||
|
||||
required property int index
|
||||
readonly property bool isTop: index === 0
|
||||
readonly property bool active: isTop === dropArea.onTopPart
|
||||
|
||||
x: Kirigami.Units.smallSpacing
|
||||
y: isTop ? Kirigami.Units.smallSpacing : dropArea.height * 0.25 + Kirigami.Units.smallSpacing
|
||||
width: dropArea.width - Kirigami.Units.smallSpacing * 2
|
||||
height: (isTop ? dropArea.height * 0.25 : dropArea.height * 0.75) - Kirigami.Units.smallSpacing * 2
|
||||
color: "transparent"
|
||||
radius: Kirigami.Units.cornerRadius
|
||||
border.color: active ? Kirigami.Theme.activeTextColor : "transparent"
|
||||
border.width: active ? 3 : 0
|
||||
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
text: dropZone.isTop
|
||||
? KI18n.i18nc("@info:drag&drop append items", "Add to Playlist")
|
||||
: KI18n.i18nc("@info:drag&drop play now", "Play Now")
|
||||
elide: Text.ElideRight
|
||||
color: "white"
|
||||
style: Text.Outline
|
||||
styleColor: "black"
|
||||
opacity: dropZone.active ? 1 : 0.7
|
||||
font.pointSize: Kirigami.Theme.defaultFont.pointSize * (dropZone.isTop ? 1.6 : 2.2)
|
||||
font.bold: true
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user