22
33import sys
44from PyQt5 .QtCore import Qt
5- from PyQt5 .QtGui import QFont , QColor , QPalette
5+ from PyQt5 .QtGui import QFont
66from PyQt5 .QtWidgets import (
7- QApplication , QDialog , QVBoxLayout , QHBoxLayout ,
7+ QApplication , QDialog , QVBoxLayout ,
88 QLabel , QPushButton , QFrame , QRadioButton , QButtonGroup ,
99)
1010
11+ _LAUNCHER_QSS = """
12+ QDialog {
13+ background: #0d1117;
14+ }
15+ QLabel {
16+ color: #e6edf3;
17+ background: transparent;
18+ }
19+ QFrame#launcher-card {
20+ background: #161b22;
21+ border: 1px solid #30363d;
22+ border-radius: 8px;
23+ }
24+ QFrame#launcher-card:hover {
25+ border-color: #39ff14;
26+ }
27+ QRadioButton {
28+ color: #e6edf3;
29+ background: transparent;
30+ spacing: 8px;
31+ }
32+ QRadioButton::indicator {
33+ width: 16px;
34+ height: 16px;
35+ border: 2px solid #30363d;
36+ border-radius: 9px;
37+ background: #0d1117;
38+ }
39+ QRadioButton::indicator:checked {
40+ background: #39ff14;
41+ border-color: #39ff14;
42+ }
43+ QRadioButton::indicator:hover {
44+ border-color: #39ff14;
45+ }
46+ """
47+
1148
1249class LauncherDialog (QDialog ):
1350 """Dark-themed dialog to select which UI variant to launch."""
@@ -16,27 +53,20 @@ def __init__(self):
1653 super ().__init__ ()
1754 self .selected_ui = None
1855 self .setWindowTitle ("Cyber Controller — Select Interface" )
19- self .setFixedSize (500 , 400 )
20- self ._apply_dark_theme ()
56+ self .setFixedSize (480 , 380 )
57+ self .setWindowFlags (
58+ Qt .Dialog
59+ | Qt .WindowTitleHint
60+ | Qt .WindowCloseButtonHint
61+ )
62+ self .setStyleSheet (_LAUNCHER_QSS )
2163 self ._build_ui ()
2264
23- def _apply_dark_theme (self ):
24- pal = self .palette ()
25- pal .setColor (QPalette .Window , QColor ("#0d1117" ))
26- pal .setColor (QPalette .WindowText , QColor ("#e6edf3" ))
27- pal .setColor (QPalette .Base , QColor ("#161b22" ))
28- pal .setColor (QPalette .Text , QColor ("#e6edf3" ))
29- pal .setColor (QPalette .Button , QColor ("#1c2128" ))
30- pal .setColor (QPalette .ButtonText , QColor ("#e6edf3" ))
31- pal .setColor (QPalette .Highlight , QColor ("#39ff14" ))
32- self .setPalette (pal )
33-
3465 def _build_ui (self ):
3566 layout = QVBoxLayout (self )
36- layout .setSpacing (16 )
67+ layout .setSpacing (12 )
3768 layout .setContentsMargins (32 , 24 , 32 , 24 )
3869
39- # Title
4070 title = QLabel ("CYBER CONTROLLER" )
4171 title .setFont (QFont ("JetBrains Mono" , 16 , QFont .Bold ))
4272 title .setStyleSheet ("color: #39ff14;" )
@@ -49,15 +79,14 @@ def _build_ui(self):
4979 subtitle .setAlignment (Qt .AlignCenter )
5080 layout .addWidget (subtitle )
5181
52- layout .addSpacing (8 )
82+ layout .addSpacing (4 )
5383
54- # Radio options
5584 self ._group = QButtonGroup (self )
5685
5786 options = [
5887 ("qt" , "Full GUI (Recommended)" ,
5988 "Complete PyQt5 interface with all features, sidebar, persistent terminal, "
60- "command palette, and custom widgets. Best for desktop use. " ),
89+ "command palette, and custom widgets." ),
6190 ("tk" , "Lightweight GUI" ,
6291 "Tkinter-based interface with core features. Lower resource usage. "
6392 "Good for older hardware or when PyQt5 is unavailable." ),
@@ -68,20 +97,13 @@ def _build_ui(self):
6897
6998 for i , (key , label , desc ) in enumerate (options ):
7099 card = QFrame ()
71- card .setObjectName (f"launcher-card-{ i } " )
72- card .setStyleSheet (
73- f"QFrame#launcher-card-{ i } {{ background: #161b22; border: 1px solid #30363d; "
74- "border-radius: 8px; padding: 12px; }"
75- f"QFrame#launcher-card-{ i } :hover {{ border-color: #39ff14; }}"
76- )
100+ card .setObjectName ("launcher-card" )
77101 card_layout = QVBoxLayout (card )
102+ card_layout .setContentsMargins (12 , 10 , 12 , 10 )
103+ card_layout .setSpacing (4 )
78104
79105 radio = QRadioButton (label )
80106 radio .setFont (QFont ("Segoe UI" , 11 , QFont .Bold ))
81- radio .setStyleSheet (
82- "QRadioButton { color: #e6edf3; }"
83- "QRadioButton::indicator { width: 16px; height: 16px; }"
84- )
85107 radio .setProperty ("ui_key" , key )
86108 if i == 0 :
87109 radio .setChecked (True )
@@ -90,21 +112,23 @@ def _build_ui(self):
90112
91113 desc_label = QLabel (desc )
92114 desc_label .setFont (QFont ("Segoe UI" , 9 ))
93- desc_label .setStyleSheet ("color: #8b949e; margin -left: 24px;" )
115+ desc_label .setStyleSheet ("color: #8b949e; padding -left: 24px;" )
94116 desc_label .setWordWrap (True )
95117 card_layout .addWidget (desc_label )
96118
97119 layout .addWidget (card )
98120
99121 layout .addStretch ()
100122
101- # Launch button
102123 btn = QPushButton ("Launch" )
103124 btn .setFont (QFont ("Segoe UI" , 11 , QFont .Bold ))
125+ btn .setCursor (Qt .PointingHandCursor )
126+ btn .setFixedHeight (40 )
104127 btn .setStyleSheet (
105128 "QPushButton { background: #39ff14; color: #0d1117; border: none; "
106- "border-radius: 6px; padding: 10px 32px; font-weight: bold; }"
129+ "border-radius: 6px; padding: 0 32px; font-weight: bold; }"
107130 "QPushButton:hover { background: #2dd912; }"
131+ "QPushButton:pressed { background: #24b00f; }"
108132 )
109133 btn .clicked .connect (self ._on_launch )
110134 layout .addWidget (btn , alignment = Qt .AlignCenter )
@@ -129,7 +153,6 @@ def select_ui() -> str:
129153 result = dialog .selected_ui or "qt"
130154
131155 if own_app :
132- # Don't exec the app -- just used it for the dialog
133156 pass
134157
135158 return result
0 commit comments