Skip to content

Commit 26d68e6

Browse files
derrylclaude
andcommitted
Move theme files into themes/default/ and add -theme flag to scripts
Theme files (Main.qml, metadata.desktop, theme.conf, assets/, components/, faces/) now live under themes/default/ instead of the project root. This enables a multi-theme workflow where users copy themes/default/ to create new themes and preview them independently. Scripts accept an optional -theme flag (defaulting to "default"): ./scripts/preview.sh -theme foobar ./scripts/test-sddm.sh -theme foobar ./scripts/lint-qml.sh -theme foobar Preview and lint scripts create temporary symlinks (preview/components, preview/assets) pointing to the selected theme so QML relative imports resolve correctly. Symlinks are cleaned up on exit and gitignored. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 061b5b8 commit 26d68e6

13 files changed

Lines changed: 150 additions & 11 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Symlinks created by preview/lint scripts at runtime
2+
preview/components
3+
preview/assets

preview/Preview.qml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import QtQuick.Window
33
import QtQuick.Layouts
44
import QtQuick.Controls
55

6-
import "../components"
6+
import "components"
77

88
/*
99
* Preview.qml - Development harness for the SDDM theme.
@@ -15,8 +15,10 @@ import "../components"
1515
* Components receive their dependencies as explicit properties, so they
1616
* work identically whether driven by SDDM or by this preview.
1717
*
18-
* Usage: qml6 preview/Preview.qml
19-
* or: qmlscene6 preview/Preview.qml
18+
* The preview script symlinks components/ and assets/ into preview/
19+
* so that relative imports and asset paths resolve to the selected theme.
20+
*
21+
* Usage: ./scripts/preview.sh [-theme <name>]
2022
*/
2123

2224
Window {
@@ -34,7 +36,7 @@ Window {
3436
id: mockConfig
3537
// Set to "" to use the solid fallback color, or provide a path
3638
// to an image (e.g. drop your own into assets/background.jpg).
37-
property string background: Qt.resolvedUrl("../assets/background.jpg")
39+
property string background: Qt.resolvedUrl("assets/background.jpg")
3840
property string type: "image"
3941
property string color: "#1a1a2e"
4042
property string primaryColor: "#ffffff"

scripts/lint-qml.sh

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
# Runs qmllint (static) on all QML source files, then launches the preview
66
# under xvfb for a few seconds to catch runtime type-assignment warnings.
77
#
8-
# Usage: ./scripts/lint-qml.sh
8+
# Usage: ./scripts/lint-qml.sh [-theme <name>]
9+
#
10+
# Options:
11+
# -theme <name> Lint a specific theme (default: lint all themes)
912
#
1013
# Exit codes:
1114
# 0 All checks passed
@@ -18,6 +21,30 @@ PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
1821

1922
cd "$PROJECT_DIR"
2023

24+
# ── Parse arguments ─────────────────────────────────────────────
25+
THEME_NAME=""
26+
27+
while [[ $# -gt 0 ]]; do
28+
case "$1" in
29+
-theme)
30+
THEME_NAME="${2:?Error: -theme requires a name}"
31+
shift 2
32+
;;
33+
-h|--help)
34+
echo "Usage: $0 [-theme <name>]"
35+
echo ""
36+
echo "Options:"
37+
echo " -theme <name> Lint a specific theme (default: lint all themes)"
38+
exit 0
39+
;;
40+
*)
41+
echo "Unknown option: $1" >&2
42+
echo "Usage: $0 [-theme <name>]" >&2
43+
exit 1
44+
;;
45+
esac
46+
done
47+
2148
# ── Locate Qt 6 tools ────────────────────────────────────────────
2249
# Binary names and paths vary across distros:
2350
# Arch: qmllint, qml6 (on PATH)
@@ -41,13 +68,27 @@ QML_RUNTIME=$(find_tool qml6 qml)
4168

4269
FAILED=0
4370

71+
# Build list of theme directories to check.
72+
if [[ -n "$THEME_NAME" ]]; then
73+
THEME_DIRS=("themes/$THEME_NAME")
74+
if [[ ! -d "${THEME_DIRS[0]}" ]]; then
75+
echo "Error: theme directory not found: ${THEME_DIRS[0]}" >&2
76+
exit 1
77+
fi
78+
else
79+
THEME_DIRS=()
80+
for d in themes/*/; do
81+
[[ -d "$d" ]] && THEME_DIRS+=("${d%/}")
82+
done
83+
fi
84+
4485
# ── Static analysis with qmllint ──────────────────────────────────
4586
echo "=== qmllint: static analysis ==="
4687

4788
if [[ -z "$QMLLINT" ]]; then
4889
echo "SKIP: qmllint not found."
4990
else
50-
QML_FILES=$(find . -name '*.qml' -not -path './.git/*')
91+
QML_FILES=$(find "${THEME_DIRS[@]}" preview -name '*.qml' -not -path './.git/*')
5192
echo "Checking: $QML_FILES"
5293
echo ""
5394

@@ -81,7 +122,14 @@ fi
81122
export QT_QUICK_CONTROLS_STYLE=Basic
82123

83124
STDERR_LOG=$(mktemp)
84-
trap 'rm -f "$STDERR_LOG"' EXIT
125+
trap 'rm -f "$STDERR_LOG" "$PROJECT_DIR/preview/components" "$PROJECT_DIR/preview/assets"' EXIT
126+
127+
# Test with the default theme (or the specified one).
128+
RUNTIME_THEME="${THEME_DIRS[0]}"
129+
RUNTIME_THEME_DIR="$PROJECT_DIR/$RUNTIME_THEME"
130+
# Symlink the theme's components and assets into preview/ so QML resolves them.
131+
ln -sfn "$RUNTIME_THEME_DIR/components" "$PROJECT_DIR/preview/components"
132+
ln -sfn "$RUNTIME_THEME_DIR/assets" "$PROJECT_DIR/preview/assets"
85133

86134
# Run preview for 3 seconds under a virtual framebuffer, capture stderr.
87135
if command -v xvfb-run &>/dev/null; then

scripts/preview.sh

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,60 @@
55
# Watches all QML, conf, and image files. On any change, kills the
66
# running qml6 process and relaunches the Preview.qml harness.
77
#
8-
# Usage: ./scripts/preview.sh
8+
# Usage: ./scripts/preview.sh [-theme <name>]
9+
#
10+
# Options:
11+
# -theme <name> Preview the theme in themes/<name>/ (default: "default")
912
#
1013

1114
set -euo pipefail
1215

1316
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
1417
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
1518

19+
# ── Parse arguments ─────────────────────────────────────────────
20+
THEME_NAME="default"
21+
22+
while [[ $# -gt 0 ]]; do
23+
case "$1" in
24+
-theme)
25+
THEME_NAME="${2:?Error: -theme requires a name}"
26+
shift 2
27+
;;
28+
-h|--help)
29+
echo "Usage: $0 [-theme <name>]"
30+
echo ""
31+
echo "Options:"
32+
echo " -theme <name> Preview the theme in themes/<name>/ (default: \"default\")"
33+
exit 0
34+
;;
35+
*)
36+
echo "Unknown option: $1" >&2
37+
echo "Usage: $0 [-theme <name>]" >&2
38+
exit 1
39+
;;
40+
esac
41+
done
42+
43+
THEME_DIR="$PROJECT_DIR/themes/$THEME_NAME"
44+
45+
if [[ ! -d "$THEME_DIR" ]]; then
46+
echo "Error: theme directory not found: $THEME_DIR" >&2
47+
echo "" >&2
48+
echo "Available themes:" >&2
49+
for d in "$PROJECT_DIR"/themes/*/; do
50+
[[ -d "$d" ]] && echo " $(basename "$d")" >&2
51+
done
52+
exit 1
53+
fi
54+
55+
# ── Setup ───────────────────────────────────────────────────────
1656
ENTR_PID=""
1757

1858
cleanup() {
1959
trap - SIGINT SIGTERM # prevent re-entry
2060
[[ -n "$ENTR_PID" ]] && kill "$ENTR_PID" 2>/dev/null && wait "$ENTR_PID" 2>/dev/null
61+
rm -f "$PROJECT_DIR/preview/components" "$PROJECT_DIR/preview/assets"
2162
echo ""
2263
echo "Preview stopped."
2364
exit 0
@@ -29,8 +70,14 @@ trap cleanup SIGINT SIGTERM
2970
# unavailable outside a full Plasma session.
3071
export QT_QUICK_CONTROLS_STYLE=Basic
3172

73+
# Symlink the theme's components and assets into preview/ so QML's
74+
# relative imports and asset paths resolve to the selected theme.
75+
ln -sfn "$THEME_DIR/components" "$PROJECT_DIR/preview/components"
76+
ln -sfn "$THEME_DIR/assets" "$PROJECT_DIR/preview/assets"
77+
3278
echo "=== KDE Lockscreen Builder — Live Preview ==="
3379
echo "Project: $PROJECT_DIR"
80+
echo "Theme: $THEME_NAME ($THEME_DIR)"
3481
echo "Press Ctrl+C to stop"
3582
echo ""
3683

scripts/test-sddm.sh

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,55 @@
66
# project directory. Shows real user list, session list, and keyboard
77
# state. Login/power actions won't actually execute in test mode.
88
#
9-
# Usage: ./scripts/test-sddm.sh
9+
# Usage: ./scripts/test-sddm.sh [-theme <name>]
10+
#
11+
# Options:
12+
# -theme <name> Test the theme in themes/<name>/ (default: "default")
1013
#
1114

1215
set -euo pipefail
1316

1417
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
1518
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
1619

20+
# ── Parse arguments ─────────────────────────────────────────────
21+
THEME_NAME="default"
22+
23+
while [[ $# -gt 0 ]]; do
24+
case "$1" in
25+
-theme)
26+
THEME_NAME="${2:?Error: -theme requires a name}"
27+
shift 2
28+
;;
29+
-h|--help)
30+
echo "Usage: $0 [-theme <name>]"
31+
echo ""
32+
echo "Options:"
33+
echo " -theme <name> Test the theme in themes/<name>/ (default: \"default\")"
34+
exit 0
35+
;;
36+
*)
37+
echo "Unknown option: $1" >&2
38+
echo "Usage: $0 [-theme <name>]" >&2
39+
exit 1
40+
;;
41+
esac
42+
done
43+
44+
THEME_DIR="$PROJECT_DIR/themes/$THEME_NAME"
45+
46+
if [[ ! -d "$THEME_DIR" ]]; then
47+
echo "Error: theme directory not found: $THEME_DIR" >&2
48+
echo "" >&2
49+
echo "Available themes:" >&2
50+
for d in "$PROJECT_DIR"/themes/*/; do
51+
[[ -d "$d" ]] && echo " $(basename "$d")" >&2
52+
done
53+
exit 1
54+
fi
55+
1756
echo "=== KDE Lockscreen Builder — SDDM Test Mode ==="
18-
echo "Theme: $PROJECT_DIR"
57+
echo "Theme: $THEME_NAME ($THEME_DIR)"
1958
echo ""
2059

21-
sddm-greeter-qt6 --test-mode --theme "$PROJECT_DIR"
60+
sddm-greeter-qt6 --test-mode --theme "$THEME_DIR"
File renamed without changes.

0 commit comments

Comments
 (0)