#!/usr/bin/env bash # NexusOS KDE Plasma theme installer — idempotent, safe to re-run. # Equivalent of assets/themes/install-theme.sh but for KDE. # # Usage: # assets/themes/KDE/install-plasma.sh [--no-sddm] # # --no-sddm skip the SDDM step (requires sudo) — useful for live testing set -euo pipefail KDE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO="$(cd "$KDE/../../.." && pwd)" NO_SDDM=0 FORCE_PANEL=0 for arg in "$@"; do [[ "$arg" == "--no-sddm" ]] && NO_SDDM=1 [[ "$arg" == "--panel" ]] && FORCE_PANEL=1 done echo "NexusOS KDE installer — repo: $REPO" # ── 1. Create target directories ──────────────────────────────────────── mkdir -p \ ~/.local/share/aurorae/themes \ ~/.local/share/plasma/desktoptheme \ ~/.local/share/color-schemes \ ~/.local/share/konsole \ ~/.config/Kvantum # ── 2. Symlink theme directories (update automatically on git pull) ────── ln -sfn "$KDE/aurorae/NexusOS" ~/.local/share/aurorae/themes/NexusOS ln -sfn "$KDE/plasma/NexusOS" ~/.local/share/plasma/desktoptheme/NexusOS ln -sfn "$KDE/kvantum/NexusOS" ~/.config/Kvantum/NexusOS echo " [ok] theme symlinks" # ── 3. Copy files that need to be in specific locations (not symlinks) ─── cp -f "$KDE/plasma/NexusOS/NexusOS.colors" ~/.local/share/color-schemes/ cp -f "$KDE/konsole/NexusOS.colorscheme" ~/.local/share/konsole/ cp -f "$KDE/konsole/NexusOS-Promethean.colorscheme" ~/.local/share/konsole/ cp -f "$KDE/konsole/Promethean.profile" ~/.local/share/konsole/ echo " [ok] color scheme + konsole files" # ── 4. KDE color scheme ────────────────────────────────────────────────── if command -v plasma-apply-colorscheme &>/dev/null; then plasma-apply-colorscheme NexusOS 2>/dev/null && echo " [ok] color scheme applied" else echo " [skip] plasma-apply-colorscheme not found — apply color scheme manually" fi # ── 5. Kvantum ─────────────────────────────────────────────────────────── if command -v kvantummanager &>/dev/null; then kvantummanager --set NexusOS 2>/dev/null && echo " [ok] Kvantum set to NexusOS" else echo " [skip] kvantummanager not found — install qt5-style-kvantum and run: kvantummanager --set NexusOS" fi # ── 6. KWin Aurorae decoration ─────────────────────────────────────────── if command -v kwriteconfig5 &>/dev/null; then kwriteconfig5 --file kwinrc \ --group "org.kde.kdecoration2" --key library "org.kde.kwin.aurorae" kwriteconfig5 --file kwinrc \ --group "org.kde.kdecoration2" --key theme "__aurorae__svg__NexusOS" # Buttons on the right: minimize, maximize, close (I=minimize, A=maximize, X=close) kwriteconfig5 --file kwinrc \ --group "org.kde.kdecoration2" --key ButtonsOnLeft "" kwriteconfig5 --file kwinrc \ --group "org.kde.kdecoration2" --key ButtonsOnRight "IAX" echo " [ok] KWin decoration: Aurorae NexusOS, buttons right" else echo " [skip] kwriteconfig5 not found — configure KWin decoration manually" fi # ── 7. Plasma shell theme ──────────────────────────────────────────────── if command -v plasma-apply-desktoptheme &>/dev/null; then plasma-apply-desktoptheme NexusOS 2>/dev/null && echo " [ok] Plasma shell theme: NexusOS" else echo " [skip] plasma-apply-desktoptheme not found — apply desktop theme manually" fi # ── 8. Lock screen ─────────────────────────────────────────────────────── # Plasma 5.27 draws the lock screen from a look-and-feel package's # contents/lockscreen, and [Greeter]Theme names that PACKAGE. The old value here # ("NexusOS") was not a look-and-feel id, so it silently fell back to Breeze. # The standalone kscreenlocker theme that value referred to targeted an earlier # kscreenlocker API that 5.27 no longer loads, and has been deleted. # # Breeze's lock UI is deliberately kept rather than replaced: a lock screen that # fails to load is one you cannot get back through. Only the wallpaper is ours, # which is what carries the brushed-metal look. if command -v kwriteconfig5 &>/dev/null; then kwriteconfig5 --file kscreenlockerrc --group Greeter --key Theme org.kde.breeze.desktop LOCK_BG="$KDE/sddm/NexusOS-QML/assets/background.png" if [[ -f "$LOCK_BG" ]]; then kwriteconfig5 --file kscreenlockerrc \ --group Greeter --group Wallpaper --group org.kde.image --group General \ --key Image "$LOCK_BG" echo " [ok] lock screen wallpaper: NexusOS brushed metal" fi fi # ── 9. GTK apps under Plasma ───────────────────────────────────────────── if command -v kwriteconfig5 &>/dev/null; then kwriteconfig5 --file kdeglobals --group KDE --key widgetStyle "kvantum-dark" kwriteconfig5 --file kdeglobals --group Icons --key Theme NexusOS kwriteconfig5 --file kdeglobals --group General \ --key font "Ubuntu,10,-1,5,50,0,0,0,0,0" echo " [ok] kdeglobals: Kvantum style, NexusOS icons, Ubuntu 10" fi if command -v gsettings &>/dev/null; then gsettings set org.gnome.desktop.interface gtk-theme NexusOS 2>/dev/null || true gsettings set org.gnome.desktop.interface icon-theme NexusOS 2>/dev/null || true echo " [ok] gsettings: GTK theme + icons = NexusOS" fi # ── 10. SDDM login theme ───────────────────────────────────────────────── if [[ $NO_SDDM -eq 0 ]]; then echo " Deploying SDDM theme + KDE session entry (requires sudo)..." sudo cp -r "$KDE/sddm/NexusOS-QML" /usr/share/sddm/themes/ sudo cp "$REPO/management/sessions/nexusos-kde.desktop" /usr/share/xsessions/ if command -v kwriteconfig5 &>/dev/null; then sudo kwriteconfig5 --file /etc/sddm.conf.d/nexusos.conf --group Theme --key Current NexusOS-QML else # Fallback: write the INI directly sudo bash -c 'printf "[Theme]\nCurrent=NexusOS-QML\n" > /etc/sddm.conf.d/nexusos.conf' fi echo " [ok] SDDM theme: NexusOS-QML" echo " [ok] KDE session: NexusOS-KDE added to /usr/share/xsessions/" else echo " [skip] SDDM (--no-sddm passed)" fi # ── 11. Promethean Terminal desktop launcher ────────────────────────────── DESKTOP_SRC="$REPO/bin/promethean/promethean-terminal.desktop" DESKTOP_DEST="$HOME/.local/share/applications/promethean-terminal.desktop" if [[ -f "$DESKTOP_SRC" ]]; then cp -f "$DESKTOP_SRC" "$DESKTOP_DEST" echo " [ok] Promethean Terminal launcher updated" fi # ── 11b. Global Theme + wallpaper ──────────────────────────────────────── # Copied, NOT symlinked, unlike the theme dirs above: KPackage silently skips a # symlinked package directory, so a symlinked look-and-feel never appears in # `lookandfeeltool -l` or System Settings at all. Aurorae/desktoptheme/Kvantum # read their directories directly and are fine as symlinks. LNF_SRC="$KDE/look-and-feel/com.nexusos.desktop" WALL_SRC="$KDE/wallpaper/NexusOS" if [[ -d "$LNF_SRC" ]]; then mkdir -p ~/.local/share/plasma/look-and-feel ~/.local/share/wallpapers rm -rf ~/.local/share/plasma/look-and-feel/com.nexusos.desktop cp -rL "$LNF_SRC" ~/.local/share/plasma/look-and-feel/ rm -rf ~/.local/share/wallpapers/NexusOS cp -rL "$WALL_SRC" ~/.local/share/wallpapers/ echo " [ok] Global Theme + wallpaper packages installed" if command -v lookandfeeltool &>/dev/null; then # Verify registration before applying. KPackage reports nothing when it # rejects a package, so without this check a botched install is silent and # you only find out by opening System Settings. if lookandfeeltool -l 2>/dev/null | grep -qx "com.nexusos.desktop"; then lookandfeeltool -a com.nexusos.desktop 2>/dev/null \ && echo " [ok] Global Theme applied (splash, colors, decoration)" else echo " [WARN] com.nexusos.desktop did not register with KPackage." echo " Most likely it was symlinked instead of copied -- KPackage" echo " skips symlinked package directories silently." fi fi if command -v plasma-apply-wallpaperimage &>/dev/null; then plasma-apply-wallpaperimage ~/.local/share/wallpapers/NexusOS &>/dev/null \ && echo " [ok] wallpaper applied" fi fi # ── 11c. Panel layout + dock ───────────────────────────────────────────── # The XFCE panel rebuilt with native Plasma widgets, plus Plank for the dock # (its config and NexusOS theme already exist under assets/themes/restore-snapshot). # # Applied ONCE, guarded by a marker file. This rewrites the panel from scratch, # so re-running it on every restore would wipe any widget you added since. Pass # --panel to force it, e.g. after a fresh install or to undo panel experiments. PANEL_MARKER="$HOME/.config/nexusos-panel-applied" PANEL_JS="$KDE/panel-layout.js" if [[ -f "$PANEL_JS" ]] && { [[ ! -f "$PANEL_MARKER" ]] || [[ $FORCE_PANEL -eq 1 ]]; }; then if qdbus org.kde.plasmashell /PlasmaShell evaluateScript \ "$(sed "s|__NEXUS_ROOT__|$REPO|g" "$PANEL_JS")" &>/dev/null; then touch "$PANEL_MARKER" echo " [ok] panel layout applied (top, 36px, Nexus launcher)" else echo " [skip] panel layout — plasmashell not running" fi elif [[ -f "$PANEL_MARKER" ]]; then echo " [ok] panel layout already applied (--panel to redo)" fi # Plank autostart. Plank is a GTK X11 app and runs fine under Plasma; this is # the same dock, config and theme the XFCE session used. if command -v plank &>/dev/null; then mkdir -p ~/.config/autostart # Symlink, matching bin/panel/install.sh. cp fails outright when the target is # already a symlink back to this same file ("are the same file"), which made # the step look like it had silently done nothing. ln -sfn "$REPO/management/autostart/plank.desktop" ~/.config/autostart/plank.desktop \ && echo " [ok] Plank autostart installed" pgrep -x plank &>/dev/null || { setsid plank /dev/null & disown; } fi # ── 11d. Custom shortcut: region screenshot to clipboard ───────────────── # Meta+Shift+S -> `xfce4-screenshooter -rc`, the equivalent of the XFCE binding. # Spectacle is not installed by kde-plasma-desktop, and xfce4-screenshooter # works fine under Plasma, so this keeps the tool that is already here. # # Written as ONE atomic replace rather than a series of kwriteconfig5 calls, # because khotkeys watches khotkeysrc and rewrites it from its own model on # every change. # # The UUID below is FIXED, not generated. kglobalaccel records the key binding # in kglobalshortcutsrc against the action's UUID, so a fresh UUID on each run # cannot take a key that the previous run's UUID already holds: the entry gets # registered with no shortcut at all, and every re-run leaves another dead # registration behind. A stable UUID means a re-run re-claims its own binding. if ! grep -q "^Key=Meta+Shift+S$" ~/.config/khotkeysrc 2>/dev/null; then python3 - <<'PYEOF' import pathlib, re # Fixed so re-runs reclaim the same kglobalaccel registration. SHORTCUT_UUID = "87a4ba1e-4f01-4a79-9cd1-b73c17d459ea" p = pathlib.Path.home() / ".config" / "khotkeysrc" s = p.read_text() if p.exists() else "[Data]\nDataCount=0\n" # Drop any half-written entry from an earlier failed attempt. for m in re.findall(r"\[Data_(\d+)\]\n(?:[^\[]*)", s): blk = re.search(r"\[Data_%s\]\n((?:[^\[]*))" % m, s) if blk and "Screenshot region to clipboard" in blk.group(1): s = re.sub(r"\n\[Data_%s[^\]]*\]\n(?:[^\[]*)" % m, "\n", s) count = int(re.search(r"\[Data\]\nDataCount=(\d+)", s).group(1)) n = count + 1 s = re.sub(r"(\[Data\]\nDataCount=)\d+", r"\g<1>%d" % n, s, count=1) s = s.rstrip("\n") + """ [Data_%d] Comment=Select a region and copy it straight to the clipboard Enabled=true Name=Screenshot region to clipboard Type=SIMPLE_ACTION_DATA [Data_%dActions] ActionsCount=1 [Data_%dActions0] CommandURL=xfce4-screenshooter -rc Type=COMMAND_URL [Data_%dConditions] Comment= ConditionsCount=0 [Data_%dTriggers] Comment=Simple_action TriggersCount=1 [Data_%dTriggers0] Key=Meta+Shift+S Type=SHORTCUT Uuid={%s} """ % (n, n, n, n, n, n, SHORTCUT_UUID) tmp = p.with_suffix(".nexustmp") tmp.write_text(s) tmp.replace(p) PYEOF qdbus org.kde.kded5 /modules/khotkeys reread_configuration &>/dev/null \ && echo " [ok] Meta+Shift+S -> region screenshot to clipboard" else echo " [ok] screenshot shortcut already bound" fi # ── 12. Apply live changes (if Plasma is running) ──────────────────────── if qdbus org.kde.KWin /KWin reconfigure 2>/dev/null; then echo " [ok] KWin reconfigured" # Restart plasmashell to pick up new shell theme. # setsid + closed stdio is load-bearing, not tidiness: the restarted shell # outlives this script, and if it inherits our stdout it holds the write end # of the caller's pipe open forever. `ncp restore` captures output, so a # plain `kstart5 plasmashell &` hangs the entire restore after the theme is # already applied -- which looks like a failure and isn't one. if command -v kquitapp5 &>/dev/null && command -v kstart5 &>/dev/null; then kquitapp5 plasmashell 2>/dev/null sleep 1 setsid kstart5 plasmashell /dev/null 2>&1 & disown 2>/dev/null || true echo " [ok] plasmashell restarted" fi fi echo "" echo "NexusOS KDE theme installed. On first KDE session:" echo " 1. System Settings → Appearance → verify all components show NexusOS" echo " 2. Panel: right-click → Edit Panel to adjust height/position" echo " 3. Konsole: Settings → Edit Profile → select Promethean (for Promethean Terminal)" echo " 4. Test lock screen: Meta+L"