Files
bbedward ccbf1d38ad widgets: bump qml-common, rename Dank* prefixed widgets to D, add
deprecation notice to plugin compatibility shims

- When qml-common became a thing, we left qs.Widgets shims in place for
  plugin compatibility
- It's annoying to need to maintain them when qml-common has any change,
  add a warning so we can safely deprecate them in the future
- One shot rename the common stuff to D to make it shorter and nicer to
  write
2026-10-05 16:47:19 -04:00

200 lines
7.3 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import qs.Common
import qs.Services
import qs.DCommon.Widgets
import qs.Modules.Settings.Widgets
FocusScope {
id: root
property string registryError: ""
property bool registryBusy: false
focus: true
function refreshRegistries() {
if (!DMSService.dmsAvailable || DMSService.apiVersion < 29)
return;
registryBusy = true;
registryError = "";
DMSService.listRegistries(response => {
registryBusy = false;
registryError = response.error || "";
});
}
Component.onCompleted: {
if (DMSService.dmsAvailable && DMSService.apiVersion >= 29)
root.refreshRegistries();
}
Connections {
target: DMSService
function onDmsAvailableChanged() {
if (DMSService.dmsAvailable && DMSService.apiVersion >= 29)
root.refreshRegistries();
}
}
SettingsPage {
id: mainColumn
SettingsCard {
iconName: "folder"
title: I18n.tr("Directory", "plugin settings card title, folder where plugins are placed")
settingKey: "pluginDirectory"
tags: ["plugins", "directory", "folder", "path"]
SettingsRow {
body: StyledText {
text: PluginService.pluginDirectory
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
isMonospace: true
width: parent.width
elide: Text.ElideMiddle
horizontalAlignment: Text.AlignLeft
}
}
SettingsRow {
body: StyledText {
text: I18n.tr("Place plugin directories here. Each plugin should have a plugin.json manifest file.")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
horizontalAlignment: Text.AlignLeft
}
}
Flow {
width: parent.width
spacing: Theme.spacingS
DButton {
text: PluginService.pluginDirectoryExists ? I18n.tr("Open folder") : I18n.tr("Create folder")
iconName: PluginService.pluginDirectoryExists ? "folder_open" : "create_new_folder"
maximumWidth: parent.width
wrapText: true
onClicked: {
if (PluginService.pluginDirectoryExists) {
PluginService.openPluginDirectory();
return;
}
PluginService.createPluginDirectory();
}
}
DButton {
text: I18n.tr("Scan", "verb, button that scans for plugins, wifi networks or bluetooth devices")
iconName: "refresh"
backgroundColor: Theme.secondaryContainer
textColor: Theme.onSecondaryContainer
maximumWidth: parent.width
wrapText: true
enabled: !DMSService.checkingPluginUpdates
onClicked: {
PluginService.scanPlugins();
if (DMSService.dmsAvailable && DMSService.apiVersion >= 8)
DMSService.listInstalled(undefined, true);
}
}
}
}
SettingsCard {
iconName: "cloud_download"
title: I18n.tr("Registries", "plugin settings card title, plugin registry sources")
settingKey: "pluginRegistries"
tags: ["plugins", "registry", "registries", "sources", "git", "themes"]
visible: DMSService.dmsAvailable && DMSService.apiVersion >= 29
SettingsRow {
body: StyledText {
text: I18n.tr("Sources for plugins and themes. Registries are git repositories with a plugins/ or themes/ directory.")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
width: parent.width
horizontalAlignment: Text.AlignLeft
}
}
SettingsRow {
visible: root.registryError !== ""
title: I18n.tr("Error")
subtitle: root.registryError
subtitleColor: Theme.error
DButton {
text: I18n.tr("Retry", "retry failed action button")
enabled: !root.registryBusy
onClicked: root.refreshRegistries()
}
}
Repeater {
model: DMSService.registries
SettingsRow {
id: registryRow
required property var modelData
title: modelData.name
subtitle: modelData.url
trailingBadge: modelData.official ? I18n.tr("official") : ""
DActionButton {
anchors.verticalCenter: parent.verticalCenter
iconName: "delete"
iconColor: Theme.error
Accessible.name: I18n.tr("Remove")
visible: !registryRow.modelData.official
enabled: !root.registryBusy
onClicked: {
root.registryBusy = true;
root.registryError = "";
DMSService.removeRegistry(registryRow.modelData.name, response => {
root.registryBusy = false;
root.registryError = response.error || "";
});
}
}
}
}
SettingsTextFieldRow {
id: registryNameField
leftIconName: "badge"
text: I18n.tr("Name")
}
SettingsTextFieldRow {
id: registryUrlField
leftIconName: "link"
text: I18n.tr("URL", "Plugin registry repository address")
placeholderText: "https://github.com/user/registry.git"
actions: DButton {
text: I18n.tr("Add")
enabled: !root.registryBusy && registryNameField.value.trim() !== "" && registryUrlField.value.trim() !== ""
onClicked: {
root.registryBusy = true;
root.registryError = "";
DMSService.addRegistry(registryNameField.value.trim(), registryUrlField.value.trim(), response => {
root.registryBusy = false;
if (response.error) {
root.registryError = response.error;
return;
}
registryNameField.value = "";
registryUrlField.value = "";
});
}
}
}
}
}
}