fix(menus): align menus and actions with KDE HIG

This commit is contained in:
tri committed 2026-11-07 20:08:28 +07:00
1 parent 309801d059
commit 0cd03335f7
18 files changed
+170 -47

No files matched your search

+18
View File
@@ -45,6 +45,8 @@ MpvItem::MpvItem(QQuickItem *parent)
observeProperty(QStringLiteral("volume"), MPV_FORMAT_INT64); observeProperty(QStringLiteral("volume"), MPV_FORMAT_INT64);
observeProperty(QStringLiteral("volume-max"), MPV_FORMAT_INT64); observeProperty(QStringLiteral("volume-max"), MPV_FORMAT_INT64);
observeProperty(QStringLiteral("mute"), MPV_FORMAT_FLAG); observeProperty(QStringLiteral("mute"), MPV_FORMAT_FLAG);
observeProperty(QStringLiteral("sub-visibility"), MPV_FORMAT_FLAG);
observeProperty(QStringLiteral("deinterlace"), MPV_FORMAT_FLAG);
observeProperty(QStringLiteral("speed"), MPV_FORMAT_DOUBLE); observeProperty(QStringLiteral("speed"), MPV_FORMAT_DOUBLE);
observeProperty(QStringLiteral("chapter-list"), MPV_FORMAT_NODE); observeProperty(QStringLiteral("chapter-list"), MPV_FORMAT_NODE);
observeProperty(QStringLiteral("chapter"), MPV_FORMAT_INT64); observeProperty(QStringLiteral("chapter"), MPV_FORMAT_INT64);
@@ -258,6 +260,16 @@ bool MpvItem::mute() const
return m_mute; return m_mute;
} }
bool MpvItem::subtitleVisible() const
{
return m_subtitleVisible;
}
bool MpvItem::deinterlace() const
{
return m_deinterlace;
}
void MpvItem::setMute(bool mute) void MpvItem::setMute(bool mute)
{ {
setPropertyAsync(QStringLiteral("mute"), mute); setPropertyAsync(QStringLiteral("mute"), mute);
@@ -414,6 +426,12 @@ void MpvItem::onPropertyChanged(const QString &property, const QVariant &value)
} else if (property == u"mute") { } else if (property == u"mute") {
m_mute = value.toBool(); m_mute = value.toBool();
Q_EMIT muteChanged(); Q_EMIT muteChanged();
} else if (property == u"sub-visibility") {
m_subtitleVisible = value.toBool();
Q_EMIT subtitleVisibleChanged();
} else if (property == u"deinterlace") {
m_deinterlace = value.toBool();
Q_EMIT deinterlaceChanged();
} else if (property == u"speed") { } else if (property == u"speed") {
m_speed = value.toDouble(); m_speed = value.toDouble();
Q_EMIT speedChanged(); Q_EMIT speedChanged();
+8
View File
@@ -36,6 +36,8 @@ class MpvItem : public MpvAbstractItem
Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged) Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged)
Q_PROPERTY(int volumeMax READ volumeMax NOTIFY volumeMaxChanged) Q_PROPERTY(int volumeMax READ volumeMax NOTIFY volumeMaxChanged)
Q_PROPERTY(bool mute READ mute WRITE setMute NOTIFY muteChanged) Q_PROPERTY(bool mute READ mute WRITE setMute NOTIFY muteChanged)
Q_PROPERTY(bool subtitleVisible READ subtitleVisible NOTIFY subtitleVisibleChanged)
Q_PROPERTY(bool deinterlace READ deinterlace NOTIFY deinterlaceChanged)
Q_PROPERTY(double speed READ speed WRITE setSpeed NOTIFY speedChanged) Q_PROPERTY(double speed READ speed WRITE setSpeed NOTIFY speedChanged)
// Chapters of the current file, each a map with title and time (in seconds). // Chapters of the current file, each a map with title and time (in seconds).
Q_PROPERTY(QVariantList chapters READ chapters NOTIFY chaptersChanged) Q_PROPERTY(QVariantList chapters READ chapters NOTIFY chaptersChanged)
@@ -76,6 +78,8 @@ public:
int volumeMax() const; int volumeMax() const;
bool mute() const; bool mute() const;
void setMute(bool mute); void setMute(bool mute);
bool subtitleVisible() const;
bool deinterlace() const;
double speed() const; double speed() const;
void setSpeed(double speed); void setSpeed(double speed);
QVariantList chapters() const; QVariantList chapters() const;
@@ -116,6 +120,8 @@ Q_SIGNALS:
void volumeChanged(); void volumeChanged();
void volumeMaxChanged(); void volumeMaxChanged();
void muteChanged(); void muteChanged();
void subtitleVisibleChanged();
void deinterlaceChanged();
void speedChanged(); void speedChanged();
void chaptersChanged(); void chaptersChanged();
void chapterChanged(); void chapterChanged();
@@ -149,6 +155,8 @@ private:
int m_volume = 100; int m_volume = 100;
int m_volumeMax = 130; int m_volumeMax = 130;
bool m_mute = false; bool m_mute = false;
bool m_subtitleVisible = true;
bool m_deinterlace = false;
double m_speed = 1.0; double m_speed = 1.0;
QVariantList m_chapters; QVariantList m_chapters;
int m_chapter = -1; int m_chapter = -1;
+42 -7
View File
@@ -22,6 +22,9 @@ Item {
readonly property bool hasFile: mpv.fileLoaded readonly property bool hasFile: mpv.fileLoaded
readonly property bool subtitlesVisible: mpv.subtitleVisible
readonly property bool deinterlacingEnabled: mpv.deinterlace
signal openFileRequested() signal openFileRequested()
// Open a known file, such as one from Recent Files. // Open a known file, such as one from Recent Files.
signal fileOpenRequested(url: url) signal fileOpenRequested(url: url)
@@ -115,7 +118,7 @@ Item {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Restart Playback") text: KI18n.i18nc("@action", "Restart Playback")
icon.name: "edit-reset" icon.name: "edit-reset"
shortcut: "F5" shortcut: "Ctrl+Shift+R"
onTriggered: root.mpv.seek(0) onTriggered: root.mpv.seek(0)
} }
@@ -138,6 +141,7 @@ Item {
property Action seekForwardSmall: Action { property Action seekForwardSmall: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Seek Small Step Forward") text: KI18n.i18nc("@action", "Seek Small Step Forward")
icon.name: "go-next"
shortcut: "Right" shortcut: "Right"
onTriggered: root.seekBy(QtPotatoSettings.seekSmallStep) onTriggered: root.seekBy(QtPotatoSettings.seekSmallStep)
} }
@@ -145,6 +149,7 @@ Item {
property Action seekBackwardSmall: Action { property Action seekBackwardSmall: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Seek Small Step Backward") text: KI18n.i18nc("@action", "Seek Small Step Backward")
icon.name: "go-previous"
shortcut: "Left" shortcut: "Left"
onTriggered: root.seekBy(-QtPotatoSettings.seekSmallStep) onTriggered: root.seekBy(-QtPotatoSettings.seekSmallStep)
} }
@@ -152,6 +157,7 @@ Item {
property Action seekForwardMedium: Action { property Action seekForwardMedium: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Seek Medium Step Forward") text: KI18n.i18nc("@action", "Seek Medium Step Forward")
icon.name: "media-seek-forward"
shortcut: "Shift+Right" shortcut: "Shift+Right"
onTriggered: root.seekBy(QtPotatoSettings.seekMediumStep) onTriggered: root.seekBy(QtPotatoSettings.seekMediumStep)
} }
@@ -159,6 +165,7 @@ Item {
property Action seekBackwardMedium: Action { property Action seekBackwardMedium: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Seek Medium Step Backward") text: KI18n.i18nc("@action", "Seek Medium Step Backward")
icon.name: "media-seek-backward"
shortcut: "Shift+Left" shortcut: "Shift+Left"
onTriggered: root.seekBy(-QtPotatoSettings.seekMediumStep) onTriggered: root.seekBy(-QtPotatoSettings.seekMediumStep)
} }
@@ -166,6 +173,7 @@ Item {
property Action seekForwardBig: Action { property Action seekForwardBig: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Seek Big Step Forward") text: KI18n.i18nc("@action", "Seek Big Step Forward")
icon.name: "arrow-right-double"
shortcut: "Up" shortcut: "Up"
onTriggered: root.seekBy(QtPotatoSettings.seekBigStep) onTriggered: root.seekBy(QtPotatoSettings.seekBigStep)
} }
@@ -173,6 +181,7 @@ Item {
property Action seekBackwardBig: Action { property Action seekBackwardBig: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Seek Big Step Backward") text: KI18n.i18nc("@action", "Seek Big Step Backward")
icon.name: "arrow-left-double"
shortcut: "Down" shortcut: "Down"
onTriggered: root.seekBy(-QtPotatoSettings.seekBigStep) onTriggered: root.seekBy(-QtPotatoSettings.seekBigStep)
} }
@@ -180,6 +189,7 @@ Item {
property Action seekNextSubtitle: Action { property Action seekNextSubtitle: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Seek To Next Subtitle") text: KI18n.i18nc("@action", "Seek To Next Subtitle")
icon.name: "go-down"
shortcut: "Ctrl+Right" shortcut: "Ctrl+Right"
onTriggered: root.mpv.commandAsync(["sub-seek", "1"]) onTriggered: root.mpv.commandAsync(["sub-seek", "1"])
} }
@@ -187,6 +197,7 @@ Item {
property Action seekPreviousSubtitle: Action { property Action seekPreviousSubtitle: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Seek To Previous Subtitle") text: KI18n.i18nc("@action", "Seek To Previous Subtitle")
icon.name: "go-up"
shortcut: "Ctrl+Left" shortcut: "Ctrl+Left"
onTriggered: root.mpv.commandAsync(["sub-seek", "-1"]) onTriggered: root.mpv.commandAsync(["sub-seek", "-1"])
} }
@@ -194,6 +205,7 @@ Item {
property Action seekNextChapter: Action { property Action seekNextChapter: Action {
enabled: root.shortcutsEnabled && root.mpv.chapters.length > 0 enabled: root.shortcutsEnabled && root.mpv.chapters.length > 0
text: KI18n.i18nc("@action", "Seek To Next Chapter") text: KI18n.i18nc("@action", "Seek To Next Chapter")
icon.name: "go-last"
shortcut: "PgUp" shortcut: "PgUp"
onTriggered: root.mpv.commandAsync(["add", "chapter", "1"]) onTriggered: root.mpv.commandAsync(["add", "chapter", "1"])
} }
@@ -201,6 +213,7 @@ Item {
property Action seekPreviousChapter: Action { property Action seekPreviousChapter: Action {
enabled: root.shortcutsEnabled && root.mpv.chapters.length > 0 enabled: root.shortcutsEnabled && root.mpv.chapters.length > 0
text: KI18n.i18nc("@action", "Seek To Previous Chapter") text: KI18n.i18nc("@action", "Seek To Previous Chapter")
icon.name: "go-first"
shortcut: "PgDown" shortcut: "PgDown"
onTriggered: root.mpv.commandAsync(["add", "chapter", "-1"]) onTriggered: root.mpv.commandAsync(["add", "chapter", "-1"])
} }
@@ -208,6 +221,7 @@ Item {
property Action frameStepForward: Action { property Action frameStepForward: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Step Frame Forward") text: KI18n.i18nc("@action", "Step Frame Forward")
icon.name: "keyframe-next"
shortcut: "." shortcut: "."
onTriggered: root.mpv.frameStep(true) onTriggered: root.mpv.frameStep(true)
} }
@@ -215,6 +229,7 @@ Item {
property Action frameStepBackward: Action { property Action frameStepBackward: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Step Frame Backward") text: KI18n.i18nc("@action", "Step Frame Backward")
icon.name: "keyframe-previous"
shortcut: "," shortcut: ","
onTriggered: root.mpv.frameStep(false) onTriggered: root.mpv.frameStep(false)
} }
@@ -222,6 +237,7 @@ Item {
property Action speedUp: Action { property Action speedUp: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Increase Playback Speed") text: KI18n.i18nc("@action", "Increase Playback Speed")
icon.name: "media-seek-forward"
shortcut: "]" shortcut: "]"
onTriggered: root.changeSpeed(0.1) onTriggered: root.changeSpeed(0.1)
} }
@@ -229,6 +245,7 @@ Item {
property Action speedDown: Action { property Action speedDown: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Decrease Playback Speed") text: KI18n.i18nc("@action", "Decrease Playback Speed")
icon.name: "media-seek-backward"
shortcut: "[" shortcut: "["
onTriggered: root.changeSpeed(-0.1) onTriggered: root.changeSpeed(-0.1)
} }
@@ -236,6 +253,7 @@ Item {
property Action speedReset: Action { property Action speedReset: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Reset Playback Speed") text: KI18n.i18nc("@action", "Reset Playback Speed")
icon.name: "speedometer"
shortcut: "Backspace" shortcut: "Backspace"
onTriggered: root.changeSpeed(0) onTriggered: root.changeSpeed(0)
} }
@@ -270,6 +288,7 @@ Item {
property Action audioCycleUp: Action { property Action audioCycleUp: Action {
enabled: root.shortcutsEnabled && root.mpv.audioTracks.length > 1 enabled: root.shortcutsEnabled && root.mpv.audioTracks.length > 1
text: KI18n.i18nc("@action", "Cycle Up Audio Track") text: KI18n.i18nc("@action", "Cycle Up Audio Track")
icon.name: "go-up"
shortcut: "Shift+3" shortcut: "Shift+3"
onTriggered: root.mpv.audioId = root.cycleTrack(root.mpv.audioTracks, root.mpv.audioId, 1) onTriggered: root.mpv.audioId = root.cycleTrack(root.mpv.audioTracks, root.mpv.audioId, 1)
} }
@@ -277,6 +296,7 @@ Item {
property Action audioCycleDown: Action { property Action audioCycleDown: Action {
enabled: root.shortcutsEnabled && root.mpv.audioTracks.length > 1 enabled: root.shortcutsEnabled && root.mpv.audioTracks.length > 1
text: KI18n.i18nc("@action", "Cycle Down Audio Track") text: KI18n.i18nc("@action", "Cycle Down Audio Track")
icon.name: "go-down"
shortcut: "Shift+2" shortcut: "Shift+2"
onTriggered: root.mpv.audioId = root.cycleTrack(root.mpv.audioTracks, root.mpv.audioId, -1) onTriggered: root.mpv.audioId = root.cycleTrack(root.mpv.audioTracks, root.mpv.audioId, -1)
} }
@@ -291,12 +311,16 @@ Item {
property Action subtitleToggle: Action { property Action subtitleToggle: Action {
enabled: root.shortcutsEnabled && root.mpv.subtitleTracks.length > 0 enabled: root.shortcutsEnabled && root.mpv.subtitleTracks.length > 0
text: KI18n.i18nc("@action", "Toggle Subtitles") text: KI18n.i18nc("@action", "Show Subtitles")
icon.name: "media-view-subtitles-symbolic"
checkable: true
checked: root.subtitlesVisible
shortcut: "Ctrl+S" shortcut: "Ctrl+S"
onTriggered: { onTriggered: {
const visible = root.mpv.getProperty("sub-visibility") const visible = root.mpv.getProperty("sub-visibility")
root.mpv.setPropertyAsync("sub-visibility", !visible) root.mpv.setPropertyAsync("sub-visibility", !visible)
root.mpv.setPropertyAsync("secondary-sub-visibility", !visible) root.mpv.setPropertyAsync("secondary-sub-visibility", !visible)
checked = Qt.binding(() => root.subtitlesVisible)
root.osd.message(visible ? KI18n.i18nc("@info:osd", "Subtitles hidden") : KI18n.i18nc("@info:osd", "Subtitles shown")) root.osd.message(visible ? KI18n.i18nc("@info:osd", "Subtitles hidden") : KI18n.i18nc("@info:osd", "Subtitles shown"))
} }
} }
@@ -304,6 +328,7 @@ Item {
property Action subtitleCycleUp: Action { property Action subtitleCycleUp: Action {
enabled: root.shortcutsEnabled && root.mpv.subtitleTracks.length > 0 enabled: root.shortcutsEnabled && root.mpv.subtitleTracks.length > 0
text: KI18n.i18nc("@action", "Cycle Up Subtitle") text: KI18n.i18nc("@action", "Cycle Up Subtitle")
icon.name: "go-up"
shortcut: "J" shortcut: "J"
onTriggered: root.mpv.subtitleId = root.cycleTrack(root.mpv.subtitleTracks, root.mpv.subtitleId, 1) onTriggered: root.mpv.subtitleId = root.cycleTrack(root.mpv.subtitleTracks, root.mpv.subtitleId, 1)
} }
@@ -311,6 +336,7 @@ Item {
property Action subtitleCycleDown: Action { property Action subtitleCycleDown: Action {
enabled: root.shortcutsEnabled && root.mpv.subtitleTracks.length > 0 enabled: root.shortcutsEnabled && root.mpv.subtitleTracks.length > 0
text: KI18n.i18nc("@action", "Cycle Down Subtitle") text: KI18n.i18nc("@action", "Cycle Down Subtitle")
icon.name: "go-down"
shortcut: "Shift+J" shortcut: "Shift+J"
onTriggered: root.mpv.subtitleId = root.cycleTrack(root.mpv.subtitleTracks, root.mpv.subtitleId, -1) onTriggered: root.mpv.subtitleId = root.cycleTrack(root.mpv.subtitleTracks, root.mpv.subtitleId, -1)
} }
@@ -318,6 +344,7 @@ Item {
property Action subtitleEarlier: Action { property Action subtitleEarlier: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Show Subtitles Earlier") text: KI18n.i18nc("@action", "Show Subtitles Earlier")
icon.name: "go-previous"
shortcut: "Z" shortcut: "Z"
onTriggered: root.changeSubtitleDelay(-0.1) onTriggered: root.changeSubtitleDelay(-0.1)
} }
@@ -325,6 +352,7 @@ Item {
property Action subtitleLater: Action { property Action subtitleLater: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Show Subtitles Later") text: KI18n.i18nc("@action", "Show Subtitles Later")
icon.name: "go-next"
shortcut: "Shift+Z" shortcut: "Shift+Z"
onTriggered: root.changeSubtitleDelay(0.1) onTriggered: root.changeSubtitleDelay(0.1)
} }
@@ -332,12 +360,14 @@ Item {
property Action subtitleDelayReset: Action { property Action subtitleDelayReset: Action {
enabled: root.shortcutsEnabled && root.hasFile && root.mpv.subtitleDelay !== 0 enabled: root.shortcutsEnabled && root.hasFile && root.mpv.subtitleDelay !== 0
text: KI18n.i18nc("@action", "Reset Subtitle Delay") text: KI18n.i18nc("@action", "Reset Subtitle Delay")
icon.name: "edit-reset"
onTriggered: root.changeSubtitleDelay(-root.mpv.subtitleDelay) onTriggered: root.changeSubtitleDelay(-root.mpv.subtitleDelay)
} }
property Action subtitleBigger: Action { property Action subtitleBigger: Action {
enabled: root.shortcutsEnabled enabled: root.shortcutsEnabled
text: KI18n.i18nc("@action", "Increase Subtitle Font Size") text: KI18n.i18nc("@action", "Increase Subtitle Font Size")
icon.name: "format-font-size-more"
shortcut: "Ctrl+Z" shortcut: "Ctrl+Z"
onTriggered: { onTriggered: {
QtPotatoSettings.subtitleFontSize = Math.min(150, QtPotatoSettings.subtitleFontSize + 2) QtPotatoSettings.subtitleFontSize = Math.min(150, QtPotatoSettings.subtitleFontSize + 2)
@@ -349,6 +379,7 @@ Item {
property Action subtitleSmaller: Action { property Action subtitleSmaller: Action {
enabled: root.shortcutsEnabled enabled: root.shortcutsEnabled
text: KI18n.i18nc("@action", "Decrease Subtitle Font Size") text: KI18n.i18nc("@action", "Decrease Subtitle Font Size")
icon.name: "format-font-size-less"
shortcut: "Ctrl+X" shortcut: "Ctrl+X"
onTriggered: { onTriggered: {
QtPotatoSettings.subtitleFontSize = Math.max(20, QtPotatoSettings.subtitleFontSize - 2) QtPotatoSettings.subtitleFontSize = Math.max(20, QtPotatoSettings.subtitleFontSize - 2)
@@ -392,11 +423,15 @@ Item {
property Action toggleDeinterlacing: Action { property Action toggleDeinterlacing: Action {
enabled: root.shortcutsEnabled && root.hasFile enabled: root.shortcutsEnabled && root.hasFile
text: KI18n.i18nc("@action", "Toggle Deinterlacing") text: KI18n.i18nc("@action", "Deinterlace")
icon.name: "view-filter"
checkable: true
checked: root.deinterlacingEnabled
shortcut: "D" shortcut: "D"
onTriggered: { onTriggered: {
const enabled = root.mpv.getProperty("deinterlace") === "yes" const enabled = root.mpv.getProperty("deinterlace") === true
root.mpv.setPropertyAsync("deinterlace", enabled ? "no" : "yes") root.mpv.setPropertyAsync("deinterlace", !enabled)
checked = Qt.binding(() => root.deinterlacingEnabled)
root.osd.message(enabled ? KI18n.i18nc("@info:osd", "Deinterlacing off") : KI18n.i18nc("@info:osd", "Deinterlacing on")) root.osd.message(enabled ? KI18n.i18nc("@info:osd", "Deinterlacing off") : KI18n.i18nc("@info:osd", "Deinterlacing on"))
} }
} }
@@ -476,6 +511,7 @@ Item {
property Action toggleHeader: Action { property Action toggleHeader: Action {
enabled: root.shortcutsEnabled enabled: root.shortcutsEnabled
text: QtPotatoSettings.showHeader ? KI18n.i18nc("@action", "Hide Toolbar") : KI18n.i18nc("@action", "Show Toolbar") text: QtPotatoSettings.showHeader ? KI18n.i18nc("@action", "Hide Toolbar") : KI18n.i18nc("@action", "Show Toolbar")
icon.name: "configure-toolbars"
shortcut: "Ctrl+H" shortcut: "Ctrl+H"
onTriggered: root.headerToggleRequested() onTriggered: root.headerToggleRequested()
} }
@@ -489,7 +525,7 @@ Item {
} }
property Action configure: Action { property Action configure: Action {
text: KI18n.i18nc("@action", "Settings") text: KI18n.i18nc("@action", "Configure QtPotato…")
icon.name: "configure" icon.name: "configure"
shortcut: "Ctrl+Shift+," shortcut: "Ctrl+Shift+,"
onTriggered: root.settingsRequested("general") onTriggered: root.settingsRequested("general")
@@ -498,7 +534,6 @@ Item {
property Action about: Action { property Action about: Action {
text: KI18n.i18nc("@action", "About QtPotato") text: KI18n.i18nc("@action", "About QtPotato")
icon.name: "help-about" icon.name: "help-about"
shortcut: "F1"
onTriggered: root.settingsRequested("about") onTriggered: root.settingsRequested("about")
} }
+23 -1
View File
@@ -1,8 +1,30 @@
// SPDX-FileCopyrightText: 2026 Tri Vo Khac // SPDX-FileCopyrightText: 2026 Tri Vo Khac
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick
import QtQuick.Controls import QtQuick.Controls
import org.kde.kirigami as Kirigami
Menu { Menu {
delegate: AppMenuItem {} id: root
readonly property bool hasCheckables: {
for (let i = 0; i < count; ++i) {
const item = itemAt(i)
if (item && item.checkable) {
return true
}
}
return false
}
// Keep long filenames and translated labels from obscuring parent menus.
readonly property real maximumWidth: Math.min(Kirigami.Units.gridUnit * 30,
(root.parent && root.parent.Window.window ? root.parent.Window.window.width : Kirigami.Units.gridUnit * 30))
width: Math.min(implicitWidth, maximumWidth)
delegate: AppMenuItem {
icon.name: subMenu ? subMenu.icon.name : (action ? action.icon.name : "")
icon.source: subMenu ? subMenu.icon.source : (action ? action.icon.source : "")
}
} }
+6 -2
View File
@@ -9,6 +9,8 @@ import org.kde.kirigami as Kirigami
MenuItem { MenuItem {
id: root id: root
property int textElide: Text.ElideRight
// org.kde.desktop sets these on its MenuItem, but other Plasma styles such // org.kde.desktop sets these on its MenuItem, but other Plasma styles such
// as org.kde.union do not, which would leave the label below empty. // as org.kde.union do not, which would leave the label below empty.
Kirigami.MnemonicData.enabled: enabled && visible Kirigami.MnemonicData.enabled: enabled && visible
@@ -33,7 +35,7 @@ MenuItem {
layoutDirection: root.mirrored ? Qt.RightToLeft : Qt.LeftToRight layoutDirection: root.mirrored ? Qt.RightToLeft : Qt.LeftToRight
Item { Item {
Layout.preferredWidth: (root.ListView.view && root.ListView.view.hasCheckables) || root.checkable Layout.preferredWidth: (root.menu && root.menu.hasCheckables) || root.checkable
? root.indicator.width : Kirigami.Units.smallSpacing ? root.indicator.width : Kirigami.Units.smallSpacing
} }
@@ -62,12 +64,14 @@ MenuItem {
textFormat: Text.StyledText textFormat: Text.StyledText
font: root.font font: root.font
color: root.pressed ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor color: root.pressed ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor
elide: Text.ElideRight elide: root.textElide
horizontalAlignment: root.mirrored ? Text.AlignRight : Text.AlignLeft horizontalAlignment: root.mirrored ? Text.AlignRight : Text.AlignLeft
} }
Label { Label {
id: shortcut id: shortcut
Layout.leftMargin: root.mirrored ? 0 : Kirigami.Units.largeSpacing - row.spacing
Layout.rightMargin: root.mirrored ? Kirigami.Units.largeSpacing - row.spacing : 0
Layout.alignment: Qt.AlignBaseline Layout.alignment: Qt.AlignBaseline
visible: !root.subMenu && root.action && root.action.shortcut !== undefined visible: !root.subMenu && root.action && root.action.shortcut !== undefined
text: visible ? itemShortcut.nativeText : "" text: visible ? itemShortcut.nativeText : ""
+1
View File
@@ -8,6 +8,7 @@ import org.kde.ki18n
AppMenu { AppMenu {
id: root id: root
icon.name: "audio-volume-high"
required property Actions actions required property Actions actions
required property MpvItem mpv required property MpvItem mpv
+9 -1
View File
@@ -11,6 +11,7 @@ import org.kde.ki18n
// Checkable list of audio tracks. // Checkable list of audio tracks.
AppMenu { AppMenu {
id: root id: root
icon.name: "audio-x-generic"
required property MpvItem mpv required property MpvItem mpv
@@ -23,14 +24,21 @@ AppMenu {
enabled: mpv.audioTracks.length > 0 enabled: mpv.audioTracks.length > 0
ButtonGroup { id: tracksGroup; exclusive: true }
Instantiator { Instantiator {
model: root.mpv.audioTracks model: root.mpv.audioTracks
delegate: AppMenuItem { delegate: AppMenuItem {
id: trackItem
required property var modelData required property var modelData
text: root.trackLabel(modelData) text: root.trackLabel(modelData)
checkable: true checkable: true
ButtonGroup.group: tracksGroup
checked: modelData.id === root.mpv.audioId checked: modelData.id === root.mpv.audioId
onTriggered: root.mpv.audioId = modelData.id onTriggered: {
root.mpv.audioId = modelData.id
checked = Qt.binding(() => trackItem.modelData.id === root.mpv.audioId)
}
} }
onObjectAdded: (index, object) => root.insertItem(index, object) onObjectAdded: (index, object) => root.insertItem(index, object)
onObjectRemoved: (index, object) => root.removeItem(object) onObjectRemoved: (index, object) => root.removeItem(object)
+15 -2
View File
@@ -8,14 +8,27 @@ import org.kde.ki18n
AppMenu { AppMenu {
id: root id: root
icon.name: "folder"
required property Actions actions required property Actions actions
// The hamburger must not instantiate application management commands.
property bool includeQuit: true
title: KI18n.i18nc("@title:menu", "&File") title: KI18n.i18nc("@title:menu", "&File")
AppMenuItem { action: root.actions.openFile } AppMenuItem { action: root.actions.openFile }
AppMenuItem { action: root.actions.openUrl } AppMenuItem { action: root.actions.openUrl }
RecentFilesMenu { actions: root.actions } RecentFilesMenu { actions: root.actions }
MenuSeparator {} Instantiator {
AppMenuItem { action: root.actions.quit } model: root.includeQuit ? 1 : 0
delegate: MenuSeparator {}
onObjectAdded: (index, object) => root.insertItem(3, object)
onObjectRemoved: (index, object) => root.removeItem(object)
}
Instantiator {
model: root.includeQuit ? 1 : 0
delegate: AppMenuItem { action: root.actions.quit }
onObjectAdded: (index, object) => root.insertItem(4, object)
onObjectRemoved: (index, object) => root.removeItem(object)
}
} }
+6 -17
View File
@@ -13,7 +13,7 @@ ToolButton {
required property Actions actions required property Actions actions
required property MpvItem mpv required property MpvItem mpv
// In the footer the menu opens upwards and also offers what the header would. // In the footer the same menu opens upwards.
property bool inFooter: false property bool inFooter: false
readonly property alias isOpen: menu.visible readonly property alias isOpen: menu.visible
@@ -36,16 +36,8 @@ ToolButton {
modal: true modal: true
dim: false dim: false
AppMenuItem { AppMenuItem { action: root.actions.openFile }
action: root.actions.openFile AppMenuItem { action: root.actions.openUrl }
visible: root.inFooter
height: visible ? implicitHeight : 0
}
AppMenuItem {
action: root.actions.openUrl
visible: root.inFooter
height: visible ? implicitHeight : 0
}
RecentFilesMenu { actions: root.actions } RecentFilesMenu { actions: root.actions }
SubtitleTracksMenu { SubtitleTracksMenu {
mpv: root.mpv mpv: root.mpv
@@ -67,17 +59,14 @@ ToolButton {
AppMenuItem { action: root.actions.togglePlaylist } AppMenuItem { action: root.actions.togglePlaylist }
AppMenuItem { action: root.actions.screenshot } AppMenuItem { action: root.actions.screenshot }
MenuSeparator {} MenuSeparator {}
AppMenuItem { AppMenuItem { action: root.actions.configure }
action: root.actions.configure
visible: root.inFooter
height: visible ? implicitHeight : 0
}
AppMenuItem { action: root.actions.toggleMenuBar } AppMenuItem { action: root.actions.toggleMenuBar }
AppMenuItem { action: root.actions.about } AppMenuItem { action: root.actions.about }
MenuSeparator {} MenuSeparator {}
AppMenu { AppMenu {
title: KI18n.i18nc("@title:menu", "&More") title: KI18n.i18nc("@title:menu", "&More")
FileMenu { actions: root.actions } icon.name: "overflow-menu"
FileMenu { actions: root.actions; includeQuit: false }
ViewMenu { actions: root.actions } ViewMenu { actions: root.actions }
PlaybackMenu { actions: root.actions } PlaybackMenu { actions: root.actions }
VideoMenu { actions: root.actions } VideoMenu { actions: root.actions }
+1
View File
@@ -8,6 +8,7 @@ import org.kde.ki18n
AppMenu { AppMenu {
id: root id: root
icon.name: "help-contents"
required property Actions actions required property Actions actions
+1
View File
@@ -18,6 +18,7 @@ AppMenu {
AppMenuItem { action: root.actions.playPreviousFile } AppMenuItem { action: root.actions.playPreviousFile }
AppMenu { AppMenu {
title: KI18n.i18nc("@title:menu", "Playback Speed") title: KI18n.i18nc("@title:menu", "Playback Speed")
icon.name: "speedometer"
AppMenuItem { action: root.actions.speedUp } AppMenuItem { action: root.actions.speedUp }
AppMenuItem { action: root.actions.speedDown } AppMenuItem { action: root.actions.speedDown }
AppMenuItem { action: root.actions.speedReset } AppMenuItem { action: root.actions.speedReset }
+2
View File
@@ -8,6 +8,7 @@ import org.kde.ki18n
AppMenu { AppMenu {
id: root id: root
icon.name: "media-playback-start"
required property Actions actions required property Actions actions
@@ -25,6 +26,7 @@ AppMenu {
MenuSeparator {} MenuSeparator {}
AppMenu { AppMenu {
title: KI18n.i18nc("@title:menu", "Seek") title: KI18n.i18nc("@title:menu", "Seek")
icon.name: "go-jump"
AppMenuItem { action: root.actions.seekForwardSmall } AppMenuItem { action: root.actions.seekForwardSmall }
AppMenuItem { action: root.actions.seekBackwardSmall } AppMenuItem { action: root.actions.seekBackwardSmall }
MenuSeparator {} MenuSeparator {}
+4 -1
View File
@@ -6,10 +6,12 @@ pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import org.kde.kirigami as Kirigami
import org.kde.ki18n import org.kde.ki18n
AppMenu { AppMenu {
id: root id: root
icon.name: "document-open-recent"
required property Actions actions required property Actions actions
@@ -23,11 +25,12 @@ AppMenu {
required property string name required property string name
required property string path required property string path
text: name text: name
textElide: Text.ElideMiddle
onTriggered: root.actions.fileOpenRequested(url) onTriggered: root.actions.fileOpenRequested(url)
ToolTip.text: path ToolTip.text: path
ToolTip.visible: hovered ToolTip.visible: hovered
ToolTip.delay: 1000 ToolTip.delay: Kirigami.Units.toolTipDelay
} }
onObjectAdded: (index, object) => root.insertItem(index, object) onObjectAdded: (index, object) => root.insertItem(index, object)
onObjectRemoved: (index, object) => root.removeItem(object) onObjectRemoved: (index, object) => root.removeItem(object)
+11 -9
View File
@@ -8,33 +8,35 @@ import org.kde.ki18n
AppMenu { AppMenu {
id: root id: root
icon.name: "settings-configure"
required property Actions actions required property Actions actions
title: KI18n.i18nc("@title:menu", "&Settings") title: KI18n.i18nc("@title:menu", "&Settings")
AppMenuItem { AppMenuItem {
text: KI18n.i18nc("@action:inmenu", "General") text: KI18n.i18nc("@action:inmenu", "General…")
icon.name: "configure"
onTriggered: root.actions.settingsRequested("general") onTriggered: root.actions.settingsRequested("general")
} }
AppMenuItem { AppMenuItem {
text: KI18n.i18nc("@action:inmenu", "Playback") text: KI18n.i18nc("@action:inmenu", "Playback…")
icon.name: "preferences-media-playback-amarok"
onTriggered: root.actions.settingsRequested("playback") onTriggered: root.actions.settingsRequested("playback")
} }
AppMenuItem { AppMenuItem {
text: KI18n.i18nc("@action:inmenu", "Subtitles") text: KI18n.i18nc("@action:inmenu", "Subtitles…")
icon.name: "preferences-desktop-font"
onTriggered: root.actions.settingsRequested("subtitles") onTriggered: root.actions.settingsRequested("subtitles")
} }
AppMenuItem { AppMenuItem {
text: KI18n.i18nc("@action:inmenu", "Translation") text: KI18n.i18nc("@action:inmenu", "Translation…")
icon.name: "translate"
onTriggered: root.actions.settingsRequested("translation") onTriggered: root.actions.settingsRequested("translation")
} }
AppMenuItem { AppMenuItem {
text: KI18n.i18nc("@action:inmenu", "Playlist") text: KI18n.i18nc("@action:inmenu", "Playlist…")
icon.name: "view-media-playlist"
onTriggered: root.actions.settingsRequested("playlist") onTriggered: root.actions.settingsRequested("playlist")
} }
AppMenuItem {
text: KI18n.i18nc("@action:inmenu", "About")
onTriggered: root.actions.settingsRequested("about")
}
} }
+11 -2
View File
@@ -11,6 +11,7 @@ import org.kde.ki18n
// Checkable list of subtitle tracks, for the primary or the secondary subtitle. // Checkable list of subtitle tracks, for the primary or the secondary subtitle.
AppMenu { AppMenu {
id: root id: root
icon.name: isPrimary ? "text-x-generic" : "text-x-script"
required property MpvItem mpv required property MpvItem mpv
property bool isPrimary: true property bool isPrimary: true
@@ -36,13 +37,16 @@ AppMenu {
enabled: mpv.subtitleTracks.length > 0 enabled: mpv.subtitleTracks.length > 0
ButtonGroup { id: tracksGroup; exclusive: true }
AppMenuItem { AppMenuItem {
text: KI18n.i18nc("@item:inmenu no subtitle", "None") text: KI18n.i18nc("@item:inmenu no subtitle", "None")
checkable: true checkable: true
ButtonGroup.group: tracksGroup
checked: root.selectedId === 0 checked: root.selectedId === 0
onTriggered: { onTriggered: {
root.select(0) root.select(0)
// Clicking a checked item unchecks it, which drops the binding. // Keep mpv authoritative after MenuItem updates its checked state.
checked = Qt.binding(() => root.selectedId === 0) checked = Qt.binding(() => root.selectedId === 0)
} }
} }
@@ -50,13 +54,18 @@ AppMenu {
Instantiator { Instantiator {
model: root.mpv.subtitleTracks model: root.mpv.subtitleTracks
delegate: AppMenuItem { delegate: AppMenuItem {
id: trackItem
required property var modelData required property var modelData
text: root.trackLabel(modelData) text: root.trackLabel(modelData)
checkable: true checkable: true
ButtonGroup.group: tracksGroup
checked: modelData.id === root.selectedId checked: modelData.id === root.selectedId
// mpv cannot show one track in both places. // mpv cannot show one track in both places.
enabled: modelData.id !== root.otherId enabled: modelData.id !== root.otherId
onTriggered: root.select(modelData.id) onTriggered: {
root.select(modelData.id)
checked = Qt.binding(() => trackItem.modelData.id === root.selectedId)
}
} }
onObjectAdded: (index, object) => root.insertItem(index + 1, object) onObjectAdded: (index, object) => root.insertItem(index + 1, object)
onObjectRemoved: (index, object) => root.removeItem(object) onObjectRemoved: (index, object) => root.removeItem(object)
+6 -5
View File
@@ -8,12 +8,14 @@ import org.kde.ki18n
AppMenu { AppMenu {
id: root id: root
icon.name: "media-view-subtitles-symbolic"
required property Actions actions required property Actions actions
required property MpvItem mpv required property MpvItem mpv
title: KI18n.i18nc("@title:menu", "&Subtitles") title: KI18n.i18nc("@title:menu", "&Subtitles")
SubtitleTracksMenu { SubtitleTracksMenu {
mpv: root.mpv mpv: root.mpv
isPrimary: true isPrimary: true
@@ -27,18 +29,17 @@ AppMenu {
MenuSeparator {} MenuSeparator {}
AppMenuItem { action: root.actions.translateSubtitle } AppMenuItem { action: root.actions.translateSubtitle }
AppMenuItem { action: root.actions.editGlossary } AppMenuItem { action: root.actions.editGlossary }
AppMenuItem { AppMenuItem { action: root.actions.cancelTranslation }
action: root.actions.cancelTranslation
visible: root.actions.cancelTranslation.enabled
height: visible ? implicitHeight : 0
}
MenuSeparator {} MenuSeparator {}
AppMenuItem { action: root.actions.addSubtitle } AppMenuItem { action: root.actions.addSubtitle }
MenuSeparator {}
AppMenuItem { action: root.actions.subtitleBigger } AppMenuItem { action: root.actions.subtitleBigger }
AppMenuItem { action: root.actions.subtitleSmaller } AppMenuItem { action: root.actions.subtitleSmaller }
MenuSeparator {}
AppMenuItem { action: root.actions.subtitleEarlier } AppMenuItem { action: root.actions.subtitleEarlier }
AppMenuItem { action: root.actions.subtitleLater } AppMenuItem { action: root.actions.subtitleLater }
AppMenuItem { action: root.actions.subtitleDelayReset } AppMenuItem { action: root.actions.subtitleDelayReset }
MenuSeparator {}
AppMenuItem { action: root.actions.subtitleToggle } AppMenuItem { action: root.actions.subtitleToggle }
AppMenuItem { action: root.actions.subtitleCycleUp } AppMenuItem { action: root.actions.subtitleCycleUp }
AppMenuItem { action: root.actions.subtitleCycleDown } AppMenuItem { action: root.actions.subtitleCycleDown }
+5
View File
@@ -8,16 +8,21 @@ import org.kde.ki18n
AppMenu { AppMenu {
id: root id: root
icon.name: "video-display"
required property Actions actions required property Actions actions
title: KI18n.i18nc("@title:menu", "&Video") title: KI18n.i18nc("@title:menu", "&Video")
AppMenuItem { action: root.actions.toggleDeinterlacing } AppMenuItem { action: root.actions.toggleDeinterlacing }
MenuSeparator {}
AppMenuItem { action: root.actions.zoomIn } AppMenuItem { action: root.actions.zoomIn }
AppMenuItem { action: root.actions.zoomOut } AppMenuItem { action: root.actions.zoomOut }
AppMenuItem { action: root.actions.zoomReset } AppMenuItem { action: root.actions.zoomReset }
MenuSeparator {}
AppMenuItem { action: root.actions.screenshot } AppMenuItem { action: root.actions.screenshot }
MenuSeparator {}
AppMenuItem { action: root.actions.rotateClockwise } AppMenuItem { action: root.actions.rotateClockwise }
AppMenuItem { action: root.actions.rotateCounterClockwise } AppMenuItem { action: root.actions.rotateCounterClockwise }
} }
+1
View File
@@ -8,6 +8,7 @@ import org.kde.ki18n
AppMenu { AppMenu {
id: root id: root
icon.name: "view-list-details"
required property Actions actions required property Actions actions