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,175 @@
|
||||
// SPDX-FileCopyrightText: 2026 Tri Vo Khac
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import org.kde.ki18n
|
||||
import org.kde.kirigami as Kirigami
|
||||
|
||||
SettingsBasePage {
|
||||
id: root
|
||||
|
||||
required property TranslationService translator
|
||||
|
||||
ColumnLayout {
|
||||
Kirigami.InlineMessage {
|
||||
Layout.fillWidth: true
|
||||
type: Kirigami.MessageType.Error
|
||||
text: root.translator.errorText || ApiKeyStore.error
|
||||
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
|
||||
}
|
||||
|
||||
TextField {
|
||||
placeholderText: "https://example.com/v1"
|
||||
text: QtPotatoSettings.apiBaseUrl
|
||||
inputMethodHints: Qt.ImhUrlCharactersOnly | Qt.ImhNoAutoUppercase
|
||||
Layout.fillWidth: true
|
||||
onTextEdited: QtPotatoSettings.apiBaseUrl = text.trim()
|
||||
onEditingFinished: QtPotatoSettings.save()
|
||||
}
|
||||
|
||||
Label {
|
||||
text: KI18n.i18nc("@label:textbox", "API key")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Kirigami.PasswordField {
|
||||
id: apiKeyField
|
||||
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
|
||||
onEditingFinished: {
|
||||
if (text.trim().length > 0) {
|
||||
ApiKeyStore.setKey(text)
|
||||
text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
visible: ApiKeyStore.hasKey
|
||||
icon.name: "edit-delete-remove"
|
||||
text: KI18n.i18nc("@action:button", "Remove")
|
||||
onClicked: ApiKeyStore.setKey("")
|
||||
|
||||
ToolTip.text: KI18n.i18nc("@info:tooltip", "Remove the saved API key from the wallet")
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: KI18n.i18nc("@label:listbox", "Model")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
ComboBox {
|
||||
id: modelCombo
|
||||
|
||||
// Swapping the list makes the combo box jump to its first entry; that
|
||||
// must not overwrite the model the user chose.
|
||||
property bool updatingList: false
|
||||
|
||||
function showModels() {
|
||||
const chosen = QtPotatoSettings.model
|
||||
updatingList = true
|
||||
model = root.translator.availableModels
|
||||
currentIndex = root.translator.availableModels.indexOf(chosen)
|
||||
editText = chosen
|
||||
updatingList = false
|
||||
}
|
||||
|
||||
editable: true
|
||||
Layout.fillWidth: true
|
||||
onEditTextChanged: if (!updatingList) QtPotatoSettings.model = editText.trim()
|
||||
onActivated: QtPotatoSettings.save()
|
||||
Component.onCompleted: showModels()
|
||||
|
||||
Connections {
|
||||
target: root.translator
|
||||
function onAvailableModelsChanged() {
|
||||
modelCombo.showModels()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
icon.name: "view-refresh"
|
||||
text: root.translator.fetchingModels
|
||||
? KI18n.i18nc("@action:button", "Loading…")
|
||||
: KI18n.i18nc("@action:button", "Load Models")
|
||||
enabled: !root.translator.fetchingModels
|
||||
onClicked: root.translator.fetchModels()
|
||||
|
||||
ToolTip.text: KI18n.i18nc("@info:tooltip", "Ask the API which models it offers")
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: 1
|
||||
visible: modelCountLabel.visible
|
||||
}
|
||||
|
||||
Label {
|
||||
id: modelCountLabel
|
||||
visible: root.translator.availableModels.length > 0
|
||||
text: KI18n.i18ncp("@info", "%1 model available", "%1 models available", root.translator.availableModels.length)
|
||||
opacity: 0.7
|
||||
}
|
||||
|
||||
Label {
|
||||
text: KI18n.i18nc("@label:textbox", "Translate into")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
TextField {
|
||||
text: QtPotatoSettings.targetLanguage
|
||||
Layout.fillWidth: true
|
||||
onTextEdited: QtPotatoSettings.targetLanguage = text.trim()
|
||||
onEditingFinished: QtPotatoSettings.save()
|
||||
}
|
||||
|
||||
Label {
|
||||
text: KI18n.i18nc("@label:spinbox", "Lines per request")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
SpinBox {
|
||||
from: 5
|
||||
to: 200
|
||||
stepSize: 5
|
||||
value: QtPotatoSettings.batchSize
|
||||
onValueModified: {
|
||||
QtPotatoSettings.batchSize = value
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user