feat: add KDE Plasma customization scripts and docs

This commit is contained in:
droid
2026-03-23 16:40:14 +08:00
commit f0ced79af7
10 changed files with 4924 additions and 0 deletions

View File

@@ -0,0 +1,148 @@
#!/usr/bin/env bash
set -euo pipefail
CONFIG_FILE="$HOME/.config/plasma-org.kde.plasma.desktop-appletsrc"
CUSTOM_PRESET_DIR="$HOME/.config/panel-colorizer/presets/LogicDock"
USER_BUILTIN_PRESET_DIR="$HOME/.local/share/plasma/plasmoids/luisbocanegra.panel.colorizer/contents/ui/presets/Dock"
SYSTEM_BUILTIN_PRESET_DIR="/usr/share/plasma/plasmoids/luisbocanegra.panel.colorizer/contents/ui/presets/Dock"
PRESET_DIR="$CUSTOM_PRESET_DIR"
[[ -d "$PRESET_DIR" ]] || PRESET_DIR="$USER_BUILTIN_PRESET_DIR"
[[ -d "$PRESET_DIR" ]] || PRESET_DIR="$SYSTEM_BUILTIN_PRESET_DIR"
wait_for_plasma() {
for _ in $(seq 1 30); do
if qdbus6 org.kde.plasmashell /PlasmaShell org.freedesktop.DBus.Introspectable.Introspect >/dev/null 2>&1; then
return 0
fi
sleep 1
done
return 1
}
get_screen_count() {
python - <<'PY'
import re, subprocess
text = subprocess.check_output(["kscreen-doctor", "-o"], text=True, errors="ignore")
text = re.sub(r'\x1b\[[0-9;]*[A-Za-z]', '', text)
blocks = re.split(r'(?=Output: )', text)
count = 0
for block in blocks:
if not block.startswith('Output: '):
continue
if re.search(r'^\s*enabled\s*$', block, re.M):
count += 1
print(max(count, 1))
PY
}
get_bottom_colorizers() {
python - <<'PY'
import configparser, json, os, pathlib, re
cfg = pathlib.Path(os.path.expanduser('~/.config/plasma-org.kde.plasma.desktop-appletsrc'))
cp = configparser.RawConfigParser(interpolation=None)
cp.optionxform = str
cp.read(cfg)
items = []
for sec in cp.sections():
m = re.fullmatch(r'Containments\]\[(\d+)', sec)
if not m:
continue
cid = int(m.group(1))
if cp.get(sec, 'plugin', fallback='') != 'org.kde.panel':
continue
if cp.get(sec, 'location', fallback='') not in ('4', 'bottom'):
continue
for asec in cp.sections():
am = re.fullmatch(rf'Containments\]\[{cid}\]\[Applets\]\[(\d+)', asec)
if not am:
continue
if cp.get(asec, 'plugin', fallback='') != 'luisbocanegra.panel.colorizer':
continue
aid = int(am.group(1))
items.append({'containment': cid, 'applet': aid})
print(json.dumps(sorted(items, key=lambda x: (x['containment'], x['applet']))))
PY
}
ensure_bottom_panels() {
local screen_count="$1"
local targets
targets=$(python - <<PY
n = int(${screen_count})
print(','.join(str(i) for i in range(n)))
PY
)
qdbus6 org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript "
function bottomPanelOnScreen(screenId) {
for (var i = 0; i < panelIds.length; ++i) {
var p = panelById(panelIds[i]);
if (p.location == 'bottom' && p.screen == screenId) return p;
}
return null;
}
function clamp(v, lo, hi) {
return Math.max(lo, Math.min(hi, v));
}
var targetScreens = [${targets}];
for (var i = 0; i < targetScreens.length; ++i) {
var sid = targetScreens[i];
var panel = bottomPanelOnScreen(sid);
if (!panel) {
panel = new Panel;
panel.screen = sid;
panel.location = 'bottom';
panel.addWidget('org.kde.plasma.icontasks');
panel.addWidget('luisbocanegra.panel.colorizer');
}
var g = screenGeometry(sid);
var h = Math.round(clamp(g.height * 0.048, 70, 76));
panel.thickness = h;
panel.height = h;
panel.lengthMode = 'fit';
panel.alignment = 'center';
panel.floating = true;
panel.hiding = 'autohide';
panel.opacity = 'adaptive';
}
"
}
apply_colorizer_preset() {
local json
json="$(get_bottom_colorizers)"
[[ -z "$json" || "$json" == "[]" ]] && return 0
python - <<'PY' "$json" "$PRESET_DIR" "$CONFIG_FILE"
import json, subprocess, sys, time
pairs = json.loads(sys.argv[1])
preset_dir = sys.argv[2]
config_file = sys.argv[3]
for item in pairs:
cid = item['containment']
aid = item['applet']
service = f'luisbocanegra.panel.colorizer.c{cid}.w{aid}'
for _ in range(12):
try:
subprocess.check_call(['qdbus6', service, '/preset', 'preset', preset_dir], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
break
except subprocess.CalledProcessError:
time.sleep(0.5)
subprocess.call([
'kwriteconfig6', '--file', config_file,
'--group', 'Containments', '--group', str(cid),
'--group', 'Applets', '--group', str(aid),
'--group', 'Configuration', '--group', 'General',
'--key', 'hideWidget', 'true'
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
PY
}
main() {
wait_for_plasma || exit 0
local screen_count
screen_count="$(get_screen_count)"
ensure_bottom_panels "$screen_count"
apply_colorizer_preset
}
main "$@"