mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-29 14:37:47 -04:00
732 lines
33 KiB
QML
732 lines
33 KiB
QML
import QtQuick
|
|
import qs.Common
|
|
import qs.Services
|
|
import qs.DCommon.Widgets
|
|
import qs.Modules.Settings.Widgets
|
|
|
|
Column {
|
|
id: root
|
|
|
|
property var parentModal: null
|
|
readonly property bool followsSurfaces: SettingsData.floatingWindowSyncGlobal ?? true
|
|
readonly property bool borderEnabled: SettingsData.blurBorderEnabled ?? false
|
|
readonly property bool layerOutlineEnabled: (SettingsData.blurLayerOutlineOpacity ?? 0) > 0
|
|
readonly property string windowRadiusKey: CompositorService.supportsLayoutConfig ? CompositorService.configKey + "LayoutRadiusOverride" : ""
|
|
|
|
width: parent?.width ?? 0
|
|
spacing: Theme.spacingL
|
|
|
|
Component.onCompleted: {
|
|
BlurService.probe();
|
|
CompositorService.refreshDmsWindowFloatingRule();
|
|
}
|
|
|
|
ConfigInclude {
|
|
id: windowRulesInclude
|
|
includeKind: "windowrules"
|
|
procTag: "windowrules-include-theme"
|
|
onFixed: {
|
|
if (CompositorService.isMango)
|
|
MangoService.reloadConfig();
|
|
CompositorService.seedDmsWindowFloatingRule();
|
|
}
|
|
}
|
|
|
|
readonly property var opacityTargets: {
|
|
SettingsData.barConfigs;
|
|
SettingsData.dockConfigs;
|
|
const frameBarId = SettingsData.frameEnabled ? SettingsData.frameBarConfig?.id : undefined;
|
|
const bars = SettingsData.barConfigs.filter(config => !SettingsData.isDotBarConfig(config)).map(config => ({
|
|
key: "bar:" + config.id,
|
|
kind: "bar",
|
|
id: config.id,
|
|
name: config.name || config.id,
|
|
enabled: config.enabled !== false,
|
|
override: config.followInterfaceStyle === false,
|
|
transparency: config.transparency ?? 1,
|
|
frame: config.id === frameBarId
|
|
}));
|
|
const docks = SettingsData.dockConfigs.map(config => ({
|
|
key: "dock:" + config.id,
|
|
kind: "dock",
|
|
id: config.id,
|
|
name: config.name,
|
|
enabled: config.enabled !== false,
|
|
override: config.followInterfaceStyle === false,
|
|
transparency: config.transparency ?? 1,
|
|
overlay: config.useOverlayLayer ?? false
|
|
}));
|
|
return bars.concat(docks);
|
|
}
|
|
|
|
function setOpacityOverride(target, patch) {
|
|
if (target.kind === "bar") {
|
|
SettingsData.updateBarConfig(target.id, patch);
|
|
return;
|
|
}
|
|
SettingsData.updateDockConfig(target.id, patch);
|
|
}
|
|
|
|
function openSurfaceBorderColorPicker() {
|
|
PopoutService.colorPickerModal.selectedColor = SettingsData.blurBorderCustomColor ?? "#ffffff";
|
|
PopoutService.colorPickerModal.pickerTitle = I18n.tr("Surface Border Color");
|
|
PopoutService.colorPickerModal.onColorSelectedCallback = function (color) {
|
|
SettingsData.set("blurBorderCustomColor", color.toString());
|
|
};
|
|
PopoutService.colorPickerModal.open();
|
|
}
|
|
|
|
SettingsCard {
|
|
tab: "theme"
|
|
title: I18n.tr("Appearance")
|
|
settingKey: "surfaceAppearance"
|
|
|
|
SettingsButtonGroupRow {
|
|
tab: "theme"
|
|
tags: ["style", "classic", "expressive", "pill", "round", "shape", "morph", "corners", "buttons"]
|
|
settingKey: "interfaceStyle"
|
|
text: I18n.tr("Style")
|
|
model: [I18n.tr("Expressive"), I18n.tr("Classic", "interface style option with one corner radius on controls and no shape change on press")]
|
|
values: ["expressive", "classic"]
|
|
value: SettingsData.interfaceStyle
|
|
fallbackValue: "expressive"
|
|
onValueSelected: value => SettingsData.set("interfaceStyle", value)
|
|
}
|
|
|
|
SettingsButtonGroupRow {
|
|
tab: "theme"
|
|
tags: ["density", "compact", "dense", "spacious", "comfortable", "spacing", "padding", "rows", "menus", "control center", "bar", "dock", "island", "frame", "size"]
|
|
settingKey: "density"
|
|
text: I18n.tr("Interface density", "interface density setting label")
|
|
model: [I18n.tr("Spacious", "interface density option with the most room between items"), I18n.tr("Comfortable", "interface density option with the default spacing"), I18n.tr("Compact", "interface density option fitting the most items on screen"), I18n.tr("Dense", "interface density option denser than compact for small text and tight rows")]
|
|
values: ["spacious", "comfortable", "compact", "dense"]
|
|
value: SettingsData.density
|
|
fallbackValue: "comfortable"
|
|
onValueSelected: value => SettingsData.set("density", value)
|
|
}
|
|
|
|
SettingsSliderRow {
|
|
tab: "theme"
|
|
tags: ["classic", "divider", "dividers", "lines", "rows", "sections", "sidebar", "outline"]
|
|
settingKey: "sectionDividerOpacity"
|
|
visible: SettingsData.interfaceStyle === "classic"
|
|
text: I18n.tr("Section dividers", "classic interface style: strength of the lines between rows of a settings section")
|
|
minimumLabel: I18n.tr("Off")
|
|
minimum: 0
|
|
maximum: 40
|
|
step: 1
|
|
value: Math.round((SettingsData.sectionDividerOpacity ?? 0) * 100)
|
|
onSliderValueChanged: newValue => SettingsData.set("sectionDividerOpacity", newValue / 100)
|
|
}
|
|
}
|
|
|
|
SettingsCard {
|
|
tab: "theme"
|
|
tags: ["surface", "popup", "transparency", "opacity", "modal", "corner", "radius", "blur", "background", "glass", "frosted", "shadow", "elevation", "foreground", "layers"]
|
|
title: I18n.tr("Surfaces", "plural noun, settings title, shell surfaces like popouts and modals")
|
|
settingKey: "surfaceStyling"
|
|
|
|
SettingsSliderRow {
|
|
tab: "theme"
|
|
tags: ["surface", "popup", "transparency", "opacity", "modal"]
|
|
settingKey: "popupTransparency"
|
|
text: I18n.tr("Opacity")
|
|
value: Math.round(SettingsData.popupTransparency * 100)
|
|
minimum: 0
|
|
maximum: 100
|
|
onSliderValueChanged: newValue => SettingsData.set("popupTransparency", newValue / 100)
|
|
}
|
|
|
|
SettingsToggleSliderRow {
|
|
tab: "theme"
|
|
tags: ["foreground", "layers", "opacity", "transparency", "contrast", "cards", "surface", "blur", "glass", "frosted"]
|
|
settingKey: "blurForegroundLayers"
|
|
valueKeys: ["foregroundLayerTransparency"]
|
|
text: I18n.tr("Foreground layers")
|
|
checked: SettingsData.blurForegroundLayers ?? true
|
|
value: Math.round((SettingsData.foregroundLayerTransparency ?? 1.0) * 100)
|
|
minimum: 0
|
|
maximum: 100
|
|
onToggled: checked => SettingsData.set("blurForegroundLayers", checked)
|
|
onSliderValueChanged: newValue => SettingsData.set("foregroundLayerTransparency", newValue / 100)
|
|
}
|
|
|
|
SettingsToggleSliderRow {
|
|
tab: "theme"
|
|
tags: ["foreground", "layers", "outline", "border", "opacity", "cards", "pills", "widgets", "notifications", "control center"]
|
|
settingKey: "blurLayerOutline"
|
|
text: I18n.tr("Layer outline")
|
|
description: I18n.tr("Faint edge on cards, pills and widgets", "surface layer outline toggle description")
|
|
checked: root.layerOutlineEnabled
|
|
value: Math.round((SettingsData.blurLayerOutlineOpacity ?? 0) * 100)
|
|
minimum: 1
|
|
maximum: 40
|
|
onToggled: checked => SettingsData.set("blurLayerOutlineOpacity", checked ? 0.12 : 0)
|
|
onSliderValueChanged: newValue => SettingsData.set("blurLayerOutlineOpacity", newValue / 100)
|
|
}
|
|
|
|
SettingsToggleSliderRow {
|
|
tab: "theme"
|
|
tags: ["surface", "popup", "modal", "border", "outline", "edge", "color", "opacity"]
|
|
settingKey: "blurBorderEnabled"
|
|
accessoryKeys: ["blurBorderColor", "blurBorderCustomColor"]
|
|
valueKeys: ["blurBorderOpacity"]
|
|
text: I18n.tr("Border")
|
|
description: I18n.tr("Edge around popups and modals", "surface border toggle description")
|
|
checked: root.borderEnabled
|
|
value: Math.round((SettingsData.blurBorderOpacity ?? 0.35) * 100)
|
|
minimum: 0
|
|
maximum: 100
|
|
onToggled: checked => SettingsData.set("blurBorderEnabled", checked)
|
|
onSliderValueChanged: newValue => SettingsData.set("blurBorderOpacity", newValue / 100)
|
|
|
|
accessory: DDropdown {
|
|
id: borderColorMenu
|
|
visible: root.borderEnabled
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: I18n.tr("Border color")
|
|
showLabel: false
|
|
downKeyOpens: false
|
|
triggerHeight: Theme.switchTrackHeight
|
|
alignPopupRight: !I18n.isRtl
|
|
options: [I18n.tr("Outline", "surface border color"), I18n.tr("Primary", "surface border color"), I18n.tr("Secondary", "surface border color"), I18n.tr("Text Color", "surface border color"), I18n.tr("Custom", "surface border color")]
|
|
optionColorMap: ({
|
|
[I18n.tr("Outline", "surface border color")]: Theme.outline,
|
|
[I18n.tr("Primary", "surface border color")]: Theme.primary,
|
|
[I18n.tr("Secondary", "surface border color")]: Theme.secondary,
|
|
[I18n.tr("Text Color", "surface border color")]: Theme.surfaceText,
|
|
[I18n.tr("Custom", "surface border color")]: SettingsData.blurBorderCustomColor ?? "#ffffff"
|
|
})
|
|
currentValue: {
|
|
switch (SettingsData.blurBorderColor) {
|
|
case "primary":
|
|
return I18n.tr("Primary", "surface border color");
|
|
case "secondary":
|
|
return I18n.tr("Secondary", "surface border color");
|
|
case "surfaceText":
|
|
return I18n.tr("Text Color", "surface border color");
|
|
case "custom":
|
|
return I18n.tr("Custom", "surface border color");
|
|
default:
|
|
return I18n.tr("Outline", "surface border color");
|
|
}
|
|
}
|
|
onValueChanged: value => {
|
|
switch (value) {
|
|
case I18n.tr("Primary", "surface border color"):
|
|
SettingsData.set("blurBorderColor", "primary");
|
|
return;
|
|
case I18n.tr("Secondary", "surface border color"):
|
|
SettingsData.set("blurBorderColor", "secondary");
|
|
return;
|
|
case I18n.tr("Text Color", "surface border color"):
|
|
SettingsData.set("blurBorderColor", "surfaceText");
|
|
return;
|
|
case I18n.tr("Custom", "surface border color"):
|
|
SettingsData.set("blurBorderColor", "custom");
|
|
root.openSurfaceBorderColorPicker();
|
|
return;
|
|
}
|
|
SettingsData.set("blurBorderColor", "outline");
|
|
}
|
|
}
|
|
}
|
|
|
|
SettingsControlledBy {
|
|
visible: SettingsData.connectedFrameModeActive && root.borderEnabled
|
|
parentModal: root.parentModal
|
|
section: "frameBorder"
|
|
settingLabel: I18n.tr("Border")
|
|
reason: I18n.tr("Managed by Frame in Connected Mode")
|
|
}
|
|
|
|
SettingsToggleSliderRow {
|
|
tab: "theme"
|
|
tags: ["blur", "background", "transparency", "glass", "frosted", "strength", "radius", "size", "passes", "reach"]
|
|
settingKey: "blurEnabled"
|
|
valueKeys: ["blurStrength"]
|
|
text: I18n.tr("Background blur")
|
|
visible: BlurService.available
|
|
checked: SettingsData.blurEnabled ?? false
|
|
value: BlurService.strength
|
|
minimum: 16
|
|
maximum: 160
|
|
unit: "px"
|
|
onToggled: checked => {
|
|
SettingsData.set("blurEnabled", checked);
|
|
if (!checked || SettingsData.blurBorderSeeded)
|
|
return;
|
|
SettingsData.set("blurBorderSeeded", true);
|
|
SettingsData.set("blurBorderEnabled", true);
|
|
SettingsSearchService.navigateToSection("blurBorderEnabled");
|
|
}
|
|
onSliderValueChanged: newValue => SettingsData.set("blurStrength", newValue)
|
|
}
|
|
|
|
SettingsNoteRow {
|
|
visible: BlurService.probed && !BlurService.available
|
|
noteIconName: "info"
|
|
tint: Theme.surfaceVariantText
|
|
tintBackground: Theme.surfaceVariantAlpha
|
|
text: I18n.tr("Your compositor does not support ext-background blur")
|
|
}
|
|
|
|
SettingsNavRow {
|
|
tab: "theme"
|
|
tags: ["blur", "xray", "compositor", "layout"]
|
|
settingKey: "blurXrayLink"
|
|
visible: BlurService.available && (CompositorService.isNiri || CompositorService.isHyprland)
|
|
title: I18n.tr("Xray options are in Compositor → Layout")
|
|
onClicked: keyboard => root.parentModal?.navigateTo("compositor_layout", keyboard)
|
|
}
|
|
|
|
SettingsSplitRow {
|
|
tab: "theme"
|
|
tags: ["elevation", "shadow", "lift", "m3", "material"]
|
|
settingKey: "m3ElevationLink"
|
|
title: I18n.tr("Shadows")
|
|
subtitle: SettingsTabs.page("surface_shadows")?.hint ?? ""
|
|
resetKeys: ["m3ElevationEnabled"]
|
|
checked: SettingsData.m3ElevationEnabled ?? true
|
|
onNavigated: keyboard => root.parentModal?.navigateTo("surface_shadows", keyboard)
|
|
onToggled: checked => SettingsData.set("m3ElevationEnabled", checked)
|
|
}
|
|
}
|
|
|
|
SettingsCard {
|
|
tab: "theme"
|
|
tags: ["corner", "radius", "rounded", "square", "fixed", "material", "shape", "window"]
|
|
title: I18n.tr("Corners")
|
|
settingKey: "surfaceCorners"
|
|
|
|
SettingsButtonGroupRow {
|
|
tab: "theme"
|
|
tags: ["corner", "radius", "rounded", "square", "fixed", "material", "shape"]
|
|
settingKey: "radiusMode"
|
|
text: I18n.tr("Corner style")
|
|
model: [I18n.tr("Material", "corner style: Material shape scale with a strength slider"), I18n.tr("Fixed", "corner style: one radius for every corner")]
|
|
currentIndex: SettingsData.radiusMode === "fixed" ? 1 : 0
|
|
onSelectionChanged: (index, selected) => {
|
|
if (selected)
|
|
SettingsData.set("radiusMode", index === 1 ? "fixed" : "scale");
|
|
}
|
|
}
|
|
|
|
SettingsSliderRow {
|
|
tab: "theme"
|
|
tags: ["corner", "radius", "rounded", "square", "strength"]
|
|
settingKey: "radiusStrength"
|
|
visible: SettingsData.radiusMode !== "fixed"
|
|
text: I18n.tr("Radius strength", "global component corner rounding")
|
|
description: I18n.tr("50 uses Material shapes. Lower values reduce rounding; higher values increase it.", "radius strength slider description")
|
|
minimumLabel: I18n.tr("Square")
|
|
value: SettingsData.radiusStrength
|
|
minimum: 0
|
|
maximum: 100
|
|
unit: ""
|
|
onSliderValueChanged: newValue => SettingsData.set("radiusStrength", newValue)
|
|
}
|
|
|
|
SettingsSliderRow {
|
|
tab: "theme"
|
|
tags: ["corner", "radius", "rounded", "square", "fixed"]
|
|
settingKey: "fixedRadius"
|
|
visible: SettingsData.radiusMode === "fixed"
|
|
text: I18n.tr("Corner radius")
|
|
minimumLabel: I18n.tr("Square")
|
|
value: SettingsData.fixedRadius
|
|
minimum: 0
|
|
maximum: 32
|
|
unit: "px"
|
|
onSliderValueChanged: newValue => SettingsData.set("fixedRadius", newValue)
|
|
}
|
|
|
|
SettingsToggleSliderRow {
|
|
tab: "theme"
|
|
tags: ["window", "corner", "radius", "match", "follow", "link", "strength", "rounded", "popout", "menu", "modal", "compositor", "niri", "hyprland", "mango"]
|
|
settingKey: "windowRadius"
|
|
text: I18n.tr("Override window radius", "toggle: stop the window radius following the corner style setting")
|
|
visible: root.windowRadiusKey !== ""
|
|
checked: Theme.compositorRadiusOverride >= 0
|
|
value: Theme.windowRadius
|
|
minimum: 0
|
|
maximum: 64
|
|
unit: "px"
|
|
onToggled: checked => SettingsData.set(root.windowRadiusKey, checked ? Math.round(Theme.windowRadius) : -1)
|
|
onSliderDragFinished: finalValue => SettingsData.set(root.windowRadiusKey, finalValue)
|
|
}
|
|
}
|
|
|
|
Repeater {
|
|
model: [
|
|
{
|
|
kind: "bar",
|
|
title: I18n.tr("Bars"),
|
|
settingKey: "barOpacityOverrides"
|
|
},
|
|
{
|
|
kind: "dock",
|
|
title: I18n.tr("Docks"),
|
|
settingKey: "dockOpacityOverrides"
|
|
}
|
|
]
|
|
|
|
SettingsCard {
|
|
id: targetCard
|
|
|
|
required property var modelData
|
|
readonly property var targets: root.opacityTargets.filter(target => target.kind === modelData.kind)
|
|
readonly property var activeTargets: targets.filter(target => target.enabled)
|
|
readonly property var hiddenTargets: targets.filter(target => !target.enabled)
|
|
// String keys: a config edit must not rebuild the row holding the focused control
|
|
readonly property string activeKeys: activeTargets.map(target => target.key).join("\n")
|
|
readonly property string hiddenKeys: hiddenTargets.map(target => target.key).join("\n")
|
|
property bool showHidden: false
|
|
|
|
tab: "theme"
|
|
tags: ["surface", "opacity", "transparency", modelData.kind, "override"]
|
|
title: modelData.title
|
|
settingKey: modelData.settingKey
|
|
visible: targets.length > 0
|
|
|
|
SettingsControlledBy {
|
|
visible: targetCard.modelData.kind === "dock" && SettingsData.connectedFrameModeActive && targetCard.activeTargets.some(target => !target.overlay)
|
|
parentModal: root.parentModal
|
|
section: "frameSurfaceOpacity"
|
|
settingLabel: I18n.tr("Opacity")
|
|
reason: I18n.tr("Managed by Frame in Connected Mode")
|
|
}
|
|
|
|
Repeater {
|
|
model: targetCard.activeKeys ? targetCard.activeKeys.split("\n") : []
|
|
delegate: opacityTargetRow
|
|
}
|
|
|
|
SettingsRow {
|
|
tab: "theme"
|
|
tags: ["surface", "opacity", "transparency", targetCard.modelData.kind, "hidden", "disabled"]
|
|
title: I18n.tr("Hidden (%1)", "island settings: hidden groups divider, %1 is count").arg(targetCard.hiddenTargets.length)
|
|
iconName: "visibility_off"
|
|
visible: targetCard.hiddenTargets.length > 0
|
|
clickable: true
|
|
onClicked: targetCard.showHidden = !targetCard.showHidden
|
|
|
|
DIcon {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
name: targetCard.showHidden ? "expand_less" : "expand_more"
|
|
size: Theme.iconSize
|
|
color: Theme.onSurfaceVariant
|
|
}
|
|
}
|
|
|
|
Repeater {
|
|
model: targetCard.showHidden && targetCard.hiddenKeys ? targetCard.hiddenKeys.split("\n") : []
|
|
delegate: opacityTargetRow
|
|
}
|
|
}
|
|
}
|
|
|
|
SettingsCard {
|
|
tab: "theme"
|
|
tags: ["floating", "window", "settings", "notepad", "authentication", "polkit", "opacity", "transparency", "foreground", "tile", "tiling", "override"]
|
|
title: I18n.tr("Floating windows")
|
|
settingKey: "floatingWindows"
|
|
|
|
SettingsToggleCard {
|
|
tab: "theme"
|
|
tags: ["floating", "window", "sync", "global", "surface", "opacity", "override"]
|
|
settingKey: "floatingWindowSyncGlobal"
|
|
title: I18n.tr("Override", "verb, toggle to override the global setting for this item")
|
|
checked: !root.followsSurfaces
|
|
onToggled: checked => SettingsData.set("floatingWindowSyncGlobal", !checked)
|
|
|
|
SettingsSliderRow {
|
|
tab: "theme"
|
|
tags: ["floating", "window", "opacity", "transparency", "settings", "notepad", "authentication", "polkit"]
|
|
settingKey: "floatingWindowTransparency"
|
|
text: I18n.tr("Opacity")
|
|
value: Math.round(Theme.floatingWindowTransparency * 100)
|
|
minimum: 0
|
|
maximum: 100
|
|
onSliderValueChanged: newValue => SettingsData.set("floatingWindowTransparency", newValue / 100)
|
|
}
|
|
|
|
SettingsToggleSliderRow {
|
|
tab: "theme"
|
|
tags: ["floating", "window", "foreground", "layers", "opacity", "transparency", "contrast", "cards", "blur", "glass"]
|
|
settingKey: "floatingWindowForegroundLayers"
|
|
valueKeys: ["floatingWindowForegroundTransparency"]
|
|
text: I18n.tr("Foreground layers")
|
|
checked: Theme.floatingWindowForegroundLayers
|
|
value: Math.round(Theme.floatingWindowForegroundTransparency * 100)
|
|
minimum: 0
|
|
maximum: 100
|
|
onToggled: checked => SettingsData.set("floatingWindowForegroundLayers", checked)
|
|
onSliderValueChanged: newValue => SettingsData.set("floatingWindowForegroundTransparency", newValue / 100)
|
|
}
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
tab: "theme"
|
|
tags: ["floating", "window", "title", "bar", "header", "csd", "decoration", "compositor", "kwin", "controls"]
|
|
settingKey: "floatingWindowTitleBars"
|
|
text: I18n.tr("Title bars")
|
|
description: I18n.tr("Off lets the compositor decorate DMS windows. Open windows update when reopened.", "theme floating windows section, title bars toggle description")
|
|
checked: SettingsData.floatingWindowTitleBars
|
|
onToggled: checked => SettingsData.set("floatingWindowTitleBars", checked)
|
|
}
|
|
|
|
SettingsToggleRow {
|
|
tab: "theme"
|
|
tags: ["floating", "window", "tile", "tiling", "compositor", "rule", "niri", "hyprland", "mango"]
|
|
settingKey: "dmsWindowsFloating"
|
|
text: I18n.tr("Open floating")
|
|
description: I18n.tr("Adds a compositor window rule so DMS windows such as Settings open floating", "theme floating windows section, open floating toggle description")
|
|
visible: windowRulesInclude.compositorSupported
|
|
checked: CompositorService.dmsWindowFloatingActive
|
|
modified: !checked
|
|
onToggled: checked => {
|
|
CompositorService.setDmsWindowFloatingRule(checked);
|
|
if (checked)
|
|
windowRulesInclude.check();
|
|
}
|
|
}
|
|
|
|
IncludeSetupBanner {
|
|
include: windowRulesInclude
|
|
visibleCondition: windowRulesInclude.compositorSupported && CompositorService.dmsWindowFloatingActive
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: opacityTargetRow
|
|
|
|
SettingsToggleSliderRow {
|
|
id: overrideRow
|
|
|
|
required property string modelData
|
|
readonly property var target: root.opacityTargets.find(entry => entry.key === modelData) ?? null
|
|
|
|
tab: "theme"
|
|
tags: ["surface", "opacity", "transparency", "bar", "dock", "override"]
|
|
settingKey: "surfaceOpacity_" + modelData.replace(":", "_")
|
|
text: target?.name ?? ""
|
|
description: target?.frame ? I18n.tr("Frame") + " · " + I18n.tr("Override") : I18n.tr("Override")
|
|
checked: target?.override ?? false
|
|
value: Math.round((target?.transparency ?? 1) * 100)
|
|
minimum: 0
|
|
maximum: 100
|
|
modified: target?.override ?? false
|
|
valueModified: (target?.transparency ?? 1) !== 1
|
|
onResetRequested: root.setOpacityOverride(target, {
|
|
followInterfaceStyle: true,
|
|
transparency: 1
|
|
})
|
|
onValueResetRequested: root.setOpacityOverride(target, {
|
|
transparency: 1
|
|
})
|
|
onToggled: checked => root.setOpacityOverride(target, {
|
|
followInterfaceStyle: !checked
|
|
})
|
|
onSliderDragFinished: finalValue => root.setOpacityOverride(target, {
|
|
transparency: finalValue / 100
|
|
})
|
|
}
|
|
}
|
|
|
|
SettingsToggleCard {
|
|
tab: "theme"
|
|
tags: ["focus", "ring", "keyboard", "outline", "highlight"]
|
|
settingKey: "focusRingEnabled"
|
|
iconName: "center_focus_strong"
|
|
title: I18n.tr("Focus ring")
|
|
checked: SettingsData.focusRingEnabled
|
|
onToggled: checked => SettingsData.set("focusRingEnabled", checked)
|
|
|
|
SettingsSliderRow {
|
|
tab: "theme"
|
|
tags: ["focus", "ring", "thickness", "width"]
|
|
settingKey: "focusRingWidth"
|
|
text: I18n.tr("Thickness")
|
|
value: Math.round(SettingsData.focusRingWidth * 10)
|
|
minimum: 10
|
|
maximum: 40
|
|
step: 5
|
|
decimals: 1
|
|
unit: "px"
|
|
onSliderValueChanged: newValue => SettingsData.set("focusRingWidth", newValue / 10)
|
|
}
|
|
|
|
SettingsDropdownRow {
|
|
tab: "theme"
|
|
tags: ["focus", "ring", "color"]
|
|
settingKey: "focusRingColor"
|
|
text: I18n.tr("Color")
|
|
options: [I18n.tr("Primary", "surface border color"), I18n.tr("Secondary", "surface border color"), I18n.tr("Outline", "surface border color"), I18n.tr("Text Color", "surface border color")]
|
|
optionColorMap: ({
|
|
[I18n.tr("Primary", "surface border color")]: Theme.primary,
|
|
[I18n.tr("Secondary", "surface border color")]: Theme.secondary,
|
|
[I18n.tr("Outline", "surface border color")]: Theme.outline,
|
|
[I18n.tr("Text Color", "surface border color")]: Theme.surfaceText
|
|
})
|
|
currentValue: {
|
|
switch (SettingsData.focusRingColor) {
|
|
case "secondary":
|
|
return I18n.tr("Secondary", "surface border color");
|
|
case "outline":
|
|
return I18n.tr("Outline", "surface border color");
|
|
case "surfaceText":
|
|
return I18n.tr("Text Color", "surface border color");
|
|
default:
|
|
return I18n.tr("Primary", "surface border color");
|
|
}
|
|
}
|
|
onValueChanged: value => {
|
|
switch (value) {
|
|
case I18n.tr("Secondary", "surface border color"):
|
|
SettingsData.set("focusRingColor", "secondary");
|
|
return;
|
|
case I18n.tr("Outline", "surface border color"):
|
|
SettingsData.set("focusRingColor", "outline");
|
|
return;
|
|
case I18n.tr("Text Color", "surface border color"):
|
|
SettingsData.set("focusRingColor", "surfaceText");
|
|
return;
|
|
}
|
|
SettingsData.set("focusRingColor", "primary");
|
|
}
|
|
}
|
|
}
|
|
|
|
SettingsToggleCard {
|
|
tab: "theme"
|
|
tags: ["scroll", "scrollbar", "scrollbars", "list", "page"]
|
|
settingKey: "scrollbarsEnabled"
|
|
iconName: "unfold_more"
|
|
title: I18n.tr("Scrollbars", "theme settings toggle, show scrollbars on lists and pages")
|
|
checked: SettingsData.scrollbarsEnabled
|
|
onToggled: checked => SettingsData.set("scrollbarsEnabled", checked)
|
|
}
|
|
|
|
SettingsCard {
|
|
tab: "theme"
|
|
tags: ["button", "color", "accent"]
|
|
title: I18n.tr("Colors")
|
|
settingKey: "surfaceColors"
|
|
|
|
SettingsDropdownRow {
|
|
tab: "theme"
|
|
tags: ["button", "color", "primary", "accent", "action"]
|
|
settingKey: "buttonColorMode"
|
|
text: I18n.tr("Button color")
|
|
options: [I18n.tr("Primary", "button color option"), I18n.tr("Primary Container", "button color option"), I18n.tr("Secondary", "button color option"), I18n.tr("Surface Variant", "button color option")]
|
|
optionColorMap: ({
|
|
[I18n.tr("Primary", "button color option")]: Theme.roleColor("primary"),
|
|
[I18n.tr("Primary Container", "button color option")]: Theme.roleColor("primaryContainer"),
|
|
[I18n.tr("Secondary", "button color option")]: Theme.roleColor("secondary"),
|
|
[I18n.tr("Surface Variant", "button color option")]: Theme.roleColor("surfaceVariant")
|
|
})
|
|
currentValue: {
|
|
switch (SettingsData.buttonColorMode) {
|
|
case "primaryContainer":
|
|
return I18n.tr("Primary Container", "button color option");
|
|
case "secondary":
|
|
return I18n.tr("Secondary", "button color option");
|
|
case "surfaceVariant":
|
|
return I18n.tr("Surface Variant", "button color option");
|
|
default:
|
|
return I18n.tr("Primary", "button color option");
|
|
}
|
|
}
|
|
onValueChanged: value => {
|
|
switch (value) {
|
|
case I18n.tr("Primary Container", "button color option"):
|
|
SettingsData.set("buttonColorMode", "primaryContainer");
|
|
return;
|
|
case I18n.tr("Secondary", "button color option"):
|
|
SettingsData.set("buttonColorMode", "secondary");
|
|
return;
|
|
case I18n.tr("Surface Variant", "button color option"):
|
|
SettingsData.set("buttonColorMode", "surfaceVariant");
|
|
return;
|
|
}
|
|
SettingsData.set("buttonColorMode", "primary");
|
|
}
|
|
}
|
|
|
|
SettingsSliderRow {
|
|
tab: "theme"
|
|
tags: ["container", "accent", "color", "saturation", "tint", "pastel", "primary", "card"]
|
|
settingKey: "containerSaturation"
|
|
text: I18n.tr("Container saturation", "theme setting, saturation of tinted accent containers")
|
|
description: I18n.tr("Tinted cards and badges across the shell", "container saturation setting description")
|
|
value: SettingsData.containerSaturation
|
|
minimum: 0
|
|
maximum: 200
|
|
step: 5
|
|
onSliderValueChanged: newValue => SettingsData.set("containerSaturation", newValue)
|
|
}
|
|
}
|
|
|
|
SettingsCard {
|
|
tab: "theme"
|
|
tags: ["control center", "icon", "scale", "size", "tile"]
|
|
title: I18n.tr("Control Center", "Control Center")
|
|
settingKey: "controlCenterIcons"
|
|
|
|
SettingsDropdownRow {
|
|
tab: "theme"
|
|
tags: ["control", "center", "tile", "button", "color", "active"]
|
|
settingKey: "controlCenterTileColorMode"
|
|
text: I18n.tr("Tile color", "control center tile color dropdown label")
|
|
options: [I18n.tr("Primary", "tile color option"), I18n.tr("Primary Container", "tile color option"), I18n.tr("Secondary", "tile color option"), I18n.tr("Surface Variant", "tile color option")]
|
|
optionColorMap: ({
|
|
[I18n.tr("Primary", "tile color option")]: Theme.roleColor("primary"),
|
|
[I18n.tr("Primary Container", "tile color option")]: Theme.roleColor("primaryContainer"),
|
|
[I18n.tr("Secondary", "tile color option")]: Theme.roleColor("secondary"),
|
|
[I18n.tr("Surface Variant", "tile color option")]: Theme.roleColor("surfaceVariant")
|
|
})
|
|
currentValue: {
|
|
switch (SettingsData.controlCenterTileColorMode) {
|
|
case "primaryContainer":
|
|
return I18n.tr("Primary Container", "tile color option");
|
|
case "secondary":
|
|
return I18n.tr("Secondary", "tile color option");
|
|
case "surfaceVariant":
|
|
return I18n.tr("Surface Variant", "tile color option");
|
|
default:
|
|
return I18n.tr("Primary", "tile color option");
|
|
}
|
|
}
|
|
onValueChanged: value => {
|
|
switch (value) {
|
|
case I18n.tr("Primary Container", "tile color option"):
|
|
SettingsData.set("controlCenterTileColorMode", "primaryContainer");
|
|
return;
|
|
case I18n.tr("Secondary", "tile color option"):
|
|
SettingsData.set("controlCenterTileColorMode", "secondary");
|
|
return;
|
|
case I18n.tr("Surface Variant", "tile color option"):
|
|
SettingsData.set("controlCenterTileColorMode", "surfaceVariant");
|
|
return;
|
|
}
|
|
SettingsData.set("controlCenterTileColorMode", "primary");
|
|
}
|
|
}
|
|
|
|
SettingsSliderRow {
|
|
tab: "theme"
|
|
tags: ["control", "center", "icon", "scale", "size", "tile", "header"]
|
|
settingKey: "controlCenterIconScale"
|
|
text: I18n.tr("Icon scale")
|
|
minimum: 50
|
|
maximum: 150
|
|
step: 5
|
|
unit: ""
|
|
decimals: 2
|
|
value: Math.round(SettingsData.controlCenterIconScale * 100)
|
|
onSliderValueChanged: value => SettingsData.set("controlCenterIconScale", value / 100)
|
|
}
|
|
}
|
|
}
|