From 0d37ee9f829e7aa2a3f722447e7557c04f692893 Mon Sep 17 00:00:00 2001 From: Bart De Vries Date: Fri, 29 Oct 2021 14:45:01 +0000 Subject: [PATCH] Make Chapter Marks accessible on desktop --- src/CMakeLists.txt | 1 + src/qml/ChapterListDelegate.qml | 17 +- src/qml/HeaderBar.qml | 271 +++++++++++++++++++++++--------- src/qml/QueuePage.qml | 1 + 4 files changed, 208 insertions(+), 82 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 90053bd4..1e1b83d9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -172,6 +172,7 @@ if(ANDROID) media-skip-forward media-playback-start media-playback-pause + view-media-playlist source-playlist arrow-down overflow-menu diff --git a/src/qml/ChapterListDelegate.qml b/src/qml/ChapterListDelegate.qml index 6ab87221..3f644453 100644 --- a/src/qml/ChapterListDelegate.qml +++ b/src/qml/ChapterListDelegate.qml @@ -14,19 +14,25 @@ import org.kde.kirigami 2.14 as Kirigami import org.kde.kasts 1.0 Kirigami.SwipeListItem { + id: root alwaysVisibleActions: true property var entry: undefined + property var overlay: undefined - ColumnLayout { + contentItem: ColumnLayout { Controls.Label { + Layout.fillWidth: true text: title + elide: Text.ElideRight } Controls.Label { + Layout.fillWidth: true opacity: 0.7 font: Kirigami.Theme.smallFont text: formattedStart - } + elide: Text.ElideRight + } } actions: [ @@ -42,11 +48,10 @@ Kirigami.SwipeListItem { AudioManager.play(); } AudioManager.position = start * 1000; + if (overlay != undefined) { + overlay.close(); + } } } ] - - //onClicked: { - // AudioManager.position = start * 1000; - //} } diff --git a/src/qml/HeaderBar.qml b/src/qml/HeaderBar.qml index c16f36f3..06ee8201 100644 --- a/src/qml/HeaderBar.qml +++ b/src/qml/HeaderBar.qml @@ -9,6 +9,7 @@ import QtQuick.Controls 2.14 as Controls import QtQuick.Layouts 1.14 import QtMultimedia 5.15 import QtGraphicalEffects 1.15 +import QtQml.Models 2.15 import org.kde.kirigami 2.14 as Kirigami @@ -24,6 +25,24 @@ Rectangle { Kirigami.Theme.colorSet: Kirigami.Theme.Header color: Kirigami.Theme.backgroundColor + function openEntry() { + if (AudioManager.entry) { + pushPage("QueuePage"); + pageStack.push("qrc:/EntryPage.qml", {"entry": AudioManager.entry}); + SettingsManager.lastOpenedPage = "QueuePage"; + pageStack.get(0).lastEntry = AudioManager.entry.id; + var model = pageStack.get(0).queueList.model; + for (var i = 0; i < model.rowCount(); i++) { + var index = model.index(i, 0); + if (AudioManager.entry == model.data(index, EpisodeModel.EntryRole)) { + pageStack.get(0).queueList.currentIndex = i; + pageStack.get(0).queueList.selectionModel.setCurrentIndex(index, ItemSelectionModel.ClearAndSelect | ItemSelectionModel.Rows); + + } + } + } + } + RowLayout { id: headerRowLayout anchors.fill: parent @@ -35,112 +54,157 @@ Rectangle { width: height absoluteRadius: 5 Layout.leftMargin: Kirigami.Units.largeSpacing + MouseArea { + anchors.fill: mainImage + onClicked: { + headerBar.openEntry(); + } + } } ColumnLayout { id: controlsLayout Layout.fillWidth: true - RowLayout { - Layout.rightMargin: Kirigami.Units.largeSpacing + Item { + id: titlesAndButtons + Layout.fillWidth: true + height: Math.max(titleLabels.implicitHeight, controlButtons.implicitHeight) + clip: true ColumnLayout { + id: titleLabels + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: controlButtons.left Kirigami.Heading { text: AudioManager.entry ? AudioManager.entry.title : i18n("No Track Title") Layout.fillWidth: true elide: Text.ElideRight horizontalAlignment: Text.AlignLeft level: 3 - // wrapMode: Text.Wrap - // maximumLineCount: 2 font.bold: true } Controls.Label { text: AudioManager.entry ? AudioManager.entry.feed.name : i18n("No Track Loaded") Layout.fillWidth: true elide: Text.ElideRight - //wrapMode: Text.Wrap - //maximumLineCount: 1 horizontalAlignment: Text.AlignLeft opacity: 0.6 Layout.bottomMargin: Kirigami.Units.largeSpacing } } - Item { - Layout.fillWidth: true + MouseArea { + anchors.fill: titleLabels + onClicked: { + openEntry(); + } } RowLayout { - property int iconSize: Kirigami.Units.gridUnit - property int buttonSize: playButton.implicitWidth + id: controlButtons + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.rightMargin: Kirigami.Units.largeSpacing + clip: true + + property int optionalButtonCollapseWidth: Kirigami.Units.gridUnit * 12 + Controls.ToolButton { - contentItem: Controls.Label { - text: AudioManager.playbackRate + "x" - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter + id: chapterButton + visible: AudioManager.entry && chapterList.count !== 0 && (titlesAndButtons.width > essentialButtons.width + infoButton.implicitWidth + implicitWidth + parent.optionalButtonCollapseWidth) + text: i18n("Chapters") + icon.name: "view-media-playlist" + icon.height: essentialButtons.iconSize + icon.width: essentialButtons.iconSize + Layout.preferredHeight: essentialButtons.buttonSize + Layout.alignment: Qt.AlignHCenter + onClicked: chapterOverlay.open(); + } + Controls.ToolButton { + id: infoButton + visible: AudioManager.entry && (titlesAndButtons.width > essentialButtons.width + implicitWidth + parent.optionalButtonCollapseWidth) + icon.name: "help-about-symbolic" + icon.height: essentialButtons.iconSize + icon.width: essentialButtons.iconSize + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: essentialButtons.buttonSize + onClicked: entryDetailsOverlay.open(); + } + RowLayout { + id: essentialButtons + property int iconSize: Kirigami.Units.gridUnit + property int buttonSize: playButton.implicitWidth + Layout.margins: 0 + clip: true + + Controls.ToolButton { + contentItem: Controls.Label { + text: AudioManager.playbackRate + "x" + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + onClicked: playbackRateDialog.open() + Layout.alignment: Qt.AlignHCenter + padding: 0 + implicitWidth: playButton.width * 1.5 + implicitHeight: playButton.height + + Controls.ToolTip.visible: hovered + Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval + Controls.ToolTip.text: i18n("Playback Rate: ") + AudioManager.playbackRate + "x" } - onClicked: playbackRateDialog.open() - Layout.alignment: Qt.AlignHCenter - padding: 0 - implicitWidth: playButton.width * 2 - implicitHeight: playButton.height + Controls.ToolButton { + icon.name: "media-seek-backward" + icon.height: parent.iconSize + icon.width: parent.iconSize + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: parent.buttonSize + onClicked: AudioManager.skipBackward() + enabled: AudioManager.canSkipBackward - Controls.ToolTip.visible: hovered - Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval - Controls.ToolTip.text: i18n("Playback Rate: ") + AudioManager.playbackRate + "x" + Controls.ToolTip.visible: hovered + Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval + Controls.ToolTip.text: i18n("Seek Backward") + } + Controls.ToolButton { + id: playButton + icon.name: AudioManager.playbackState === Audio.PlayingState ? "media-playback-pause" : "media-playback-start" + icon.height: parent.iconSize + icon.width: parent.iconSize + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: parent.buttonSize + onClicked: AudioManager.playbackState === Audio.PlayingState ? AudioManager.pause() : AudioManager.play() + enabled: AudioManager.canPlay - } - Controls.ToolButton { - icon.name: "media-seek-backward" - icon.height: parent.iconSize - icon.width: parent.iconSize - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: parent.buttonSize - onClicked: AudioManager.skipBackward() - enabled: AudioManager.canSkipBackward + Controls.ToolTip.visible: hovered + Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval + Controls.ToolTip.text: AudioManager.playbackState === Audio.PlayingState ? i18n("Pause") : i18n("Play") + } + Controls.ToolButton { + icon.name: "media-seek-forward" + icon.height: parent.iconSize + icon.width: parent.iconSize + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: parent.buttonSize + onClicked: AudioManager.skipForward() + enabled: AudioManager.canSkipForward - Controls.ToolTip.visible: hovered - Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval - Controls.ToolTip.text: i18n("Seek Backward") - - } - Controls.ToolButton { - id: playButton - icon.name: AudioManager.playbackState === Audio.PlayingState ? "media-playback-pause" : "media-playback-start" - icon.height: parent.iconSize - icon.width: parent.iconSize - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: parent.buttonSize - onClicked: AudioManager.playbackState === Audio.PlayingState ? AudioManager.pause() : AudioManager.play() - enabled: AudioManager.canPlay - - Controls.ToolTip.visible: hovered - Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval - Controls.ToolTip.text: AudioManager.playbackState === Audio.PlayingState ? i18n("Pause") : i18n("Play") - - } - Controls.ToolButton { - icon.name: "media-seek-forward" - icon.height: parent.iconSize - icon.width: parent.iconSize - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: parent.buttonSize - onClicked: AudioManager.skipForward() - enabled: AudioManager.canSkipForward - - Controls.ToolTip.visible: hovered - Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval - Controls.ToolTip.text: i18n("Seek Forward") - } - Controls.ToolButton { - icon.name: "media-skip-forward" - icon.height: parent.iconSize - icon.width: parent.iconSize - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: parent.buttonSize - onClicked: AudioManager.next() - enabled: AudioManager.canGoNext - - Controls.ToolTip.visible: hovered - Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval - Controls.ToolTip.text: i18n("Skip Forward") + Controls.ToolTip.visible: hovered + Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval + Controls.ToolTip.text: i18n("Seek Forward") + } + Controls.ToolButton { + icon.name: "media-skip-forward" + icon.height: parent.iconSize + icon.width: parent.iconSize + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: parent.buttonSize + onClicked: AudioManager.next() + enabled: AudioManager.canGoNext + Controls.ToolTip.visible: hovered + Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval + Controls.ToolTip.text: i18n("Skip Forward") + } } } } @@ -182,4 +246,59 @@ Rectangle { } } } + + Kirigami.OverlaySheet { + id: chapterOverlay + + showCloseButton: true + + header: Kirigami.Heading { + text: i18n("Chapters") + level: 2 + wrapMode: Text.Wrap + } + + ListView { + Layout.preferredWidth: Kirigami.Units.gridUnit * 25 + id: chapterList + width: parent.width + height: contentItem.childrenRect.height + model: ChapterModel { + enclosureId: AudioManager.entry ? AudioManager.entry.id : "" + enclosurePath: AudioManager.entry ? AudioManager.entry.enclosure.path : "" + } + clip: true + visible: chapterList.count !== 0 + anchors.fill: parent + delegate: ChapterListDelegate { + id: chapterDelegate + width: chapterList.width + entry: AudioManager.entry + overlay: chapterOverlay + } + } + } + + Kirigami.OverlaySheet { + id: entryDetailsOverlay + + showCloseButton: true + + header: Kirigami.Heading { + text: AudioManager.entry ? AudioManager.entry.title : i18n("No Track Title") + level: 2 + elide: Text.ElideRight + } + + contentItem: Controls.Label { + id: text + Layout.preferredWidth: Kirigami.Units.gridUnit * 25 + text: AudioManager.entry ? AudioManager.entry.content : i18n("No Track Loaded") + verticalAlignment: Text.AlignTop + baseUrl: AudioManager.entry ? AudioManager.entry.baseUrl : "" + textFormat: Text.RichText + wrapMode: Text.WordWrap + onLinkActivated: Qt.openUrlExternally(link) + } + } } diff --git a/src/qml/QueuePage.qml b/src/qml/QueuePage.qml index 65996773..ccca5ed7 100644 --- a/src/qml/QueuePage.qml +++ b/src/qml/QueuePage.qml @@ -19,6 +19,7 @@ Kirigami.ScrollablePage { property var lastEntry: "" property string pageName: "queuepage" + property alias queueList: queueList supportsRefreshing: true onRefreshingChanged: {