1- from PySide6 .QtWidgets import QWidget , QVBoxLayout , QHBoxLayout , QLabel , QSpinBox , QComboBox , QGroupBox , QPushButton , QCheckBox , QFrame , QColorDialog
2- from PySide6 .QtCore import Qt , Slot
3- from PySide6 .QtGui import QColor , QPalette
1+ from PySide6 .QtWidgets import QWidget , QVBoxLayout , QScrollArea
2+ from PySide6 .QtCore import Slot
43from .settings_manager import SettingsManager
4+ from .ui .components import (
5+ PositionSettingsGroup , VisualSettingsGroup ,
6+ LaneSettingsGroup , KeyViewerSettingsGroup
7+ )
8+ from .ui .theme import DARK_THEME
59
610class SettingsWindow (QWidget ):
711 def __init__ (self , settings_manager : SettingsManager ):
812 super ().__init__ ()
913 self .settings = settings_manager
1014 self .config = self .settings .app_config
1115 self .setWindowTitle (f"RainingKeys Config v{ self .config .VERSION } " )
12- self .resize (300 , 350 )
16+ self .resize (340 , 500 )
17+
18+ # Apply Theme
19+ self .setStyleSheet (DARK_THEME )
1320
1421 # Recording State
1522 self .is_recording = False
@@ -18,198 +25,51 @@ def __init__(self, settings_manager: SettingsManager):
1825 self .init_ui ()
1926
2027 def init_ui (self ):
21- layout = QVBoxLayout ()
22-
23- # Position Group
24- pos_group = QGroupBox ("Overlay Position" )
25- pos_layout = QHBoxLayout ()
26-
27- self .spin_x = QSpinBox ()
28- self .spin_x .setRange (- 10000 , 10000 )
29- self .spin_x .setPrefix ("X: " )
30- self .spin_x .setValue (self .config .position .x )
31- self .spin_x .valueChanged .connect (self .on_pos_changed )
32-
33- self .spin_y = QSpinBox ()
34- self .spin_y .setRange (- 10000 , 10000 )
35- self .spin_y .setPrefix ("Y: " )
36- self .spin_y .setValue (self .config .position .y )
37- self .spin_y .valueChanged .connect (self .on_pos_changed )
38-
39- pos_layout .addWidget (self .spin_x )
40- pos_layout .addWidget (self .spin_y )
41- pos_group .setLayout (pos_layout )
42- layout .addWidget (pos_group )
43-
44- # Visual Group
45- vis_group = QGroupBox ("Visual Settings" )
46- vis_layout = QVBoxLayout ()
47-
48- # Speed
49- speed_layout = QHBoxLayout ()
50- speed_layout .addWidget (QLabel ("Scroll Speed (px/s):" ))
51- self .spin_speed = QSpinBox ()
52- self .spin_speed .setRange (100 , 5000 )
53- self .spin_speed .setSingleStep (50 )
54- self .spin_speed .setValue (self .config .visual .scroll_speed )
55- self .spin_speed .valueChanged .connect (self .on_visual_changed )
56- speed_layout .addWidget (self .spin_speed )
57- vis_layout .addLayout (speed_layout )
58-
59- # Custom Color
60- color_layout = QHBoxLayout ()
61- color_layout .addWidget (QLabel ("Bar Color:" ))
62- self .btn_color = QPushButton ("Choose Color" )
63- self .btn_color .clicked .connect (self .choose_color )
64- self .update_color_btn_style ()
65- color_layout .addWidget (self .btn_color )
66- vis_layout .addLayout (color_layout )
67-
68- vis_group .setLayout (vis_layout )
69- layout .addWidget (vis_group )
28+ main_layout = QVBoxLayout (self )
29+ main_layout .setContentsMargins (10 , 10 , 10 , 10 )
30+ main_layout .setSpacing (10 )
31+
32+ # Scroll Area for better usability on small screens
33+ scroll = QScrollArea ()
34+ scroll .setWidgetResizable (True )
35+ scroll .setStyleSheet ("QScrollArea { border: none; background: transparent; }" )
7036
71- # Lane Configuration Group
72- lane_group = QGroupBox ( "Lane Configuration" )
73- lane_layout = QVBoxLayout ( )
37+ content_widget = QWidget ()
38+ layout = QVBoxLayout ( content_widget )
39+ layout . setSpacing ( 15 )
7440
75- self . lbl_lane_status = QLabel ( "Current Keys: " + str ( len ( self . config . lane_map )))
76- self .lbl_lane_status . setWordWrap ( True )
77- lane_layout .addWidget (self .lbl_lane_status )
41+ # Components
42+ self .pos_group = PositionSettingsGroup ( self . settings )
43+ layout .addWidget (self .pos_group )
7844
79- self .btn_record = QPushButton ("Record Lane Keys" )
80- self .btn_record .clicked .connect (self .toggle_recording )
81- lane_layout .addWidget (self .btn_record )
45+ self .vis_group = VisualSettingsGroup (self .settings )
46+ layout .addWidget (self .vis_group )
8247
83- self .lbl_instruction = QLabel ("Click 'Record', then press keys in order.\n Click 'Stop' when done." )
84- self .lbl_instruction .setStyleSheet ("color: gray; font-size: 10px;" )
85- lane_layout .addWidget (self .lbl_instruction )
86-
87- lane_group .setLayout (lane_layout )
88- layout .addWidget (lane_group )
89-
90- # KeyViewer Configuration Group
91- kv_group = QGroupBox ("KeyViewer Panel" )
92- kv_layout = QVBoxLayout ()
93-
94- self .chk_kv_enabled = QCheckBox ("Enable KeyViewer" )
95- self .chk_kv_enabled .setChecked (self .config .key_viewer .enabled )
96- self .chk_kv_enabled .stateChanged .connect (self .on_kv_changed )
97- kv_layout .addWidget (self .chk_kv_enabled )
98-
99- # Layout & Position
100- kv_grid = QHBoxLayout ()
101- kv_grid .addWidget (QLabel ("Height:" ))
102- self .spin_kv_height = QSpinBox ()
103- self .spin_kv_height .setRange (10 , 500 )
104- self .spin_kv_height .setValue (self .config .key_viewer .height )
105- self .spin_kv_height .valueChanged .connect (self .on_kv_changed )
106- kv_grid .addWidget (self .spin_kv_height )
48+ self .lane_group = LaneSettingsGroup (self .settings )
49+ self .lane_group .record_toggled .connect (self .on_record_toggled )
50+ layout .addWidget (self .lane_group )
10751
108- kv_grid .addWidget (QLabel ("Pos:" ))
109- self .combo_kv_pos = QComboBox ()
110- self .combo_kv_pos .addItems (["below" , "above" ])
111- current = self .config .key_viewer .panel_position
112- if current not in ["below" , "above" ]:
113- current = "below"
114- self .combo_kv_pos .setCurrentText (current )
115- self .combo_kv_pos .currentTextChanged .connect (self .on_kv_changed )
116- kv_grid .addWidget (self .combo_kv_pos )
117- kv_layout .addLayout (kv_grid )
118-
119- # Offsets
120- off_layout = QHBoxLayout ()
121- off_layout .addWidget (QLabel ("Offset X:" ))
122- self .spin_kv_off_x = QSpinBox ()
123- self .spin_kv_off_x .setRange (- 1000 , 1000 )
124- self .spin_kv_off_x .setValue (self .config .key_viewer .panel_offset_x )
125- self .spin_kv_off_x .valueChanged .connect (self .on_kv_changed )
126- off_layout .addWidget (self .spin_kv_off_x )
127- off_layout .addWidget (QLabel ("Y:" ))
128- self .spin_kv_off_y = QSpinBox ()
129- self .spin_kv_off_y .setRange (- 1000 , 1000 )
130- self .spin_kv_off_y .setValue (self .config .key_viewer .panel_offset_y )
131- self .spin_kv_off_y .valueChanged .connect (self .on_kv_changed )
132- off_layout .addWidget (self .spin_kv_off_y )
133- kv_layout .addLayout (off_layout )
134-
135- # Transparency Control
136- trans_layout = QHBoxLayout ()
137- trans_layout .addWidget (QLabel ("Inactive Opacity:" ))
138- self .spin_kv_opacity = QSpinBox ()
139- self .spin_kv_opacity .setRange (0 , 100 )
140- self .spin_kv_opacity .setSuffix ("%" )
141- self .spin_kv_opacity .setValue (int (self .config .key_viewer .opacity * 100 ))
142- self .spin_kv_opacity .valueChanged .connect (self .on_kv_changed )
143- trans_layout .addWidget (self .spin_kv_opacity )
144- kv_layout .addLayout (trans_layout )
145-
146- self .chk_kv_counts = QCheckBox ("Show Key Counts" )
147- self .chk_kv_counts .setChecked (self .config .key_viewer .show_counts )
148- self .chk_kv_counts .stateChanged .connect (self .on_kv_changed )
149- kv_layout .addWidget (self .chk_kv_counts )
150-
151- kv_group .setLayout (kv_layout )
152- layout .addWidget (kv_group )
52+ self .kv_group = KeyViewerSettingsGroup (self .settings )
53+ layout .addWidget (self .kv_group )
15354
15455 layout .addStretch ()
155- self .setLayout (layout )
156-
157- def on_pos_changed (self ):
158- self .config .position .x = self .spin_x .value ()
159- self .config .position .y = self .spin_y .value ()
160- self .settings .save ()
161-
162- def choose_color (self ):
163- current = self .config .visual .bar_color
164- color = QColorDialog .getColor (current , self , "Select Bar Color" , QColorDialog .ShowAlphaChannel )
165- if color .isValid ():
166- rgba = f"{ color .red ()} ,{ color .green ()} ,{ color .blue ()} ,{ color .alpha ()} "
167- self .config .visual .bar_color_str = rgba
168- self .settings .save ()
169- self .update_color_btn_style ()
170-
171- def update_color_btn_style (self ):
172- c = self .config .visual .bar_color
173- # Text color contrasting
174- text_col = "black" if c .lightness () > 128 else "white"
175- style = f"background-color: rgba({ c .red ()} ,{ c .green ()} ,{ c .blue ()} ,{ c .alpha ()} ); color: { text_col } ;"
176- self .btn_color .setStyleSheet (style )
177- self .btn_color .setText (f"RGBA({ c .red ()} ,{ c .green ()} ,{ c .blue ()} ,{ c .alpha ()} )" )
17856
179- def on_visual_changed (self ):
180- self .config .visual .scroll_speed = self .spin_speed .value ()
181- self .settings .save ()
57+ scroll .setWidget (content_widget )
58+ main_layout .addWidget (scroll )
18259
183- def on_kv_changed (self ):
184- self .config .key_viewer .enabled = self .chk_kv_enabled .isChecked ()
185- self .config .key_viewer .height = self .spin_kv_height .value ()
186- self .config .key_viewer .panel_position = self .combo_kv_pos .currentText ()
187- self .config .key_viewer .panel_offset_x = self .spin_kv_off_x .value ()
188- self .config .key_viewer .panel_offset_y = self .spin_kv_off_y .value ()
189- self .config .key_viewer .show_counts = self .chk_kv_counts .isChecked ()
190- self .config .key_viewer .opacity = self .spin_kv_opacity .value () / 100.0
191- self .settings .save ()
192-
193- def toggle_recording (self ):
194- if not self .is_recording :
60+ def on_record_toggled (self , is_recording ):
61+ self .is_recording = is_recording
62+ if self .is_recording :
19563 # Start Recording
196- self .is_recording = True
19764 self .recorded_keys = []
198- self .btn_record .setText ("Stop Recording" )
199- self .lbl_lane_status .setText ("Recording... Press keys!" )
200- self .lbl_lane_status .setStyleSheet ("color: red; font-weight: bold;" )
20165 else :
20266 # Stop Recording
203- self .is_recording = False
204- self .btn_record .setText ("Record Lane Keys" )
205- self .lbl_lane_status .setStyleSheet ("" )
206-
20767 if self .recorded_keys :
20868 # Save
20969 self .settings .update_lanes (self .recorded_keys )
210- self .lbl_lane_status . setText (f"Saved { len (self .recorded_keys )} lane keys." )
70+ self .lane_group . update_status (f"Saved { len (self .recorded_keys )} lane keys." )
21171 else :
212- self .lbl_lane_status . setText ("No keys recorded. Canceled." )
72+ self .lane_group . update_status ("No keys recorded. Canceled." )
21373
21474 @Slot (str )
21575 def handle_raw_key (self , key_str ):
@@ -218,4 +78,4 @@ def handle_raw_key(self, key_str):
21878 # Avoid duplicates if desired
21979 if key_str not in self .recorded_keys :
22080 self .recorded_keys .append (key_str )
221- self .lbl_lane_status . setText (f"Recorded: { ', ' .join (self .recorded_keys )} " )
81+ self .lane_group . update_status (f"Recorded: { ', ' .join (self .recorded_keys )} " )
0 commit comments