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,502 @@
|
||||
// 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
|
||||
|
||||
// Every command of the player, shared by the menus, the toolbar buttons and the
|
||||
// keyboard shortcuts. Shortcuts follow Haruna's defaults.
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property MpvItem mpv
|
||||
required property PlaylistModel playlist
|
||||
required property TranslationService translator
|
||||
required property Osd osd
|
||||
|
||||
// Off while a dialog has the keyboard, so typing there does not seek or pause.
|
||||
property bool shortcutsEnabled: true
|
||||
property bool fullscreen: false
|
||||
|
||||
readonly property bool hasFile: mpv.fileLoaded
|
||||
|
||||
signal openFileRequested()
|
||||
// Open a known file, such as one from Recent Files.
|
||||
signal fileOpenRequested(url: url)
|
||||
signal openUrlRequested()
|
||||
signal addSubtitleRequested()
|
||||
signal settingsRequested(page: string)
|
||||
signal fullscreenToggleRequested()
|
||||
signal fullscreenExitRequested()
|
||||
signal playlistToggleRequested()
|
||||
signal menuBarToggleRequested()
|
||||
signal headerToggleRequested()
|
||||
signal contextMenuRequested()
|
||||
signal translateRequested()
|
||||
|
||||
function seekBy(seconds: real) {
|
||||
mpv.seekBy(seconds)
|
||||
}
|
||||
|
||||
function changeVolume(steps: int) {
|
||||
mpv.volume = mpv.volume + steps * QtPotatoSettings.volumeStep
|
||||
osd.message(KI18n.i18nc("@info:osd", "Volume: %1", mpv.volume))
|
||||
}
|
||||
|
||||
function changeSpeed(delta: real) {
|
||||
mpv.speed = delta === 0 ? 1.0 : mpv.speed + delta
|
||||
osd.message(KI18n.i18nc("@info:osd", "Playback speed: %1", Number(mpv.speed).toFixed(2)))
|
||||
}
|
||||
|
||||
function changeSubtitleDelay(seconds: real) {
|
||||
mpv.subtitleDelay = mpv.subtitleDelay + seconds
|
||||
osd.message(KI18n.i18nc("@info:osd", "Subtitle delay: %1 ms", Math.round(mpv.subtitleDelay * 1000)))
|
||||
}
|
||||
|
||||
function cycleTrack(tracks: var, currentId: int, step: int): int {
|
||||
// Track ids with 0 ("off") first, as mpv's cycle commands do.
|
||||
const ids = [0].concat(tracks.map(track => track.id))
|
||||
const index = Math.max(0, ids.indexOf(currentId))
|
||||
return ids[(index + step + ids.length) % ids.length]
|
||||
}
|
||||
|
||||
// The next or previous file, following the playback behavior setting.
|
||||
function playNext(): bool {
|
||||
return playlist.playNext(QtPotatoSettings.playbackBehavior === "RepeatPlaylist")
|
||||
}
|
||||
|
||||
function playPrevious(): bool {
|
||||
return playlist.playPrevious(QtPotatoSettings.playbackBehavior === "RepeatPlaylist")
|
||||
}
|
||||
|
||||
property Action openFile: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: KI18n.i18nc("@action", "Open File…")
|
||||
icon.name: "folder-videos"
|
||||
shortcut: StandardKey.Open
|
||||
onTriggered: root.openFileRequested()
|
||||
}
|
||||
|
||||
property Action openUrl: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: KI18n.i18nc("@action", "Open URL…")
|
||||
icon.name: "internet-services"
|
||||
shortcut: "Ctrl+Shift+O"
|
||||
onTriggered: root.openUrlRequested()
|
||||
}
|
||||
|
||||
property Action quit: Action {
|
||||
text: KI18n.i18nc("@action", "Quit")
|
||||
icon.name: "application-exit"
|
||||
shortcut: StandardKey.Quit
|
||||
onTriggered: Qt.quit()
|
||||
}
|
||||
|
||||
property Action playPause: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Play/Pause")
|
||||
icon.name: root.mpv.paused ? "media-playback-start" : "media-playback-pause"
|
||||
shortcut: "Space"
|
||||
onTriggered: root.mpv.togglePause()
|
||||
}
|
||||
|
||||
property Action stop: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Stop")
|
||||
icon.name: "media-playback-stop"
|
||||
shortcut: "Media Stop"
|
||||
onTriggered: root.mpv.stop()
|
||||
}
|
||||
|
||||
property Action restart: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Restart Playback")
|
||||
icon.name: "edit-reset"
|
||||
shortcut: "F5"
|
||||
onTriggered: root.mpv.seek(0)
|
||||
}
|
||||
|
||||
property Action playNextFile: Action {
|
||||
enabled: root.shortcutsEnabled && root.playlist.count > 1
|
||||
text: KI18n.i18nc("@action", "Play Next")
|
||||
icon.name: "media-skip-forward"
|
||||
shortcut: "Shift+."
|
||||
onTriggered: root.playNext()
|
||||
}
|
||||
|
||||
property Action playPreviousFile: Action {
|
||||
enabled: root.shortcutsEnabled && root.playlist.count > 1
|
||||
text: KI18n.i18nc("@action", "Play Previous")
|
||||
icon.name: "media-skip-backward"
|
||||
shortcut: "Shift+,"
|
||||
onTriggered: root.playPrevious()
|
||||
}
|
||||
|
||||
property Action seekForwardSmall: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Seek Small Step Forward")
|
||||
shortcut: "Right"
|
||||
onTriggered: root.seekBy(QtPotatoSettings.seekSmallStep)
|
||||
}
|
||||
|
||||
property Action seekBackwardSmall: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Seek Small Step Backward")
|
||||
shortcut: "Left"
|
||||
onTriggered: root.seekBy(-QtPotatoSettings.seekSmallStep)
|
||||
}
|
||||
|
||||
property Action seekForwardMedium: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Seek Medium Step Forward")
|
||||
shortcut: "Shift+Right"
|
||||
onTriggered: root.seekBy(QtPotatoSettings.seekMediumStep)
|
||||
}
|
||||
|
||||
property Action seekBackwardMedium: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Seek Medium Step Backward")
|
||||
shortcut: "Shift+Left"
|
||||
onTriggered: root.seekBy(-QtPotatoSettings.seekMediumStep)
|
||||
}
|
||||
|
||||
property Action seekForwardBig: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Seek Big Step Forward")
|
||||
shortcut: "Up"
|
||||
onTriggered: root.seekBy(QtPotatoSettings.seekBigStep)
|
||||
}
|
||||
|
||||
property Action seekBackwardBig: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Seek Big Step Backward")
|
||||
shortcut: "Down"
|
||||
onTriggered: root.seekBy(-QtPotatoSettings.seekBigStep)
|
||||
}
|
||||
|
||||
property Action seekNextSubtitle: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Seek To Next Subtitle")
|
||||
shortcut: "Ctrl+Right"
|
||||
onTriggered: root.mpv.commandAsync(["sub-seek", "1"])
|
||||
}
|
||||
|
||||
property Action seekPreviousSubtitle: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Seek To Previous Subtitle")
|
||||
shortcut: "Ctrl+Left"
|
||||
onTriggered: root.mpv.commandAsync(["sub-seek", "-1"])
|
||||
}
|
||||
|
||||
property Action seekNextChapter: Action {
|
||||
enabled: root.shortcutsEnabled && root.mpv.chapters.length > 0
|
||||
text: KI18n.i18nc("@action", "Seek To Next Chapter")
|
||||
shortcut: "PgUp"
|
||||
onTriggered: root.mpv.commandAsync(["add", "chapter", "1"])
|
||||
}
|
||||
|
||||
property Action seekPreviousChapter: Action {
|
||||
enabled: root.shortcutsEnabled && root.mpv.chapters.length > 0
|
||||
text: KI18n.i18nc("@action", "Seek To Previous Chapter")
|
||||
shortcut: "PgDown"
|
||||
onTriggered: root.mpv.commandAsync(["add", "chapter", "-1"])
|
||||
}
|
||||
|
||||
property Action frameStepForward: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Step Frame Forward")
|
||||
shortcut: "."
|
||||
onTriggered: root.mpv.frameStep(true)
|
||||
}
|
||||
|
||||
property Action frameStepBackward: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Step Frame Backward")
|
||||
shortcut: ","
|
||||
onTriggered: root.mpv.frameStep(false)
|
||||
}
|
||||
|
||||
property Action speedUp: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Increase Playback Speed")
|
||||
shortcut: "]"
|
||||
onTriggered: root.changeSpeed(0.1)
|
||||
}
|
||||
|
||||
property Action speedDown: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Decrease Playback Speed")
|
||||
shortcut: "["
|
||||
onTriggered: root.changeSpeed(-0.1)
|
||||
}
|
||||
|
||||
property Action speedReset: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Reset Playback Speed")
|
||||
shortcut: "Backspace"
|
||||
onTriggered: root.changeSpeed(0)
|
||||
}
|
||||
|
||||
property Action mute: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: root.mpv.mute ? KI18n.i18nc("@action", "Unmute") : KI18n.i18nc("@action", "Mute")
|
||||
icon.name: root.mpv.mute ? "player-volume" : "player-volume-muted"
|
||||
shortcut: "M"
|
||||
onTriggered: {
|
||||
root.mpv.mute = !root.mpv.mute
|
||||
root.osd.message(root.mpv.mute ? KI18n.i18nc("@info:osd", "Audio muted") : KI18n.i18nc("@info:osd", "Audio unmuted"))
|
||||
}
|
||||
}
|
||||
|
||||
property Action volumeUp: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: KI18n.i18nc("@action", "Volume Up")
|
||||
icon.name: "audio-volume-high"
|
||||
shortcut: "9"
|
||||
onTriggered: root.changeVolume(1)
|
||||
}
|
||||
|
||||
property Action volumeDown: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: KI18n.i18nc("@action", "Volume Down")
|
||||
icon.name: "audio-volume-low"
|
||||
shortcut: "0"
|
||||
onTriggered: root.changeVolume(-1)
|
||||
}
|
||||
|
||||
property Action audioCycleUp: Action {
|
||||
enabled: root.shortcutsEnabled && root.mpv.audioTracks.length > 1
|
||||
text: KI18n.i18nc("@action", "Cycle Up Audio Track")
|
||||
shortcut: "Shift+3"
|
||||
onTriggered: root.mpv.audioId = root.cycleTrack(root.mpv.audioTracks, root.mpv.audioId, 1)
|
||||
}
|
||||
|
||||
property Action audioCycleDown: Action {
|
||||
enabled: root.shortcutsEnabled && root.mpv.audioTracks.length > 1
|
||||
text: KI18n.i18nc("@action", "Cycle Down Audio Track")
|
||||
shortcut: "Shift+2"
|
||||
onTriggered: root.mpv.audioId = root.cycleTrack(root.mpv.audioTracks, root.mpv.audioId, -1)
|
||||
}
|
||||
|
||||
property Action addSubtitle: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Add External Subtitle…")
|
||||
icon.name: "add-subtitle"
|
||||
shortcut: "Alt+S"
|
||||
onTriggered: root.addSubtitleRequested()
|
||||
}
|
||||
|
||||
property Action subtitleToggle: Action {
|
||||
enabled: root.shortcutsEnabled && root.mpv.subtitleTracks.length > 0
|
||||
text: KI18n.i18nc("@action", "Toggle Subtitles")
|
||||
shortcut: "Ctrl+S"
|
||||
onTriggered: {
|
||||
const visible = root.mpv.getProperty("sub-visibility")
|
||||
root.mpv.setPropertyAsync("sub-visibility", !visible)
|
||||
root.mpv.setPropertyAsync("secondary-sub-visibility", !visible)
|
||||
root.osd.message(visible ? KI18n.i18nc("@info:osd", "Subtitles hidden") : KI18n.i18nc("@info:osd", "Subtitles shown"))
|
||||
}
|
||||
}
|
||||
|
||||
property Action subtitleCycleUp: Action {
|
||||
enabled: root.shortcutsEnabled && root.mpv.subtitleTracks.length > 0
|
||||
text: KI18n.i18nc("@action", "Cycle Up Subtitle")
|
||||
shortcut: "J"
|
||||
onTriggered: root.mpv.subtitleId = root.cycleTrack(root.mpv.subtitleTracks, root.mpv.subtitleId, 1)
|
||||
}
|
||||
|
||||
property Action subtitleCycleDown: Action {
|
||||
enabled: root.shortcutsEnabled && root.mpv.subtitleTracks.length > 0
|
||||
text: KI18n.i18nc("@action", "Cycle Down Subtitle")
|
||||
shortcut: "Shift+J"
|
||||
onTriggered: root.mpv.subtitleId = root.cycleTrack(root.mpv.subtitleTracks, root.mpv.subtitleId, -1)
|
||||
}
|
||||
|
||||
property Action subtitleEarlier: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Show Subtitles Earlier")
|
||||
shortcut: "Z"
|
||||
onTriggered: root.changeSubtitleDelay(-0.1)
|
||||
}
|
||||
|
||||
property Action subtitleLater: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Show Subtitles Later")
|
||||
shortcut: "Shift+Z"
|
||||
onTriggered: root.changeSubtitleDelay(0.1)
|
||||
}
|
||||
|
||||
property Action subtitleDelayReset: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile && root.mpv.subtitleDelay !== 0
|
||||
text: KI18n.i18nc("@action", "Reset Subtitle Delay")
|
||||
onTriggered: root.changeSubtitleDelay(-root.mpv.subtitleDelay)
|
||||
}
|
||||
|
||||
property Action subtitleBigger: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: KI18n.i18nc("@action", "Increase Subtitle Font Size")
|
||||
shortcut: "Ctrl+Z"
|
||||
onTriggered: {
|
||||
QtPotatoSettings.subtitleFontSize = Math.min(150, QtPotatoSettings.subtitleFontSize + 2)
|
||||
QtPotatoSettings.save()
|
||||
root.osd.message(KI18n.i18nc("@info:osd", "Subtitle font size: %1", QtPotatoSettings.subtitleFontSize))
|
||||
}
|
||||
}
|
||||
|
||||
property Action subtitleSmaller: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: KI18n.i18nc("@action", "Decrease Subtitle Font Size")
|
||||
shortcut: "Ctrl+X"
|
||||
onTriggered: {
|
||||
QtPotatoSettings.subtitleFontSize = Math.max(20, QtPotatoSettings.subtitleFontSize - 2)
|
||||
QtPotatoSettings.save()
|
||||
root.osd.message(KI18n.i18nc("@info:osd", "Subtitle font size: %1", QtPotatoSettings.subtitleFontSize))
|
||||
}
|
||||
}
|
||||
|
||||
property Action translateSubtitle: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile && root.mpv.subtitleId > 0 && !root.translator.busy
|
||||
text: KI18n.i18nc("@action", "Translate Subtitle into %1", QtPotatoSettings.targetLanguage)
|
||||
icon.name: "translate"
|
||||
shortcut: "Ctrl+T"
|
||||
onTriggered: root.translateRequested()
|
||||
}
|
||||
|
||||
property Action cancelTranslation: Action {
|
||||
enabled: root.translator.busy
|
||||
text: KI18n.i18nc("@action", "Cancel Translation")
|
||||
icon.name: "dialog-cancel"
|
||||
onTriggered: root.translator.cancel()
|
||||
}
|
||||
|
||||
property Action screenshot: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Screenshot")
|
||||
icon.name: "image-x-generic"
|
||||
shortcut: "S"
|
||||
onTriggered: {
|
||||
root.mpv.screenshot()
|
||||
root.osd.message(KI18n.i18nc("@info:osd", "Screenshot saved"))
|
||||
}
|
||||
}
|
||||
|
||||
property Action toggleDeinterlacing: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Toggle Deinterlacing")
|
||||
shortcut: "D"
|
||||
onTriggered: {
|
||||
const enabled = root.mpv.getProperty("deinterlace") === "yes"
|
||||
root.mpv.setPropertyAsync("deinterlace", enabled ? "no" : "yes")
|
||||
root.osd.message(enabled ? KI18n.i18nc("@info:osd", "Deinterlacing off") : KI18n.i18nc("@info:osd", "Deinterlacing on"))
|
||||
}
|
||||
}
|
||||
|
||||
property Action zoomIn: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Zoom In")
|
||||
icon.name: "zoom-in"
|
||||
shortcut: StandardKey.ZoomIn
|
||||
onTriggered: root.mpv.commandAsync(["add", "video-zoom", "0.1"])
|
||||
}
|
||||
|
||||
property Action zoomOut: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Zoom Out")
|
||||
icon.name: "zoom-out"
|
||||
shortcut: StandardKey.ZoomOut
|
||||
onTriggered: root.mpv.commandAsync(["add", "video-zoom", "-0.1"])
|
||||
}
|
||||
|
||||
property Action zoomReset: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Reset Zoom")
|
||||
icon.name: "zoom-original"
|
||||
shortcut: "Ctrl+0"
|
||||
onTriggered: root.mpv.setPropertyAsync("video-zoom", 0)
|
||||
}
|
||||
|
||||
property Action rotateClockwise: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Rotate Clockwise")
|
||||
icon.name: "object-rotate-right"
|
||||
shortcut: "Ctrl+R"
|
||||
onTriggered: root.mpv.setPropertyAsync("video-rotate", (root.mpv.getProperty("video-rotate") + 90) % 360)
|
||||
}
|
||||
|
||||
property Action rotateCounterClockwise: Action {
|
||||
enabled: root.shortcutsEnabled && root.hasFile
|
||||
text: KI18n.i18nc("@action", "Rotate Counter Clockwise")
|
||||
icon.name: "object-rotate-left"
|
||||
shortcut: "Ctrl+E"
|
||||
onTriggered: root.mpv.setPropertyAsync("video-rotate", (root.mpv.getProperty("video-rotate") + 270) % 360)
|
||||
}
|
||||
|
||||
property Action toggleFullscreen: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: KI18n.i18nc("@action", "Toggle Fullscreen")
|
||||
icon.name: "view-fullscreen"
|
||||
shortcut: "F"
|
||||
onTriggered: root.fullscreenToggleRequested()
|
||||
}
|
||||
|
||||
property Action exitFullscreen: Action {
|
||||
// Only while full screen, so Esc still reaches everything else.
|
||||
enabled: root.shortcutsEnabled && root.fullscreen
|
||||
text: KI18n.i18nc("@action", "Exit Fullscreen")
|
||||
shortcut: "Escape"
|
||||
onTriggered: root.fullscreenExitRequested()
|
||||
}
|
||||
|
||||
property Action togglePlaylist: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: KI18n.i18nc("@action", "Playlist")
|
||||
icon.name: "view-media-playlist"
|
||||
shortcut: "P"
|
||||
onTriggered: root.playlistToggleRequested()
|
||||
}
|
||||
|
||||
property Action toggleMenuBar: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: QtPotatoSettings.showMenuBar ? KI18n.i18nc("@action", "Hide Menubar") : KI18n.i18nc("@action", "Show Menubar")
|
||||
icon.name: "show-menu"
|
||||
shortcut: "Ctrl+M"
|
||||
onTriggered: root.menuBarToggleRequested()
|
||||
}
|
||||
|
||||
property Action toggleHeader: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: QtPotatoSettings.showHeader ? KI18n.i18nc("@action", "Hide Toolbar") : KI18n.i18nc("@action", "Show Toolbar")
|
||||
shortcut: "Ctrl+H"
|
||||
onTriggered: root.headerToggleRequested()
|
||||
}
|
||||
|
||||
property Action openContextMenu: Action {
|
||||
enabled: root.shortcutsEnabled
|
||||
text: KI18n.i18nc("@action", "Open Context Menu")
|
||||
icon.name: "application-menu"
|
||||
shortcut: "Menu"
|
||||
onTriggered: root.contextMenuRequested()
|
||||
}
|
||||
|
||||
property Action configure: Action {
|
||||
text: KI18n.i18nc("@action", "Settings")
|
||||
icon.name: "configure"
|
||||
shortcut: "Ctrl+Shift+,"
|
||||
onTriggered: root.settingsRequested("general")
|
||||
}
|
||||
|
||||
property Action about: Action {
|
||||
text: KI18n.i18nc("@action", "About QtPotato")
|
||||
icon.name: "help-about"
|
||||
shortcut: "F1"
|
||||
onTriggered: root.settingsRequested("about")
|
||||
}
|
||||
|
||||
property Action reportBug: Action {
|
||||
text: KI18n.i18nc("@action", "Report Bug")
|
||||
icon.name: "tools-report-bug"
|
||||
onTriggered: Qt.openUrlExternally("https://github.com/vokhactri/QtPotato/issues")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user