From ba5ed59bee859acbfa1847da19d112f372ee54f4 Mon Sep 17 00:00:00 2001 From: Luis Bocanegra Date: Sun, 29 Sep 2024 16:43:53 -0600 Subject: [PATCH] feat: unified background areas Removed the default layout spacing and added our own, to the left of each widget (or top for vertival panel) Uses a MiltiEffect mask and paddingRect to hide border/shadow when needed refs: https://github.com/luisbocanegra/plasma-panel-colorizer/issues/39 --- package/contents/config/config.qml | 16 +- package/contents/ui/code/globals.js | 16 +- .../ui/components/WidgetCardUnifiedBg.qml | 106 +++++++++++ .../contents/ui/configUnifiedBackground.qml | 124 +++++++++++++ package/contents/ui/main.qml | 164 ++++++++++++++---- 5 files changed, 385 insertions(+), 41 deletions(-) create mode 100644 package/contents/ui/components/WidgetCardUnifiedBg.qml create mode 100644 package/contents/ui/configUnifiedBackground.qml diff --git a/package/contents/config/config.qml b/package/contents/config/config.qml index 4cf6283..adb6e1d 100644 --- a/package/contents/config/config.qml +++ b/package/contents/config/config.qml @@ -9,6 +9,12 @@ ConfigModel { source: "configGeneral.qml" } + ConfigCategory { + name: i18n("Presets autoloading") + icon: "system-run" + source: "configPresetAutoload.qml" + } + ConfigCategory { name: i18n("Appearance") icon: "preferences" @@ -16,15 +22,15 @@ ConfigModel { } ConfigCategory { - name: i18n("Overrides") + name: i18n("Unified backgrounds") icon: "preferences" - source: "configPerWidget.qml" + source: "configUnifiedBackground.qml" } ConfigCategory { - name: i18n("Presets autoloading") - icon: "system-run" - source: "configPresetAutoload.qml" + name: i18n("Overrides") + icon: "preferences" + source: "configPerWidget.qml" } ConfigCategory { diff --git a/package/contents/ui/code/globals.js b/package/contents/ui/code/globals.js index bde4171..cedef3a 100644 --- a/package/contents/ui/code/globals.js +++ b/package/contents/ui/code/globals.js @@ -154,6 +154,10 @@ const basePadding = { }, } +const baseUnfiedBackground = { + "org.kde.plasma.digitalclock": 0 +} + const basePanelConfig = { "enabled": false, "blurBehind": false, @@ -164,6 +168,7 @@ const basePanelConfig = { "padding": basePadding, "border": baseBorder, "shadow": baseShadowConfig, + "unfiedBackground": baseUnfiedBackground } const baseWidgetConfig = { @@ -176,6 +181,7 @@ const baseWidgetConfig = { "spacing": 3, "border": baseBorder, "shadow": baseShadowConfig, + "unfiedBackground": baseUnfiedBackground } const baseTrayConfig = { @@ -187,6 +193,7 @@ const baseTrayConfig = { "margin": baseMargin, "border": baseBorder, "shadow": baseShadowConfig, + "unfiedBackground": baseUnfiedBackground } const baseOverrideConfig = { @@ -238,7 +245,12 @@ const defaultConfig = { "floating": false }, "configurationOverrides": {}, - "overrideAssociations": {} + "overrideAssociations": {}, + "unifiedBackground": { + "org.kde.netspeedWidget": 1, + "org.kde.plasma.systemtray": 2, + "org.kde.plasma.digitalclock": 3 + } } const ignoredConfigs = [ @@ -247,5 +259,5 @@ const ignoredConfigs = [ "panelWidgets", "objectName", "lastPreset", - "presetAutoloading" + "presetAutoloading", ] diff --git a/package/contents/ui/components/WidgetCardUnifiedBg.qml b/package/contents/ui/components/WidgetCardUnifiedBg.qml new file mode 100644 index 0000000..82eeda9 --- /dev/null +++ b/package/contents/ui/components/WidgetCardUnifiedBg.qml @@ -0,0 +1,106 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import org.kde.kirigami as Kirigami + +Kirigami.AbstractCard { + id: root + property var widget + signal updateWidget(unifyBgType: int) + checked: widget.unifyBgType !== 0 + + contentItem: RowLayout { + Kirigami.Icon { + width: Kirigami.Units.gridUnit + height: width + source: widget.icon + } + ColumnLayout { + RowLayout { + Label { + text: widget.title + } + Rectangle { + visible: widget.inTray + color: Kirigami.Theme.highlightColor + Kirigami.Theme.colorSet: root.Kirigami.Theme["Selection"] + radius: parent.height / 2 + width: label.width + 12 + height: label.height + 2 + Kirigami.Theme.inherit: false + Label { + anchors.centerIn: parent + id: label + text: i18n("System Tray") + color: Kirigami.Theme.textColor + Kirigami.Theme.colorSet: root.Kirigami.Theme["Selection"] + Kirigami.Theme.inherit: false + } + } + } + TextEdit { + text: widget.name + opacity: 0.6 + readOnly: true + color: Kirigami.Theme.textColor + selectedTextColor: Kirigami.Theme.highlightedTextColor + selectionColor: Kirigami.Theme.highlightColor + } + } + Item { + Layout.fillWidth: true + } + Button { + text: i18n("D") + checkable: true + checked: widget?.unifyBgType === index + icon.name: checked ? "checkmark-symbolic" : "dialog-close-symbolic" + Layout.preferredWidth: 50 + property int index: 0 + ButtonGroup.group: unifyButtonGroup + } + Button { + text: i18n("S") + checkable: true + checked: widget?.unifyBgType === index + icon.name: checked ? "checkmark-symbolic" : "dialog-close-symbolic" + Layout.preferredWidth: 50 + property int index: 1 + ButtonGroup.group: unifyButtonGroup + } + Button { + text: i18n("M") + checkable: true + checked: widget?.unifyBgType === index + icon.name: checked ? "checkmark-symbolic" : "dialog-close-symbolic" + Layout.preferredWidth: 50 + property int index: 2 + ButtonGroup.group: unifyButtonGroup + } + Button { + text: i18n("E") + checkable: true + checked: widget?.unifyBgType === index + icon.name: checked ? "checkmark-symbolic" : "dialog-close-symbolic" + property int index: 3 + Layout.preferredWidth: 50 + ButtonGroup.group: unifyButtonGroup + } + ButtonGroup { + id: unifyButtonGroup + onCheckedButtonChanged: { + if (checkedButton) { + widget.unifyBgType = checkedButton.index + updateWidget(widget.unifyBgType) + } + } + } + // ComboBox { + // model: ["Disabled", "Start", "Middle", "End"] + // currentIndex: widget?.unifyBgType ?? 0 + // onCurrentIndexChanged: { + // updateWidget(currentIndex) + // } + // } + } +} diff --git a/package/contents/ui/configUnifiedBackground.qml b/package/contents/ui/configUnifiedBackground.qml new file mode 100644 index 0000000..c896df4 --- /dev/null +++ b/package/contents/ui/configUnifiedBackground.qml @@ -0,0 +1,124 @@ +import QtCore +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import org.kde.kcmutils as KCM +import org.kde.kirigami as Kirigami +import org.kde.plasma.plasmoid +import "components" as Components +import "code/utils.js" as Utils + +KCM.SimpleKCM { + id:root + property alias cfg_isEnabled: headerComponent.isEnabled + property string cfg_panelWidgets + property bool clearing: false + property string cfg_allSettings + property var config: JSON.parse(cfg_allSettings) + property var unifiedBackgroundSettings + property bool loaded: false + property string configDir: StandardPaths.writableLocation( + StandardPaths.HomeLocation).toString().substring(7) + "/.config/panel-colorizer/" + property string importCmd: "cat '" + configDir + "forceForegroundColor.json'" + property string crateConfigDirCmd: "mkdir -p " + configDir + + Component.onCompleted: { + unifiedBackgroundSettings = config.unifiedBackground + console.error(JSON.stringify(unifiedBackgroundSettings, null, null)) + initWidgets() + updateWidgetsModel() + } + + function updateConfig() { + for (let i = 0; i < widgetsModel.count; i++) { + const widget = widgetsModel.get(i) + const widgetName = widget.name + const unifyBgType = widget.unifyBgType + console.error(widgetName, unifyBgType) + unifiedBackgroundSettings[widgetName] = unifyBgType + } + config.unifiedBackground = unifiedBackgroundSettings + cfg_allSettings = JSON.stringify(config, null, null) + } + + ListModel { + id: widgetsModel + } + + RunCommand { + id: runCommand + } + + function initWidgets(){ + widgetsModel.clear() + const object = JSON.parse(cfg_panelWidgets) + for (const widget of object) { + const name = widget.name + const title = widget.title + const icon = widget.icon + const inTray = widget.inTray + if (inTray) continue + widgetsModel.append({ + "name": name, "title": title, "icon": icon, "inTray":inTray, + "unifyBgType": 0 + }) + } + } + + function updateWidgetsModel(){ + for (let i = 0; i < widgetsModel.count; i++) { + const widget = widgetsModel.get(i) + const name = widget.name + if (name in unifiedBackgroundSettings) { + let unifyBgType = unifiedBackgroundSettings[name] + widgetsModel.set(i, {"unifyBgType": unifyBgType}) + } else { + widgetsModel.set(i, {"unifyBgType": 0}) + } + } + loaded = true + } + + header: ColumnLayout { + Components.Header { + id: headerComponent + Layout.leftMargin: Kirigami.Units.mediumSpacing + Layout.rightMargin: Kirigami.Units.mediumSpacing + } + } + + ColumnLayout { + + Kirigami.FormLayout { + Kirigami.Separator { + Kirigami.FormData.isSection: true + Kirigami.FormData.label: i18n("Unify widget backgrounds") + } + } + Kirigami.FormLayout { + + Label { + text: i18n("[D]isabled
[S]tart unified background
[M]iddle: unified background
[E]nd unified background") + opacity: 0.7 + Layout.maximumWidth: widgetCards.width + wrapMode: Text.Wrap + } + + ColumnLayout { + id: widgetCards + Repeater { + model: widgetsModel + delegate: Components.WidgetCardUnifiedBg { + widget: model + onUpdateWidget: (unifyBgType) => { + if (!loaded) return + console.log(model.name, unifyBgType) + widgetsModel.set(index, {"unifyBgType": unifyBgType}) + root.updateConfig() + } + } + } + } + } + } +} diff --git a/package/contents/ui/main.qml b/package/contents/ui/main.qml index 91f9e3b..d98eab9 100644 --- a/package/contents/ui/main.qml +++ b/package/contents/ui/main.qml @@ -83,6 +83,7 @@ PlasmoidItem { property var widgetSettings: cfg.widgets property var panelSettings: cfg.panel property var trayWidgetSettings: cfg.trayWidgets + property var unifiedBackgroundSettings: cfg.unifiedBackground property var forceRecolorList: forceForegroundColor?.widgets ?? {} property int forceRecolorInterval: forceForegroundColor?.reloadInterval ?? 0 property int forceRecolorCount: Object.keys(forceRecolorList).length @@ -253,6 +254,8 @@ PlasmoidItem { property bool luisbocanegraPanelColorizerBgManaged: true property string widgetName: isTrayArrow ? "org.kde.plasma.systemtray.expand" : Utils.getWidgetName(target) property bool requiresRefresh: forceRecolorList[widgetName]?.reload ?? false + // 0: default | 1: start | 2: middle | 3: end + property int unifyBgType: unifiedBackgroundSettings[widgetName] ?? 0 property var itemConfig: Utils.getItemCfg(itemType, widgetName, main.cfg, configurationOverrides) property var cfg: itemConfig.settings property bool cfgOverride: itemConfig.override @@ -265,6 +268,27 @@ PlasmoidItem { property bool bgEnabled: cfgEnabled ? bgColorCfg.enabled : false property bool fgEnabled: fgColorCfg.enabled && cfgEnabled property bool radiusEnabled: cfg.radius.enabled && cfgEnabled + property int topLeftRadius: !radiusEnabled || unifyBgType === 2 || unifyBgType === 3 + ? 0 + : cfg.radius.corner.topLeft ?? 0 + property int topRightRadius: !radiusEnabled || + (horizontal && (unifyBgType === 1 || unifyBgType === 2)) || + (!horizontal && (unifyBgType === 2 || unifyBgType === 3)) + ? 0 + : cfg.radius.corner.topRight ?? 0 + + property int bottomLeftRadius: !radiusEnabled || + (horizontal && (unifyBgType === 2 || unifyBgType === 3)) || + (!horizontal && (unifyBgType === 1 || unifyBgType === 2)) + ? 0 + : cfg.radius.corner.bottomLeft ?? 0 + + property int bottomRightRadius: !radiusEnabled || + unifyBgType === 1 || unifyBgType === 2 || + (!horizontal && (unifyBgType === 1 || unifyBgType === 2)) + ? 0 + : cfg.radius.corner.bottomRight ?? 0 + property bool marginEnabled: cfg.margin.enabled && cfgEnabled property bool borderEnabled: cfg.border.enabled && cfgEnabled property bool bgShadowEnabled: cfg.shadow.background.enabled && cfgEnabled @@ -294,9 +318,10 @@ PlasmoidItem { id: fgColorHolder height: 6 width: height - visible: debug + visible: false radius: height / 2 color: fgColor + anchors.right: parent.right } // Label { // id: debugLabel @@ -304,10 +329,10 @@ PlasmoidItem { // font.pixelSize: 8 // } corners { - topLeftRadius: radiusEnabled ? cfg.radius.corner.topLeft : 0 - topRightRadius: radiusEnabled ? cfg.radius.corner.topRight : 0 - bottomLeftRadius: radiusEnabled ? cfg.radius.corner.bottomLeft : 0 - bottomRightRadius: radiusEnabled ? cfg.radius.corner.bottomRight : 0 + topLeftRadius: topLeftRadius + topRightRadius: topRightRadius + bottomLeftRadius: bottomLeftRadius + bottomRightRadius: bottomRightRadius } color: { if (bgEnabled) { @@ -416,8 +441,9 @@ PlasmoidItem { Binding { target: rect.target property: "Layout.leftMargin" - value: marginLeft - when: marginEnabled && isWidget + // our own horizontal spacing starting from the second widget for the unified widget feature + value: (targetIndex !== 0 && unifyBgType<=1 && horizontal ? widgetSettings.spacing : 0) + (marginEnabled ? marginLeft : 0) + when: isWidget delayed: true } @@ -432,8 +458,9 @@ PlasmoidItem { Binding { target: rect.target property: "Layout.topMargin" - value: marginTop - when: marginEnabled && isWidget + // our own vertical spacing starting from the second widget for the unified widget feature + value: (targetIndex !== 0 && unifyBgType<=1 && !horizontal ? widgetSettings.spacing : 0) + (marginEnabled ? marginTop : 0) + when: isWidget delayed: true } @@ -550,7 +577,7 @@ PlasmoidItem { id: borderRec anchors.fill: parent color: "transparent" - visible: borderEnabled + visible: borderEnabled && Math.min(rect.height, rect.width) > 1 property var borderColorCfg: cfg.border.color Kirigami.Theme.colorSet: Kirigami.Theme[borderColorCfg.systemColorSet] Kirigami.Theme.inherit: !(borderColorCfg.sourceType === 1) @@ -593,18 +620,57 @@ PlasmoidItem { } Kirigami.ShadowedRectangle { + id: normalBorder anchors.fill: parent color: "transparent" - visible: !cfg.border.customSides + // the mask source needs to be hidden by default + visible: false border { color: borderRec.borderColor width: cfg.border.width || -1 } corners { - topLeftRadius: radiusEnabled ? cfg.radius.corner.topLeft : 0 - topRightRadius: radiusEnabled ? cfg.radius.corner.topRight : 0 - bottomLeftRadius: radiusEnabled ? cfg.radius.corner.bottomLeft : 0 - bottomRightRadius: radiusEnabled ? cfg.radius.corner.bottomRight : 0 + topLeftRadius: topLeftRadius + topRightRadius: topRightRadius + bottomLeftRadius: bottomLeftRadius + bottomRightRadius: bottomRightRadius + } + } + + // Mask to hide one or two borders for unified backgrounds + MultiEffect { + source: normalBorder + anchors.fill: normalBorder + maskEnabled: true + maskSource: rightBorderMask + maskInverted: true + } + Item { + id: rightBorderMask + layer.enabled: true + visible: false + width: borderRec.width + height: borderRec.height + Rectangle { + id: rect1 + width: horizontal ? cfg.border.width : borderRec.width - (cfg.border.width * 2) + height: horizontal ? borderRec.height - (cfg.border.width * 2) : cfg.border.width + color: (unifyBgType === 1 || unifyBgType === 2) ? "black" : "transparent" + anchors.right: horizontal ? parent.right : undefined + anchors.bottom: !horizontal ? parent.bottom : undefined + anchors.verticalCenter: horizontal ? parent.verticalCenter : undefined + anchors.horizontalCenter: !horizontal ? parent.horizontalCenter : undefined + + } + Rectangle { + id: rect2 + width: horizontal ? cfg.border.width : borderRec.width - (cfg.border.width * 2) + height: horizontal ? borderRec.height - (cfg.border.width * 2) : cfg.border.width + color: (unifyBgType === 2 || unifyBgType === 3) ? "black" : "transparent" + anchors.left: horizontal ? parent.left : undefined + anchors.top: !horizontal ? parent.top : undefined + anchors.verticalCenter: horizontal ? parent.verticalCenter : undefined + anchors.horizontalCenter: !horizontal ? parent.horizontalCenter : undefined } } @@ -619,10 +685,10 @@ PlasmoidItem { width: rect.width height: rect.height corners { - topLeftRadius: radiusEnabled ? cfg.radius.corner.topLeft : 0 - topRightRadius: radiusEnabled ? cfg.radius.corner.topRight : 0 - bottomLeftRadius: radiusEnabled ? cfg.radius.corner.bottomLeft : 0 - bottomRightRadius: radiusEnabled ? cfg.radius.corner.bottomRight : 0 + topLeftRadius: topLeftRadius + topRightRadius: topRightRadius + bottomLeftRadius: bottomLeftRadius + bottomRightRadius: bottomRightRadius } } } @@ -632,7 +698,7 @@ PlasmoidItem { shadow { property var shadowColorCfg: bgShadow.color Kirigami.Theme.colorSet: Kirigami.Theme[shadowColorCfg.systemColorSet] - size: bgShadowEnabled ? bgShadow.size : 0 + size: (bgShadowEnabled && Math.min(rect.height, rect.width) > 1) ? bgShadow.size : 0 color: { return getColor(shadowColorCfg, targetIndex, rect.color, itemType) } @@ -640,10 +706,36 @@ PlasmoidItem { yOffset: bgShadow.yOffset } + // paddingRect to hide the shadow in one or two sides Qt.rect(left,top,right,bottom) + layer.enabled: bgShadowEnabled && unifyBgType !== 0 + // how much padding are we hiding + property int ps: Math.max(bgShadow.size, bgShadow.xOffset, bgShadow.yOffset) + layer.effect: MultiEffect { + autoPaddingEnabled: true + paddingRect: { + if (unifyBgType === 1) { + return horizontal ? Qt.rect(ps,ps,0,ps) : Qt.rect(ps,ps,ps,0) + } + if (unifyBgType === 2) { + return horizontal ? Qt.rect(0,ps,0,ps) : Qt.rect(ps,0,ps,0) + } + if (unifyBgType === 3) { + return horizontal ? Qt.rect(0,ps,ps,ps) : Qt.rect(ps,0,ps,ps) + } + } + } + DropShadow { - height: target.height - width: target.width - anchors.centerIn: parent + anchors.fill: parent + // we need to compensate because we now space widgets with margins + // instead of the layout spacing for the unified background feature + // can't anchor to center because we can also add different margin + // on each side, the shadow position is off otherwise + anchors.leftMargin: horizontal ? rect.marginLeft : undefined + anchors.rightMargin: horizontal ? rect.marginRight : undefined + anchors.topMargin: horizontal ? undefined : rect.marginTop + anchors.bottomMargin: horizontal ? undefined : rect.marginBottom + property var shadowColorCfg: fgShadow.color Kirigami.Theme.colorSet: Kirigami.Theme[shadowColorCfg.systemColorSet] horizontalOffset: fgShadow.xOffset @@ -664,7 +756,7 @@ PlasmoidItem { if (floatigness > 0) { return marginLeft } else { - return (panelElement.width - rect.width) / 2 + return (panelElement.width - borderRec.width) / 2 } } else { return marginLeft @@ -677,7 +769,7 @@ PlasmoidItem { if (floatigness > 0) { return marginTop } else { - return (panelElement.height - rect.height) / 2 + return (panelElement.height - borderRec.height) / 2 } } else { return marginTop @@ -689,11 +781,11 @@ PlasmoidItem { running: true repeat: true onTriggered: { - position = Utils.getGlobalPosition(rect, panelElement) + position = Utils.getGlobalPosition(borderRec, panelElement) } } - property var position: Utils.getGlobalPosition(rect, panelElement) + property var position: Utils.getGlobalPosition(borderRec, panelElement) property var positionX: position.x property var positionY: position.y property var fl: floatigness @@ -709,6 +801,7 @@ PlasmoidItem { anchors.fill: parent color: "black" z:-1 + opacity: 0.5 } } Label { @@ -718,12 +811,13 @@ PlasmoidItem { anchors.fill: parent color: "black" z:-1 + opacity: 0.5 } } } Label { - text: parseInt(rect.width)+"x"+parseInt(rect.height) + text: parseInt(borderRec.width)+"x"+parseInt(borderRec.height) font.pixelSize: 8 anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter @@ -760,7 +854,7 @@ PlasmoidItem { } onFlChanged: { - position = Utils.getGlobalPosition(rect, panelElement) + position = Utils.getGlobalPosition(borderRec, panelElement) } onPositionXChanged: { @@ -787,12 +881,12 @@ PlasmoidItem { if (panelColorizer === null || !blurBehind) return panelColorizer.updatePanelMask( maskIndex, - rect, + borderRec, rect.corners.topLeftRadius, rect.corners.topRightRadius, rect.corners.bottomLeftRadius, rect.corners.bottomRightRadius, - Qt.point(rect.position.x-moveX, rect.position.y-moveY), + Qt.point(rect.positionX-moveX, rect.positionY-moveY), 5 ) }) @@ -810,8 +904,10 @@ PlasmoidItem { let candidate = main.parent; while (candidate) { if (candidate instanceof GridLayout) { - candidate.rowSpacing = widgetSettings.spacing - candidate.columnSpacing = widgetSettings.spacing + // we will do spacing manually on all widgets + // this is needed to allow us to 'unify' background areas + candidate.rowSpacing = 0 + candidate.columnSpacing = 0 return candidate; } candidate = candidate.parent; @@ -856,7 +952,7 @@ PlasmoidItem { delayed: true } - // TODO: should I just remove option for blur from per-widget settings? + // TODO: should we remove option for blur from per-widget settings? // IMO doesn't make much sense to have only some widgets blurred... Binding { target: panelElement