Skip to content

Commit c7dc2a3

Browse files
committed
refactor(ui): modularize components, add dark theme, and align overlay
1 parent 0d6d7d3 commit c7dc2a3

4 files changed

Lines changed: 340 additions & 181 deletions

File tree

core/gui.py

Lines changed: 40 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
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
43
from .settings_manager import SettingsManager
4+
from .ui.components import (
5+
PositionSettingsGroup, VisualSettingsGroup,
6+
LaneSettingsGroup, KeyViewerSettingsGroup
7+
)
8+
from .ui.theme import DARK_THEME
59

610
class 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.\nClick '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)}")

core/overlay.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from PySide6.QtCore import Qt, QTimer, QRectF
66
from PySide6.QtGui import QPainter, QBrush, QColor, QFont
77
from .configuration import AppConfig
8+
from .ui.theme import COLOR_TEXT_BRIGHT
89

910
# Windows API for click-through
1011
try:
@@ -423,7 +424,7 @@ def _draw_key_button(self, ctx):
423424
if "KEY." in display_text:
424425
display_text = display_text.replace("KEY.", "")
425426

426-
painter.setPen(QColor("white"))
427+
painter.setPen(QColor(COLOR_TEXT_BRIGHT))
427428
painter.drawText(k_rect, Qt.AlignCenter, display_text)
428429

429430
# 3. Count

0 commit comments

Comments
 (0)