fix(settings): align settings pages with KDE HIG

This commit is contained in:
tri committed 2026-11-07 20:08:28 +07:00
1 parent de9e6484ee
commit 3d8f644d8d
10 files changed
+200 -186

No files matched your search

+20 -30
View File
@@ -13,23 +13,19 @@ SettingsBasePage {
required property MpvItem mpv
GridLayout {
columns: 2
Kirigami.FormLayout {
SettingsHeader {
text: KI18n.i18nc("@title", "Interface")
topMargin: 0
Layout.columnSpan: 2
Layout.fillWidth: true
}
Label {
text: KI18n.i18nc("@label:listbox", "Footer style")
Layout.alignment: Qt.AlignRight
}
RowLayout {
spacing: Kirigami.Units.smallSpacing
Kirigami.FormData.label: KI18n.i18nc("@label:listbox", "Footer style")
Kirigami.FormData.buddyFor: footerStyleCombo
ComboBox {
id: footerStyleCombo
textRole: "text"
valueRole: "value"
model: [
@@ -48,9 +44,7 @@ SettingsBasePage {
}
}
Item { Layout.preferredWidth: 1 }
CheckBox {
Switch {
text: KI18n.i18nc("@option:check", "Show menu bar")
checked: QtPotatoSettings.showMenuBar
onClicked: {
@@ -59,9 +53,7 @@ SettingsBasePage {
}
}
Item { Layout.preferredWidth: 1 }
CheckBox {
Switch {
text: KI18n.i18nc("@option:check", "Show toolbar")
checked: QtPotatoSettings.showHeader
onClicked: {
@@ -70,13 +62,12 @@ SettingsBasePage {
}
}
Label {
text: KI18n.i18nc("@label:spinbox", "Maximum recent files")
Layout.alignment: Qt.AlignRight
}
RowLayout {
spacing: Kirigami.Units.smallSpacing
Kirigami.FormData.label: KI18n.i18nc("@label:spinbox", "Maximum recent files")
Kirigami.FormData.buddyFor: maxRecentSpin
SpinBox {
id: maxRecentSpin
from: 0
to: 50
value: QtPotatoSettings.maxRecentFiles
@@ -93,14 +84,12 @@ SettingsBasePage {
SettingsHeader {
text: KI18n.i18nc("@title", "mpv")
Layout.columnSpan: 2
Layout.fillWidth: true
}
Item { Layout.preferredWidth: 1 }
RowLayout {
CheckBox {
spacing: Kirigami.Units.smallSpacing
Switch {
text: KI18n.i18nc("@option:check", "Use mpv.conf")
checked: QtPotatoSettings.loadMpvConfig
onClicked: {
@@ -114,7 +103,13 @@ SettingsBasePage {
}
}
Item { Layout.preferredWidth: 1 }
Label {
text: KI18n.i18nc("@info", "Restart QtPotato to apply changes to this setting or to mpv.conf.")
wrapMode: Text.WordWrap
font: Kirigami.Theme.smallFont
color: Kirigami.Theme.disabledTextColor
Layout.fillWidth: true
}
Label {
text: root.mpv.loadedUserConfigFiles.length > 0
@@ -127,11 +122,6 @@ SettingsBasePage {
Layout.fillWidth: true
}
Item {
Layout.preferredWidth: 1
visible: root.mpv.skippedUserOptions.length > 0
}
Label {
visible: root.mpv.skippedUserOptions.length > 0
text: KI18n.i18nc("@info", "Ignored because they would break the built-in player: %1", root.mpv.skippedUserOptions.join(", "))
+6 -25
View File
@@ -5,27 +5,21 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.ki18n
SettingsBasePage {
id: root
GridLayout {
columns: 2
Kirigami.FormLayout {
SettingsHeader {
text: KI18n.i18nc("@title", "Seeking")
topMargin: 0
Layout.columnSpan: 2
Layout.fillWidth: true
}
Label {
text: KI18n.i18nc("@label:spinbox", "Small step")
Layout.alignment: Qt.AlignRight
}
SpinBox {
Kirigami.FormData.label: KI18n.i18nc("@label:spinbox", "Small step")
from: 1
to: 600
value: QtPotatoSettings.seekSmallStep
@@ -37,12 +31,8 @@ SettingsBasePage {
}
}
Label {
text: KI18n.i18nc("@label:spinbox", "Medium step")
Layout.alignment: Qt.AlignRight
}
SpinBox {
Kirigami.FormData.label: KI18n.i18nc("@label:spinbox", "Medium step")
from: 1
to: 600
value: QtPotatoSettings.seekMediumStep
@@ -54,12 +44,8 @@ SettingsBasePage {
}
}
Label {
text: KI18n.i18nc("@label:spinbox", "Big step")
Layout.alignment: Qt.AlignRight
}
SpinBox {
Kirigami.FormData.label: KI18n.i18nc("@label:spinbox", "Big step")
from: 1
to: 600
value: QtPotatoSettings.seekBigStep
@@ -73,16 +59,11 @@ SettingsBasePage {
SettingsHeader {
text: KI18n.i18nc("@title", "Audio")
Layout.columnSpan: 2
Layout.fillWidth: true
}
Label {
text: KI18n.i18nc("@label:spinbox", "Volume step")
Layout.alignment: Qt.AlignRight
}
SpinBox {
Kirigami.FormData.label: KI18n.i18nc("@label:spinbox", "Volume step")
from: 1
to: 100
value: QtPotatoSettings.volumeStep
+15 -25
View File
@@ -5,20 +5,18 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.ki18n
SettingsBasePage {
id: root
GridLayout {
columns: 2
Label {
text: KI18n.i18nc("@label:listbox", "Position")
Layout.alignment: Qt.AlignRight
}
Kirigami.FormLayout {
ComboBox {
Layout.fillWidth: true
Layout.minimumWidth: 0
Kirigami.FormData.label: KI18n.i18nc("@label:listbox", "Position")
textRole: "text"
valueRole: "value"
model: [
@@ -32,12 +30,10 @@ SettingsBasePage {
}
}
Label {
text: KI18n.i18nc("@label:listbox", "When a file ends")
Layout.alignment: Qt.AlignRight
}
ComboBox {
Layout.fillWidth: true
Layout.minimumWidth: 0
Kirigami.FormData.label: KI18n.i18nc("@label:listbox", "When a file ends")
textRole: "text"
valueRole: "value"
model: [
@@ -53,11 +49,10 @@ SettingsBasePage {
}
}
Item { Layout.preferredWidth: 1 }
RowLayout {
CheckBox {
text: KI18n.i18nc("@option:check", "Add the other files of the folder")
spacing: Kirigami.Units.smallSpacing
Switch {
text: KI18n.i18nc("@option:check", "Add other files from the folder")
checked: QtPotatoSettings.playlistLoadSiblings
onClicked: {
QtPotatoSettings.playlistLoadSiblings = checked
@@ -70,9 +65,7 @@ SettingsBasePage {
}
}
Item { Layout.preferredWidth: 1 }
CheckBox {
Switch {
text: KI18n.i18nc("@option:check", "Overlay video")
checked: QtPotatoSettings.playlistOverlayVideo
onClicked: {
@@ -81,10 +74,9 @@ SettingsBasePage {
}
}
Item { Layout.preferredWidth: 1 }
RowLayout {
CheckBox {
spacing: Kirigami.Units.smallSpacing
Switch {
text: KI18n.i18nc("@option:check", "Open with the mouse")
checked: QtPotatoSettings.playlistToggleWithMouse
onClicked: {
@@ -98,9 +90,7 @@ SettingsBasePage {
}
}
Item { Layout.preferredWidth: 1 }
CheckBox {
Switch {
text: KI18n.i18nc("@option:check", "Show row numbers")
checked: QtPotatoSettings.playlistShowRowNumber
onClicked: {
+1
View File
@@ -6,6 +6,7 @@ import org.kde.kirigami as Kirigami
// Page of the settings window. Changes are saved as they are made.
Kirigami.ScrollablePage {
padding: Kirigami.Units.largeSpacing
globalToolBarStyle: Kirigami.ApplicationHeaderStyle.None
Component.onDestruction: QtPotatoSettings.save()
}
+4 -28
View File
@@ -2,36 +2,12 @@
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
// Section title of a settings page, between two lines.
ColumnLayout {
id: root
// FormLayout supplies the standard section heading and group spacing.
Item {
property string text: ""
property int topMargin: Kirigami.Units.gridUnit
spacing: 0
RowLayout {
Layout.topMargin: root.topMargin
Rectangle {
color: Kirigami.Theme.alternateBackgroundColor
Layout.preferredWidth: Kirigami.Units.gridUnit
Layout.preferredHeight: 1
}
Kirigami.Heading {
text: root.text
level: 1
}
Rectangle {
color: Kirigami.Theme.alternateBackgroundColor
Layout.preferredHeight: 1
Layout.fillWidth: true
}
}
Kirigami.FormData.label: text
Kirigami.FormData.isSection: true
}
+5 -4
View File
@@ -109,10 +109,10 @@ Loader {
property Item currentPage: null
width: 800
height: 600
minimumWidth: 750
minimumHeight: 400
width: Kirigami.Units.gridUnit * 45
height: Kirigami.Units.gridUnit * 34
minimumWidth: Kirigami.Units.gridUnit * 41
minimumHeight: Kirigami.Units.gridUnit * 22
title: KI18n.i18nc("@title:window", "Settings")
visible: true
@@ -132,6 +132,7 @@ Loader {
text: modelData.text
icon.name: modelData.iconName
highlighted: index === ListView.view.currentIndex
font.bold: highlighted
onClicked: settingsWindow.showPage(modelData.name)
}
}
+7 -12
View File
@@ -5,21 +5,20 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.ki18n
SettingsBasePage {
id: root
GridLayout {
columns: 2
Label {
text: KI18n.i18nc("@label:spinbox", "Font size")
Layout.alignment: Qt.AlignRight
}
Kirigami.FormLayout {
RowLayout {
spacing: Kirigami.Units.smallSpacing
Kirigami.FormData.label: KI18n.i18nc("@label:spinbox", "Font size")
Kirigami.FormData.buddyFor: fontSizeSpin
SpinBox {
id: fontSizeSpin
from: 20
to: 150
stepSize: 2
@@ -35,12 +34,8 @@ SettingsBasePage {
}
}
Label {
text: KI18n.i18nc("@label:spinbox", "Outline size")
Layout.alignment: Qt.AlignRight
}
SpinBox {
Kirigami.FormData.label: KI18n.i18nc("@label:spinbox", "Outline size")
from: 0
to: 10
value: QtPotatoSettings.subtitleOutlineSize
+89 -59
View File
@@ -13,44 +13,73 @@ SettingsBasePage {
required property TranslationService translator
ColumnLayout {
spacing: Kirigami.Units.largeSpacing
Label {
text: KI18n.i18nc("@info", "Use an OpenAI-compatible API to translate subtitles. Tracks are translated in batches and saved for reuse.")
wrapMode: Text.WordWrap
Layout.preferredWidth: form.implicitWidth
Layout.alignment: Qt.AlignHCenter
}
Kirigami.InlineMessage {
Layout.fillWidth: true
Layout.preferredWidth: form.implicitWidth
Layout.alignment: Qt.AlignHCenter
type: Kirigami.MessageType.Error
text: root.translator.errorText || ApiKeyStore.error
text: root.translator.errorText
visible: text.length > 0
showCloseButton: true
onVisibleChanged: if (!visible) root.translator.clearError()
}
GridLayout {
columns: 2
Label {
text: KI18n.i18nc("@label:textbox", "API base URL")
Layout.alignment: Qt.AlignRight
}
Kirigami.FormLayout {
id: form
TextField {
Kirigami.FormData.label: KI18n.i18nc("@label:textbox", "API base URL")
id: apiUrlField
// Keep an invalid draft in the field; only valid URLs reach KConfig.
property bool edited: false
readonly property bool valid: /^https?:\/\/(?:\[[0-9a-f:.]+\]|[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*\.?)(?::[0-9]+)?(?:[/?#][^\s]*)?$/i.test(text.trim())
function saveUrl() {
if (valid) {
QtPotatoSettings.apiBaseUrl = text.trim()
QtPotatoSettings.save()
}
}
placeholderText: "https://example.com/v1"
text: QtPotatoSettings.apiBaseUrl
inputMethodHints: Qt.ImhUrlCharactersOnly | Qt.ImhNoAutoUppercase
Layout.fillWidth: true
onTextEdited: QtPotatoSettings.apiBaseUrl = text.trim()
onEditingFinished: QtPotatoSettings.save()
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
onTextEdited: edited = true
onEditingFinished: saveUrl()
}
Label {
text: KI18n.i18nc("@label:textbox", "API key")
Layout.alignment: Qt.AlignRight
Kirigami.InlineMessage {
Layout.fillWidth: true
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
type: Kirigami.MessageType.Error
text: KI18n.i18nc("@info", "Enter a valid API base URL with http:// or https:// and a host name.")
visible: !apiUrlField.valid && (apiUrlField.edited || apiUrlField.text.length > 0)
}
RowLayout {
spacing: Kirigami.Units.smallSpacing
Layout.fillWidth: true
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
Kirigami.FormData.label: KI18n.i18nc("@label:textbox", "API key")
Kirigami.FormData.buddyFor: apiKeyField
Kirigami.PasswordField {
id: apiKeyField
enabled: !ApiKeyStore.busy
placeholderText: ApiKeyStore.hasKey
? KI18n.i18nc("@info:placeholder", "Saved in the wallet. Type a new key to replace it.")
: KI18n.i18nc("@info:placeholder", "Not set")
Layout.fillWidth: true
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
onEditingFinished: {
if (text.trim().length > 0) {
ApiKeyStore.setKey(text)
@@ -61,6 +90,7 @@ SettingsBasePage {
Button {
visible: ApiKeyStore.hasKey
enabled: !ApiKeyStore.busy
icon.name: "edit-delete-remove"
text: KI18n.i18nc("@action:button", "Remove")
onClicked: ApiKeyStore.setKey("")
@@ -71,12 +101,26 @@ SettingsBasePage {
}
}
Label {
text: KI18n.i18nc("@label:listbox", "Model")
Layout.alignment: Qt.AlignRight
Kirigami.InlineMessage {
Layout.fillWidth: true
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
type: Kirigami.MessageType.Error
text: ApiKeyStore.error
visible: text.length > 0
actions: Kirigami.Action {
text: KI18n.i18nc("@action:button", "Retry")
icon.name: "view-refresh"
enabled: !ApiKeyStore.busy
onTriggered: ApiKeyStore.retry()
}
}
RowLayout {
spacing: Kirigami.Units.smallSpacing
Layout.fillWidth: true
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
Kirigami.FormData.label: KI18n.i18nc("@label:listbox", "Model")
Kirigami.FormData.buddyFor: modelCombo
ComboBox {
id: modelCombo
@@ -95,6 +139,7 @@ SettingsBasePage {
editable: true
Layout.fillWidth: true
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
onEditTextChanged: if (!updatingList) QtPotatoSettings.model = editText.trim()
onActivated: QtPotatoSettings.save()
Component.onCompleted: showModels()
@@ -112,8 +157,11 @@ SettingsBasePage {
text: root.translator.fetchingModels
? KI18n.i18nc("@action:button", "Loading…")
: KI18n.i18nc("@action:button", "Load Models")
enabled: !root.translator.fetchingModels
onClicked: root.translator.fetchModels()
enabled: apiUrlField.valid && !root.translator.fetchingModels
onClicked: {
apiUrlField.saveUrl()
root.translator.fetchModels()
}
ToolTip.text: KI18n.i18nc("@info:tooltip", "Ask the API which models it offers")
ToolTip.visible: hovered
@@ -121,11 +169,6 @@ SettingsBasePage {
}
}
Item {
Layout.preferredWidth: 1
visible: modelCountLabel.visible
}
Label {
id: modelCountLabel
visible: root.translator.availableModels.length > 0
@@ -133,26 +176,20 @@ SettingsBasePage {
opacity: 0.7
}
Label {
text: KI18n.i18nc("@label:textbox", "Translate into")
Layout.alignment: Qt.AlignRight
}
TextField {
Kirigami.FormData.label: KI18n.i18nc("@label:textbox", "Translate into")
text: QtPotatoSettings.targetLanguage
Layout.fillWidth: true
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
onTextEdited: QtPotatoSettings.targetLanguage = text.trim()
onEditingFinished: QtPotatoSettings.save()
}
Label {
text: KI18n.i18nc("@label:listbox", "Preset")
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
}
ComboBox {
Kirigami.FormData.label: KI18n.i18nc("@label:listbox", "Preset")
id: presetCombo
Layout.fillWidth: true
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
model: root.translator.translationPresets
textRole: "name"
valueRole: "id"
@@ -163,46 +200,49 @@ SettingsBasePage {
}
}
Item { Layout.preferredWidth: 1 }
Label {
text: presetCombo.currentIndex >= 0 ? presetCombo.model[presetCombo.currentIndex].description : ""
wrapMode: Text.WordWrap
opacity: 0.7
font: Kirigami.Theme.smallFont
Layout.fillWidth: true
}
Label {
text: KI18n.i18nc("@label:textbox", "Additional instructions")
Layout.alignment: Qt.AlignRight | Qt.AlignBaseline
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
}
TextArea {
Kirigami.FormData.label: KI18n.i18nc("@label:textbox", "Additional instructions")
text: QtPotatoSettings.customInstructions
placeholderText: KI18n.i18nc("@info:placeholder", "e.g. Translate 'Young Master' as 'Thiếu gia'. Use 'ta/ngươi' between enemies.")
wrapMode: TextArea.Wrap
Layout.fillWidth: true
Layout.alignment: Qt.AlignBaseline
Layout.preferredHeight: Kirigami.Units.gridUnit * 4
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
Kirigami.FormData.labelAlignment: Qt.AlignTop
implicitHeight: Math.max(contentHeight + topPadding + bottomPadding, Kirigami.Units.gridUnit * 4)
// TextArea has no textEdited before Qt 6.9.
onTextChanged: QtPotatoSettings.customInstructions = text
onEditingFinished: QtPotatoSettings.save()
}
CheckBox {
text: KI18n.i18nc("@option:check", "Build a glossary automatically before translating")
Switch {
text: KI18n.i18nc("@option:check", "Build glossary automatically")
checked: QtPotatoSettings.autoBuildGlossary
Layout.columnSpan: 2
onToggled: { QtPotatoSettings.autoBuildGlossary = checked; QtPotatoSettings.save() }
onClicked: {
QtPotatoSettings.autoBuildGlossary = checked
QtPotatoSettings.save()
}
}
Label {
text: KI18n.i18nc("@label:spinbox", "Lines per request")
Layout.alignment: Qt.AlignRight
text: KI18n.i18nc("@info", "Collect names and terms before translating.")
wrapMode: Text.WordWrap
font: Kirigami.Theme.smallFont
color: Kirigami.Theme.disabledTextColor
Layout.fillWidth: true
Layout.preferredWidth: Kirigami.Units.gridUnit * 19
}
SpinBox {
Kirigami.FormData.label: KI18n.i18nc("@label:spinbox", "Lines per request")
from: 5
to: 200
stepSize: 5
@@ -212,16 +252,6 @@ SettingsBasePage {
QtPotatoSettings.save()
}
}
Item { Layout.preferredWidth: 1 }
Label {
text: KI18n.i18nc("@info", "Works with any OpenAI-compatible API. The whole subtitle track is translated in batches before it is shown, and the result is kept so the same track is never translated twice.")
wrapMode: Text.WordWrap
opacity: 0.7
Layout.fillWidth: true
Layout.topMargin: Kirigami.Units.largeSpacing
}
}
}
}