feat(assets): NexusOS asset + theme rebrand
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@@ -0,0 +1,30 @@
|
||||
[General]
|
||||
TitleAlignment=Left
|
||||
TitleEdgeTop=0
|
||||
TitleEdgeBottom=0
|
||||
TitleEdgeLeft=12
|
||||
TitleEdgeRight=8
|
||||
TitleBorderLeft=0
|
||||
TitleBorderRight=0
|
||||
TitleHeight=30
|
||||
BorderLeft=1
|
||||
BorderRight=1
|
||||
BorderBottom=5
|
||||
BorderTop=0
|
||||
ButtonWidth=32
|
||||
ButtonSize=32
|
||||
ButtonSpacing=8
|
||||
ButtonMarginTop=0
|
||||
ExplicitButtonSpacer=0
|
||||
PaddingTop=0
|
||||
PaddingBottom=0
|
||||
PaddingRight=0
|
||||
PaddingLeft=0
|
||||
ActiveTextColor=#f2f2f2
|
||||
ActiveTextShadowColor=0,0,0,0
|
||||
InactiveTextColor=#6e7173
|
||||
InactiveTextShadowColor=0,0,0,0
|
||||
Shadow=false
|
||||
ShadowColor=0,0,0,180
|
||||
ShadowStrength=100
|
||||
Animation=0
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
|
||||
<g id="active-center">
|
||||
<circle cx="7.5" cy="7.5" r="1.5" fill="#a8a8a8"/>
|
||||
<circle cx="12.5" cy="7.5" r="1.5" fill="#a8a8a8"/>
|
||||
<circle cx="7.5" cy="12.5" r="1.5" fill="#a8a8a8"/>
|
||||
<circle cx="12.5" cy="12.5" r="1.5" fill="#a8a8a8"/>
|
||||
</g>
|
||||
<g id="hover-center">
|
||||
<circle cx="10" cy="10" r="9" fill="#88008f"/>
|
||||
<circle cx="7.5" cy="7.5" r="1.5" fill="#ffffff"/>
|
||||
<circle cx="12.5" cy="7.5" r="1.5" fill="#ffffff"/>
|
||||
<circle cx="7.5" cy="12.5" r="1.5" fill="#ffffff"/>
|
||||
<circle cx="12.5" cy="12.5" r="1.5" fill="#ffffff"/>
|
||||
</g>
|
||||
<g id="pressed-center">
|
||||
<circle cx="10" cy="10" r="9" fill="#5e0066"/>
|
||||
<circle cx="7.5" cy="7.5" r="1.5" fill="#ffffff"/>
|
||||
<circle cx="12.5" cy="7.5" r="1.5" fill="#ffffff"/>
|
||||
<circle cx="7.5" cy="12.5" r="1.5" fill="#ffffff"/>
|
||||
<circle cx="12.5" cy="12.5" r="1.5" fill="#ffffff"/>
|
||||
</g>
|
||||
<g id="inactive-center">
|
||||
<circle cx="7.5" cy="7.5" r="1.5" fill="#6e7173"/>
|
||||
<circle cx="12.5" cy="7.5" r="1.5" fill="#6e7173"/>
|
||||
<circle cx="7.5" cy="12.5" r="1.5" fill="#6e7173"/>
|
||||
<circle cx="12.5" cy="12.5" r="1.5" fill="#6e7173"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
|
||||
<g id="active-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#e9524a"/>
|
||||
</g>
|
||||
<g id="hover-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#e9524a"/>
|
||||
<path d="M7.5,7.5 L12.5,12.5 M12.5,7.5 L7.5,12.5" stroke="#4a0000" stroke-width="1.2" stroke-linecap="round"/>
|
||||
</g>
|
||||
<g id="pressed-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#c04040"/>
|
||||
<path d="M7.5,7.5 L12.5,12.5 M12.5,7.5 L7.5,12.5" stroke="#4a0000" stroke-width="1.2" stroke-linecap="round"/>
|
||||
</g>
|
||||
<g id="inactive-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#5d5d5d"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 674 B |
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
NexusOS Aurorae decoration — PlasmaCore.FrameSvg format.
|
||||
|
||||
Aurorae uses PlasmaCore.FrameSvg, which requires elements named:
|
||||
{prefix}-topleft {prefix}-top {prefix}-topright
|
||||
{prefix}-left {prefix}-center {prefix}-right
|
||||
{prefix}-bottomleft {prefix}-bottom {prefix}-bottomright
|
||||
|
||||
Prefixes used: decoration, decoration-inactive,
|
||||
decoration-maximized, decoration-maximized-inactive
|
||||
|
||||
All elements sit at (0,0). QSvgRenderer renders each by ID independently
|
||||
so coordinate overlap is harmless — FrameSvg uses each element's own
|
||||
bounding box as the source rect and stretches/tiles it as needed.
|
||||
|
||||
Corner sizes drive FrameSvg margin inference:
|
||||
topleft = 1×30 → left=1px, top(titlebar)=30px
|
||||
bottomleft = 1×5 → bottom=5px, right=1px
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="32" height="36">
|
||||
|
||||
<!-- ══ ACTIVE (non-maximized) — prefix: decoration ══════════════════ -->
|
||||
|
||||
<g id="decoration-topleft">
|
||||
<rect x="0" y="0" width="1" height="29" fill="#1e1526"/>
|
||||
<rect x="0" y="29" width="1" height="1" fill="#8cc63f"/>
|
||||
</g>
|
||||
<g id="decoration-top">
|
||||
<rect x="0" y="0" width="32" height="29" fill="#1e1526"/>
|
||||
<rect x="0" y="29" width="32" height="1" fill="#8cc63f"/>
|
||||
</g>
|
||||
<g id="decoration-topright">
|
||||
<rect x="0" y="0" width="1" height="29" fill="#1e1526"/>
|
||||
<rect x="0" y="29" width="1" height="1" fill="#8cc63f"/>
|
||||
</g>
|
||||
|
||||
<rect id="decoration-left" x="0" y="0" width="1" height="1" fill="#2e3236"/>
|
||||
<rect id="decoration-center" x="0" y="0" width="32" height="1" fill="none"/>
|
||||
<rect id="decoration-right" x="0" y="0" width="1" height="1" fill="#2e3236"/>
|
||||
|
||||
<rect id="decoration-bottomleft" x="0" y="0" width="1" height="5" fill="#2e3236"/>
|
||||
<rect id="decoration-bottom" x="0" y="0" width="32" height="5" fill="#2e3236"/>
|
||||
<rect id="decoration-bottomright" x="0" y="0" width="1" height="5" fill="#2e3236"/>
|
||||
|
||||
|
||||
<!-- ══ INACTIVE (non-maximized) — prefix: decoration-inactive ═══════ -->
|
||||
|
||||
<rect id="decoration-inactive-topleft" x="0" y="0" width="1" height="30" fill="#1a1a20"/>
|
||||
<rect id="decoration-inactive-top" x="0" y="0" width="32" height="30" fill="#1a1a20"/>
|
||||
<rect id="decoration-inactive-topright" x="0" y="0" width="1" height="30" fill="#1a1a20"/>
|
||||
|
||||
<rect id="decoration-inactive-left" x="0" y="0" width="1" height="1" fill="#252525"/>
|
||||
<rect id="decoration-inactive-center" x="0" y="0" width="32" height="1" fill="none"/>
|
||||
<rect id="decoration-inactive-right" x="0" y="0" width="1" height="1" fill="#252525"/>
|
||||
|
||||
<rect id="decoration-inactive-bottomleft" x="0" y="0" width="1" height="5" fill="#252525"/>
|
||||
<rect id="decoration-inactive-bottom" x="0" y="0" width="32" height="5" fill="#252525"/>
|
||||
<rect id="decoration-inactive-bottomright" x="0" y="0" width="1" height="5" fill="#252525"/>
|
||||
|
||||
|
||||
<!-- ══ MAXIMIZED ACTIVE — prefix: decoration-maximized ═════════════ -->
|
||||
<!-- FrameSvg uses NoBorder for maximized: only -center is rendered,
|
||||
stretched to fill the full width × maximizedBorders.top (TitleHeight). -->
|
||||
|
||||
<g id="decoration-maximized-center">
|
||||
<rect x="0" y="0" width="32" height="29" fill="#1e1526"/>
|
||||
<rect x="0" y="29" width="32" height="1" fill="#8cc63f"/>
|
||||
</g>
|
||||
|
||||
<rect id="decoration-maximized-topleft" x="0" y="0" width="1" height="30" fill="#1e1526"/>
|
||||
<rect id="decoration-maximized-top" x="0" y="0" width="32" height="30" fill="#1e1526"/>
|
||||
<rect id="decoration-maximized-topright" x="0" y="0" width="1" height="30" fill="#1e1526"/>
|
||||
<rect id="decoration-maximized-left" x="0" y="0" width="1" height="1" fill="none"/>
|
||||
<rect id="decoration-maximized-right" x="0" y="0" width="1" height="1" fill="none"/>
|
||||
<rect id="decoration-maximized-bottomleft" x="0" y="0" width="1" height="1" fill="none"/>
|
||||
<rect id="decoration-maximized-bottom" x="0" y="0" width="32" height="1" fill="none"/>
|
||||
<rect id="decoration-maximized-bottomright" x="0" y="0" width="1" height="1" fill="none"/>
|
||||
|
||||
|
||||
<!-- ══ MAXIMIZED INACTIVE — prefix: decoration-maximized-inactive ══ -->
|
||||
|
||||
<rect id="decoration-maximized-inactive-center" x="0" y="0" width="32" height="30" fill="#1a1a20"/>
|
||||
<rect id="decoration-maximized-inactive-topleft" x="0" y="0" width="1" height="30" fill="#1a1a20"/>
|
||||
<rect id="decoration-maximized-inactive-top" x="0" y="0" width="32" height="30" fill="#1a1a20"/>
|
||||
<rect id="decoration-maximized-inactive-topright" x="0" y="0" width="1" height="30" fill="#1a1a20"/>
|
||||
<rect id="decoration-maximized-inactive-left" x="0" y="0" width="1" height="1" fill="none"/>
|
||||
<rect id="decoration-maximized-inactive-right" x="0" y="0" width="1" height="1" fill="none"/>
|
||||
<rect id="decoration-maximized-inactive-bottomleft" x="0" y="0" width="1" height="1" fill="none"/>
|
||||
<rect id="decoration-maximized-inactive-bottom" x="0" y="0" width="32" height="1" fill="none"/>
|
||||
<rect id="decoration-maximized-inactive-bottomright" x="0" y="0" width="1" height="1" fill="none"/>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
|
||||
<g id="active-center">
|
||||
<path d="M5,13 L10,7 L15,13" fill="none" stroke="#a8a8a8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<g id="hover-center">
|
||||
<circle cx="10" cy="10" r="9" fill="#88008f"/>
|
||||
<path d="M5,13 L10,7 L15,13" fill="none" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<g id="pressed-center">
|
||||
<circle cx="10" cy="10" r="9" fill="#5e0066"/>
|
||||
<path d="M5,13 L10,7 L15,13" fill="none" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<g id="inactive-center">
|
||||
<path d="M5,13 L10,7 L15,13" fill="none" stroke="#6e7173" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 862 B |
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
|
||||
<g id="active-center">
|
||||
<path d="M5,7 L10,13 L15,7" fill="none" stroke="#a8a8a8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<g id="hover-center">
|
||||
<circle cx="10" cy="10" r="9" fill="#88008f"/>
|
||||
<path d="M5,7 L10,13 L15,7" fill="none" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<g id="pressed-center">
|
||||
<circle cx="10" cy="10" r="9" fill="#5e0066"/>
|
||||
<path d="M5,7 L10,13 L15,7" fill="none" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<g id="inactive-center">
|
||||
<path d="M5,7 L10,13 L15,7" fill="none" stroke="#6e7173" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 858 B |
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
|
||||
<g id="active-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#59c837"/>
|
||||
</g>
|
||||
<g id="hover-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#59c837"/>
|
||||
<rect x="7" y="7" width="6" height="6" rx="0.8" fill="none" stroke="#003a00" stroke-width="1.1"/>
|
||||
</g>
|
||||
<g id="pressed-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#3d9a1f"/>
|
||||
<rect x="7" y="7" width="6" height="6" rx="0.8" fill="none" stroke="#003a00" stroke-width="1.1"/>
|
||||
</g>
|
||||
<g id="inactive-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#5d5d5d"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 648 B |
@@ -0,0 +1,18 @@
|
||||
[Desktop Entry]
|
||||
Name=NexusOS
|
||||
Comment=Flat dark-purple window decoration, lime-green focus accent
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=org.kde.kwin.decoration
|
||||
|
||||
[KWin]
|
||||
Type=Aurorae
|
||||
|
||||
X-KDE-PluginInfo-Author=Jon
|
||||
X-KDE-PluginInfo-Email=
|
||||
X-KDE-PluginInfo-Name=NexusOS
|
||||
X-KDE-PluginInfo-Version=1.0
|
||||
X-KDE-PluginInfo-Website=
|
||||
X-KDE-PluginInfo-Category=
|
||||
X-KDE-PluginInfo-Depends=
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
X-KDE-PluginInfo-EnabledByDefault=false
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
|
||||
<g id="active-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#f1ae1b"/>
|
||||
</g>
|
||||
<g id="hover-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#f1ae1b"/>
|
||||
<line x1="7" y1="10" x2="13" y2="10" stroke="#4a3000" stroke-width="1.2" stroke-linecap="round"/>
|
||||
</g>
|
||||
<g id="pressed-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#c48a00"/>
|
||||
<line x1="7" y1="10" x2="13" y2="10" stroke="#4a3000" stroke-width="1.2" stroke-linecap="round"/>
|
||||
</g>
|
||||
<g id="inactive-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#5d5d5d"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 648 B |
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
|
||||
<g id="active-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#59c837"/>
|
||||
</g>
|
||||
<g id="hover-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#59c837"/>
|
||||
<rect x="8" y="6" width="4.5" height="4.5" rx="0.6" fill="none" stroke="#003a00" stroke-width="1.0"/>
|
||||
<rect x="6.5" y="8" width="4.5" height="4.5" rx="0.6" fill="#59c837" stroke="#003a00" stroke-width="1.0"/>
|
||||
</g>
|
||||
<g id="pressed-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#3d9a1f"/>
|
||||
<rect x="8" y="6" width="4.5" height="4.5" rx="0.6" fill="none" stroke="#003a00" stroke-width="1.0"/>
|
||||
<rect x="6.5" y="8" width="4.5" height="4.5" rx="0.6" fill="#3d9a1f" stroke="#003a00" stroke-width="1.0"/>
|
||||
</g>
|
||||
<g id="inactive-center">
|
||||
<circle cx="10" cy="10" r="6" fill="#5d5d5d"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 878 B |
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">
|
||||
<g id="active-center">
|
||||
<line x1="5" y1="7" x2="15" y2="7" stroke="#a8a8a8" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M5,10 L10,14 L15,10" fill="none" stroke="#a8a8a8" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<g id="hover-center">
|
||||
<circle cx="10" cy="10" r="9" fill="#88008f"/>
|
||||
<line x1="5" y1="7" x2="15" y2="7" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M5,10 L10,14 L15,10" fill="none" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<g id="pressed-center">
|
||||
<circle cx="10" cy="10" r="9" fill="#5e0066"/>
|
||||
<line x1="5" y1="7" x2="15" y2="7" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M5,10 L10,14 L15,10" fill="none" stroke="#ffffff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<g id="inactive-center">
|
||||
<line x1="5" y1="7" x2="15" y2="7" stroke="#6e7173" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M5,10 L10,14 L15,10" fill="none" stroke="#6e7173" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate NexusOS.colors (KDE KColorScheme format) from _palette.py.
|
||||
|
||||
Run from anywhere:
|
||||
python3 assets/themes/KDE/generate_plasma_colors.py
|
||||
|
||||
Writes to assets/themes/KDE/plasma/NexusOS/NexusOS.colors (relative to repo root).
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Resolve repo root relative to this script's location
|
||||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
REPO_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, "../../.."))
|
||||
sys.path.insert(0, os.path.join(REPO_ROOT, "assets/themes"))
|
||||
|
||||
import _palette as p # noqa: E402
|
||||
|
||||
OUT = os.path.join(SCRIPT_DIR, "plasma/NexusOS/NexusOS.colors")
|
||||
|
||||
|
||||
def rgb(hexstr):
|
||||
h = hexstr.lstrip("#")
|
||||
return f"{int(h[0:2],16)},{int(h[2:4],16)},{int(h[4:6],16)}"
|
||||
|
||||
|
||||
def section(name, bg_normal, bg_alt, fg_normal, fg_inactive, fg_active,
|
||||
fg_link, fg_visited, fg_neg, fg_neutral, fg_pos,
|
||||
deco_focus, deco_hover):
|
||||
return f"""[Colors:{name}]
|
||||
BackgroundNormal={rgb(bg_normal)}
|
||||
BackgroundAlternate={rgb(bg_alt)}
|
||||
ForegroundNormal={rgb(fg_normal)}
|
||||
ForegroundInactive={rgb(fg_inactive)}
|
||||
ForegroundActive={rgb(fg_active)}
|
||||
ForegroundLink={rgb(fg_link)}
|
||||
ForegroundVisited={rgb(fg_visited)}
|
||||
ForegroundNegative={rgb(fg_neg)}
|
||||
ForegroundNeutral={rgb(fg_neutral)}
|
||||
ForegroundPositive={rgb(fg_pos)}
|
||||
DecorationFocus={rgb(deco_focus)}
|
||||
DecorationHover={rgb(deco_hover)}
|
||||
"""
|
||||
|
||||
|
||||
SHARED = dict(
|
||||
fg_normal = "#" + p.TEXT_PRIMARY,
|
||||
fg_inactive = "#" + p.TEXT_SECONDARY,
|
||||
fg_active = "#" + p.BRAND_GREEN,
|
||||
fg_link = "#" + p.BRAND_GREEN_LIGHT,
|
||||
fg_visited = "#" + p.BRAND_PURPLE_LIGHT,
|
||||
fg_neg = "#" + p.ERROR,
|
||||
fg_neutral = "#" + p.WARNING,
|
||||
fg_pos = "#" + p.SUCCESS,
|
||||
deco_focus = "#" + p.BRAND_GREEN,
|
||||
deco_hover = "#" + p.BRAND_PURPLE,
|
||||
)
|
||||
|
||||
content = f"""\
|
||||
[ColorEffects:Disabled]
|
||||
Color=56,56,56
|
||||
ColorAmount=0
|
||||
ColorEffect=0
|
||||
ContrastAmount=0.1
|
||||
ContrastEffect=2
|
||||
IntensityAmount=0
|
||||
IntensityEffect=0
|
||||
|
||||
[ColorEffects:Inactive]
|
||||
ChangeSelectionColor=true
|
||||
Color=112,111,110
|
||||
ColorAmount=0.025
|
||||
ColorEffect=0
|
||||
ContrastAmount=0.1
|
||||
ContrastEffect=2
|
||||
Enable=false
|
||||
IntensityAmount=0
|
||||
IntensityEffect=0
|
||||
|
||||
""" + section(
|
||||
"Window",
|
||||
bg_normal="#" + p.BASE_BG,
|
||||
bg_alt ="#" + p.SURFACE_BG,
|
||||
**SHARED,
|
||||
) + section(
|
||||
"View",
|
||||
bg_normal="#" + p.BASE_BG,
|
||||
bg_alt ="#" + p.SURFACE_BG,
|
||||
**SHARED,
|
||||
) + section(
|
||||
"Button",
|
||||
bg_normal="#" + p.SURFACE_BG_ALT,
|
||||
bg_alt ="#" + p.BASE_BG,
|
||||
**SHARED,
|
||||
) + section(
|
||||
"Selection",
|
||||
bg_normal ="#" + p.BRAND_PURPLE,
|
||||
bg_alt ="#" + p.BRAND_GREEN_DARK,
|
||||
fg_normal ="#" + p.TEXT_ON_SELECTION,
|
||||
fg_inactive="#" + p.TEXT_ON_SELECTION,
|
||||
fg_active ="#" + p.BRAND_GREEN,
|
||||
fg_link ="#" + p.BRAND_GREEN_LIGHT,
|
||||
fg_visited="#" + p.BRAND_PURPLE_LIGHT,
|
||||
fg_neg ="#" + p.ERROR,
|
||||
fg_neutral="#" + p.WARNING,
|
||||
fg_pos ="#" + p.SUCCESS,
|
||||
deco_focus="#" + p.BRAND_GREEN,
|
||||
deco_hover="#" + p.BRAND_PURPLE,
|
||||
) + section(
|
||||
"Tooltip",
|
||||
bg_normal="#" + p.OVERLAY_BG,
|
||||
bg_alt ="#" + p.BORDER_STRONG,
|
||||
**SHARED,
|
||||
) + section(
|
||||
"Complementary",
|
||||
bg_normal="#" + p.SURFACE_BG_ALT,
|
||||
bg_alt ="#" + p.OVERLAY_BG,
|
||||
**SHARED,
|
||||
) + section(
|
||||
"Header",
|
||||
bg_normal="#" + p.BASE_BG,
|
||||
bg_alt ="#" + p.SURFACE_BG_ALT,
|
||||
**SHARED,
|
||||
) + f"""\
|
||||
[General]
|
||||
ColorScheme=NexusOS
|
||||
Name=NexusOS
|
||||
shadeSortColumn=true
|
||||
|
||||
[KDE]
|
||||
contrast=4
|
||||
"""
|
||||
|
||||
os.makedirs(os.path.dirname(OUT), exist_ok=True)
|
||||
with open(OUT, "w") as f:
|
||||
f.write(content)
|
||||
|
||||
print(f"Written: {OUT}")
|
||||
@@ -0,0 +1,145 @@
|
||||
#!/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
|
||||
for arg in "$@"; do
|
||||
[[ "$arg" == "--no-sddm" ]] && NO_SDDM=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 \
|
||||
~/.local/share/kscreenlocker/themes \
|
||||
~/.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/kscreenlocker/NexusOS" ~/.local/share/kscreenlocker/themes/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. kscreenlocker ─────────────────────────────────────────────────────
|
||||
if command -v kwriteconfig5 &>/dev/null; then
|
||||
kwriteconfig5 --file kscreenlockerrc --group Greeter --key Theme NexusOS
|
||||
echo " [ok] kscreenlocker theme: NexusOS"
|
||||
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 --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
|
||||
|
||||
# ── 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
|
||||
if command -v kquitapp5 &>/dev/null && command -v kstart5 &>/dev/null; then
|
||||
kquitapp5 plasmashell 2>/dev/null
|
||||
sleep 1
|
||||
kstart5 plasmashell &
|
||||
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"
|
||||
@@ -0,0 +1,94 @@
|
||||
[General]
|
||||
Description=NexusOS Promethean
|
||||
Opacity=1
|
||||
Wallpaper=
|
||||
|
||||
[Background]
|
||||
Color=26,0,48
|
||||
|
||||
[BackgroundFaint]
|
||||
Color=13,0,16
|
||||
|
||||
[BackgroundIntense]
|
||||
Color=61,0,96
|
||||
|
||||
[Foreground]
|
||||
Color=204,204,204
|
||||
|
||||
[ForegroundFaint]
|
||||
Color=140,140,140
|
||||
|
||||
[ForegroundIntense]
|
||||
Color=230,230,230
|
||||
|
||||
[Color0]
|
||||
Color=26,0,48
|
||||
|
||||
[Color0Faint]
|
||||
Color=13,0,24
|
||||
|
||||
[Color0Intense]
|
||||
Color=61,0,96
|
||||
|
||||
[Color1]
|
||||
Color=218,68,83
|
||||
|
||||
[Color1Faint]
|
||||
Color=160,50,60
|
||||
|
||||
[Color1Intense]
|
||||
Color=235,100,110
|
||||
|
||||
[Color2]
|
||||
Color=39,174,96
|
||||
|
||||
[Color2Faint]
|
||||
Color=28,128,70
|
||||
|
||||
[Color2Intense]
|
||||
Color=80,200,120
|
||||
|
||||
[Color3]
|
||||
Color=246,116,0
|
||||
|
||||
[Color3Faint]
|
||||
Color=180,85,0
|
||||
|
||||
[Color3Intense]
|
||||
Color=255,160,50
|
||||
|
||||
[Color4]
|
||||
Color=136,0,143
|
||||
|
||||
[Color4Faint]
|
||||
Color=94,0,100
|
||||
|
||||
[Color4Intense]
|
||||
Color=176,64,192
|
||||
|
||||
[Color5]
|
||||
Color=176,64,192
|
||||
|
||||
[Color5Faint]
|
||||
Color=120,40,135
|
||||
|
||||
[Color5Intense]
|
||||
Color=210,110,225
|
||||
|
||||
[Color6]
|
||||
Color=140,198,63
|
||||
|
||||
[Color6Faint]
|
||||
Color=100,145,45
|
||||
|
||||
[Color6Intense]
|
||||
Color=184,227,115
|
||||
|
||||
[Color7]
|
||||
Color=204,204,204
|
||||
|
||||
[Color7Faint]
|
||||
Color=150,150,150
|
||||
|
||||
[Color7Intense]
|
||||
Color=230,230,230
|
||||
@@ -0,0 +1,94 @@
|
||||
[General]
|
||||
Description=NexusOS
|
||||
Opacity=1
|
||||
Wallpaper=
|
||||
|
||||
[Background]
|
||||
Color=30,21,38
|
||||
|
||||
[BackgroundFaint]
|
||||
Color=31,34,37
|
||||
|
||||
[BackgroundIntense]
|
||||
Color=46,50,54
|
||||
|
||||
[Foreground]
|
||||
Color=242,242,242
|
||||
|
||||
[ForegroundFaint]
|
||||
Color=168,168,168
|
||||
|
||||
[ForegroundIntense]
|
||||
Color=255,255,255
|
||||
|
||||
[Color0]
|
||||
Color=31,34,37
|
||||
|
||||
[Color0Faint]
|
||||
Color=20,20,25
|
||||
|
||||
[Color0Intense]
|
||||
Color=58,61,65
|
||||
|
||||
[Color1]
|
||||
Color=218,68,83
|
||||
|
||||
[Color1Faint]
|
||||
Color=160,50,60
|
||||
|
||||
[Color1Intense]
|
||||
Color=235,100,110
|
||||
|
||||
[Color2]
|
||||
Color=39,174,96
|
||||
|
||||
[Color2Faint]
|
||||
Color=28,128,70
|
||||
|
||||
[Color2Intense]
|
||||
Color=80,200,120
|
||||
|
||||
[Color3]
|
||||
Color=246,116,0
|
||||
|
||||
[Color3Faint]
|
||||
Color=180,85,0
|
||||
|
||||
[Color3Intense]
|
||||
Color=255,160,50
|
||||
|
||||
[Color4]
|
||||
Color=136,0,143
|
||||
|
||||
[Color4Faint]
|
||||
Color=94,0,100
|
||||
|
||||
[Color4Intense]
|
||||
Color=162,50,168
|
||||
|
||||
[Color5]
|
||||
Color=162,50,168
|
||||
|
||||
[Color5Faint]
|
||||
Color=110,30,115
|
||||
|
||||
[Color5Intense]
|
||||
Color=200,100,210
|
||||
|
||||
[Color6]
|
||||
Color=140,198,63
|
||||
|
||||
[Color6Faint]
|
||||
Color=100,145,45
|
||||
|
||||
[Color6Intense]
|
||||
Color=184,227,115
|
||||
|
||||
[Color7]
|
||||
Color=168,168,168
|
||||
|
||||
[Color7Faint]
|
||||
Color=110,113,115
|
||||
|
||||
[Color7Intense]
|
||||
Color=242,242,242
|
||||
@@ -0,0 +1,36 @@
|
||||
[Appearance]
|
||||
ColorScheme=NexusOS-Promethean
|
||||
Font=Monospace,12,-1,5,50,0,0,0,0,0
|
||||
LineSpacing=1
|
||||
UseFontLineCharacters=false
|
||||
|
||||
[Cursor Options]
|
||||
CursorShape=0
|
||||
CustomCursorColor=#b040c0
|
||||
UseCustomCursorColor=true
|
||||
|
||||
[General]
|
||||
Command=/bin/bash --rcfile /home/jon/nexus-core/.promethean_bashrc -i
|
||||
Name=Promethean
|
||||
Parent=FALLBACK/
|
||||
TerminalCenter=false
|
||||
TerminalColumns=110
|
||||
TerminalRows=30
|
||||
|
||||
[Interaction Options]
|
||||
AutoCopySelectedText=false
|
||||
UnderlineFilesEnabled=false
|
||||
|
||||
[Scrolling]
|
||||
HistoryMode=2
|
||||
HistorySize=5000
|
||||
ScrollBarPosition=2
|
||||
|
||||
[Terminal Features]
|
||||
BidiRenderingEnabled=true
|
||||
BlinkingCursorEnabled=true
|
||||
BlinkingTextEnabled=true
|
||||
UrlHintsModifiers=0
|
||||
|
||||
[Window]
|
||||
RememberWindowSize=true
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1200" width="1920" height="1200">
|
||||
<defs>
|
||||
<linearGradient id="metalBase" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#1a1a2e;stop-opacity:1"/>
|
||||
<stop offset="35%" style="stop-color:#16213e;stop-opacity:1"/>
|
||||
<stop offset="65%" style="stop-color:#0f1626;stop-opacity:1"/>
|
||||
<stop offset="100%" style="stop-color:#0a0e1a;stop-opacity:1"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="vignette" cx="50%" cy="50%" r="70%">
|
||||
<stop offset="0%" style="stop-color:transparent;stop-opacity:0"/>
|
||||
<stop offset="100%" style="stop-color:#000000;stop-opacity:0.6"/>
|
||||
</radialGradient>
|
||||
<pattern id="brushLines" x="0" y="0" width="4" height="4" patternUnits="userSpaceOnUse">
|
||||
<line x1="0" y1="4" x2="4" y2="0" stroke="#ffffff" stroke-width="0.3" opacity="0.03"/>
|
||||
</pattern>
|
||||
<pattern id="machineLines" x="0" y="0" width="100" height="3" patternUnits="userSpaceOnUse">
|
||||
<line x1="0" y1="1.5" x2="100" y2="1.5" stroke="#ffffff" stroke-width="0.2" opacity="0.025"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1920" height="1200" fill="url(#metalBase)"/>
|
||||
<rect width="1920" height="1200" fill="url(#brushLines)"/>
|
||||
<rect width="1920" height="1200" fill="url(#machineLines)"/>
|
||||
<ellipse cx="960" cy="340" rx="1200" ry="280" fill="#ffffff" opacity="0.012"/>
|
||||
<ellipse cx="960" cy="220" rx="400" ry="170" fill="#00d4ff" opacity="0.015"/>
|
||||
<rect width="1920" height="1200" fill="url(#vignette)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 185 KiB |
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
|
||||
<kcfgfile name=""/>
|
||||
<group name="General">
|
||||
</group>
|
||||
</kcfg>
|
||||
@@ -0,0 +1,268 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
|
||||
/*
|
||||
* NexusOS kscreenlocker theme.
|
||||
* Mirrors the SDDM NexusOS-QML aesthetic: logo upper-center,
|
||||
* clock/date bottom-center, centered password box.
|
||||
*
|
||||
* kscreenlocker API differences from SDDM:
|
||||
* - authenticator.tryUnlock(password) instead of sddm.login(...)
|
||||
* - authenticator.failed / authenticator.succeeded signals
|
||||
* - No session selector, no power buttons
|
||||
* - walletModel, userModel available but not mandatory
|
||||
*/
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
// kscreenlocker injects these from the surrounding PlasmaShell context
|
||||
property bool locked: true
|
||||
|
||||
readonly property color accentColor: "#8cc63f" // brand_green
|
||||
readonly property color bgDark: "#1e1526" // base_bg
|
||||
readonly property color textPrimary: "#f2f2f2"
|
||||
readonly property color textMuted: "#a8a8a8"
|
||||
readonly property color fieldBg: "#1f2225" // surface_bg
|
||||
readonly property color fieldBorder: "#4d3461" // menu_border
|
||||
readonly property color errorColor: "#da4453"
|
||||
|
||||
anchors.fill: parent
|
||||
color: bgDark
|
||||
|
||||
// ── Background image (reuses SDDM background asset) ────────────────
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: Qt.resolvedUrl("../../assets/background.svg")
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
smooth: true
|
||||
asynchronous: false
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#000000"
|
||||
opacity: 0.30
|
||||
}
|
||||
|
||||
// ── Logo area ───────────────────────────────────────────────────────
|
||||
Item {
|
||||
id: logoArea
|
||||
width: 100
|
||||
height: 100
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: parent.height * 0.10
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width * 1.6
|
||||
height: parent.height * 1.6
|
||||
radius: width / 2
|
||||
color: accentColor
|
||||
opacity: 0.06
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: Qt.resolvedUrl("../../assets/logo.png")
|
||||
sourceSize: Qt.size(200, 200)
|
||||
smooth: true
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "NexusOS"
|
||||
color: textPrimary
|
||||
font.family: "Sans"
|
||||
font.pixelSize: 26
|
||||
font.letterSpacing: 6
|
||||
font.weight: Font.Light
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: logoArea.bottom
|
||||
anchors.topMargin: 14
|
||||
}
|
||||
|
||||
// ── Password box ────────────────────────────────────────────────────
|
||||
Rectangle {
|
||||
id: loginBox
|
||||
width: 340
|
||||
height: loginColumn.height + 56
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: Qt.rgba(30/255, 21/255, 38/255, 0.80)
|
||||
radius: 12
|
||||
border.color: fieldBorder
|
||||
border.width: 1
|
||||
|
||||
SequentialAnimation {
|
||||
id: shakeAnim
|
||||
NumberAnimation { target: loginBox; property: "x"; to: loginBox.x - 10; duration: 50 }
|
||||
NumberAnimation { target: loginBox; property: "x"; to: loginBox.x + 10; duration: 50 }
|
||||
NumberAnimation { target: loginBox; property: "x"; to: loginBox.x - 6; duration: 50 }
|
||||
NumberAnimation { target: loginBox; property: "x"; to: loginBox.x + 6; duration: 50 }
|
||||
NumberAnimation { target: loginBox; property: "x"; to: loginBox.x; duration: 40 }
|
||||
}
|
||||
|
||||
Column {
|
||||
id: loginColumn
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 28
|
||||
spacing: 12
|
||||
|
||||
// Username label (read-only; kscreenlocker always locks current session)
|
||||
Text {
|
||||
width: parent.width
|
||||
text: kscreenlocker_userName || userModel.data(userModel.index(0, 0), Qt.DisplayRole) || ""
|
||||
color: textPrimary
|
||||
font.pixelSize: 14
|
||||
font.weight: Font.Medium
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
// Password field
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 44
|
||||
color: fieldBg
|
||||
radius: 6
|
||||
border.color: passwordInput.activeFocus ? accentColor : fieldBorder
|
||||
border.width: 1
|
||||
|
||||
TextInput {
|
||||
id: passwordInput
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 14
|
||||
anchors.rightMargin: 14
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
color: textPrimary
|
||||
font.pixelSize: 14
|
||||
echoMode: TextInput.Password
|
||||
focus: true
|
||||
clip: true
|
||||
|
||||
Keys.onReturnPressed: authenticator.tryUnlock(passwordInput.text)
|
||||
Keys.onEnterPressed: authenticator.tryUnlock(passwordInput.text)
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 14
|
||||
text: "Password"
|
||||
color: textMuted
|
||||
font.pixelSize: 14
|
||||
visible: passwordInput.text.length === 0 && !passwordInput.activeFocus
|
||||
}
|
||||
}
|
||||
|
||||
// Error message
|
||||
Text {
|
||||
id: errorMsg
|
||||
width: parent.width
|
||||
text: ""
|
||||
color: errorColor
|
||||
font.pixelSize: 12
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
visible: text !== ""
|
||||
}
|
||||
|
||||
// Unlock button
|
||||
Rectangle {
|
||||
id: unlockButton
|
||||
width: parent.width
|
||||
height: 44
|
||||
radius: 6
|
||||
color: unlockMouse.pressed
|
||||
? Qt.darker(accentColor, 1.3)
|
||||
: unlockMouse.containsMouse
|
||||
? Qt.lighter(accentColor, 1.15)
|
||||
: accentColor
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "UNLOCK"
|
||||
color: "#0a0a00" // text_on_accent
|
||||
font.pixelSize: 14
|
||||
font.letterSpacing: 3
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: unlockMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: authenticator.tryUnlock(passwordInput.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Authenticator connections ───────────────────────────────────────
|
||||
Connections {
|
||||
target: authenticator
|
||||
|
||||
function onFailed() {
|
||||
errorMsg.text = "Incorrect password — try again."
|
||||
passwordInput.text = ""
|
||||
passwordInput.forceActiveFocus()
|
||||
shakeAnim.start()
|
||||
}
|
||||
|
||||
function onSucceeded() {
|
||||
errorMsg.text = ""
|
||||
}
|
||||
|
||||
function onGraceLockedChanged() {}
|
||||
function onMessage(msg) {}
|
||||
function onError(err) {
|
||||
errorMsg.text = err
|
||||
}
|
||||
}
|
||||
|
||||
// ── Clock / date (bottom) ───────────────────────────────────────────
|
||||
Column {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: parent.height * 0.05
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
id: clockText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: textPrimary
|
||||
font.family: "Sans"
|
||||
font.pixelSize: 42
|
||||
font.weight: Font.Thin
|
||||
}
|
||||
|
||||
Text {
|
||||
id: dateText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: textMuted
|
||||
font.family: "Sans"
|
||||
font.pixelSize: 14
|
||||
font.letterSpacing: 2
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 1000
|
||||
running: true
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
onTriggered: {
|
||||
var d = new Date()
|
||||
clockText.text = Qt.formatTime(d, "hh:mm")
|
||||
dateText.text = Qt.formatDate(d, "dddd, MMMM d")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
[Desktop Entry]
|
||||
Name=NexusOS
|
||||
Comment=NexusOS lock screen — dark purple, lime-green accents
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=org.kde.kscreenlocker.Greeter
|
||||
|
||||
[ScreenLocker]
|
||||
Name=NexusOS
|
||||
Description=NexusOS lock screen — dark purple, lime-green accents
|
||||
MainScript=contents/ui/LockScreenUi.qml
|
||||
@@ -0,0 +1,397 @@
|
||||
[%GradualConfiguration]
|
||||
# Toolbar / menubar gradient — flat: both ends same color
|
||||
left.header.color=#2a2e32
|
||||
right.header.color=#2a2e32
|
||||
header.text.color=#f2f2f2
|
||||
header.text.shadow.color=0,0,0,0
|
||||
left.dock.header.color=#1e1526
|
||||
right.dock.header.color=#1e1526
|
||||
dock.header.text.color=#f2f2f2
|
||||
dock.header.text.shadow.color=0,0,0,0
|
||||
|
||||
[%ThemeHacks]
|
||||
transparent.menus=false
|
||||
transparent.tooltips=false
|
||||
blurring=false
|
||||
composite=false
|
||||
|
||||
[General]
|
||||
author=NexusOS
|
||||
comment=Flat dark purple theme, lime-green accents, purple selections
|
||||
x11drag=all
|
||||
double.click.exception=
|
||||
group.label.boldFont=false
|
||||
menubar.mouse.tracking=true
|
||||
toolbutton.style=0
|
||||
dialog.button.layout=0
|
||||
splitter.width=4
|
||||
scroll.arrows=false
|
||||
scroll.min.extent=36
|
||||
tooltip.delay=500
|
||||
tooltip.count=1
|
||||
vertical.center.dialogs=true
|
||||
inline.spin.indicators=true
|
||||
transient.scrollbar=false
|
||||
submenu.overlap=3
|
||||
submenu.delay=250
|
||||
shadow.spread=0
|
||||
shadow.x.offset=0
|
||||
shadow.y.offset=0
|
||||
focus.rect.color=#8cc63f
|
||||
reduce.window.opacity=0
|
||||
reduce.menu.opacity=0
|
||||
small.icon.size=16
|
||||
large.icon.size=32
|
||||
button.icon.size=16
|
||||
toolbar.icon.size=16
|
||||
|
||||
[PanelButtonCommand]
|
||||
inherits=PanelButtonTool
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=button
|
||||
interior.x.padding=8
|
||||
interior.y.padding=4
|
||||
indicator.size=0
|
||||
text.shadow=0
|
||||
text.margin=1
|
||||
text.bold=false
|
||||
min.height=26
|
||||
min.width=60
|
||||
|
||||
[PanelButtonTool]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=toolbutton
|
||||
interior.x.padding=6
|
||||
interior.y.padding=3
|
||||
indicator.size=0
|
||||
text.shadow=0
|
||||
text.margin=0
|
||||
text.bold=false
|
||||
min.height=22
|
||||
min.width=0
|
||||
|
||||
[ToolbarButton]
|
||||
inherits=PanelButtonTool
|
||||
|
||||
[Dock]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=dock
|
||||
|
||||
[DockTitle]
|
||||
frame=false
|
||||
interior=false
|
||||
indicator.element=arrow
|
||||
text.margin=3
|
||||
text.shadow=0
|
||||
|
||||
[TitleBar]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=titlebar
|
||||
indicator.element=button
|
||||
min.height=30
|
||||
text.margin=4
|
||||
text.shadow=0
|
||||
text.bold=false
|
||||
|
||||
[GroupBox]
|
||||
frame=true
|
||||
frame.element=groupbox
|
||||
frame.top=6
|
||||
frame.bottom=2
|
||||
frame.left=2
|
||||
frame.right=2
|
||||
interior=false
|
||||
text.margin=4
|
||||
text.shadow=0
|
||||
text.bold=false
|
||||
text.italic=false
|
||||
|
||||
[LineEdit]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=lineedit
|
||||
interior.x.padding=8
|
||||
interior.y.padding=4
|
||||
min.height=26
|
||||
min.width=0
|
||||
|
||||
[DropDownButton]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=button
|
||||
indicator.element=arrow-down
|
||||
indicator.size=10
|
||||
|
||||
[ToolboxTab]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=tab
|
||||
text.margin=4
|
||||
text.shadow=0
|
||||
text.bold=false
|
||||
|
||||
[Tab]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=tab
|
||||
interior.x.padding=10
|
||||
interior.y.padding=4
|
||||
indicator.element=tab-close
|
||||
indicator.size=12
|
||||
text.shadow=0
|
||||
text.margin=2
|
||||
min.height=26
|
||||
min.width=60
|
||||
|
||||
[TabFrame]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=tabframe
|
||||
frame.top=0
|
||||
frame.bottom=0
|
||||
frame.left=0
|
||||
frame.right=0
|
||||
|
||||
[TreeExpander]
|
||||
frame=false
|
||||
interior=false
|
||||
indicator.element=arrow
|
||||
indicator.size=10
|
||||
|
||||
[HeaderSection]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=header
|
||||
interior.x.padding=6
|
||||
interior.y.padding=3
|
||||
indicator.element=arrow
|
||||
indicator.size=10
|
||||
text.shadow=0
|
||||
min.height=24
|
||||
|
||||
[SizeGrip]
|
||||
frame=false
|
||||
interior=false
|
||||
indicator.element=sizegrip
|
||||
indicator.size=14
|
||||
|
||||
[Splitter]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=splitter
|
||||
min.height=4
|
||||
min.width=4
|
||||
|
||||
[Slider]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=slider
|
||||
indicator.element=slider-handle
|
||||
indicator.size=16
|
||||
min.height=4
|
||||
min.width=4
|
||||
|
||||
[SliderCursorFlat]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=slider-handle
|
||||
min.height=16
|
||||
min.width=16
|
||||
|
||||
[ProgressbarContents]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=progressbar-fill
|
||||
|
||||
[Progressbar]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=progressbar
|
||||
indicator.size=0
|
||||
text.shadow=0
|
||||
min.height=6
|
||||
min.width=0
|
||||
|
||||
[ItemView]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=itemview
|
||||
interior.x.padding=4
|
||||
interior.y.padding=2
|
||||
|
||||
[Toolbar]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=toolbar
|
||||
interior.x.padding=2
|
||||
interior.y.padding=2
|
||||
indicator.element=toolbar-handle
|
||||
indicator.size=8
|
||||
|
||||
[ScrollbarSlider]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=scrollbar-slider
|
||||
min.height=36
|
||||
min.width=8
|
||||
|
||||
[ScrollbarGroove]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=scrollbar-groove
|
||||
|
||||
[Scrollbar]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=scrollbar-groove
|
||||
indicator.element=arrow
|
||||
indicator.size=0
|
||||
min.height=8
|
||||
min.width=8
|
||||
|
||||
[ScrollArrow]
|
||||
frame=false
|
||||
interior=false
|
||||
indicator.element=arrow
|
||||
indicator.size=8
|
||||
min.height=0
|
||||
min.width=0
|
||||
|
||||
[CheckBox]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=checkbox
|
||||
indicator.element=checkbox-indicator
|
||||
indicator.size=14
|
||||
text.shadow=0
|
||||
text.margin=3
|
||||
min.height=16
|
||||
min.width=16
|
||||
|
||||
[RadioButton]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=radiobutton
|
||||
indicator.element=radiobutton-indicator
|
||||
indicator.size=8
|
||||
text.shadow=0
|
||||
text.margin=3
|
||||
min.height=16
|
||||
min.width=16
|
||||
|
||||
[Separator]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=separator
|
||||
min.height=1
|
||||
min.width=1
|
||||
|
||||
[ComboBox]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=combobox
|
||||
interior.x.padding=8
|
||||
interior.y.padding=4
|
||||
indicator.element=arrow-down
|
||||
indicator.size=10
|
||||
min.height=26
|
||||
min.width=0
|
||||
|
||||
[SpinBox]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=spinbox
|
||||
interior.x.padding=6
|
||||
interior.y.padding=3
|
||||
indicator.element=arrow
|
||||
indicator.size=10
|
||||
min.height=26
|
||||
min.width=0
|
||||
|
||||
[Frame]
|
||||
frame=true
|
||||
frame.element=frame
|
||||
frame.top=1
|
||||
frame.bottom=1
|
||||
frame.left=1
|
||||
frame.right=1
|
||||
interior=false
|
||||
|
||||
[MenuItem]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=menuitem
|
||||
interior.x.padding=6
|
||||
interior.y.padding=1
|
||||
indicator.element=menuitem-arrow
|
||||
indicator.size=10
|
||||
text.shadow=0
|
||||
min.height=22
|
||||
|
||||
[Menu]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=menu
|
||||
interior.x.padding=0
|
||||
interior.y.padding=2
|
||||
text.shadow=0
|
||||
min.height=0
|
||||
min.width=0
|
||||
|
||||
[Menubar]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=menubar
|
||||
text.shadow=0
|
||||
|
||||
[MenubarItem]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=menubaritem
|
||||
interior.x.padding=10
|
||||
interior.y.padding=4
|
||||
text.shadow=0
|
||||
|
||||
[ToolTip]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=tooltip
|
||||
interior.x.padding=8
|
||||
interior.y.padding=4
|
||||
text.shadow=0
|
||||
min.height=0
|
||||
min.width=0
|
||||
|
||||
[StatusBar]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=statusbar
|
||||
|
||||
[Window]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=window
|
||||
interior.x.padding=0
|
||||
interior.y.padding=0
|
||||
|
||||
[Dialog]
|
||||
frame=false
|
||||
interior=true
|
||||
interior.element=window
|
||||
|
||||
[MessageBox]
|
||||
inherits=Dialog
|
||||
text.bold=false
|
||||
|
||||
[GenericFrame]
|
||||
frame=true
|
||||
frame.element=frame
|
||||
frame.top=1
|
||||
frame.bottom=1
|
||||
frame.left=1
|
||||
frame.right=1
|
||||
interior=false
|
||||
@@ -0,0 +1,619 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
NexusOS Kvantum SVG
|
||||
Palette: dark purple base + lime green accents + purple selections.
|
||||
Layout: each element type occupies one row (y-step=50px). States
|
||||
are arranged left-to-right within each row (x-step=110px):
|
||||
col 0 (x=0): normal
|
||||
col 1 (x=110): focused
|
||||
col 2 (x=220): hover
|
||||
col 3 (x=330): pressed / active
|
||||
col 4 (x=440): disabled
|
||||
col 5 (x=550): toggled
|
||||
col 6 (x=660): toggled-focused / toggled-hover
|
||||
|
||||
Kvantum looks up elements by id; exact (x,y) positions are ignored.
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
|
||||
width="800" height="2000">
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
BUTTON (y=0)
|
||||
Used by: PanelButtonCommand, PanelButtonTool, DropDownButton
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="button">
|
||||
<rect x="1" y="1" width="98" height="38" rx="4"
|
||||
fill="#2a2e32" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="button-focused">
|
||||
<rect x="111" y="1" width="98" height="38" rx="4"
|
||||
fill="#2a2e32" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="button-hover">
|
||||
<rect x="221" y="1" width="98" height="38" rx="4"
|
||||
fill="#353a3e" stroke="#4a4f54" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="button-pressed">
|
||||
<rect x="331" y="1" width="98" height="38" rx="4"
|
||||
fill="#8cc63f" stroke="#6ba62a" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="button-disabled">
|
||||
<rect x="441" y="1" width="98" height="38" rx="4"
|
||||
fill="#1f2225" stroke="#2e3236" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="button-toggled">
|
||||
<rect x="551" y="1" width="98" height="38" rx="4"
|
||||
fill="#88008f" stroke="#5e0066" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="button-toggled-focused">
|
||||
<rect x="661" y="1" width="98" height="38" rx="4"
|
||||
fill="#88008f" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="button-toggled-hover">
|
||||
<rect x="1" y="51" width="98" height="38" rx="4"
|
||||
fill="#a232a8" stroke="#88008f" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
TOOLBUTTON (y=100) — flatter, no minimum width enforcement
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="toolbutton">
|
||||
<rect x="1" y="101" width="98" height="38" rx="4"
|
||||
fill="none" stroke="none"/>
|
||||
</g>
|
||||
<g id="toolbutton-focused">
|
||||
<rect x="111" y="101" width="98" height="38" rx="4"
|
||||
fill="#2a2e32" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="toolbutton-hover">
|
||||
<rect x="221" y="101" width="98" height="38" rx="4"
|
||||
fill="#2a2e32" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="toolbutton-pressed">
|
||||
<rect x="331" y="101" width="98" height="38" rx="4"
|
||||
fill="#8cc63f" stroke="#6ba62a" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="toolbutton-disabled">
|
||||
<rect x="441" y="101" width="98" height="38" rx="4"
|
||||
fill="none" stroke="none"/>
|
||||
</g>
|
||||
<g id="toolbutton-toggled">
|
||||
<rect x="551" y="101" width="98" height="38" rx="4"
|
||||
fill="#88008f" stroke="#5e0066" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="toolbutton-toggled-hover">
|
||||
<rect x="661" y="101" width="98" height="38" rx="4"
|
||||
fill="#a232a8" stroke="#88008f" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
LINE EDIT / TEXT FIELD (y=150)
|
||||
Used by: LineEdit, SpinBox field, ComboBox field
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="lineedit">
|
||||
<rect x="1" y="151" width="98" height="38" rx="4"
|
||||
fill="#1f2225" stroke="#2e3236" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="lineedit-focused">
|
||||
<rect x="111" y="151" width="98" height="38" rx="4"
|
||||
fill="#1f2225" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="lineedit-hover">
|
||||
<rect x="221" y="151" width="98" height="38" rx="4"
|
||||
fill="#1f2225" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="lineedit-disabled">
|
||||
<rect x="331" y="151" width="98" height="38" rx="4"
|
||||
fill="#1e1526" stroke="#2e3236" stroke-width="1" opacity="0.6"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
COMBO BOX (y=200)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="combobox">
|
||||
<rect x="1" y="201" width="98" height="38" rx="4"
|
||||
fill="#1f2225" stroke="#2e3236" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="combobox-focused">
|
||||
<rect x="111" y="201" width="98" height="38" rx="4"
|
||||
fill="#1f2225" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="combobox-hover">
|
||||
<rect x="221" y="201" width="98" height="38" rx="4"
|
||||
fill="#1f2225" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="combobox-pressed">
|
||||
<rect x="331" y="201" width="98" height="38" rx="4"
|
||||
fill="#1f2225" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="combobox-disabled">
|
||||
<rect x="441" y="201" width="98" height="38" rx="4"
|
||||
fill="#1e1526" stroke="#2e3236" stroke-width="1" opacity="0.6"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
SPIN BOX (y=250)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="spinbox">
|
||||
<rect x="1" y="251" width="98" height="38" rx="4"
|
||||
fill="#1f2225" stroke="#2e3236" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="spinbox-focused">
|
||||
<rect x="111" y="251" width="98" height="38" rx="4"
|
||||
fill="#1f2225" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="spinbox-hover">
|
||||
<rect x="221" y="251" width="98" height="38" rx="4"
|
||||
fill="#1f2225" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="spinbox-disabled">
|
||||
<rect x="331" y="251" width="98" height="38" rx="4"
|
||||
fill="#1e1526" stroke="#2e3236" stroke-width="1" opacity="0.6"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
MENU BACKGROUND (y=300)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="menu">
|
||||
<rect x="1" y="301" width="98" height="78" rx="6"
|
||||
fill="#2a1d33" stroke="#4d3461" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
MENU ITEM (y=400) — just a fill highlight, no outline
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="menuitem">
|
||||
<rect x="1" y="401" width="98" height="28" rx="3"
|
||||
fill="none"/>
|
||||
</g>
|
||||
<g id="menuitem-hover">
|
||||
<rect x="111" y="401" width="98" height="28" rx="3"
|
||||
fill="#8cc63f" fill-opacity="0.18"/>
|
||||
</g>
|
||||
<g id="menuitem-pressed">
|
||||
<rect x="221" y="401" width="98" height="28" rx="3"
|
||||
fill="#8cc63f"/>
|
||||
</g>
|
||||
<g id="menuitem-disabled">
|
||||
<rect x="331" y="401" width="98" height="28" rx="3"
|
||||
fill="none"/>
|
||||
</g>
|
||||
<g id="menuitem-selected">
|
||||
<rect x="441" y="401" width="98" height="28" rx="3"
|
||||
fill="#8cc63f"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
MENU BAR (y=450)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="menubar">
|
||||
<rect x="1" y="451" width="98" height="28" rx="0"
|
||||
fill="#2a2e32" stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
MENU BAR ITEM (y=480)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="menubaritem">
|
||||
<rect x="1" y="481" width="98" height="28" rx="3"
|
||||
fill="none"/>
|
||||
</g>
|
||||
<g id="menubaritem-hover">
|
||||
<rect x="111" y="481" width="98" height="28" rx="3"
|
||||
fill="#8cc63f" fill-opacity="0.18"/>
|
||||
</g>
|
||||
<g id="menubaritem-pressed">
|
||||
<rect x="221" y="481" width="98" height="28" rx="3"
|
||||
fill="#8cc63f"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
TOOLTIP (y=530)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="tooltip">
|
||||
<rect x="1" y="531" width="98" height="38" rx="6"
|
||||
fill="#2e3236" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
TAB (in tab bar) (y=580)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="tab">
|
||||
<rect x="1" y="581" width="98" height="34" rx="4"
|
||||
fill="none"/>
|
||||
</g>
|
||||
<g id="tab-focused">
|
||||
<rect x="111" y="581" width="98" height="34" rx="4"
|
||||
fill="#2a2e32" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="tab-hover">
|
||||
<rect x="221" y="581" width="98" height="34" rx="4"
|
||||
fill="#2a2e32" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="tab-pressed">
|
||||
<rect x="331" y="581" width="98" height="34" rx="4"
|
||||
fill="#2a2e32" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="tab-disabled">
|
||||
<rect x="441" y="581" width="98" height="34" rx="4"
|
||||
fill="none" opacity="0.4"/>
|
||||
</g>
|
||||
<g id="tab-toggled">
|
||||
<rect x="551" y="581" width="98" height="34" rx="4"
|
||||
fill="#2a2e32" stroke="#8cc63f" stroke-width="2"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
TAB FRAME (content area) (y=630)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="tabframe">
|
||||
<rect x="1" y="631" width="98" height="58" rx="0"
|
||||
fill="#1f2225" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
PROGRESS BAR TRACK (y=700)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="progressbar">
|
||||
<rect x="1" y="701" width="98" height="8" rx="4"
|
||||
fill="#2a2e32" stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
PROGRESS BAR FILL (y=720)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="progressbar-fill">
|
||||
<rect x="1" y="721" width="98" height="8" rx="4"
|
||||
fill="#8cc63f"/>
|
||||
</g>
|
||||
<g id="progressbar-fill-disabled">
|
||||
<rect x="111" y="721" width="98" height="8" rx="4"
|
||||
fill="#3a3d41"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
SCROLLBAR GROOVE (y=740)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="scrollbar-groove">
|
||||
<rect x="1" y="741" width="8" height="98" rx="4"
|
||||
fill="#2a2e32" stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
SCROLLBAR SLIDER (thumb) (y=850)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="scrollbar-slider">
|
||||
<rect x="1" y="851" width="8" height="36" rx="4"
|
||||
fill="#3a3d41"/>
|
||||
</g>
|
||||
<g id="scrollbar-slider-hover">
|
||||
<rect x="11" y="851" width="8" height="36" rx="4"
|
||||
fill="#8cc63f"/>
|
||||
</g>
|
||||
<g id="scrollbar-slider-pressed">
|
||||
<rect x="21" y="851" width="8" height="36" rx="4"
|
||||
fill="#6ba62a"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
SLIDER GROOVE (y=900)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="slider">
|
||||
<rect x="1" y="901" width="98" height="4" rx="2"
|
||||
fill="#2a2e32" stroke="none"/>
|
||||
</g>
|
||||
<g id="slider-focused">
|
||||
<rect x="1" y="901" width="98" height="4" rx="2"
|
||||
fill="#2a2e32" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
SLIDER HANDLE (y=920)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="slider-handle">
|
||||
<circle cx="9" cy="929" r="8" fill="#3a3d41" stroke="#4a4f54" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="slider-handle-focused">
|
||||
<circle cx="9" cy="929" r="8" fill="#3a3d41" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="slider-handle-hover">
|
||||
<circle cx="9" cy="929" r="8" fill="#8cc63f" stroke="#6ba62a" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="slider-handle-pressed">
|
||||
<circle cx="9" cy="929" r="8" fill="#6ba62a" stroke="#6ba62a" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="slider-handle-disabled">
|
||||
<circle cx="9" cy="929" r="8" fill="#2e3236" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
CHECK BOX BACKGROUND (y=950)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="checkbox">
|
||||
<rect x="1" y="951" width="16" height="16" rx="3"
|
||||
fill="#1f2225" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="checkbox-focused">
|
||||
<rect x="19" y="951" width="16" height="16" rx="3"
|
||||
fill="#1f2225" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="checkbox-hover">
|
||||
<rect x="37" y="951" width="16" height="16" rx="3"
|
||||
fill="#2a2e32" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="checkbox-toggled">
|
||||
<rect x="55" y="951" width="16" height="16" rx="3"
|
||||
fill="#8cc63f" stroke="#6ba62a" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="checkbox-toggled-focused">
|
||||
<rect x="73" y="951" width="16" height="16" rx="3"
|
||||
fill="#8cc63f" stroke="#8cc63f" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="checkbox-disabled">
|
||||
<rect x="91" y="951" width="16" height="16" rx="3"
|
||||
fill="#1e1526" stroke="#2e3236" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- checkbox checkmark indicator -->
|
||||
<g id="checkbox-indicator">
|
||||
<!-- invisible placeholder for unchecked state -->
|
||||
<path d="M3,979 L6,983 L11,975" fill="none" stroke="none"/>
|
||||
</g>
|
||||
<g id="checkbox-indicator-toggled">
|
||||
<path d="M3,979 L6,983 L11,975"
|
||||
fill="none" stroke="#0a0a00" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<g id="checkbox-indicator-disabled">
|
||||
<path d="M93,979 L96,983 L101,975"
|
||||
fill="none" stroke="#6e7173" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
RADIO BUTTON BACKGROUND (y=1000)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="radiobutton">
|
||||
<circle cx="9" cy="1009" r="8" fill="#1f2225" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="radiobutton-focused">
|
||||
<circle cx="27" cy="1009" r="8" fill="#1f2225" stroke="#8cc63f" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="radiobutton-hover">
|
||||
<circle cx="45" cy="1009" r="8" fill="#2a2e32" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="radiobutton-toggled">
|
||||
<circle cx="63" cy="1009" r="8" fill="#8cc63f" stroke="#6ba62a" stroke-width="1"/>
|
||||
</g>
|
||||
<g id="radiobutton-toggled-focused">
|
||||
<circle cx="81" cy="1009" r="8" fill="#8cc63f" stroke="#8cc63f" stroke-width="2"/>
|
||||
</g>
|
||||
<g id="radiobutton-disabled">
|
||||
<circle cx="99" cy="1009" r="8" fill="#1e1526" stroke="#2e3236" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- radio dot indicator -->
|
||||
<g id="radiobutton-indicator">
|
||||
<circle cx="9" cy="1009" r="3.5" fill="#0a0a00"/>
|
||||
</g>
|
||||
<g id="radiobutton-indicator-disabled">
|
||||
<circle cx="99" cy="1009" r="3.5" fill="#6e7173"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
HEADER SECTION (table/tree column header) (y=1030)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="header">
|
||||
<rect x="1" y="1031" width="98" height="28" rx="0"
|
||||
fill="#2a2e32" stroke="none"/>
|
||||
</g>
|
||||
<g id="header-hover">
|
||||
<rect x="111" y="1031" width="98" height="28" rx="0"
|
||||
fill="#353a3e" stroke="none"/>
|
||||
</g>
|
||||
<g id="header-pressed">
|
||||
<rect x="221" y="1031" width="98" height="28" rx="0"
|
||||
fill="#8cc63f" stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
ITEM VIEW (list/tree row) (y=1070)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="itemview">
|
||||
<rect x="1" y="1071" width="98" height="24" rx="0"
|
||||
fill="none"/>
|
||||
</g>
|
||||
<g id="itemview-hover">
|
||||
<rect x="111" y="1071" width="98" height="24" rx="0"
|
||||
fill="#8cc63f" fill-opacity="0.12"/>
|
||||
</g>
|
||||
<g id="itemview-pressed">
|
||||
<rect x="221" y="1071" width="98" height="24" rx="0"
|
||||
fill="#88008f" fill-opacity="0.8"/>
|
||||
</g>
|
||||
<g id="itemview-toggled">
|
||||
<rect x="331" y="1071" width="98" height="24" rx="0"
|
||||
fill="#88008f"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
TOOLBAR (y=1110)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="toolbar">
|
||||
<rect x="1" y="1111" width="98" height="38" rx="0"
|
||||
fill="#2a2e32" stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- toolbar separator handle indicator -->
|
||||
<g id="toolbar-handle">
|
||||
<line x1="3" y1="1115" x2="3" y2="1143"
|
||||
stroke="#3a3d41" stroke-width="2" stroke-dasharray="1,2"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
DOCK (y=1160)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="dock">
|
||||
<rect x="1" y="1161" width="98" height="58" rx="0"
|
||||
fill="#1e1526" stroke="#2e3236" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
SPLITTER (y=1230)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="splitter">
|
||||
<rect x="1" y="1231" width="4" height="98" rx="2"
|
||||
fill="#2e3236"/>
|
||||
</g>
|
||||
<g id="splitter-hover">
|
||||
<rect x="7" y="1231" width="4" height="98" rx="2"
|
||||
fill="#8cc63f" fill-opacity="0.4"/>
|
||||
</g>
|
||||
<g id="splitter-pressed">
|
||||
<rect x="13" y="1231" width="4" height="98" rx="2"
|
||||
fill="#8cc63f"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
SEPARATOR (y=1340)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="separator">
|
||||
<rect x="1" y="1341" width="98" height="1" rx="0"
|
||||
fill="#3a3d41"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
GENERIC FRAME (y=1350)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="frame">
|
||||
<rect x="1" y="1351" width="98" height="78" rx="4"
|
||||
fill="none" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
GROUP BOX (y=1440)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="groupbox">
|
||||
<rect x="1" y="1441" width="98" height="78" rx="4"
|
||||
fill="none" stroke="#3a3d41" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
STATUS BAR (y=1530)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="statusbar">
|
||||
<rect x="1" y="1531" width="98" height="22" rx="0"
|
||||
fill="#1e1526" stroke="none"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
WINDOW / DIALOG BACKGROUND (y=1560)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="window">
|
||||
<rect x="1" y="1561" width="98" height="78" rx="0"
|
||||
fill="#1e1526"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
TITLEBAR (y=1650)
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
<g id="titlebar">
|
||||
<rect x="1" y="1651" width="98" height="30" rx="0"
|
||||
fill="#1e1526"/>
|
||||
</g>
|
||||
<g id="titlebar-inactive">
|
||||
<rect x="111" y="1651" width="98" height="30" rx="0"
|
||||
fill="#1a1a20"/>
|
||||
</g>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════
|
||||
ARROWS / INDICATORS (y=1700)
|
||||
Kvantum scales these as needed; drawn in NexusOS text colors
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- generic arrow down (for combo, dropdowns) -->
|
||||
<g id="arrow-down">
|
||||
<path d="M2,1703 L8,1711 L14,1703 Z" fill="#a8a8a8"/>
|
||||
</g>
|
||||
<g id="arrow-down-hover">
|
||||
<path d="M2,1703 L8,1711 L14,1703 Z" fill="#f2f2f2"/>
|
||||
</g>
|
||||
<g id="arrow-down-pressed">
|
||||
<path d="M2,1703 L8,1711 L14,1703 Z" fill="#0a0a00"/>
|
||||
</g>
|
||||
<g id="arrow-down-disabled">
|
||||
<path d="M2,1703 L8,1711 L14,1703 Z" fill="#6e7173"/>
|
||||
</g>
|
||||
|
||||
<g id="arrow-up">
|
||||
<path d="M2,1721 L8,1713 L14,1721 Z" fill="#a8a8a8"/>
|
||||
</g>
|
||||
<g id="arrow-up-hover">
|
||||
<path d="M2,1721 L8,1713 L14,1721 Z" fill="#f2f2f2"/>
|
||||
</g>
|
||||
<g id="arrow-up-disabled">
|
||||
<path d="M2,1721 L8,1713 L14,1721 Z" fill="#6e7173"/>
|
||||
</g>
|
||||
|
||||
<g id="arrow-left">
|
||||
<path d="M15,1733 L7,1739 L15,1745 Z" fill="#a8a8a8"/>
|
||||
</g>
|
||||
<g id="arrow-left-hover">
|
||||
<path d="M15,1733 L7,1739 L15,1745 Z" fill="#f2f2f2"/>
|
||||
</g>
|
||||
<g id="arrow-left-disabled">
|
||||
<path d="M15,1733 L7,1739 L15,1745 Z" fill="#6e7173"/>
|
||||
</g>
|
||||
|
||||
<g id="arrow-right">
|
||||
<path d="M1,1753 L9,1759 L1,1765 Z" fill="#a8a8a8"/>
|
||||
</g>
|
||||
<g id="arrow-right-hover">
|
||||
<path d="M1,1753 L9,1759 L1,1765 Z" fill="#f2f2f2"/>
|
||||
</g>
|
||||
<g id="arrow-right-disabled">
|
||||
<path d="M1,1753 L9,1759 L1,1765 Z" fill="#6e7173"/>
|
||||
</g>
|
||||
|
||||
<!-- generic arrow (used by TreeExpander, SpinBox, ScrollArrow) -->
|
||||
<g id="arrow">
|
||||
<path d="M2,1773 L8,1781 L14,1773 Z" fill="#a8a8a8"/>
|
||||
</g>
|
||||
<g id="arrow-hover">
|
||||
<path d="M2,1773 L8,1781 L14,1773 Z" fill="#f2f2f2"/>
|
||||
</g>
|
||||
<g id="arrow-disabled">
|
||||
<path d="M2,1773 L8,1781 L14,1773 Z" fill="#6e7173"/>
|
||||
</g>
|
||||
|
||||
<!-- menuitem submenu arrow -->
|
||||
<g id="menuitem-arrow">
|
||||
<path d="M1,1793 L7,1799 L1,1805 Z" fill="#a8a8a8"/>
|
||||
</g>
|
||||
<g id="menuitem-arrow-hover">
|
||||
<path d="M1,1793 L7,1799 L1,1805 Z" fill="#f2f2f2"/>
|
||||
</g>
|
||||
<g id="menuitem-arrow-pressed">
|
||||
<path d="M1,1793 L7,1799 L1,1805 Z" fill="#0a0a00"/>
|
||||
</g>
|
||||
|
||||
<!-- tab close button indicator -->
|
||||
<g id="tab-close">
|
||||
<path d="M 0,0 L 8,8 M 8,0 L 0,8" transform="translate(1,1813)"
|
||||
fill="none" stroke="#a8a8a8" stroke-width="1.5"
|
||||
stroke-linecap="round"/>
|
||||
</g>
|
||||
<g id="tab-close-hover">
|
||||
<circle cx="5" cy="1821" r="7" fill="#da4453"/>
|
||||
<path d="M 0,0 L 8,8 M 8,0 L 0,8" transform="translate(1,1817)"
|
||||
fill="none" stroke="#ffffff" stroke-width="1.5"
|
||||
stroke-linecap="round"/>
|
||||
</g>
|
||||
|
||||
<!-- size grip -->
|
||||
<g id="sizegrip">
|
||||
<path d="M6,1840 L12,1840 M10,1836 L12,1836 L12,1838 M4,1842 L12,1842"
|
||||
fill="none" stroke="#3a3d41" stroke-width="1" stroke-linecap="round"/>
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,118 @@
|
||||
[ColorEffects:Disabled]
|
||||
Color=56,56,56
|
||||
ColorAmount=0
|
||||
ColorEffect=0
|
||||
ContrastAmount=0.1
|
||||
ContrastEffect=2
|
||||
IntensityAmount=0
|
||||
IntensityEffect=0
|
||||
|
||||
[ColorEffects:Inactive]
|
||||
ChangeSelectionColor=true
|
||||
Color=112,111,110
|
||||
ColorAmount=0.025
|
||||
ColorEffect=0
|
||||
ContrastAmount=0.1
|
||||
ContrastEffect=2
|
||||
Enable=false
|
||||
IntensityAmount=0
|
||||
IntensityEffect=0
|
||||
|
||||
[Colors:Window]
|
||||
BackgroundNormal=30,21,38
|
||||
BackgroundAlternate=31,34,37
|
||||
ForegroundNormal=242,242,242
|
||||
ForegroundInactive=168,168,168
|
||||
ForegroundActive=140,198,63
|
||||
ForegroundLink=184,227,115
|
||||
ForegroundVisited=162,50,168
|
||||
ForegroundNegative=218,68,83
|
||||
ForegroundNeutral=246,116,0
|
||||
ForegroundPositive=39,174,96
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
[Colors:View]
|
||||
BackgroundNormal=30,21,38
|
||||
BackgroundAlternate=31,34,37
|
||||
ForegroundNormal=242,242,242
|
||||
ForegroundInactive=168,168,168
|
||||
ForegroundActive=140,198,63
|
||||
ForegroundLink=184,227,115
|
||||
ForegroundVisited=162,50,168
|
||||
ForegroundNegative=218,68,83
|
||||
ForegroundNeutral=246,116,0
|
||||
ForegroundPositive=39,174,96
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
[Colors:Button]
|
||||
BackgroundNormal=42,46,50
|
||||
BackgroundAlternate=30,21,38
|
||||
ForegroundNormal=242,242,242
|
||||
ForegroundInactive=168,168,168
|
||||
ForegroundActive=140,198,63
|
||||
ForegroundLink=184,227,115
|
||||
ForegroundVisited=162,50,168
|
||||
ForegroundNegative=218,68,83
|
||||
ForegroundNeutral=246,116,0
|
||||
ForegroundPositive=39,174,96
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
[Colors:Selection]
|
||||
BackgroundNormal=136,0,143
|
||||
BackgroundAlternate=107,166,42
|
||||
ForegroundNormal=255,255,255
|
||||
ForegroundInactive=255,255,255
|
||||
ForegroundActive=140,198,63
|
||||
ForegroundLink=184,227,115
|
||||
ForegroundVisited=162,50,168
|
||||
ForegroundNegative=218,68,83
|
||||
ForegroundNeutral=246,116,0
|
||||
ForegroundPositive=39,174,96
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
[Colors:Tooltip]
|
||||
BackgroundNormal=46,50,54
|
||||
BackgroundAlternate=58,61,65
|
||||
ForegroundNormal=242,242,242
|
||||
ForegroundInactive=168,168,168
|
||||
ForegroundActive=140,198,63
|
||||
ForegroundLink=184,227,115
|
||||
ForegroundVisited=162,50,168
|
||||
ForegroundNegative=218,68,83
|
||||
ForegroundNeutral=246,116,0
|
||||
ForegroundPositive=39,174,96
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
[Colors:Complementary]
|
||||
BackgroundNormal=42,46,50
|
||||
BackgroundAlternate=46,50,54
|
||||
ForegroundNormal=242,242,242
|
||||
ForegroundInactive=168,168,168
|
||||
ForegroundActive=140,198,63
|
||||
ForegroundLink=184,227,115
|
||||
ForegroundVisited=162,50,168
|
||||
ForegroundNegative=218,68,83
|
||||
ForegroundNeutral=246,116,0
|
||||
ForegroundPositive=39,174,96
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
[Colors:Header]
|
||||
BackgroundNormal=30,21,38
|
||||
BackgroundAlternate=42,46,50
|
||||
ForegroundNormal=242,242,242
|
||||
ForegroundInactive=168,168,168
|
||||
ForegroundActive=140,198,63
|
||||
ForegroundLink=184,227,115
|
||||
ForegroundVisited=162,50,168
|
||||
ForegroundNegative=218,68,83
|
||||
ForegroundNeutral=246,116,0
|
||||
ForegroundPositive=39,174,96
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
[General]
|
||||
ColorScheme=NexusOS
|
||||
Name=NexusOS
|
||||
shadeSortColumn=true
|
||||
|
||||
[KDE]
|
||||
contrast=4
|
||||
@@ -0,0 +1,53 @@
|
||||
[Colors:Window]
|
||||
BackgroundNormal=30,21,38
|
||||
BackgroundAlternate=31,34,37
|
||||
ForegroundNormal=242,242,242
|
||||
ForegroundInactive=168,168,168
|
||||
ForegroundActive=140,198,63
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
|
||||
[Colors:Button]
|
||||
BackgroundNormal=42,46,50
|
||||
BackgroundAlternate=30,21,38
|
||||
ForegroundNormal=242,242,242
|
||||
ForegroundInactive=168,168,168
|
||||
ForegroundActive=140,198,63
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
|
||||
[Colors:View]
|
||||
BackgroundNormal=30,21,38
|
||||
BackgroundAlternate=31,34,37
|
||||
ForegroundNormal=242,242,242
|
||||
ForegroundInactive=168,168,168
|
||||
ForegroundActive=140,198,63
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
|
||||
[Colors:Selection]
|
||||
BackgroundNormal=136,0,143
|
||||
BackgroundAlternate=107,166,42
|
||||
ForegroundNormal=255,255,255
|
||||
ForegroundInactive=255,255,255
|
||||
ForegroundActive=140,198,63
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
|
||||
[Colors:Tooltip]
|
||||
BackgroundNormal=46,50,54
|
||||
BackgroundAlternate=58,61,65
|
||||
ForegroundNormal=242,242,242
|
||||
ForegroundInactive=168,168,168
|
||||
ForegroundActive=140,198,63
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
|
||||
[Colors:Complementary]
|
||||
BackgroundNormal=42,46,50
|
||||
BackgroundAlternate=46,50,54
|
||||
ForegroundNormal=242,242,242
|
||||
ForegroundInactive=168,168,168
|
||||
ForegroundActive=140,198,63
|
||||
DecorationFocus=140,198,63
|
||||
DecorationHover=136,0,143
|
||||
@@ -0,0 +1,16 @@
|
||||
[Desktop Entry]
|
||||
Name=NexusOS
|
||||
Comment=Dark purple Plasma shell theme, lime-green accents
|
||||
Type=Service
|
||||
|
||||
[KPackageStructure]
|
||||
X-KDE-ServiceTypes=Plasma/Theme
|
||||
|
||||
X-KDE-PluginInfo-Author=Jon
|
||||
X-KDE-PluginInfo-Email=
|
||||
X-KDE-PluginInfo-Name=NexusOS
|
||||
X-KDE-PluginInfo-Version=1.0
|
||||
X-KDE-PluginInfo-Website=
|
||||
X-KDE-PluginInfo-Category=
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
X-KDE-PluginInfo-EnabledByDefault=false
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
NexusOS opaque panel-background.svg — no transparency.
|
||||
Used when compositor is disabled or "Opaque when maximized" is set.
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
|
||||
width="100" height="100">
|
||||
|
||||
<rect id="center"
|
||||
x="4" y="4" width="92" height="92"
|
||||
fill="#1e1526"/>
|
||||
|
||||
<rect id="top" x="4" y="0" width="92" height="4" fill="#4d3461"/>
|
||||
<rect id="bottom" x="4" y="96" width="92" height="4" fill="#4d3461"/>
|
||||
<rect id="left" x="0" y="4" width="4" height="92" fill="#1e1526"/>
|
||||
<rect id="right" x="96" y="4" width="4" height="92" fill="#1e1526"/>
|
||||
<rect id="topleft" x="0" y="0" width="4" height="4" fill="#4d3461"/>
|
||||
<rect id="topright" x="96" y="0" width="4" height="4" fill="#4d3461"/>
|
||||
<rect id="bottomleft" x="0" y="96" width="4" height="4" fill="#4d3461"/>
|
||||
<rect id="bottomright" x="96" y="96" width="4" height="4" fill="#4d3461"/>
|
||||
|
||||
<rect id="hint-left-margin" x="0" y="0" width="4" height="1" fill="none"/>
|
||||
<rect id="hint-top-margin" x="0" y="0" width="1" height="4" fill="none"/>
|
||||
<rect id="hint-right-margin" x="96" y="0" width="4" height="1" fill="none"/>
|
||||
<rect id="hint-bottom-margin" x="0" y="96" width="1" height="4" fill="none"/>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
NexusOS default widget background (desktop widgets, plasmoids).
|
||||
Same 9-slice structure as panel-background but solid surface_bg.
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
|
||||
width="100" height="100">
|
||||
|
||||
<rect id="center"
|
||||
x="4" y="4" width="92" height="92"
|
||||
fill="#1f2225"/>
|
||||
|
||||
<rect id="top" x="4" y="0" width="92" height="4" fill="#3a3d41"/>
|
||||
<rect id="bottom" x="4" y="96" width="92" height="4" fill="#3a3d41"/>
|
||||
<rect id="left" x="0" y="4" width="4" height="92" fill="#1f2225"/>
|
||||
<rect id="right" x="96" y="4" width="4" height="92" fill="#1f2225"/>
|
||||
<rect id="topleft" x="0" y="0" width="4" height="4" fill="#3a3d41"/>
|
||||
<rect id="topright" x="96" y="0" width="4" height="4" fill="#3a3d41"/>
|
||||
<rect id="bottomleft" x="0" y="96" width="4" height="4" fill="#3a3d41"/>
|
||||
<rect id="bottomright" x="96" y="96" width="4" height="4" fill="#3a3d41"/>
|
||||
|
||||
<rect id="hint-left-margin" x="0" y="0" width="4" height="1" fill="none"/>
|
||||
<rect id="hint-top-margin" x="0" y="0" width="1" height="4" fill="none"/>
|
||||
<rect id="hint-right-margin" x="96" y="0" width="4" height="1" fill="none"/>
|
||||
<rect id="hint-bottom-margin" x="0" y="96" width="1" height="4" fill="none"/>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
NexusOS Plasma button.svg — used for panel applet buttons.
|
||||
States: normal (transparent), hover (lime wash), pressed (solid lime),
|
||||
focus, checked.
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
|
||||
width="100" height="100">
|
||||
|
||||
<!-- normal: transparent (no visible bg) -->
|
||||
<rect id="normal"
|
||||
x="2" y="2" width="96" height="96" rx="4"
|
||||
fill="none"/>
|
||||
|
||||
<!-- hover: lime green wash -->
|
||||
<rect id="hover"
|
||||
x="2" y="2" width="96" height="96" rx="4"
|
||||
fill="#8cc63f" fill-opacity="0.18"/>
|
||||
|
||||
<!-- pressed -->
|
||||
<rect id="pressed"
|
||||
x="2" y="2" width="96" height="96" rx="4"
|
||||
fill="#8cc63f" fill-opacity="0.35"/>
|
||||
|
||||
<!-- focus: green outline -->
|
||||
<rect id="focus"
|
||||
x="2" y="2" width="96" height="96" rx="4"
|
||||
fill="none" stroke="#8cc63f" stroke-width="2"/>
|
||||
|
||||
<!-- checked / toggled on -->
|
||||
<rect id="checked"
|
||||
x="2" y="2" width="96" height="96" rx="4"
|
||||
fill="#8cc63f" fill-opacity="0.25"
|
||||
stroke="#8cc63f" stroke-width="1"/>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
NexusOS Plasma panel-background.svg
|
||||
9-slice: Plasma stretches the center element and tiles the edges/corners.
|
||||
Semi-transparent dark purple panel with a subtle 1px purple top/bottom border.
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100" height="100">
|
||||
|
||||
<!-- Margin hints for Plasma (pixels to use as non-stretched borders) -->
|
||||
<inkscape:perspective id="margin-hint"
|
||||
inkscape:label="4 4 4 4"/>
|
||||
|
||||
<!-- center — main stretchable fill (semi-transparent dark purple) -->
|
||||
<rect id="center"
|
||||
x="4" y="4" width="92" height="92"
|
||||
fill="#1e1526" fill-opacity="0.88"/>
|
||||
|
||||
<!-- top edge -->
|
||||
<rect id="top"
|
||||
x="4" y="0" width="92" height="4"
|
||||
fill="#4d3461"/>
|
||||
|
||||
<!-- bottom edge -->
|
||||
<rect id="bottom"
|
||||
x="4" y="96" width="92" height="4"
|
||||
fill="#4d3461"/>
|
||||
|
||||
<!-- left edge -->
|
||||
<rect id="left"
|
||||
x="0" y="4" width="4" height="92"
|
||||
fill="#1e1526" fill-opacity="0.88"/>
|
||||
|
||||
<!-- right edge -->
|
||||
<rect id="right"
|
||||
x="96" y="4" width="4" height="92"
|
||||
fill="#1e1526" fill-opacity="0.88"/>
|
||||
|
||||
<!-- corners -->
|
||||
<rect id="topleft" x="0" y="0" width="4" height="4" fill="#4d3461"/>
|
||||
<rect id="topright" x="96" y="0" width="4" height="4" fill="#4d3461"/>
|
||||
<rect id="bottomleft" x="0" y="96" width="4" height="4" fill="#4d3461"/>
|
||||
<rect id="bottomright" x="96" y="96" width="4" height="4" fill="#4d3461"/>
|
||||
|
||||
<!-- shadow — empty for flat design -->
|
||||
<rect id="shadow" x="0" y="0" width="1" height="1" fill="none"/>
|
||||
<rect id="hint-left-margin" x="0" y="0" width="4" height="1" fill="none"/>
|
||||
<rect id="hint-top-margin" x="0" y="0" width="1" height="4" fill="none"/>
|
||||
<rect id="hint-right-margin" x="96" y="0" width="4" height="1" fill="none"/>
|
||||
<rect id="hint-bottom-margin" x="0" y="96" width="1" height="4" fill="none"/>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- NexusOS Plasma plasmoid heading (widget title bar) -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
|
||||
width="100" height="100">
|
||||
|
||||
<rect id="center"
|
||||
x="0" y="0" width="100" height="100"
|
||||
fill="#2a2e32"/>
|
||||
|
||||
<!-- lime-green bottom accent line -->
|
||||
<rect id="bottom"
|
||||
x="0" y="97" width="100" height="3"
|
||||
fill="#8cc63f" fill-opacity="0.5"/>
|
||||
|
||||
<rect id="top" x="0" y="0" width="100" height="2" fill="#2a2e32"/>
|
||||
<rect id="left" x="0" y="0" width="2" height="100" fill="#2a2e32"/>
|
||||
<rect id="right" x="98" y="0" width="2" height="100" fill="#2a2e32"/>
|
||||
<rect id="topleft" x="0" y="0" width="2" height="2" fill="#2a2e32"/>
|
||||
<rect id="topright" x="98" y="0" width="2" height="2" fill="#2a2e32"/>
|
||||
<rect id="bottomleft" x="0" y="97" width="2" height="3" fill="#8cc63f" fill-opacity="0.5"/>
|
||||
<rect id="bottomright" x="98" y="97" width="2" height="3" fill="#8cc63f" fill-opacity="0.5"/>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1023 B |
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- NexusOS Plasma tooltip background -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
|
||||
width="100" height="100">
|
||||
|
||||
<rect id="center"
|
||||
x="6" y="6" width="88" height="88"
|
||||
fill="#2e3236"/>
|
||||
|
||||
<rect id="top" x="6" y="0" width="88" height="6" fill="#3a3d41"/>
|
||||
<rect id="bottom" x="6" y="94" width="88" height="6" fill="#3a3d41"/>
|
||||
<rect id="left" x="0" y="6" width="6" height="88" fill="#2e3236"/>
|
||||
<rect id="right" x="94" y="6" width="6" height="88" fill="#2e3236"/>
|
||||
<rect id="topleft" x="0" y="0" width="6" height="6" fill="#3a3d41"/>
|
||||
<rect id="topright" x="94" y="0" width="6" height="6" fill="#3a3d41"/>
|
||||
<rect id="bottomleft" x="0" y="94" width="6" height="6" fill="#3a3d41"/>
|
||||
<rect id="bottomright" x="94" y="94" width="6" height="6" fill="#3a3d41"/>
|
||||
|
||||
<rect id="hint-left-margin" x="0" y="0" width="6" height="1" fill="none"/>
|
||||
<rect id="hint-top-margin" x="0" y="0" width="1" height="6" fill="none"/>
|
||||
<rect id="hint-right-margin" x="94" y="0" width="6" height="1" fill="none"/>
|
||||
<rect id="hint-bottom-margin" x="0" y="94" width="1" height="6" fill="none"/>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,397 @@
|
||||
import QtQuick 2.0
|
||||
import SddmComponents 2.0
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
width: 1920
|
||||
height: 1200
|
||||
|
||||
readonly property color accentColor: "#8cc63f" // brand_green
|
||||
readonly property color bgDark: "#1e1526" // base_bg
|
||||
readonly property color textPrimary: "#f2f2f2" // text_primary
|
||||
readonly property color textMuted: "#a8a8a8" // text_secondary
|
||||
readonly property color fieldBg: "#1f2225" // surface_bg
|
||||
readonly property color fieldBorder: "#4d3461" // menu_border (purple tint)
|
||||
readonly property color errorColor: "#da4453" // error_color
|
||||
|
||||
property int sessionIndex: sessionModel.lastIndex
|
||||
|
||||
Connections {
|
||||
target: sddm
|
||||
onLoginFailed: {
|
||||
errorMsg.text = "Login failed — check your credentials."
|
||||
passwordInput.text = ""
|
||||
passwordInput.focus = true
|
||||
shakeAnim.start()
|
||||
}
|
||||
onLoginSucceeded: {
|
||||
errorMsg.text = ""
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: "assets/background.svg"
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
smooth: true
|
||||
asynchronous: false
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: "#000000"
|
||||
opacity: 0.25
|
||||
}
|
||||
|
||||
Item {
|
||||
id: logoArea
|
||||
width: 120
|
||||
height: 120
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: parent.height * 0.10
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width * 1.6
|
||||
height: parent.height * 1.6
|
||||
radius: width / 2
|
||||
color: accentColor
|
||||
opacity: 0.06
|
||||
}
|
||||
|
||||
Image {
|
||||
id: logo
|
||||
anchors.fill: parent
|
||||
source: "assets/logo.png"
|
||||
sourceSize: Qt.size(200, 200)
|
||||
smooth: true
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: brandLabel
|
||||
text: "NexusOS"
|
||||
color: textPrimary
|
||||
font.family: "Sans"
|
||||
font.pixelSize: 28
|
||||
font.letterSpacing: 6
|
||||
font.weight: Font.Light
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: logoArea.bottom
|
||||
anchors.topMargin: 16
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: loginBox
|
||||
width: 360
|
||||
height: loginColumn.height + 60
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: brandLabel.bottom
|
||||
anchors.topMargin: parent.height * 0.08
|
||||
color: Qt.rgba(15/255, 22/255, 38/255, 0.75)
|
||||
radius: 12
|
||||
border.color: fieldBorder
|
||||
border.width: 1
|
||||
|
||||
SequentialAnimation {
|
||||
id: shakeAnim
|
||||
NumberAnimation { target: loginBox; property: "x"; to: loginBox.x - 10; duration: 50 }
|
||||
NumberAnimation { target: loginBox; property: "x"; to: loginBox.x + 10; duration: 50 }
|
||||
NumberAnimation { target: loginBox; property: "x"; to: loginBox.x - 6; duration: 50 }
|
||||
NumberAnimation { target: loginBox; property: "x"; to: loginBox.x + 6; duration: 50 }
|
||||
NumberAnimation { target: loginBox; property: "x"; to: loginBox.x; duration: 40 }
|
||||
}
|
||||
|
||||
Column {
|
||||
id: loginColumn
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 30
|
||||
spacing: 14
|
||||
|
||||
Rectangle {
|
||||
id: sessionBox
|
||||
width: parent.width
|
||||
height: 40
|
||||
color: fieldBg
|
||||
radius: 6
|
||||
border.color: sessionDropdown.visible ? accentColor : fieldBorder
|
||||
border.width: 1
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 14
|
||||
anchors.right: sessionArrow.left
|
||||
anchors.rightMargin: 8
|
||||
text: sessionModel.data(sessionModel.index(sessionIndex, 0), Qt.DisplayRole) || "Session"
|
||||
color: textPrimary
|
||||
font.pixelSize: 13
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Text {
|
||||
id: sessionArrow
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 14
|
||||
text: sessionDropdown.visible ? "▲" : "▼"
|
||||
color: textMuted
|
||||
font.pixelSize: 10
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (!sessionDropdown.visible) {
|
||||
var pos = sessionBox.mapToItem(root, 0, sessionBox.height)
|
||||
sessionDropdown.x = pos.x
|
||||
sessionDropdown.y = pos.y + 2
|
||||
sessionDropdown.width = sessionBox.width
|
||||
}
|
||||
sessionDropdown.visible = !sessionDropdown.visible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 44
|
||||
color: fieldBg
|
||||
radius: 6
|
||||
border.color: usernameInput.activeFocus ? accentColor : fieldBorder
|
||||
border.width: 1
|
||||
|
||||
TextInput {
|
||||
id: usernameInput
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 14
|
||||
anchors.rightMargin: 14
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
color: textPrimary
|
||||
font.pixelSize: 14
|
||||
clip: true
|
||||
text: userModel.lastUser
|
||||
|
||||
Keys.onTabPressed: passwordInput.forceActiveFocus()
|
||||
Keys.onReturnPressed: sddm.login(usernameInput.text, passwordInput.text, sessionIndex)
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 14
|
||||
text: "Username"
|
||||
color: textMuted
|
||||
font.pixelSize: 14
|
||||
visible: usernameInput.text.length === 0 && !usernameInput.activeFocus
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 44
|
||||
color: fieldBg
|
||||
radius: 6
|
||||
border.color: passwordInput.activeFocus ? accentColor : fieldBorder
|
||||
border.width: 1
|
||||
|
||||
TextInput {
|
||||
id: passwordInput
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: 14
|
||||
anchors.rightMargin: 14
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
color: textPrimary
|
||||
font.pixelSize: 14
|
||||
echoMode: TextInput.Password
|
||||
clip: true
|
||||
focus: true
|
||||
|
||||
Keys.onReturnPressed: sddm.login(usernameInput.text, passwordInput.text, sessionIndex)
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 14
|
||||
text: "Password"
|
||||
color: textMuted
|
||||
font.pixelSize: 14
|
||||
visible: passwordInput.text.length === 0 && !passwordInput.activeFocus
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: errorMsg
|
||||
width: parent.width
|
||||
text: ""
|
||||
color: errorColor
|
||||
font.pixelSize: 12
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
visible: text !== ""
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: loginButton
|
||||
width: parent.width
|
||||
height: 44
|
||||
radius: 6
|
||||
color: loginMouse.pressed
|
||||
? Qt.darker(accentColor, 1.3)
|
||||
: loginMouse.containsMouse
|
||||
? Qt.lighter(accentColor, 1.15)
|
||||
: accentColor
|
||||
|
||||
Behavior on color { ColorAnimation { duration: 150 } }
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "LOGIN"
|
||||
color: "#0a0a00" // text_on_accent (dark on lime green)
|
||||
font.pixelSize: 14
|
||||
font.letterSpacing: 3
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: loginMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: sddm.login(usernameInput.text, passwordInput.text, sessionIndex)
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 30
|
||||
|
||||
Row {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 30
|
||||
|
||||
Text {
|
||||
text: "⏻ Shutdown"
|
||||
color: textMuted
|
||||
font.pixelSize: 12
|
||||
opacity: shutdownMouse.containsMouse ? 1.0 : 0.7
|
||||
Behavior on opacity { NumberAnimation { duration: 120 } }
|
||||
|
||||
MouseArea {
|
||||
id: shutdownMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: sddm.powerOff()
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "↻ Reboot"
|
||||
color: textMuted
|
||||
font.pixelSize: 12
|
||||
opacity: rebootMouse.containsMouse ? 1.0 : 0.7
|
||||
Behavior on opacity { NumberAnimation { duration: 120 } }
|
||||
|
||||
MouseArea {
|
||||
id: rebootMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: sddm.reboot()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: sessionDropdown
|
||||
visible: false
|
||||
z: 999
|
||||
color: fieldBg
|
||||
radius: 6
|
||||
border.color: fieldBorder
|
||||
border.width: 1
|
||||
height: sessionList.contentHeight
|
||||
clip: true
|
||||
|
||||
ListView {
|
||||
id: sessionList
|
||||
anchors.fill: parent
|
||||
model: sessionModel
|
||||
interactive: false
|
||||
|
||||
delegate: Rectangle {
|
||||
width: sessionList.width
|
||||
height: 36
|
||||
color: sessionItemMouse.containsMouse ? Qt.lighter(fieldBg, 1.4) : "transparent"
|
||||
radius: 4
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 14
|
||||
text: model.name || ""
|
||||
color: index === sessionIndex ? accentColor : textPrimary
|
||||
font.pixelSize: 13
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: sessionItemMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
sessionIndex = index
|
||||
sessionDropdown.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: parent.height * 0.05
|
||||
spacing: 2
|
||||
|
||||
Text {
|
||||
id: clockText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: textPrimary
|
||||
font.family: "Sans"
|
||||
font.pixelSize: 42
|
||||
font.weight: Font.Thin
|
||||
}
|
||||
|
||||
Text {
|
||||
id: dateText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: textMuted
|
||||
font.family: "Sans"
|
||||
font.pixelSize: 14
|
||||
font.letterSpacing: 2
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 1000
|
||||
running: true
|
||||
repeat: true
|
||||
triggeredOnStart: true
|
||||
onTriggered: {
|
||||
var d = new Date()
|
||||
clockText.text = Qt.formatTime(d, "hh:mm")
|
||||
dateText.text = Qt.formatDate(d, "dddd, MMMM d")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1200" width="1920" height="1200">
|
||||
<defs>
|
||||
<linearGradient id="metalBase" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#1a1a2e;stop-opacity:1"/>
|
||||
<stop offset="35%" style="stop-color:#16213e;stop-opacity:1"/>
|
||||
<stop offset="65%" style="stop-color:#0f1626;stop-opacity:1"/>
|
||||
<stop offset="100%" style="stop-color:#0a0e1a;stop-opacity:1"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="vignette" cx="50%" cy="50%" r="70%">
|
||||
<stop offset="0%" style="stop-color:transparent;stop-opacity:0"/>
|
||||
<stop offset="100%" style="stop-color:#000000;stop-opacity:0.6"/>
|
||||
</radialGradient>
|
||||
<pattern id="brushLines" x="0" y="0" width="4" height="4" patternUnits="userSpaceOnUse">
|
||||
<line x1="0" y1="4" x2="4" y2="0" stroke="#ffffff" stroke-width="0.3" opacity="0.03"/>
|
||||
</pattern>
|
||||
<pattern id="machineLines" x="0" y="0" width="100" height="3" patternUnits="userSpaceOnUse">
|
||||
<line x1="0" y1="1.5" x2="100" y2="1.5" stroke="#ffffff" stroke-width="0.2" opacity="0.025"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="1920" height="1200" fill="url(#metalBase)"/>
|
||||
<rect width="1920" height="1200" fill="url(#brushLines)"/>
|
||||
<rect width="1920" height="1200" fill="url(#machineLines)"/>
|
||||
<ellipse cx="960" cy="340" rx="1200" ry="280" fill="#ffffff" opacity="0.012"/>
|
||||
<ellipse cx="960" cy="220" rx="400" ry="170" fill="#00d4ff" opacity="0.015"/>
|
||||
<rect width="1920" height="1200" fill="url(#vignette)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 185 KiB |
@@ -0,0 +1,10 @@
|
||||
[SddmGreeterTheme]
|
||||
Name=NexusOS-QML
|
||||
Description=Dark brushed-metal lockscreen theme with flat N logo, upper-center branding, and centered login box.
|
||||
Author=Jon
|
||||
Version=1.0
|
||||
Website=
|
||||
Screenshot=
|
||||
MainScript=Main.qml
|
||||
ConfigFile=theme.conf
|
||||
TranslationsDirectory=
|
||||
@@ -0,0 +1,16 @@
|
||||
[General]
|
||||
# ── NexusOS-QML Theme Configuration ──
|
||||
|
||||
background=assets/background.svg
|
||||
logo=assets/logo.png
|
||||
|
||||
# Color palette
|
||||
accentColor=#8cc63f
|
||||
bgDark=#1e1526
|
||||
textPrimary=#f2f2f2
|
||||
textMuted=#a8a8a8
|
||||
fieldBg=#1f2225
|
||||
fieldBorder=#4d3461
|
||||
errorColor=#da4453
|
||||
|
||||
type=color
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 882 B After Width: | Height: | Size: 882 B |
|
Before Width: | Height: | Size: 955 B After Width: | Height: | Size: 955 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 921 B After Width: | Height: | Size: 921 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Code chevrons + slash -->
|
||||
<path d="M 52 42 L 34 64 L 52 86" fill="none" stroke="#f2f2f2"
|
||||
stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M 76 42 L 94 64 L 76 86" fill="none" stroke="#f2f2f2"
|
||||
stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<line x1="71" y1="38" x2="57" y2="90" stroke="#f2f2f2"
|
||||
stroke-width="8" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 636 B |
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Gamepad -->
|
||||
<rect x="36" y="50" width="56" height="30" rx="15" fill="#f2f2f2"/>
|
||||
<rect x="48" y="62.5" width="16" height="5" rx="1" fill="#5e0066"/>
|
||||
<rect x="53.5" y="57" width="5" height="16" rx="1" fill="#5e0066"/>
|
||||
<circle cx="76" cy="60" r="3.5" fill="#5e0066"/>
|
||||
<circle cx="84" cy="68" r="3.5" fill="#5e0066"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 549 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Framed picture: sun + mountains -->
|
||||
<rect x="34" y="40" width="60" height="48" rx="5" fill="none" stroke="#f2f2f2" stroke-width="7"/>
|
||||
<circle cx="51" cy="55" r="6" fill="#f2f2f2"/>
|
||||
<path d="M 40 84 L 56 63 L 67 74 L 78 58 L 88 84 Z" fill="#f2f2f2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 481 B |
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Globe -->
|
||||
<circle cx="64" cy="64" r="28" fill="none" stroke="#f2f2f2" stroke-width="7"/>
|
||||
<ellipse cx="64" cy="64" rx="12" ry="28" fill="none" stroke="#f2f2f2" stroke-width="7"/>
|
||||
<line x1="38" y1="55" x2="90" y2="55" stroke="#f2f2f2" stroke-width="7" stroke-linecap="round"/>
|
||||
<line x1="38" y1="73" x2="90" y2="73" stroke="#f2f2f2" stroke-width="7" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 605 B |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Play triangle -->
|
||||
<path d="M 51 40 L 51 88 L 92 64 Z" fill="#f2f2f2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 298 B |
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Document with folded corner + text lines -->
|
||||
<path d="M 44 32 L 74 32 L 86 44 L 86 96 L 44 96 Z" fill="#f2f2f2"/>
|
||||
<path d="M 74 32 L 74 44 L 86 44 Z" fill="#5e0066"/>
|
||||
<line x1="52" y1="58" x2="78" y2="58" stroke="#5e0066" stroke-width="5" stroke-linecap="round"/>
|
||||
<line x1="52" y1="70" x2="78" y2="70" stroke="#5e0066" stroke-width="5" stroke-linecap="round"/>
|
||||
<line x1="52" y1="82" x2="70" y2="82" stroke="#5e0066" stroke-width="5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 693 B |
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Erlenmeyer flask -->
|
||||
<path d="M 56 34 L 56 58 L 38 88 Q 35 95 43 95 L 85 95 Q 93 95 90 88 L 72 58 L 72 34"
|
||||
fill="none" stroke="#f2f2f2" stroke-width="7" stroke-linejoin="round"/>
|
||||
<line x1="51" y1="34" x2="77" y2="34" stroke="#f2f2f2" stroke-width="8" stroke-linecap="round"/>
|
||||
<path d="M 51 76 L 77 76 L 86 88 Q 89 93 83 93 L 45 93 Q 39 93 42 88 Z" fill="#f2f2f2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 604 B |
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Monitor -->
|
||||
<rect x="32" y="36" width="64" height="44" rx="5" fill="#f2f2f2"/>
|
||||
<rect x="40" y="44" width="48" height="28" rx="2" fill="#5e0066"/>
|
||||
<rect x="56" y="80" width="16" height="9" fill="#f2f2f2"/>
|
||||
<rect x="44" y="89" width="40" height="7" rx="3" fill="#f2f2f2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 504 B |
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Open-end wrench -->
|
||||
<g transform="rotate(45 64 64)">
|
||||
<rect x="58" y="44" width="12" height="44" rx="5" fill="#f2f2f2"/>
|
||||
<circle cx="64" cy="44" r="14" fill="#f2f2f2"/>
|
||||
<rect x="57" y="27" width="14" height="17" fill="#5e0066"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 474 B |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Settings cog -->
|
||||
<rect x="57" y="27" width="14" height="21" rx="2" transform="rotate(0 64 64)" fill="#f2f2f2"/>
|
||||
<rect x="57" y="27" width="14" height="21" rx="2" transform="rotate(45 64 64)" fill="#f2f2f2"/>
|
||||
<rect x="57" y="27" width="14" height="21" rx="2" transform="rotate(90 64 64)" fill="#f2f2f2"/>
|
||||
<rect x="57" y="27" width="14" height="21" rx="2" transform="rotate(135 64 64)" fill="#f2f2f2"/>
|
||||
<rect x="57" y="27" width="14" height="21" rx="2" transform="rotate(180 64 64)" fill="#f2f2f2"/>
|
||||
<rect x="57" y="27" width="14" height="21" rx="2" transform="rotate(225 64 64)" fill="#f2f2f2"/>
|
||||
<rect x="57" y="27" width="14" height="21" rx="2" transform="rotate(270 64 64)" fill="#f2f2f2"/>
|
||||
<rect x="57" y="27" width="14" height="21" rx="2" transform="rotate(315 64 64)" fill="#f2f2f2"/>
|
||||
<circle cx="64" cy="64" r="25" fill="#f2f2f2"/>
|
||||
<circle cx="64" cy="64" r="10" fill="#5e0066"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Crescent moon + Z -->
|
||||
<path d="M 66 39 A 28 28 0 1 0 66 91 A 28 28 0 0 1 66 39 Z"
|
||||
fill="#f2f2f2"/>
|
||||
<path d="M 78 34 L 99 34 L 78 56 L 99 56" fill="none" stroke="#f2f2f2"
|
||||
stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 481 B |
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Padlock -->
|
||||
<path d="M 52 64 L 52 50 A 12 12 0 0 1 76 50 L 76 64" fill="none"
|
||||
stroke="#f2f2f2" stroke-width="8" stroke-linecap="round"/>
|
||||
<rect x="40" y="62" width="48" height="40" rx="7" fill="#f2f2f2"/>
|
||||
<circle cx="64" cy="78" r="6" fill="#5e0066"/>
|
||||
<rect x="61" y="80" width="6" height="13" rx="3" fill="#5e0066"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 558 B |
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Doorway bracket, open on the right -->
|
||||
<path d="M 72 34 L 42 34 L 42 94 L 72 94" fill="none" stroke="#f2f2f2"
|
||||
stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<!-- Arrow exiting to the right -->
|
||||
<path d="M 56 64 L 92 64" fill="none" stroke="#f2f2f2"
|
||||
stroke-width="9" stroke-linecap="round"/>
|
||||
<path d="M 80 50 L 96 64 L 80 78" fill="none" stroke="#f2f2f2"
|
||||
stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 695 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Circular arrow -->
|
||||
<path d="M 64 40 A 24 24 0 1 1 41 71" fill="none" stroke="#f2f2f2"
|
||||
stroke-width="9" stroke-linecap="round"/>
|
||||
<path d="M 50 32 L 70 40 L 56 56 Z" fill="#f2f2f2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 418 B |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Power symbol: broken ring (gap at top) + stem -->
|
||||
<path d="M 55 51 A 22 22 0 1 0 73 51" fill="none" stroke="#f2f2f2"
|
||||
stroke-width="10" stroke-linecap="round"/>
|
||||
<rect x="59" y="35" width="10" height="31" rx="5" fill="#f2f2f2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 464 B |
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Crescent moon: big disc minus a disc shifted right -->
|
||||
<path d="M 74 33 A 33 33 0 1 0 74 95 A 33 33 0 0 1 74 33 Z"
|
||||
fill="#f2f2f2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 367 B |
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<circle cx="64" cy="64" r="52" fill="#5e0066" stroke="#8cc63f" stroke-width="6"/>
|
||||
<!-- Two person silhouettes -->
|
||||
<circle cx="78" cy="56" r="13" fill="#f2f2f2"/>
|
||||
<path d="M 56 96 Q 56 72 78 72 Q 100 72 100 96 Z" fill="#f2f2f2"/>
|
||||
<circle cx="48" cy="60" r="12" fill="#f2f2f2"/>
|
||||
<path d="M 28 96 Q 28 76 48 76 Q 60 76 65 84 L 56 88
|
||||
Q 56 84 56 96 Z" fill="#f2f2f2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 521 B |
@@ -0,0 +1,278 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
NexusOS action-icon generator.
|
||||
|
||||
Builds the icons the XFCE logoff dialog (xfce4-session-logout) and the
|
||||
Whisker menu command buttons request — shutdown / reboot / log-out /
|
||||
suspend / hibernate / switch-user / lock-screen / settings — in the
|
||||
NexusOS palette (white glyph on a deep-purple disc with a lime ring).
|
||||
|
||||
Emits one SVG per icon into actions/, rasterizes to
|
||||
~/.icons/NexusOS/<size>/actions/<name>.png at 16/22/24/32/48/64/128,
|
||||
then writes the alias copies (xfsm-*, system-suspend-hibernate, and the
|
||||
settings-manager app-icon names that Whisker's Settings button uses).
|
||||
|
||||
Run: python3 build_actions.py # SVGs + PNGs + aliases
|
||||
python3 build_actions.py --svg-only # just rewrite SVGs
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
ACTIONS = ROOT / "actions"
|
||||
ICONS_OUT = Path.home() / ".icons" / "NexusOS"
|
||||
SIZES = [16, 22, 24, 32, 48, 64, 128]
|
||||
|
||||
# ── colors (mirror gtk-3.0/colors.css) ────────────────────────────────
|
||||
BODY = "#5e0066" # brand_purple_dark — disc fill
|
||||
RING = "#8cc63f" # brand_green — disc ring
|
||||
GLYPH = "#f2f2f2" # text_primary — glyph
|
||||
|
||||
# ── master: purple disc + lime ring, viewBox 0 0 128 128 ──────────────
|
||||
# Glyph area: a ~70px box centered on (64, 64).
|
||||
DISC = f' <circle cx="64" cy="64" r="52" fill="{BODY}" ' \
|
||||
f'stroke="{RING}" stroke-width="6"/>\n'
|
||||
|
||||
|
||||
def _gear_glyph() -> str:
|
||||
"""Settings cog: 8 teeth on a white disc with a punched centre hole."""
|
||||
teeth = "".join(
|
||||
f' <rect x="57" y="27" width="14" height="21" rx="2" '
|
||||
f'transform="rotate({k * 45} 64 64)" fill="{GLYPH}"/>\n'
|
||||
for k in range(8)
|
||||
)
|
||||
return (
|
||||
" <!-- Settings cog -->\n"
|
||||
+ teeth
|
||||
+ f' <circle cx="64" cy="64" r="25" fill="{GLYPH}"/>\n'
|
||||
+ f' <circle cx="64" cy="64" r="10" fill="{BODY}"/>\n'
|
||||
)
|
||||
|
||||
|
||||
# ── glyph fragments — white, centered on (64, 64) ─────────────────────
|
||||
GLYPHS = {
|
||||
"system-shutdown": f"""\
|
||||
<!-- Power symbol: broken ring (gap at top) + stem -->
|
||||
<path d="M 55 51 A 22 22 0 1 0 73 51" fill="none" stroke="{GLYPH}"
|
||||
stroke-width="10" stroke-linecap="round"/>
|
||||
<rect x="59" y="35" width="10" height="31" rx="5" fill="{GLYPH}"/>
|
||||
""",
|
||||
|
||||
"system-reboot": f"""\
|
||||
<!-- Circular arrow -->
|
||||
<path d="M 64 40 A 24 24 0 1 1 41 71" fill="none" stroke="{GLYPH}"
|
||||
stroke-width="9" stroke-linecap="round"/>
|
||||
<path d="M 50 32 L 70 40 L 56 56 Z" fill="{GLYPH}"/>
|
||||
""",
|
||||
|
||||
"system-log-out": f"""\
|
||||
<!-- Doorway bracket, open on the right -->
|
||||
<path d="M 72 34 L 42 34 L 42 94 L 72 94" fill="none" stroke="{GLYPH}"
|
||||
stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<!-- Arrow exiting to the right -->
|
||||
<path d="M 56 64 L 92 64" fill="none" stroke="{GLYPH}"
|
||||
stroke-width="9" stroke-linecap="round"/>
|
||||
<path d="M 80 50 L 96 64 L 80 78" fill="none" stroke="{GLYPH}"
|
||||
stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
""",
|
||||
|
||||
"system-suspend": f"""\
|
||||
<!-- Crescent moon: big disc minus a disc shifted right -->
|
||||
<path d="M 74 33 A 33 33 0 1 0 74 95 A 33 33 0 0 1 74 33 Z"
|
||||
fill="{GLYPH}"/>
|
||||
""",
|
||||
|
||||
"system-hibernate": f"""\
|
||||
<!-- Crescent moon + Z -->
|
||||
<path d="M 66 39 A 28 28 0 1 0 66 91 A 28 28 0 0 1 66 39 Z"
|
||||
fill="{GLYPH}"/>
|
||||
<path d="M 78 34 L 99 34 L 78 56 L 99 56" fill="none" stroke="{GLYPH}"
|
||||
stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
""",
|
||||
|
||||
"system-switch-user": f"""\
|
||||
<!-- Two person silhouettes -->
|
||||
<circle cx="78" cy="56" r="13" fill="{GLYPH}"/>
|
||||
<path d="M 56 96 Q 56 72 78 72 Q 100 72 100 96 Z" fill="{GLYPH}"/>
|
||||
<circle cx="48" cy="60" r="12" fill="{GLYPH}"/>
|
||||
<path d="M 28 96 Q 28 76 48 76 Q 60 76 65 84 L 56 88
|
||||
Q 56 84 56 96 Z" fill="{GLYPH}"/>
|
||||
""",
|
||||
|
||||
"system-lock-screen": f"""\
|
||||
<!-- Padlock -->
|
||||
<path d="M 52 64 L 52 50 A 12 12 0 0 1 76 50 L 76 64" fill="none"
|
||||
stroke="{GLYPH}" stroke-width="8" stroke-linecap="round"/>
|
||||
<rect x="40" y="62" width="48" height="40" rx="7" fill="{GLYPH}"/>
|
||||
<circle cx="64" cy="78" r="6" fill="{BODY}"/>
|
||||
<rect x="61" y="80" width="6" height="13" rx="3" fill="{BODY}"/>
|
||||
""",
|
||||
|
||||
"preferences-desktop": _gear_glyph(),
|
||||
|
||||
# ── Whisker menu application-category glyphs ──────────────────────
|
||||
"applications-internet": f"""\
|
||||
<!-- Globe -->
|
||||
<circle cx="64" cy="64" r="28" fill="none" stroke="{GLYPH}" stroke-width="7"/>
|
||||
<ellipse cx="64" cy="64" rx="12" ry="28" fill="none" stroke="{GLYPH}" stroke-width="7"/>
|
||||
<line x1="38" y1="55" x2="90" y2="55" stroke="{GLYPH}" stroke-width="7" stroke-linecap="round"/>
|
||||
<line x1="38" y1="73" x2="90" y2="73" stroke="{GLYPH}" stroke-width="7" stroke-linecap="round"/>
|
||||
""",
|
||||
|
||||
"applications-development": f"""\
|
||||
<!-- Code chevrons + slash -->
|
||||
<path d="M 52 42 L 34 64 L 52 86" fill="none" stroke="{GLYPH}"
|
||||
stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M 76 42 L 94 64 L 76 86" fill="none" stroke="{GLYPH}"
|
||||
stroke-width="9" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<line x1="71" y1="38" x2="57" y2="90" stroke="{GLYPH}"
|
||||
stroke-width="8" stroke-linecap="round"/>
|
||||
""",
|
||||
|
||||
"applications-multimedia": f"""\
|
||||
<!-- Play triangle -->
|
||||
<path d="M 51 40 L 51 88 L 92 64 Z" fill="{GLYPH}"/>
|
||||
""",
|
||||
|
||||
"applications-office": f"""\
|
||||
<!-- Document with folded corner + text lines -->
|
||||
<path d="M 44 32 L 74 32 L 86 44 L 86 96 L 44 96 Z" fill="{GLYPH}"/>
|
||||
<path d="M 74 32 L 74 44 L 86 44 Z" fill="{BODY}"/>
|
||||
<line x1="52" y1="58" x2="78" y2="58" stroke="{BODY}" stroke-width="5" stroke-linecap="round"/>
|
||||
<line x1="52" y1="70" x2="78" y2="70" stroke="{BODY}" stroke-width="5" stroke-linecap="round"/>
|
||||
<line x1="52" y1="82" x2="70" y2="82" stroke="{BODY}" stroke-width="5" stroke-linecap="round"/>
|
||||
""",
|
||||
|
||||
"applications-graphics": f"""\
|
||||
<!-- Framed picture: sun + mountains -->
|
||||
<rect x="34" y="40" width="60" height="48" rx="5" fill="none" stroke="{GLYPH}" stroke-width="7"/>
|
||||
<circle cx="51" cy="55" r="6" fill="{GLYPH}"/>
|
||||
<path d="M 40 84 L 56 63 L 67 74 L 78 58 L 88 84 Z" fill="{GLYPH}"/>
|
||||
""",
|
||||
|
||||
"applications-system": f"""\
|
||||
<!-- Monitor -->
|
||||
<rect x="32" y="36" width="64" height="44" rx="5" fill="{GLYPH}"/>
|
||||
<rect x="40" y="44" width="48" height="28" rx="2" fill="{BODY}"/>
|
||||
<rect x="56" y="80" width="16" height="9" fill="{GLYPH}"/>
|
||||
<rect x="44" y="89" width="40" height="7" rx="3" fill="{GLYPH}"/>
|
||||
""",
|
||||
|
||||
"applications-utilities": f"""\
|
||||
<!-- Open-end wrench -->
|
||||
<g transform="rotate(45 64 64)">
|
||||
<rect x="58" y="44" width="12" height="44" rx="5" fill="{GLYPH}"/>
|
||||
<circle cx="64" cy="44" r="14" fill="{GLYPH}"/>
|
||||
<rect x="57" y="27" width="14" height="17" fill="{BODY}"/>
|
||||
</g>
|
||||
""",
|
||||
|
||||
"applications-games": f"""\
|
||||
<!-- Gamepad -->
|
||||
<rect x="36" y="50" width="56" height="30" rx="15" fill="{GLYPH}"/>
|
||||
<rect x="48" y="62.5" width="16" height="5" rx="1" fill="{BODY}"/>
|
||||
<rect x="53.5" y="57" width="5" height="16" rx="1" fill="{BODY}"/>
|
||||
<circle cx="76" cy="60" r="3.5" fill="{BODY}"/>
|
||||
<circle cx="84" cy="68" r="3.5" fill="{BODY}"/>
|
||||
""",
|
||||
|
||||
"applications-science": f"""\
|
||||
<!-- Erlenmeyer flask -->
|
||||
<path d="M 56 34 L 56 58 L 38 88 Q 35 95 43 95 L 85 95 Q 93 95 90 88 L 72 58 L 72 34"
|
||||
fill="none" stroke="{GLYPH}" stroke-width="7" stroke-linejoin="round"/>
|
||||
<line x1="51" y1="34" x2="77" y2="34" stroke="{GLYPH}" stroke-width="8" stroke-linecap="round"/>
|
||||
<path d="M 51 76 L 77 76 L 86 88 Q 89 93 83 93 L 45 93 Q 39 93 42 88 Z" fill="{GLYPH}"/>
|
||||
""",
|
||||
}
|
||||
|
||||
# Extra filenames that render the same art (XFCE's xfsm-* lookup names,
|
||||
# the hybrid-sleep alias, and the Whisker command-button names).
|
||||
ALIASES = {
|
||||
"xfsm-logout": "system-log-out",
|
||||
"xfsm-reboot": "system-reboot",
|
||||
"xfsm-shutdown": "system-shutdown",
|
||||
"xfsm-suspend": "system-suspend",
|
||||
"xfsm-hibernate": "system-hibernate",
|
||||
"xfsm-switch-user": "system-switch-user",
|
||||
"system-suspend-hibernate": "system-suspend",
|
||||
"xfsm-lock": "system-lock-screen",
|
||||
"preferences-system": "preferences-desktop",
|
||||
"org.xfce.settings.manager": "preferences-desktop",
|
||||
"xfce4-settings-manager": "preferences-desktop",
|
||||
# XFCE's "Accessories" menu uses xfce-accessories.directory
|
||||
# (Icon=applications-accessories), NOT the freedesktop Utility name, so
|
||||
# it needs the same wrench/tools badge as applications-utilities.
|
||||
"applications-accessories": "applications-utilities",
|
||||
}
|
||||
|
||||
|
||||
def svg_for(glyph: str) -> str:
|
||||
return (
|
||||
'<?xml version="1.0" encoding="UTF-8"?>\n'
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" '
|
||||
'viewBox="0 0 128 128">\n'
|
||||
f"{DISC}{glyph}</svg>\n"
|
||||
)
|
||||
|
||||
|
||||
def write_svgs() -> list[str]:
|
||||
ACTIONS.mkdir(parents=True, exist_ok=True)
|
||||
for name, glyph in GLYPHS.items():
|
||||
(ACTIONS / f"{name}.svg").write_text(svg_for(glyph))
|
||||
return list(GLYPHS)
|
||||
|
||||
|
||||
def render_pngs(names: list[str]) -> None:
|
||||
for name in names:
|
||||
svg = ACTIONS / f"{name}.svg"
|
||||
for size in SIZES:
|
||||
out_dir = ICONS_OUT / f"{size}x{size}" / "actions"
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
out = out_dir / f"{name}.png"
|
||||
subprocess.run(
|
||||
[
|
||||
"inkscape",
|
||||
str(svg),
|
||||
"--export-type=png",
|
||||
f"--export-filename={out}",
|
||||
f"--export-width={size}",
|
||||
f"--export-height={size}",
|
||||
],
|
||||
check=True,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
print(f" rendered {name} @ {size}")
|
||||
|
||||
|
||||
def write_aliases() -> None:
|
||||
for alias, src in ALIASES.items():
|
||||
for size in SIZES:
|
||||
d = ICONS_OUT / f"{size}x{size}" / "actions"
|
||||
src_png = d / f"{src}.png"
|
||||
if src_png.exists():
|
||||
shutil.copy2(src_png, d / f"{alias}.png")
|
||||
print(f" alias {alias} -> {src}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
svg_only = "--svg-only" in sys.argv
|
||||
names = write_svgs()
|
||||
print(f"Wrote {len(names)} SVGs into {ACTIONS}")
|
||||
if svg_only:
|
||||
return
|
||||
render_pngs(names)
|
||||
write_aliases()
|
||||
subprocess.run(
|
||||
["gtk-update-icon-cache", "-f", str(ICONS_OUT)],
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
print("\nDone. Reload: xfdesktop --reload & xfce4-panel -r")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
NexusOS battery-icon recolorizer.
|
||||
|
||||
xfce4-power-manager draws the panel battery from the icon theme's
|
||||
`battery-*-charging-symbolic` icons. Papirus-Dark (which NexusOS
|
||||
inherits from) paints the charging bolt/fill in its own material green
|
||||
(#4caf50). This script copies every charging battery symbolic icon into
|
||||
the NexusOS theme with that green swapped for brand_green (#8cc63f), so
|
||||
the charging indicator matches the rest of the NexusOS accent.
|
||||
|
||||
Only the green is touched — the gray battery body (#dfdfdf) is left
|
||||
alone (it already reads fine on the dark panel). Symlinked aliases
|
||||
(good/low/medium/caution/empty-charging) are resolved and written as
|
||||
real recolored files so every requested name overrides Papirus.
|
||||
|
||||
Run: python3 build_battery.py
|
||||
Then: gtk-update-icon-cache -f -t ../NexusOS-icons
|
||||
xfce4-panel -r # reload panel to pick up new icons
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
OUT = ROOT.parent / "NexusOS-icons" / "scalable" / "status"
|
||||
SRC = Path("/usr/share/icons/Papirus-Dark/symbolic/status")
|
||||
|
||||
PAPIRUS_GREEN = "#4caf50"
|
||||
NEXUS_GREEN = "#8cc63f" # brand_green
|
||||
|
||||
|
||||
def main() -> None:
|
||||
OUT.mkdir(parents=True, exist_ok=True)
|
||||
# Every charging battery symbolic icon (charged-100 has no green, so
|
||||
# the replace is a harmless no-op there; we copy it too for a
|
||||
# consistent battery set under the NexusOS theme).
|
||||
sources = sorted(SRC.glob("battery-*charg*-symbolic.svg"))
|
||||
written = 0
|
||||
for src in sources:
|
||||
# read_text follows symlinks, so alias names get the real content
|
||||
content = src.read_text()
|
||||
if PAPIRUS_GREEN not in content:
|
||||
# charged/full icons with no green — skip; let them fall
|
||||
# through to Papirus unchanged.
|
||||
continue
|
||||
recolored = content.replace(PAPIRUS_GREEN, NEXUS_GREEN)
|
||||
(OUT / src.name).write_text(recolored)
|
||||
written += 1
|
||||
print(f"Recolored {written} charging battery icons "
|
||||
f"({PAPIRUS_GREEN} -> {NEXUS_GREEN}) into {OUT}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,398 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
NexusOS network status icons generator.
|
||||
|
||||
Generates flat symbolic-style SVGs for nm-tray and any other Qt/GTK app
|
||||
that requests network-* status icons. Output goes to
|
||||
scalable/status/ of the NexusOS-icons theme.
|
||||
|
||||
Design language:
|
||||
* 16×16 viewBox, scalable SVG (no rasterization needed — Qt5 + GTK3
|
||||
both handle SVG fine in scalable/ dirs)
|
||||
* Light off-white stroke for base shape (wifi fan, ethernet plug,
|
||||
globe) — readable on the dark NexusOS surfaces
|
||||
* Lime brand accent for connected / active states
|
||||
* Purple lock for encryption
|
||||
* Red for error, orange for acquiring / no-route
|
||||
|
||||
Run: python3 build_status.py
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import math
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
OUT = ROOT.parent / "NexusOS-icons" / "scalable" / "status"
|
||||
|
||||
# Palette — mirrors gtk-3.0/colors.css.
|
||||
BASE = "#f2f2f2" # text_primary
|
||||
MUTED = "#6e7173" # text_disabled
|
||||
GOOD = "#8cc63f" # brand_green
|
||||
LOCK = "#f2f2f2" # text_primary (white) — neutral attribute indicator
|
||||
# while green is reserved for active signal strength.
|
||||
ERROR = "#da4453" # error_color
|
||||
WARN = "#f67400" # warning_color
|
||||
|
||||
SW = 1.6
|
||||
# Wifi fan arc geometry: half-angle from vertical. Smaller half-angle ⇒
|
||||
# narrower sweep but allows bigger radius (taller fan) before endpoints
|
||||
# run off the sides at 16x16. 40° (80° total sweep) is a sweet spot.
|
||||
ARC_HALF_ANGLE = 40
|
||||
S_ARC = math.sin(math.radians(ARC_HALF_ANGLE)) # x offset coefficient
|
||||
C_ARC = math.cos(math.radians(ARC_HALF_ANGLE)) # y offset coefficient
|
||||
|
||||
|
||||
def svg(body: str) -> str:
|
||||
return (
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" '
|
||||
'viewBox="0 0 16 16" width="16" height="16">\n'
|
||||
+ body.rstrip()
|
||||
+ "\n</svg>\n"
|
||||
)
|
||||
|
||||
|
||||
# ── wifi fan ────────────────────────────────────────────────────────
|
||||
# Fan sits low in the viewBox with arcs reaching almost the top edge so
|
||||
# the rendered icon matches the height of neighboring tray icons (shield,
|
||||
# bluetooth, etc.). Outermost r=11.5 with the narrower 80° arc sweep
|
||||
# keeps endpoints inside x=[0.61, 15.39] — fits with stroke-cap margin.
|
||||
WIFI_CX, WIFI_CY = 8, 13.0
|
||||
WIFI_R = [3.0, 5.5, 8.5, 11.5]
|
||||
DOT_R = 1.3
|
||||
|
||||
|
||||
def _arc(r: float, color: str, opacity: float = 1.0) -> str:
|
||||
x0 = WIFI_CX - r * S_ARC
|
||||
x1 = WIFI_CX + r * S_ARC
|
||||
y = WIFI_CY - r * C_ARC
|
||||
return (
|
||||
f' <path d="M {x0:.2f} {y:.2f} A {r} {r} 0 0 1 {x1:.2f} {y:.2f}" '
|
||||
f'fill="none" stroke="{color}" stroke-width="{SW}" '
|
||||
f'stroke-linecap="round" opacity="{opacity}"/>'
|
||||
)
|
||||
|
||||
|
||||
def wifi_fan(level: int, active_color: str = GOOD) -> str:
|
||||
"""level 0 (none) .. 4 (excellent). Filled arcs use brand_green by
|
||||
default so signal strength reads as the primary visual element."""
|
||||
parts = []
|
||||
for i, r in enumerate(WIFI_R):
|
||||
if i < level:
|
||||
parts.append(_arc(r, active_color, 1.0))
|
||||
else:
|
||||
parts.append(_arc(r, MUTED, 0.35))
|
||||
if level > 0:
|
||||
parts.append(
|
||||
f' <circle cx="{WIFI_CX}" cy="{WIFI_CY}" r="{DOT_R}" '
|
||||
f'fill="{active_color}"/>'
|
||||
)
|
||||
else:
|
||||
parts.append(
|
||||
f' <circle cx="{WIFI_CX}" cy="{WIFI_CY}" r="{DOT_R}" '
|
||||
f'fill="{MUTED}" opacity="0.45"/>'
|
||||
)
|
||||
return "\n".join(parts)
|
||||
|
||||
|
||||
# ── ethernet plug (RJ45) ────────────────────────────────────────────
|
||||
# Sized to fill ~75% of the viewBox vertically (y=2→14) and horizontally
|
||||
# (x=2→14) so the rendered icon matches the height of neighboring tray
|
||||
# icons (shield, notification, bluetooth) instead of looking like a tiny
|
||||
# crate in the middle of the slot.
|
||||
def ethernet_plug(color: str = GOOD, opacity: float = 1.0) -> str:
|
||||
return (
|
||||
f' <g stroke="{color}" stroke-width="{SW}" stroke-linecap="round" '
|
||||
f'stroke-linejoin="round" fill="none" opacity="{opacity}">\n'
|
||||
# Pentagonal RJ45 outline
|
||||
' <path d="M 2 2 L 14 2 L 14 10.5 L 12 14 L 4 14 L 2 10.5 Z"/>\n'
|
||||
# Three pins, spread wider to match the bigger body
|
||||
' <line x1="5" y1="4.5" x2="5" y2="8.5"/>\n'
|
||||
' <line x1="8" y1="4.5" x2="8" y2="8.5"/>\n'
|
||||
' <line x1="11" y1="4.5" x2="11" y2="8.5"/>\n'
|
||||
" </g>"
|
||||
)
|
||||
|
||||
|
||||
# ── globe (generic network) ─────────────────────────────────────────
|
||||
def globe(color: str = BASE, opacity: float = 1.0) -> str:
|
||||
return (
|
||||
f' <g stroke="{color}" stroke-width="{SW}" stroke-linecap="round" '
|
||||
f'stroke-linejoin="round" fill="none" opacity="{opacity}">\n'
|
||||
' <circle cx="8" cy="8" r="5.5"/>\n'
|
||||
' <ellipse cx="8" cy="8" rx="2.5" ry="5.5"/>\n'
|
||||
' <line x1="2.5" y1="8" x2="13.5" y2="8"/>\n'
|
||||
" </g>"
|
||||
)
|
||||
|
||||
|
||||
# ── key (vpn) ───────────────────────────────────────────────────────
|
||||
def vpn_key(color: str = GOOD, opacity: float = 1.0) -> str:
|
||||
"""Horizontal key: round bow on the left, shaft to the right with
|
||||
two teeth hanging down. Stroke-only so it doesn't visually dominate
|
||||
the way the filled globe did."""
|
||||
return (
|
||||
f' <g stroke="{color}" stroke-width="1.7" stroke-linecap="round" '
|
||||
f'stroke-linejoin="round" fill="none" opacity="{opacity}">\n'
|
||||
# Bow (handle) — outline circle on the left
|
||||
' <circle cx="4.6" cy="7" r="2.7"/>\n'
|
||||
# Shaft
|
||||
' <path d="M 7.3 7 H 14"/>\n'
|
||||
# Two teeth pointing down
|
||||
' <path d="M 11.7 7 V 9.6 M 13.6 7 V 8.7"/>\n'
|
||||
" </g>"
|
||||
)
|
||||
|
||||
|
||||
# ── state overlays / badges ─────────────────────────────────────────
|
||||
# nm-tray's MultiIconDelegate stacks state icons on top of the signal-
|
||||
# level base, so each overlay icon is *just the badge* — no wifi fan,
|
||||
# no globe. That way stacking signal-good + encrypted gives fan + lock
|
||||
# instead of fan + fan + lock, and adding -disconnected on top of an
|
||||
# unsaved network adds a single X instead of another fan.
|
||||
|
||||
def standalone_lock(color: str = LOCK) -> str:
|
||||
"""Centered padlock filling most of the 16x16 box. This is the icon
|
||||
nm-tray actually loads for encryption — it requests `security-high`
|
||||
/ `security-high-symbolic` (NOT `network-wireless-encrypted`) and
|
||||
overlays it on top of a `network-wireless-signal-*` base via its
|
||||
MultiIconDelegate, scaling our full-size lock into a corner badge.
|
||||
|
||||
Keyhole detail intentionally omitted: at the corner-badge render
|
||||
size nm-tray uses, it's invisible anyway, and a dark keyhole on a
|
||||
white body reads as visual noise rather than as a lock detail."""
|
||||
return (
|
||||
# Body: 8.5w x 6h, centered horizontally, sitting low
|
||||
f' <rect x="3.75" y="7.5" width="8.5" height="6.5" rx="1.0" '
|
||||
f'fill="{color}"/>\n'
|
||||
# Shackle: pronounced U above the body
|
||||
f' <path d="M 5.5 7.5 V 4.5 a 2.5 2.5 0 0 1 5 0 V 7.5" '
|
||||
f'fill="none" stroke="{color}" stroke-width="1.8" '
|
||||
f'stroke-linecap="round" stroke-linejoin="round"/>'
|
||||
)
|
||||
|
||||
|
||||
def badge_lock() -> str:
|
||||
"""Lock badge: body 4.4w × 3.8h + shackle 3w × 2h on top, lower-right
|
||||
corner. Made deliberately larger and with a thicker shackle stroke
|
||||
than a typical badge — at 16-24px render, a small thin-stroke lock
|
||||
blurs into a shield-like rounded shape. The big-shackle proportions
|
||||
here keep the lock recognizable down to ~18px icon size."""
|
||||
return (
|
||||
' <g transform="translate(9.5 9.0)">\n'
|
||||
f' <rect x="0" y="3.0" width="4.4" height="3.8" rx="0.45" '
|
||||
f'fill="{LOCK}"/>\n'
|
||||
f' <path d="M 0.7 3.0 V 1.1 a 1.5 1.5 0 0 1 3.0 0 V 3.0" '
|
||||
f'fill="none" stroke="{LOCK}" stroke-width="1.15" '
|
||||
f'stroke-linecap="round" stroke-linejoin="round"/>\n'
|
||||
" </g>"
|
||||
)
|
||||
|
||||
|
||||
def badge_x(color: str = ERROR) -> str:
|
||||
return (
|
||||
f' <g stroke="{color}" stroke-width="1.4" stroke-linecap="round" '
|
||||
'transform="translate(10 10)">\n'
|
||||
' <line x1="0" y1="0" x2="4.5" y2="4.5"/>\n'
|
||||
' <line x1="4.5" y1="0" x2="0" y2="4.5"/>\n'
|
||||
" </g>"
|
||||
)
|
||||
|
||||
|
||||
def badge_dots(color: str = WARN) -> str:
|
||||
return (
|
||||
f' <g fill="{color}">\n'
|
||||
' <circle cx="10.5" cy="13" r="0.9"/>\n'
|
||||
' <circle cx="13" cy="13" r="0.9"/>\n'
|
||||
' <circle cx="15.5" cy="13" r="0.9"/>\n'
|
||||
" </g>"
|
||||
)
|
||||
|
||||
|
||||
def badge_excl(color: str = ERROR) -> str:
|
||||
return (
|
||||
f' <g fill="{color}" stroke="none">\n'
|
||||
' <rect x="11.4" y="9" width="1.4" height="3" rx="0.5"/>\n'
|
||||
' <circle cx="12.1" cy="13.5" r="0.85"/>\n'
|
||||
" </g>"
|
||||
)
|
||||
|
||||
|
||||
def badge_slash(color: str = MUTED) -> str:
|
||||
return (
|
||||
f' <line x1="2.5" y1="13.5" x2="13.5" y2="2.5" '
|
||||
f'stroke="{color}" stroke-width="1.6" stroke-linecap="round"/>'
|
||||
)
|
||||
|
||||
|
||||
def badge_arrow_up(color: str = GOOD) -> str:
|
||||
return (
|
||||
f' <path d="M 12.5 14 V 9 M 10.5 11 L 12.5 9 L 14.5 11" '
|
||||
f'fill="none" stroke="{color}" stroke-width="1.4" '
|
||||
'stroke-linecap="round" stroke-linejoin="round"/>'
|
||||
)
|
||||
|
||||
|
||||
def badge_arrow_down(color: str = GOOD) -> str:
|
||||
return (
|
||||
f' <path d="M 3.5 9 V 14 M 1.5 12 L 3.5 14 L 5.5 12" '
|
||||
f'fill="none" stroke="{color}" stroke-width="1.4" '
|
||||
'stroke-linecap="round" stroke-linejoin="round"/>'
|
||||
)
|
||||
|
||||
|
||||
# ── icon catalog ────────────────────────────────────────────────────
|
||||
def cell_tech(label: str) -> str:
|
||||
"""Wifi fan + tiny generation-tech label (2G/3G/4G/5G/E/G/H/U/1x)."""
|
||||
return svg(
|
||||
wifi_fan(3) + "\n"
|
||||
f' <text x="11" y="13" font-family="sans-serif" font-size="4.5" '
|
||||
f'font-weight="bold" fill="{BASE}">{label}</text>'
|
||||
)
|
||||
|
||||
|
||||
ICONS = {
|
||||
# wireless signal levels
|
||||
"network-wireless-signal-none": svg(wifi_fan(0)),
|
||||
"network-wireless-signal-weak": svg(wifi_fan(1)),
|
||||
"network-wireless-signal-ok": svg(wifi_fan(2)),
|
||||
"network-wireless-signal-good": svg(wifi_fan(3)),
|
||||
"network-wireless-signal-excellent": svg(wifi_fan(4)),
|
||||
|
||||
# wireless — nm-tray picks one icon per row, so each name is a
|
||||
# self-contained composite (signal-level fan + state badge if any).
|
||||
"network-wireless": svg(wifi_fan(3)),
|
||||
"network-wireless-connected": svg(wifi_fan(4, GOOD)),
|
||||
# Disconnected: faded-empty fan. NO X badge — nm-tray overlays this
|
||||
# on top of saved-network rows, so an X here would visually pile up
|
||||
# with the encrypted-lock overlay. The dim level-0 fan already reads
|
||||
# as "no signal/disconnected" without the extra badge.
|
||||
"network-wireless-disconnected": svg(wifi_fan(0)),
|
||||
"network-wireless-disabled": svg(wifi_fan(0) + "\n" + badge_slash()),
|
||||
"network-wireless-acquiring": svg(wifi_fan(2) + "\n" + badge_dots()),
|
||||
"network-wireless-error": svg(wifi_fan(2) + "\n" + badge_excl()),
|
||||
"network-wireless-no-route": svg(wifi_fan(3) + "\n" + badge_excl(WARN)),
|
||||
"network-wireless-offline": svg(wifi_fan(0)),
|
||||
"network-wireless-encrypted": svg(wifi_fan(3) + "\n" + badge_lock()),
|
||||
"network-wireless-hotspot": svg(wifi_fan(4, GOOD) + "\n" + badge_dots(GOOD)),
|
||||
"network-wireless-hardware-disabled": svg(wifi_fan(0) + "\n" + badge_slash(ERROR)),
|
||||
|
||||
# wired
|
||||
"network-wired": svg(ethernet_plug()),
|
||||
"network-wired-disconnected": svg(ethernet_plug(MUTED, 0.55) + "\n" + badge_x()),
|
||||
"network-wired-acquiring": svg(ethernet_plug() + "\n" + badge_dots()),
|
||||
"network-wired-error": svg(ethernet_plug() + "\n" + badge_excl()),
|
||||
"network-wired-no-route": svg(ethernet_plug() + "\n" + badge_excl(WARN)),
|
||||
"network-wired-offline": svg(ethernet_plug(MUTED, 0.55)),
|
||||
|
||||
# vpn — green key. Stroke-only so it doesn't dominate the menu row.
|
||||
"network-vpn": svg(vpn_key()),
|
||||
"network-vpn-connected": svg(vpn_key()),
|
||||
"network-vpn-acquiring": svg(vpn_key() + "\n" + badge_dots()),
|
||||
"network-vpn-disconnected": svg(vpn_key(MUTED, 0.55) + "\n" + badge_x()),
|
||||
"network-vpn-error": svg(vpn_key(ERROR)),
|
||||
"network-vpn-no-route": svg(vpn_key() + "\n" + badge_excl(WARN)),
|
||||
"network-vpn-offline": svg(vpn_key(MUTED, 0.55)),
|
||||
|
||||
# generic
|
||||
"network-error": svg(globe() + "\n" + badge_excl()),
|
||||
"network-idle": svg(globe()),
|
||||
"network-offline": svg(globe(MUTED, 0.55) + "\n" + badge_slash()),
|
||||
"network-no-route": svg(globe() + "\n" + badge_excl(WARN)),
|
||||
"network-acquiring": svg(globe() + "\n" + badge_dots()),
|
||||
"network-transmit": svg(globe() + "\n" + badge_arrow_up()),
|
||||
"network-receive": svg(globe() + "\n" + badge_arrow_down()),
|
||||
"network-transmit-receive": svg(globe() + "\n" + badge_arrow_up() + "\n" + badge_arrow_down()),
|
||||
|
||||
# cellular — same fan, with state badges
|
||||
"network-cellular-signal-none": svg(wifi_fan(0)),
|
||||
"network-cellular-signal-weak": svg(wifi_fan(1)),
|
||||
"network-cellular-signal-ok": svg(wifi_fan(2)),
|
||||
"network-cellular-signal-good": svg(wifi_fan(3)),
|
||||
"network-cellular-signal-excellent": svg(wifi_fan(4)),
|
||||
"network-cellular-acquiring": svg(wifi_fan(2) + "\n" + badge_dots()),
|
||||
"network-cellular-connected": svg(wifi_fan(4, GOOD)),
|
||||
"network-cellular-disabled": svg(wifi_fan(0) + "\n" + badge_slash()),
|
||||
"network-cellular-disconnected": svg(wifi_fan(0) + "\n" + badge_x()),
|
||||
"network-cellular-error": svg(wifi_fan(2) + "\n" + badge_excl()),
|
||||
"network-cellular-hardware-disabled": svg(wifi_fan(0) + "\n" + badge_slash(ERROR)),
|
||||
"network-cellular-no-route": svg(wifi_fan(3) + "\n" + badge_excl(WARN)),
|
||||
"network-cellular-offline": svg(wifi_fan(0)),
|
||||
|
||||
# security indicators — nm-tray's actual encryption overlay icon
|
||||
"security-high": svg(standalone_lock()),
|
||||
"security-high-symbolic": svg(standalone_lock()),
|
||||
"security-medium": svg(standalone_lock(WARN)),
|
||||
"security-medium-symbolic": svg(standalone_lock(WARN)),
|
||||
"security-low": svg(standalone_lock(ERROR)),
|
||||
"security-low-symbolic": svg(standalone_lock(ERROR)),
|
||||
|
||||
# cellular generation-tech labels
|
||||
"network-cellular-2g": cell_tech("2G"),
|
||||
"network-cellular-3g": cell_tech("3G"),
|
||||
"network-cellular-4g": cell_tech("4G"),
|
||||
"network-cellular-5g": cell_tech("5G"),
|
||||
"network-cellular-edge": cell_tech("E"),
|
||||
"network-cellular-gprs": cell_tech("G"),
|
||||
"network-cellular-cdma-1x": cell_tech("1x"),
|
||||
"network-cellular-hspa": cell_tech("H"),
|
||||
"network-cellular-umts": cell_tech("U"),
|
||||
}
|
||||
|
||||
|
||||
# ── genmon panel applet PNGs ─────────────────────────────────────────
|
||||
# bin/panel/network-applet.sh (the XFCE genmon network applet) loads PNGs
|
||||
# directly from assets/panel-icons/ by path — it does NOT go through the
|
||||
# icon theme. Rasterize the relevant status icons there too so the applet
|
||||
# stays in sync with the canonical SVG design above (otherwise the PNGs
|
||||
# drift into a different look, e.g. solid filled cones vs. arc bars).
|
||||
PANEL_PNG_DIR = ROOT.parent.parent / "panel-icons" # assets/panel-icons
|
||||
PANEL_PNG_SIZE = 22
|
||||
PANEL_PNG_NAMES = [
|
||||
"network-wireless-signal-none",
|
||||
"network-wireless-signal-weak",
|
||||
"network-wireless-signal-ok",
|
||||
"network-wireless-signal-good",
|
||||
"network-wireless-signal-excellent",
|
||||
"network-wired",
|
||||
"network-offline",
|
||||
]
|
||||
|
||||
|
||||
def _rasterize_panel_pngs() -> int:
|
||||
import subprocess
|
||||
if not PANEL_PNG_DIR.is_dir():
|
||||
return 0
|
||||
n = 0
|
||||
for name in PANEL_PNG_NAMES:
|
||||
svg_path = OUT / f"{name}.svg"
|
||||
if not svg_path.exists():
|
||||
continue
|
||||
subprocess.run(
|
||||
["inkscape", str(svg_path), "--export-type=png",
|
||||
f"--export-filename={PANEL_PNG_DIR / (name + '.png')}",
|
||||
f"--export-width={PANEL_PNG_SIZE}",
|
||||
f"--export-height={PANEL_PNG_SIZE}",
|
||||
"--export-background-opacity=0"],
|
||||
check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
||||
)
|
||||
n += 1
|
||||
return n
|
||||
|
||||
|
||||
def main() -> None:
|
||||
OUT.mkdir(parents=True, exist_ok=True)
|
||||
# Sweep any leftover Papirus fallback symlinks from the same dir.
|
||||
cleaned = 0
|
||||
for entry in OUT.iterdir():
|
||||
if entry.is_symlink():
|
||||
entry.unlink()
|
||||
cleaned += 1
|
||||
for name, body in ICONS.items():
|
||||
(OUT / f"{name}.svg").write_text(body)
|
||||
print(f"Cleared {cleaned} symlinks, wrote {len(ICONS)} SVGs to {OUT}")
|
||||
n = _rasterize_panel_pngs()
|
||||
print(f"Rasterized {n} genmon panel PNGs to {PANEL_PNG_DIR}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<defs>
|
||||
<radialGradient id="ring" cx="50%" cy="30%" r="70%">
|
||||
<stop offset="0%" stop-color="#8cc63f"/>
|
||||
<stop offset="100%" stop-color="#5a9020"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="frame" cx="50%" cy="30%" r="70%">
|
||||
<stop offset="0%" stop-color="#b040c0"/>
|
||||
<stop offset="100%" stop-color="#4a0050"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<!-- Lime outer ring -->
|
||||
<rect x="0" y="0" width="128" height="128" rx="30" fill="url(#ring)"/>
|
||||
<!-- Purple gradient frame inset 8px from ring -->
|
||||
<rect x="8" y="8" width="112" height="112" rx="26" fill="url(#frame)"/>
|
||||
<!-- Dark inner border -->
|
||||
<rect x="12" y="12" width="104" height="104" rx="22" fill="#120018"/>
|
||||
<!-- App icon face -->
|
||||
<rect x="18" y="18" width="92" height="92" rx="16" fill="#262626"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 933 B |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
|
||||
<defs>
|
||||
<radialGradient id="frame" cx="50%" cy="30%" r="70%">
|
||||
<stop offset="0%" stop-color="#b040c0"/>
|
||||
<stop offset="100%" stop-color="#4a0050"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<!-- Outer purple gradient frame -->
|
||||
<rect x="0" y="0" width="128" height="128" rx="30" fill="url(#frame)"/>
|
||||
<!-- Dark inner border -->
|
||||
<rect x="8" y="8" width="112" height="112" rx="24" fill="#120018"/>
|
||||
<!-- App icon face -->
|
||||
<rect x="14" y="14" width="100" height="100" rx="18" fill="#262626"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 642 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 994 B After Width: | Height: | Size: 994 B |
|
Before Width: | Height: | Size: 802 B After Width: | Height: | Size: 802 B |
|
Before Width: | Height: | Size: 942 B After Width: | Height: | Size: 942 B |
|
Before Width: | Height: | Size: 981 B After Width: | Height: | Size: 981 B |
|
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 247 KiB |
|
Before Width: | Height: | Size: 802 B After Width: | Height: | Size: 802 B |
|
Before Width: | Height: | Size: 1014 B After Width: | Height: | Size: 1014 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 984 B After Width: | Height: | Size: 984 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |