200 lines
6.1 KiB
Bash
Executable File
200 lines
6.1 KiB
Bash
Executable File
#!/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
|
|
}
|
|
|
|
get_bottom_taskmanagers() {
|
|
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='') != 'org.kde.plasma.icontasks':
|
|
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_taskmanager_behavior() {
|
|
local json
|
|
json="$(get_bottom_taskmanagers)"
|
|
[[ -z "$json" || "$json" == "[]" ]] && return 0
|
|
python - <<'PY' "$json" "$CONFIG_FILE"
|
|
import json, subprocess, sys
|
|
pairs = json.loads(sys.argv[1])
|
|
config_file = sys.argv[2]
|
|
for item in pairs:
|
|
cid = item['containment']
|
|
aid = item['applet']
|
|
subprocess.call([
|
|
'kwriteconfig6', '--file', config_file,
|
|
'--group', 'Containments', '--group', str(cid),
|
|
'--group', 'Applets', '--group', str(aid),
|
|
'--group', 'Configuration', '--group', 'General',
|
|
'--key', 'unhideOnAttention', 'false'
|
|
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
PY
|
|
}
|
|
|
|
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_taskmanager_behavior
|
|
apply_colorizer_preset
|
|
}
|
|
|
|
main "$@"
|