diff --git a/qml/app/MpvqcContentSplitView.qml b/qml/app/MpvqcContentSplitView.qml index 2ff79158..fc6840f8 100644 --- a/qml/app/MpvqcContentSplitView.qml +++ b/qml/app/MpvqcContentSplitView.qml @@ -20,7 +20,7 @@ along with this program. If not, see . import QtQuick import QtQuick.Controls -import "../footer" +import "../footer2" import "../player" import "../table" diff --git a/qml/footer2/MpvqcFooter.qml b/qml/footer2/MpvqcFooter.qml new file mode 100644 index 00000000..921d164b --- /dev/null +++ b/qml/footer2/MpvqcFooter.qml @@ -0,0 +1,118 @@ +/* +mpvQC + +Copyright (C) 2024 mpvQC developers + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +import QtQuick + +import "../settings" + +Item { + id: root + + required property var mpvqcApplication + + height: 25 + visible: !root.mpvqcApplication.fullscreen + + QtObject { + id: _impl + + readonly property var mpvqcSettings: root.mpvqcApplication.mpvqcSettings + readonly property var mpvqcCommentTable: root.mpvqcApplication.mpvqcCommentTable + readonly property var mpvqcLabelWidthCalculator: root.mpvqcApplication.mpvqcLabelWidthCalculator + readonly property var mpvqcMpvPlayerPropertiesPyObject: root.mpvqcApplication.mpvqcMpvPlayerPropertiesPyObject + readonly property var mpvqcUtilityPyObject: root.mpvqcApplication.mpvqcUtilityPyObject + + function formatTime(time: int): string { + if (mpvqcMpvPlayerPropertiesPyObject.duration >= 60 * 60) { + return mpvqcUtilityPyObject.formatTimeToStringLong(time); + } else { + return mpvqcUtilityPyObject.formatTimeToStringShort(time); + } + } + + function recalculateVideoTimeLabelWidth(): real { + const items = [_content.videoTimeLabelText]; + _content.videoTimeLabelWidth = mpvqcLabelWidthCalculator.calculateWidthFor(items, root); // qmllint disable + } + } + + MpvqcFooterContent { + id: _content + + anchors.fill: parent + + isApplicationMazimized: root.mpvqcApplication.maximized + + selectedCommentIndex: _impl.mpvqcCommentTable.selectedCommentIndex + totalCommentCount: _impl.mpvqcCommentTable.commentCount + + playerPercentPosition: _impl.mpvqcMpvPlayerPropertiesPyObject.percent_pos + playerDuration: _impl.mpvqcMpvPlayerPropertiesPyObject.duration + playerVideoLoaded: _impl.mpvqcMpvPlayerPropertiesPyObject.video_loaded + playerTimePosition: _impl.mpvqcMpvPlayerPropertiesPyObject.time_pos + playerTimeRemaining: _impl.mpvqcMpvPlayerPropertiesPyObject.time_remaining + + isStatusbarDisplayPercentage: _impl.mpvqcSettings.statusbarPercentage + + isTimeFormatCurrentTotalTime: _impl.mpvqcSettings.timeFormat === MpvqcSettings.TimeFormat.CURRENT_TOTAL_TIME + isTimeFormatCurrentTime: _impl.mpvqcSettings.timeFormat === MpvqcSettings.TimeFormat.CURRENT_TIME + isTimeFormatRemainingTime: _impl.mpvqcSettings.timeFormat === MpvqcSettings.TimeFormat.REMAINING_TIME + isTimeFormatEmpty: _impl.mpvqcSettings.timeFormat === MpvqcSettings.TimeFormat.EMPTY + + formatTimeFunc: _impl.formatTime + + videoTimeLabelWidth: 0 + + onCurrentTotalTimeSelected: { + _impl.mpvqcSettings.timeFormat = MpvqcSettings.TimeFormat.CURRENT_TOTAL_TIME; + } + + onCurrentTimeSelected: { + _impl.mpvqcSettings.timeFormat = MpvqcSettings.TimeFormat.CURRENT_TIME; + } + + onRemainingTimeSelected: { + _impl.mpvqcSettings.timeFormat = MpvqcSettings.TimeFormat.REMAINING_TIME; + } + + onEmptyTimeSelected: { + _impl.mpvqcSettings.timeFormat = MpvqcSettings.TimeFormat.EMPTY; + } + + onStatusBarPercentageToggled: { + _impl.mpvqcSettings.statusbarPercentage = !_impl.mpvqcSettings.statusbarPercentage; + } + } + + Connections { + target: _impl.mpvqcSettings + + function onTimeFormatChanged() { + _impl.recalculateVideoTimeLabelWidth(); + } + } + + Connections { + target: _impl.mpvqcMpvPlayerPropertiesPyObject + + function onDurationChanged() { + _impl.recalculateVideoTimeLabelWidth(); + } + } +} diff --git a/qml/footer2/MpvqcFooterContent.qml b/qml/footer2/MpvqcFooterContent.qml new file mode 100644 index 00000000..99649edb --- /dev/null +++ b/qml/footer2/MpvqcFooterContent.qml @@ -0,0 +1,238 @@ +/* +mpvQC + +Copyright (C) 2024 mpvQC developers + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +pragma ComponentBehavior: Bound + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import "../shared" + +Item { + id: root + + required property bool isApplicationMazimized + + required property int selectedCommentIndex + required property int totalCommentCount + + required property real playerPercentPosition + required property int playerDuration + required property bool playerVideoLoaded + required property int playerTimePosition + required property int playerTimeRemaining + + required property bool isStatusbarDisplayPercentage + + required property bool isTimeFormatCurrentTotalTime + required property bool isTimeFormatCurrentTime + required property bool isTimeFormatRemainingTime + required property bool isTimeFormatEmpty + + required property var formatTimeFunc + + required property int videoTimeLabelWidth + readonly property alias videoTimeLabelText: _impl.videoTimeLabelText + + signal currentTotalTimeSelected + signal currentTimeSelected + signal remainingTimeSelected + signal emptyTimeSelected + signal statusBarPercentageToggled + + QtObject { + id: _impl + + readonly property int bottomMargin: root.isApplicationMazimized ? 2 : 0 + + readonly property string videoTimeLabelText: { + if (root.isTimeFormatCurrentTotalTime) { + const current = root.formatTimeFunc(root.playerTimePosition); // qmllint disable + const total = root.formatTimeFunc(root.playerDuration); // qmllint disable + return `${current}/${total}`; + } + if (root.isTimeFormatCurrentTime) { + return root.formatTimeFunc(root.playerTimePosition); // qmllint disable + } + if (root.isTimeFormatRemainingTime) { + const remaining = root.formatTimeFunc(root.playerTimeRemaining); // qmllint disable + return `-${remaining}`; + } + return ""; + } + } + + MenuSeparator { + id: _separator + + topPadding: 1 + bottomPadding: 1 + + anchors { + top: root.top + left: root.left + right: root.right + } + } + + RowLayout { + spacing: 0 + + anchors { + top: _separator.top + left: root.left + right: root.right + bottom: root.bottom + } + + Label { + id: _rowSelectionLabelText + + text: (root.selectedCommentIndex + 1) + '/' + root.totalCommentCount + visible: root.totalCommentCount + + verticalAlignment: Text.AlignVCenter + + Layout.bottomMargin: _impl.bottomMargin + Layout.leftMargin: 3 + } + + Item { + Layout.fillWidth: true + } + + Label { + id: _videoPercentLabel + + text: `${root.playerPercentPosition.toFixed(0)}%` + visible: root.playerVideoLoaded && root.isStatusbarDisplayPercentage + + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + + Layout.bottomMargin: _impl.bottomMargin + } + + Label { + id: _videoTimeLabel + + text: _impl.videoTimeLabelText + visible: root.playerVideoLoaded && !root.isTimeFormatEmpty + + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + + Layout.preferredWidth: root.videoTimeLabelWidth + Layout.bottomMargin: _impl.bottomMargin + Layout.leftMargin: 15 + } + + ToolButton { + id: _toolButton + + icon.source: "qrc:/data/icons/expand_more_black_24dp.svg" + focusPolicy: Qt.NoFocus + padding: 2 + + Layout.maximumWidth: 22 + Layout.maximumHeight: 22 + Layout.bottomMargin: _impl.bottomMargin + Layout.leftMargin: padding + + onPressed: { + _contextMenuLoader.openContextMenu(); + } + } + } + + Loader { + id: _contextMenuLoader + + function openContextMenu(): void { + if (active) { + item.open(); // qmllint disable + } else { + active = true; + } + } + + active: false + asynchronous: true + visible: active + + onLoaded: item.open() // qmllint disable + + sourceComponent: MpvqcMenu { + x: mMirrored ? _toolButton.x : _toolButton.x + _toolButton.width - width + y: -height + + transformOrigin: mMirrored ? Popup.BottomLeft : Popup.BottomRight + + modal: true + dim: false + + MenuItem { + text: qsTranslate("MainWindow", "Default format") + checked: root.isTimeFormatCurrentTotalTime + autoExclusive: true + checkable: true + + onTriggered: root.currentTotalTimeSelected() + } + + MenuItem { + text: qsTranslate("MainWindow", "Current time") + checked: root.isTimeFormatCurrentTime + autoExclusive: true + checkable: true + + onTriggered: root.currentTimeSelected() + } + + MenuItem { + text: qsTranslate("MainWindow", "Remaining time") + checked: root.isTimeFormatRemainingTime + autoExclusive: true + checkable: true + + onTriggered: root.remainingTimeSelected() + } + + MenuItem { + text: qsTranslate("MainWindow", "Hide time") + checked: root.isTimeFormatEmpty + autoExclusive: true + checkable: true + + onTriggered: root.emptyTimeSelected() + } + + MenuSeparator {} + + Action { + text: qsTranslate("MainWindow", "Progress in percent") + checked: root.isStatusbarDisplayPercentage + checkable: true + + onTriggered: root.statusBarPercentageToggled() + } + } + } +} diff --git a/qml/footer2/qmldir b/qml/footer2/qmldir new file mode 100644 index 00000000..bbe2d289 --- /dev/null +++ b/qml/footer2/qmldir @@ -0,0 +1,3 @@ +module footer2 + +MpvqcFooter MpvqcFooter.qml