feat: add KDE Plasma customization scripts and docs
This commit is contained in:
148
scripts/recalc-plasma-bottom-docks.sh
Executable file
148
scripts/recalc-plasma-bottom-docks.sh
Executable 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 "$@"
|
||||
Reference in New Issue
Block a user