1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-18 09:05:24 -04:00

feat(dbar): add workspace & widget color customization options

This commit is contained in:
purian23
2026-06-17 00:02:51 -04:00
parent f26c0af39a
commit 68410e882d
8 changed files with 601 additions and 234 deletions
+7
View File
@@ -164,6 +164,8 @@ Singleton {
property real popupTransparency: 1.0
property real dockTransparency: 1
property string widgetBackgroundColor: "sch"
property string widgetBackgroundCustomColor: "#6750A4"
property real widgetBackgroundCustomStrength: 0.50
property string widgetColorMode: "default"
property string controlCenterTileColorMode: "primary"
property string buttonColorMode: "primary"
@@ -385,11 +387,16 @@ Singleton {
property bool dwlShowAllTags: false
property bool workspaceActiveAppHighlightEnabled: false
property string workspaceColorMode: "default"
property string workspaceFocusedCustomColor: "#6750A4"
property string workspaceOccupiedColorMode: "none"
property string workspaceOccupiedCustomColor: "#625B71"
property string workspaceUnfocusedColorMode: "default"
property string workspaceUnfocusedCustomColor: "#49454E"
property string workspaceUrgentColorMode: "default"
property string workspaceUrgentCustomColor: "#B3261E"
property bool workspaceFocusedBorderEnabled: false
property string workspaceFocusedBorderColor: "primary"
property string workspaceFocusedBorderCustomColor: "#6750A4"
property int workspaceFocusedBorderThickness: 2
property var workspaceNameIcons: ({})
property bool waveProgressEnabled: true
+27 -2
View File
@@ -450,7 +450,9 @@ Singleton {
"primaryText": getMatugenColor("on_primary", "#ffffff"),
"primaryContainer": getMatugenColor("primary_container", "#1976d2"),
"secondary": getMatugenColor("secondary", "#8ab4f8"),
"secondaryContainer": getMatugenColor("secondary_container", getMatugenColor("surface_container_high", "#292b2f")),
"tertiary": getMatugenColor("tertiary", "#efb8c8"),
"tertiaryContainer": getMatugenColor("tertiary_container", getMatugenColor("surface_container_high", "#292b2f")),
"surface": getMatugenColor("surface", "#1a1c1e"),
"surfaceText": getMatugenColor("on_background", "#e3e8ef"),
"surfaceVariant": getMatugenColor("surface_variant", "#44464f"),
@@ -521,7 +523,6 @@ Singleton {
property color primary: currentThemeData.primary
property color primaryText: currentThemeData.primaryText
property color primaryContainer: currentThemeData.primaryContainer
property color secondary: currentThemeData.secondary
property color tertiary: currentThemeData.tertiary || currentThemeData.secondary
property color surface: currentThemeData.surface
@@ -536,6 +537,9 @@ Singleton {
property color surfaceContainer: currentThemeData.surfaceContainer
property color surfaceContainerHigh: currentThemeData.surfaceContainerHigh
property color surfaceContainerHighest: currentThemeData.surfaceContainerHighest || surfaceContainerHigh
property color primaryContainer: currentThemeData.primaryContainer || blend(surfaceContainerHigh, primary, 0.45)
property color secondaryContainer: currentThemeData.secondaryContainer || blend(surfaceContainerHigh, secondary, 0.35)
property color tertiaryContainer: currentThemeData.tertiaryContainer || blend(surfaceContainerHigh, tertiary, 0.35)
property color onSurface: surfaceText
property color onSurfaceVariant: surfaceVariantText
@@ -1430,9 +1434,22 @@ Singleton {
property bool widgetBackgroundHasAlpha: {
const colorMode = typeof SettingsData !== "undefined" ? SettingsData.widgetBackgroundColor : "sch";
return colorMode === "sth";
return colorMode === "sth" || colorMode === "custom";
}
function safeColor(value, fallback) {
try {
if (value === undefined || value === null || value === "")
return fallback;
return Qt.color(value);
} catch (e) {
return fallback;
}
}
readonly property color widgetBackgroundCustomBaseColor: safeColor(typeof SettingsData !== "undefined" ? SettingsData.widgetBackgroundCustomColor : "#6750A4", primaryContainer)
readonly property real widgetBackgroundCustomStrength: Math.max(0, Math.min(1, typeof SettingsData !== "undefined" ? (SettingsData.widgetBackgroundCustomStrength ?? 0.4) : 0.4))
property var widgetBaseBackgroundColor: {
const colorMode = typeof SettingsData !== "undefined" ? SettingsData.widgetBackgroundColor : "sch";
switch (colorMode) {
@@ -1442,6 +1459,14 @@ Singleton {
return surfaceContainer;
case "sch":
return surfaceContainerHigh;
case "primaryContainer":
return primaryContainer;
case "secondaryContainer":
return secondaryContainer;
case "tertiaryContainer":
return tertiaryContainer;
case "custom":
return blend(surfaceContainerHigh, widgetBackgroundCustomBaseColor, widgetBackgroundCustomStrength);
case "sth":
default:
return surfaceTextHover;
@@ -19,6 +19,8 @@ var SPEC = {
dockTransparency: { def: 1.0, coerce: percentToUnit },
widgetBackgroundColor: { def: "sch" },
widgetBackgroundCustomColor: { def: "#6750A4" },
widgetBackgroundCustomStrength: { def: 0.50, coerce: percentToUnit },
widgetColorMode: { def: "default" },
controlCenterTileColorMode: { def: "primary" },
buttonColorMode: { def: "primary" },
@@ -144,11 +146,16 @@ var SPEC = {
dwlShowAllTags: { def: false },
workspaceActiveAppHighlightEnabled: { def: false },
workspaceColorMode: { def: "default" },
workspaceFocusedCustomColor: { def: "#6750A4" },
workspaceOccupiedColorMode: { def: "none" },
workspaceOccupiedCustomColor: { def: "#625B71" },
workspaceUnfocusedColorMode: { def: "default" },
workspaceUnfocusedCustomColor: { def: "#49454E" },
workspaceUrgentColorMode: { def: "default" },
workspaceUrgentCustomColor: { def: "#B3261E" },
workspaceFocusedBorderEnabled: { def: false },
workspaceFocusedBorderColor: { def: "primary" },
workspaceFocusedBorderCustomColor: { def: "#6750A4" },
workspaceFocusedBorderThickness: { def: 2 },
workspaceNameIcons: { def: {} },
waveProgressEnabled: { def: true },
@@ -1192,38 +1192,25 @@ Item {
return Math.max(baseHeight + iconsExtraHeight, contentImplicitHeight + padding);
}
readonly property color unfocusedColor: {
switch (SettingsData.workspaceUnfocusedColorMode) {
case "s":
return Theme.surface;
case "sc":
return Theme.surfaceContainer;
case "sch":
return Theme.surfaceContainerHigh;
default:
return Theme.surfaceTextAlpha;
}
}
readonly property color activeColor: {
switch (SettingsData.workspaceColorMode) {
case "s":
return Theme.surface;
case "sc":
return Theme.surfaceContainer;
case "sch":
return Theme.surfaceContainerHigh;
case "none":
return unfocusedColor;
default:
function colorFromMode(mode, fallbackColor, customColor, customFallbackColor) {
switch (mode) {
case "primary":
case "pri":
return Theme.primary;
}
}
readonly property color occupiedColor: {
switch (SettingsData.workspaceOccupiedColorMode) {
case "primaryContainer":
return Theme.primaryContainer;
case "secondary":
case "sec":
return Theme.secondary;
case "secondaryContainer":
return Theme.secondaryContainer;
case "tertiary":
case "ter":
return Theme.tertiary;
case "tertiaryContainer":
return Theme.tertiaryContainer;
case "surfaceText":
return Theme.surfaceText;
case "s":
return Theme.surface;
case "sc":
@@ -1232,37 +1219,34 @@ Item {
return Theme.surfaceContainerHigh;
case "schh":
return Theme.surfaceContainerHighest;
default:
return unfocusedColor;
}
}
readonly property color urgentColor: {
switch (SettingsData.workspaceUrgentColorMode) {
case "primary":
return Theme.primary;
case "secondary":
return Theme.secondary;
case "s":
return Theme.surface;
case "sc":
return Theme.surfaceContainer;
default:
case "error":
case "err":
return Theme.error;
case "custom":
return Theme.safeColor(customColor, customFallbackColor);
default:
return fallbackColor;
}
}
readonly property color focusedBorderColor: {
switch (SettingsData.workspaceFocusedBorderColor) {
case "surfaceText":
return Theme.surfaceText;
case "secondary":
return Theme.secondary;
default:
return Theme.primary;
}
readonly property color unfocusedColor: colorFromMode(SettingsData.workspaceUnfocusedColorMode, Theme.surfaceTextAlpha, SettingsData.workspaceUnfocusedCustomColor, Theme.surfaceTextAlpha)
readonly property color activeColor: {
if (SettingsData.workspaceColorMode === "none")
return unfocusedColor;
return colorFromMode(SettingsData.workspaceColorMode, Theme.primary, SettingsData.workspaceFocusedCustomColor, Theme.primary);
}
readonly property color occupiedColor: {
if (SettingsData.workspaceOccupiedColorMode === "none")
return unfocusedColor;
return colorFromMode(SettingsData.workspaceOccupiedColorMode, unfocusedColor, SettingsData.workspaceOccupiedCustomColor, Theme.secondary);
}
readonly property color urgentColor: colorFromMode(SettingsData.workspaceUrgentColorMode, Theme.error, SettingsData.workspaceUrgentCustomColor, Theme.error)
readonly property color focusedBorderColor: colorFromMode(SettingsData.workspaceFocusedBorderColor, Theme.primary, SettingsData.workspaceFocusedBorderCustomColor, Theme.primary)
function getContrastingIconColor(bgColor) {
const luminance = 0.299 * bgColor.r + 0.587 * bgColor.g + 0.114 * bgColor.b;
return luminance > 0.4 ? Qt.rgba(0.15, 0.15, 0.15, 1) : Qt.rgba(0.8, 0.8, 0.8, 1);
+59 -31
View File
@@ -20,6 +20,31 @@ Item {
property var cachedMatugenSchemes: Theme.availableMatugenSchemes.map(option => option.label)
property var installedRegistryThemes: []
property var templateDetection: []
readonly property var widgetBackgroundOptions: [({
"value": "sth",
"label": I18n.tr("Subtle Overlay", "widget background color option")
}), ({
"value": "s",
"label": I18n.tr("Surface", "widget background color option")
}), ({
"value": "sc",
"label": I18n.tr("Surface Container", "widget background color option")
}), ({
"value": "sch",
"label": I18n.tr("Surface High", "widget background color option")
}), ({
"value": "primaryContainer",
"label": I18n.tr("Primary Container", "widget background color option")
}), ({
"value": "secondaryContainer",
"label": I18n.tr("Secondary Container", "widget background color option")
}), ({
"value": "tertiaryContainer",
"label": I18n.tr("Tertiary Container", "widget background color option")
}), ({
"value": "custom",
"label": I18n.tr("Custom", "widget background color option")
})]
property var cursorIncludeStatus: ({
"exists": false,
@@ -1524,10 +1549,10 @@ Item {
SettingsButtonGroupRow {
tab: "theme"
tags: ["widget", "style", "colorful", "default"]
tags: ["widget", "text", "style", "colorful", "default"]
settingKey: "widgetColorMode"
text: I18n.tr("Widget Style")
description: I18n.tr("Change bar appearance")
text: I18n.tr("Widget Text Style")
description: I18n.tr("Choose neutral or accent-colored widget text")
model: [I18n.tr("Default", "widget style option"), I18n.tr("Colorful", "widget style option")]
currentIndex: SettingsData.widgetColorMode === "colorful" ? 1 : 0
onSelectionChanged: (index, selected) => {
@@ -1537,38 +1562,41 @@ Item {
}
}
SettingsButtonGroupRow {
WorkspaceColorRow {
tab: "theme"
tags: ["widget", "background", "color"]
tags: ["widget", "background", "color", "surface", "material"]
settingKey: "widgetBackgroundColor"
text: I18n.tr("Widget Background Color")
description: I18n.tr("Choose the background color for widgets")
model: ["sth", "s", "sc", "sch"]
buttonHeight: 20
minButtonWidth: 32
buttonPadding: Theme.spacingS
checkIconSize: Theme.iconSizeSmall - 2
textSize: Theme.fontSizeSmall - 2
spacing: 1
currentIndex: {
switch (SettingsData.widgetBackgroundColor) {
case "sth":
return 0;
case "s":
return 1;
case "sc":
return 2;
case "sch":
return 3;
default:
return 0;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
const colorOptions = ["sth", "s", "sc", "sch"];
SettingsData.set("widgetBackgroundColor", colorOptions[index]);
dropdownWidth: 220
options: themeColorsTab.widgetBackgroundOptions
currentMode: SettingsData.widgetBackgroundColor
customColor: SettingsData.widgetBackgroundCustomColor || "#6750A4"
pickerTitle: I18n.tr("Widget Background Color")
onModeSelected: mode => SettingsData.set("widgetBackgroundColor", mode)
onCustomColorSelected: selectedColor => SettingsData.set("widgetBackgroundCustomColor", selectedColor.toString())
}
SettingsSliderRow {
id: widgetBackgroundCustomStrengthSlider
visible: SettingsData.widgetBackgroundColor === "custom"
tab: "theme"
tags: ["widget", "background", "color", "custom", "blend"]
settingKey: "widgetBackgroundCustomStrength"
text: I18n.tr("Custom Blend")
description: I18n.tr("Blend between Surface High and the selected custom color")
value: Math.round(SettingsData.widgetBackgroundCustomStrength * 100)
minimum: 0
maximum: 100
unit: "%"
defaultValue: 40
onSliderValueChanged: newValue => SettingsData.set("widgetBackgroundCustomStrength", newValue / 100)
Binding {
target: widgetBackgroundCustomStrengthSlider
property: "value"
value: Math.round(SettingsData.widgetBackgroundCustomStrength * 100)
restoreMode: Binding.RestoreBinding
}
}
@@ -4,41 +4,195 @@ import qs.Services
import qs.Modules.Settings.Widgets
SettingsCard {
id: root
iconName: "palette"
title: I18n.tr("Workspace Appearance")
settingKey: "workspaceAppearance"
collapsible: true
expanded: false
SettingsButtonGroupRow {
readonly property var focusedColorOptions: [({
"value": "default",
"label": I18n.tr("Primary", "workspace color option")
}), ({
"value": "primaryContainer",
"label": I18n.tr("Primary Container", "workspace color option")
}), ({
"value": "secondary",
"label": I18n.tr("Secondary", "workspace color option")
}), ({
"value": "secondaryContainer",
"label": I18n.tr("Secondary Container", "workspace color option")
}), ({
"value": "tertiary",
"label": I18n.tr("Tertiary", "workspace color option")
}), ({
"value": "tertiaryContainer",
"label": I18n.tr("Tertiary Container", "workspace color option")
}), ({
"value": "s",
"label": I18n.tr("Surface", "workspace color option")
}), ({
"value": "sc",
"label": I18n.tr("Surface Container", "workspace color option")
}), ({
"value": "sch",
"label": I18n.tr("Surface High", "workspace color option")
}), ({
"value": "schh",
"label": I18n.tr("Surface Highest", "workspace color option")
}), ({
"value": "none",
"label": I18n.tr("None", "workspace color option")
}), ({
"value": "custom",
"label": I18n.tr("Custom", "workspace color option")
})]
readonly property var occupiedColorOptions: [({
"value": "none",
"label": I18n.tr("None", "workspace color option")
}), ({
"value": "primary",
"label": I18n.tr("Primary", "workspace color option")
}), ({
"value": "primaryContainer",
"label": I18n.tr("Primary Container", "workspace color option")
}), ({
"value": "sec",
"label": I18n.tr("Secondary", "workspace color option")
}), ({
"value": "secondaryContainer",
"label": I18n.tr("Secondary Container", "workspace color option")
}), ({
"value": "tertiary",
"label": I18n.tr("Tertiary", "workspace color option")
}), ({
"value": "tertiaryContainer",
"label": I18n.tr("Tertiary Container", "workspace color option")
}), ({
"value": "s",
"label": I18n.tr("Surface", "workspace color option")
}), ({
"value": "sc",
"label": I18n.tr("Surface Container", "workspace color option")
}), ({
"value": "sch",
"label": I18n.tr("Surface High", "workspace color option")
}), ({
"value": "schh",
"label": I18n.tr("Surface Highest", "workspace color option")
}), ({
"value": "custom",
"label": I18n.tr("Custom", "workspace color option")
})]
readonly property var unfocusedColorOptions: [({
"value": "default",
"label": I18n.tr("Default", "workspace color option")
}), ({
"value": "surfaceText",
"label": I18n.tr("Surface Text", "workspace color option")
}), ({
"value": "primary",
"label": I18n.tr("Primary", "workspace color option")
}), ({
"value": "secondary",
"label": I18n.tr("Secondary", "workspace color option")
}), ({
"value": "tertiary",
"label": I18n.tr("Tertiary", "workspace color option")
}), ({
"value": "s",
"label": I18n.tr("Surface", "workspace color option")
}), ({
"value": "sc",
"label": I18n.tr("Surface Container", "workspace color option")
}), ({
"value": "sch",
"label": I18n.tr("Surface High", "workspace color option")
}), ({
"value": "schh",
"label": I18n.tr("Surface Highest", "workspace color option")
}), ({
"value": "custom",
"label": I18n.tr("Custom", "workspace color option")
})]
readonly property var urgentColorOptions: [({
"value": "default",
"label": I18n.tr("Error", "workspace color option")
}), ({
"value": "primary",
"label": I18n.tr("Primary", "workspace color option")
}), ({
"value": "primaryContainer",
"label": I18n.tr("Primary Container", "workspace color option")
}), ({
"value": "secondary",
"label": I18n.tr("Secondary", "workspace color option")
}), ({
"value": "secondaryContainer",
"label": I18n.tr("Secondary Container", "workspace color option")
}), ({
"value": "tertiary",
"label": I18n.tr("Tertiary", "workspace color option")
}), ({
"value": "tertiaryContainer",
"label": I18n.tr("Tertiary Container", "workspace color option")
}), ({
"value": "s",
"label": I18n.tr("Surface", "workspace color option")
}), ({
"value": "sc",
"label": I18n.tr("Surface Container", "workspace color option")
}), ({
"value": "sch",
"label": I18n.tr("Surface High", "workspace color option")
}), ({
"value": "custom",
"label": I18n.tr("Custom", "workspace color option")
})]
readonly property var borderColorOptions: [({
"value": "surfaceText",
"label": I18n.tr("Surface Text", "workspace color option")
}), ({
"value": "primary",
"label": I18n.tr("Primary", "workspace color option")
}), ({
"value": "primaryContainer",
"label": I18n.tr("Primary Container", "workspace color option")
}), ({
"value": "secondary",
"label": I18n.tr("Secondary", "workspace color option")
}), ({
"value": "secondaryContainer",
"label": I18n.tr("Secondary Container", "workspace color option")
}), ({
"value": "tertiary",
"label": I18n.tr("Tertiary", "workspace color option")
}), ({
"value": "tertiaryContainer",
"label": I18n.tr("Tertiary Container", "workspace color option")
}), ({
"value": "custom",
"label": I18n.tr("Custom", "workspace color option")
})]
readonly property bool workspaceStateColorsVisible: CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isMango
readonly property bool urgentWorkspaceColorsVisible: workspaceStateColorsVisible || CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle
WorkspaceColorRow {
text: I18n.tr("Focused Color")
model: ["pri", "s", "sc", "sch", "none"]
buttonHeight: 22
minButtonWidth: 36
buttonPadding: Theme.spacingS
checkIconSize: Theme.iconSizeSmall - 2
textSize: Theme.fontSizeSmall - 1
spacing: 1
currentIndex: {
switch (SettingsData.workspaceColorMode) {
case "s":
return 1;
case "sc":
return 2;
case "sch":
return 3;
case "none":
return 4;
default:
return 0;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
const modes = ["default", "s", "sc", "sch", "none"];
SettingsData.set("workspaceColorMode", modes[index]);
}
settingKey: "workspaceColorMode"
tags: ["workspace", "focused", "color", "custom"]
options: root.focusedColorOptions
currentMode: SettingsData.workspaceColorMode
customColor: SettingsData.workspaceFocusedCustomColor || "#6750A4"
onModeSelected: mode => SettingsData.set("workspaceColorMode", mode)
onCustomColorSelected: selectedColor => SettingsData.set("workspaceFocusedCustomColor", selectedColor.toString())
}
Rectangle {
@@ -48,38 +202,16 @@ SettingsCard {
opacity: 0.15
}
SettingsButtonGroupRow {
WorkspaceColorRow {
text: I18n.tr("Occupied Color")
model: ["none", "sec", "s", "sc", "sch", "schh"]
visible: CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isMango
buttonHeight: 22
minButtonWidth: 36
buttonPadding: Theme.spacingS
checkIconSize: Theme.iconSizeSmall - 2
textSize: Theme.fontSizeSmall - 1
spacing: 1
currentIndex: {
switch (SettingsData.workspaceOccupiedColorMode) {
case "sec":
return 1;
case "s":
return 2;
case "sc":
return 3;
case "sch":
return 4;
case "schh":
return 5;
default:
return 0;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
const modes = ["none", "sec", "s", "sc", "sch", "schh"];
SettingsData.set("workspaceOccupiedColorMode", modes[index]);
}
settingKey: "workspaceOccupiedColorMode"
tags: ["workspace", "occupied", "color", "custom"]
visible: root.workspaceStateColorsVisible
options: root.occupiedColorOptions
currentMode: SettingsData.workspaceOccupiedColorMode
customColor: SettingsData.workspaceOccupiedCustomColor || "#625B71"
onModeSelected: mode => SettingsData.set("workspaceOccupiedColorMode", mode)
onCustomColorSelected: selectedColor => SettingsData.set("workspaceOccupiedCustomColor", selectedColor.toString())
}
Rectangle {
@@ -90,33 +222,16 @@ SettingsCard {
visible: CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isMango
}
SettingsButtonGroupRow {
WorkspaceColorRow {
text: I18n.tr("Unfocused Color")
model: ["def", "s", "sc", "sch"]
buttonHeight: 22
minButtonWidth: 36
buttonPadding: Theme.spacingS
checkIconSize: Theme.iconSizeSmall - 2
textSize: Theme.fontSizeSmall - 1
spacing: 1
currentIndex: {
switch (SettingsData.workspaceUnfocusedColorMode) {
case "s":
return 1;
case "sc":
return 2;
case "sch":
return 3;
default:
return 0;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
const modes = ["default", "s", "sc", "sch"];
SettingsData.set("workspaceUnfocusedColorMode", modes[index]);
}
settingKey: "workspaceUnfocusedColorMode"
tags: ["workspace", "unfocused", "color", "custom"]
options: root.unfocusedColorOptions
defaultColor: Theme.surfaceText
currentMode: SettingsData.workspaceUnfocusedColorMode
customColor: SettingsData.workspaceUnfocusedCustomColor || "#49454E"
onModeSelected: mode => SettingsData.set("workspaceUnfocusedColorMode", mode)
onCustomColorSelected: selectedColor => SettingsData.set("workspaceUnfocusedCustomColor", selectedColor.toString())
}
Rectangle {
@@ -127,36 +242,17 @@ SettingsCard {
visible: CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isMango || CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle
}
SettingsButtonGroupRow {
WorkspaceColorRow {
text: I18n.tr("Urgent Color")
visible: CompositorService.isNiri || CompositorService.isHyprland || CompositorService.isMango || CompositorService.isSway || CompositorService.isScroll || CompositorService.isMiracle
model: ["err", "pri", "sec", "s", "sc"]
buttonHeight: 22
minButtonWidth: 36
buttonPadding: Theme.spacingS
checkIconSize: Theme.iconSizeSmall - 2
textSize: Theme.fontSizeSmall - 1
spacing: 1
currentIndex: {
switch (SettingsData.workspaceUrgentColorMode) {
case "primary":
return 1;
case "secondary":
return 2;
case "s":
return 3;
case "sc":
return 4;
default:
return 0;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
const modes = ["default", "primary", "secondary", "s", "sc"];
SettingsData.set("workspaceUrgentColorMode", modes[index]);
}
settingKey: "workspaceUrgentColorMode"
tags: ["workspace", "urgent", "color", "custom"]
visible: root.urgentWorkspaceColorsVisible
options: root.urgentColorOptions
defaultColor: Theme.error
currentMode: SettingsData.workspaceUrgentColorMode
customColor: SettingsData.workspaceUrgentCustomColor || "#B3261E"
onModeSelected: mode => SettingsData.set("workspaceUrgentColorMode", mode)
onCustomColorSelected: selectedColor => SettingsData.set("workspaceUrgentCustomColor", selectedColor.toString())
}
Rectangle {
@@ -181,39 +277,16 @@ SettingsCard {
visible: SettingsData.workspaceFocusedBorderEnabled
leftPadding: Theme.spacingM
SettingsButtonGroupRow {
WorkspaceColorRow {
width: parent.width - parent.leftPadding
text: I18n.tr("Border Color")
model: [I18n.tr("Surface"), I18n.tr("Secondary"), I18n.tr("Primary")]
currentIndex: {
switch (SettingsData.workspaceFocusedBorderColor) {
case "surfaceText":
return 0;
case "secondary":
return 1;
case "primary":
return 2;
default:
return 2;
}
}
onSelectionChanged: (index, selected) => {
if (!selected)
return;
let newColor = "primary";
switch (index) {
case 0:
newColor = "surfaceText";
break;
case 1:
newColor = "secondary";
break;
case 2:
newColor = "primary";
break;
}
SettingsData.set("workspaceFocusedBorderColor", newColor);
}
settingKey: "workspaceFocusedBorderColor"
tags: ["workspace", "focused", "border", "color", "custom"]
options: root.borderColorOptions
currentMode: SettingsData.workspaceFocusedBorderColor
customColor: SettingsData.workspaceFocusedBorderCustomColor || "#6750A4"
onModeSelected: mode => SettingsData.set("workspaceFocusedBorderColor", mode)
onCustomColorSelected: selectedColor => SettingsData.set("workspaceFocusedBorderCustomColor", selectedColor.toString())
}
SettingsSliderRow {
@@ -0,0 +1,211 @@
pragma ComponentBehavior: Bound
import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
import qs.Modules.Settings.Widgets
Column {
id: root
property string text: ""
property string description: ""
property string settingKey: ""
property string tab: ""
property var tags: []
property var options: []
property string currentMode: "default"
property color customColor: "#6750A4"
property string pickerTitle: text
property int dropdownWidth: 230
property color defaultColor: Theme.primary
readonly property var optionColorMap: {
var map = {};
for (var i = 0; i < options.length; i++)
map[options[i].label] = root.colorForValue(options[i].value);
return map;
}
function colorForValue(value) {
switch (value) {
case "primary":
case "pri":
return Theme.primary;
case "primaryContainer":
return Theme.primaryContainer;
case "secondary":
case "sec":
return Theme.secondary;
case "secondaryContainer":
return Theme.secondaryContainer;
case "tertiary":
case "ter":
return Theme.tertiary;
case "tertiaryContainer":
return Theme.tertiaryContainer;
case "surfaceText":
return Theme.surfaceText;
case "s":
return Theme.surface;
case "sc":
return Theme.surfaceContainer;
case "sch":
return Theme.surfaceContainerHigh;
case "schh":
return Theme.surfaceContainerHighest;
case "sth":
return Theme.surfaceTextHover;
case "error":
case "err":
return Theme.error;
case "custom":
return root.customColor;
case "none":
return "transparent";
default:
return root.defaultColor;
}
}
signal modeSelected(string mode)
signal customColorSelected(color selectedColor)
width: parent?.width ?? 0
spacing: Theme.spacingS
function optionLabels() {
return options.map(option => option.label);
}
function optionLabel(value) {
for (var i = 0; i < options.length; i++) {
if (options[i].value === value)
return options[i].label;
}
return options.length > 0 ? options[0].label : "";
}
function optionValue(label) {
for (var i = 0; i < options.length; i++) {
if (options[i].label === label)
return options[i].value;
}
return options.length > 0 ? options[0].value : "default";
}
function openCustomColorPicker() {
PopoutService.colorPickerModal.selectedColor = root.customColor;
PopoutService.colorPickerModal.pickerTitle = root.pickerTitle;
PopoutService.colorPickerModal.onColorSelectedCallback = function (selectedColor) {
root.customColorSelected(selectedColor);
root.modeSelected("custom");
};
PopoutService.colorPickerModal.show();
}
SettingsDropdownRow {
text: root.text
description: root.description
tab: root.tab
settingKey: root.settingKey
tags: root.tags
options: root.optionLabels()
optionColorMap: root.optionColorMap
currentValue: root.optionLabel(root.currentMode)
dropdownWidth: root.dropdownWidth
onValueChanged: value => root.modeSelected(root.optionValue(value))
}
Item {
width: parent.width
height: root.currentMode === "custom" ? customChip.height : 0
opacity: root.currentMode === "custom" ? 1 : 0
clip: true
Behavior on height {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Rectangle {
id: customChip
width: parent.width
height: 56
radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh
Row {
anchors.fill: parent
anchors.leftMargin: Theme.spacingM
anchors.rightMargin: Theme.spacingM
spacing: Theme.spacingM
Rectangle {
width: 36
height: 36
radius: 18
color: root.customColor
border.color: Theme.outline
border.width: 1
anchors.verticalCenter: parent.verticalCenter
DankIcon {
anchors.centerIn: parent
name: "colorize"
size: 16
color: (root.customColor.r * 0.299 + root.customColor.g * 0.587 + root.customColor.b * 0.114) > 0.5 ? "#000000" : "#ffffff"
}
}
Column {
width: parent.width - 36 - editIcon.width - Theme.spacingM * 2
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXS
StyledText {
text: I18n.tr("Custom Color")
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: Theme.surfaceText
width: parent.width
horizontalAlignment: Text.AlignLeft
}
StyledText {
text: root.customColor.toString()
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
width: parent.width
elide: Text.ElideRight
horizontalAlignment: Text.AlignLeft
}
}
DankIcon {
id: editIcon
name: "edit"
size: Theme.iconSizeSmall
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
}
StateLayer {
stateColor: Theme.surfaceText
onClicked: root.openCustomColorPicker()
}
}
}
}
+34 -2
View File
@@ -28,6 +28,7 @@ Item {
property var optionIcons: []
property bool enableFuzzySearch: false
property var optionIconMap: ({})
property var optionColorMap: ({})
function rebuildIconMap() {
const map = {};
@@ -160,7 +161,24 @@ Item {
anchors.rightMargin: Theme.spacingS
spacing: Theme.spacingS
Rectangle {
id: triggerSwatch
property var swatchColor: root.optionColorMap[root.currentValue]
width: 16
height: 16
radius: 8
color: swatchColor !== undefined ? swatchColor : "transparent"
border.color: Theme.outline
border.width: 1
anchors.verticalCenter: parent.verticalCenter
visible: swatchColor !== undefined
}
DankIcon {
id: triggerIcon
name: root.optionIconMap[root.currentValue] ?? ""
size: 18
color: Theme.surfaceText
@@ -173,7 +191,7 @@ Item {
text: root.currentValue !== "" ? root.currentValue : root.emptyText
font.pixelSize: Theme.fontSizeMedium
color: root.currentValue !== "" ? Theme.surfaceText : Theme.outline
width: contentRow.width - (contentRow.children[0].visible ? contentRow.children[0].width + contentRow.spacing : 0)
width: contentRow.width - (triggerSwatch.visible ? triggerSwatch.width + contentRow.spacing : 0) - (triggerIcon.visible ? triggerIcon.width + contentRow.spacing : 0)
elide: Text.ElideRight
wrapMode: Text.NoWrap
horizontalAlignment: Text.AlignLeft
@@ -406,6 +424,7 @@ Item {
property bool isSelected: dropdownMenu.selectedIndex === index
property bool isCurrentValue: root.currentValue === modelData
property string iconName: root.optionIconMap[modelData] ?? ""
property var swatchColor: root.optionColorMap[modelData]
width: ListView.view.width
height: 32
@@ -420,6 +439,19 @@ Item {
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingS
Rectangle {
id: optionSwatch
width: 16
height: 16
radius: 8
color: delegateRoot.swatchColor !== undefined ? delegateRoot.swatchColor : "transparent"
border.color: delegateRoot.isCurrentValue ? Theme.primary : Theme.outline
border.width: 1
anchors.verticalCenter: parent.verticalCenter
visible: delegateRoot.swatchColor !== undefined
}
DankIcon {
name: delegateRoot.iconName
size: 18
@@ -433,7 +465,7 @@ Item {
font.pixelSize: Theme.fontSizeMedium
color: delegateRoot.isCurrentValue ? Theme.primary : Theme.surfaceText
font.weight: delegateRoot.isCurrentValue ? Font.Medium : Font.Normal
width: root.popupWidth > 0 ? undefined : (delegateRoot.width - parent.x - Theme.spacingS * 2)
width: root.popupWidth > 0 ? undefined : (delegateRoot.width - parent.x - Theme.spacingS * 2 - (optionSwatch.visible ? optionSwatch.width + parent.spacing : 0))
elide: root.popupWidth > 0 ? Text.ElideNone : Text.ElideRight
wrapMode: Text.NoWrap
horizontalAlignment: Text.AlignLeft