[multimedia/haruna] src/transcript: Transcript: add subtitle selection

George Florea Bănuș <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 0db9f19f3fd4259fee211b19c26fb914c9bccd6f by George Florea Bănuș, on behalf of M. Sadık Uğursoy.
Committed on 13/08/2026 at 21:02.
Pushed by georgefb into branch 'master'.

Transcript: add subtitle selection

M  +85   -1    src/transcript/Transcript.qml

https://invent.kde.org/multimedia/haruna/-/commit/0db9f19f3fd4259fee211b19c26fb914c9bccd6f

diff --git a/src/transcript/Transcript.qml b/src/transcript/Transcript.qml
index 380f8015..79e5c158 100644
--- a/src/transcript/Transcript.qml
+++ b/src/transcript/Transcript.qml
@@ -21,6 +21,7 @@ ResizeablePage {
     id: root
 
     property TranscriptModel transcriptModel: TranscriptModel {}
+    property int selectedTrackId: -1
 
     edge: PlaylistSettings.position === "right" ? Qt.LeftEdge : Qt.RightEdge
     customWidth: 380
@@ -30,6 +31,31 @@ ResizeablePage {
         return Math.min(Math.max(pWidth, 260), mainWindowWidth - 50)
     }
 
+    function loadCurrentSubtitle() {
+        // Load displayed subtitle until user explicitly selects a subtitle to load.
+        let selectedTrackId = root.selectedTrackId
+        if (selectedTrackId === -1) {
+            selectedTrackId = root.m_mpv.subtitleId
+        }
+
+        const subtitleTracksModel = root.m_mpv.subtitleTracksModel
+        const trackRow = subtitleTracksModel.findTrackRow(selectedTrackId)
+        const modelIndex = subtitleTracksModel.index(trackRow, 0)
+
+        if (!modelIndex) {
+            return
+        }
+        const externalPath = subtitleTracksModel.data(modelIndex, TracksModel.Roles.ExternalPathRole)
+        const streamIndex = subtitleTracksModel.data(modelIndex, TracksModel.Roles.StreamIndexRole)
+
+        if (externalPath && externalPath.toString() !== "") {
+            root.transcriptModel.loadSubtitle(externalPath, streamIndex)
+        } else {
+            root.transcriptModel.loadSubtitle(root.m_mpv.currentUrl, streamIndex)
+        }
+        subtitleMenu.loadedTrackId = selectedTrackId
+    }
+
     onResize: function (delta) {
         // invert the drag delta when the playlist is anchored to the right
         // dragging left (pX is negative) expands a right-aligned playlist, but shrinks a left-aligned one
@@ -37,6 +63,16 @@ ResizeablePage {
         root.customWidth = root.limitWidth(root.customWidth + widthDelta)
     }
 
+    onStateChanged: {
+        if (root.state === "visible") {
+            root.loadCurrentSubtitle()
+        }
+        if (root.state === "hidden") {
+            root.transcriptModel.clearSubtitle()
+            subtitleMenu.loadedTrackId = 0
+        }
+    }
+
     header: ToolBar {
         id: toolbar
 
@@ -50,11 +86,59 @@ ResizeablePage {
                 icon.width: root.buttonSize
                 icon.height: root.buttonSize
                 focusPolicy: Qt.NoFocus
-                enabled: false
+                enabled: root.m_mpv.subtitleTracksModel.rowCount > 1
                 opacity: enabled ? 1.0 : 0.6
                 display: AbstractButton.IconOnly
 
                 ToolTip.text: KI18n.i18nc("@info:tooltip", "Select subtitle")
+
+                onReleased: {
+                    subtitleMenu.visible = !subtitleMenu.visible
+                }
+
+                Menu {
+                    id: subtitleMenu
+
+                    // Tracks current loaded and displayed trackId
+                    property int loadedTrackId: 0
+
+                    y: parent.height
+
+                    Instantiator {
+                        model: root.m_mpv.subtitleTracksModel
+
+                        delegate: MenuItem {
+                            id: delegate
+
+                            required property int trackId
+                            required property string displayText
+                            required property int streamIndex
+                            required property url externalPath
+
+                            autoExclusive: true
+                            checkable: true
+                            checked: delegate.trackId === subtitleMenu.loadedTrackId
+                            text: delegate.displayText
+
+                            onTriggered: {
+                                root.selectedTrackId = delegate.trackId
+                                if (delegate.externalPath && delegate.externalPath.toString() !== "") {
+                                    root.transcriptModel.loadSubtitle(delegate.externalPath, delegate.streamIndex)
+                                } else {
+                                    root.transcriptModel.loadSubtitle(root.m_mpv.currentUrl, delegate.streamIndex)
+                                }
+                            }
+                        }
+
+                        onObjectAdded: function (index, object) {
+                            subtitleMenu.insertItem(index, object)
+                        }
+
+                        onObjectRemoved: function (index, object) {
+                            subtitleMenu.removeItem(object)
+                        }
+                    }
+                }
             }
 
             Kirigami.SearchField {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.