4
4
5
5
from kevinbotlib .comm import CommunicationClient , BaseSendable
6
6
from kevinbotlib .logger import Logger
7
+ from kevinbotlib .ui .theme import Theme , ThemeStyle
8
+
7
9
from PySide6 .QtCore import (
8
10
QItemSelection ,
9
11
QModelIndex ,
40
42
QTreeView ,
41
43
QVBoxLayout ,
42
44
QWidget ,
45
+ QRadioButton ,
46
+ QSizePolicy ,
47
+ QApplication ,
43
48
)
44
49
45
- from kevinbotlib_dashboard .grid_theme import Themes
50
+ from kevinbotlib_dashboard .grid_theme import Themes as GridThemes
46
51
from kevinbotlib_dashboard .toast import Notifier , Severity
47
52
from kevinbotlib_dashboard .tree import DictTreeModel
48
53
from kevinbotlib_dashboard .widgets import Divider
@@ -203,7 +208,7 @@ def delete_self(self):
203
208
204
209
205
210
class GridGraphicsView (QGraphicsView ):
206
- def __init__ (self , parent = None , grid_size : int = 48 , rows = 10 , cols = 10 , theme : Themes = Themes .Dark ):
211
+ def __init__ (self , parent = None , grid_size : int = 48 , rows = 10 , cols = 10 , theme : GridThemes = GridThemes .Dark ):
207
212
super ().__init__ (parent )
208
213
self .grid_size = grid_size
209
214
self .rows , self .cols = rows , cols
@@ -223,6 +228,11 @@ def __init__(self, parent=None, grid_size: int = 48, rows=10, cols=10, theme: Th
223
228
self .highlight_rect .setZValue (3 )
224
229
self .highlight_rect .hide ()
225
230
231
+ def set_theme (self , theme : GridThemes ):
232
+ self .theme = theme
233
+ self .setBackgroundBrush (QColor (theme .value .background ))
234
+ self .update ()
235
+
226
236
def is_valid_drop_position (self , position , dragging_widget = None , span_x = 1 , span_y = 1 ):
227
237
grid_size = self .grid_size
228
238
rows , cols = self .rows , self .cols
@@ -452,6 +462,11 @@ def __init__(self, parent, settings: QSettings):
452
462
self .form = QFormLayout ()
453
463
self .root_layout .addLayout (self .form )
454
464
465
+ self .form .addRow (Divider ("Theme" ))
466
+
467
+ self .theme = UiColorSettingsSwitcher (settings , "theme" , parent )
468
+ self .form .addRow ("Theme" , self .theme )
469
+
455
470
self .form .addRow (Divider ("Grid" ))
456
471
457
472
self .grid_size = QSpinBox (minimum = 8 , maximum = 256 , singleStep = 2 , value = self .settings .value ("grid" , 48 , int )) # type: ignore
@@ -487,6 +502,49 @@ def apply(self):
487
502
self .on_applied .emit ()
488
503
489
504
505
+ class UiColorSettingsSwitcher (QFrame ):
506
+ def __init__ (
507
+ self ,
508
+ settings : QSettings ,
509
+ key : str ,
510
+ main_window : 'Application' ,
511
+ ):
512
+ super ().__init__ ()
513
+ self .setSizePolicy (QSizePolicy .Policy .Minimum , QSizePolicy .Policy .Preferred )
514
+
515
+ self .settings = settings
516
+ self .key = key
517
+ self .main_window = main_window
518
+
519
+ root_layout = QHBoxLayout ()
520
+ self .setLayout (root_layout )
521
+
522
+ self .dark_mode = QRadioButton ("Dark" )
523
+ self .light_mode = QRadioButton ("Light" )
524
+ self .system_mode = QRadioButton ("System" )
525
+
526
+ root_layout .addWidget (self .dark_mode )
527
+ root_layout .addWidget (self .light_mode )
528
+ root_layout .addWidget (self .system_mode )
529
+
530
+ # Load saved theme setting
531
+ current_theme = self .settings .value (self .key , "Dark" )
532
+ if current_theme == "Dark" :
533
+ self .dark_mode .setChecked (True )
534
+ elif current_theme == "Light" :
535
+ self .light_mode .setChecked (True )
536
+ else :
537
+ self .system_mode .setChecked (True )
538
+
539
+ self .dark_mode .toggled .connect (lambda : self .save_setting ("Dark" ))
540
+ self .light_mode .toggled .connect (lambda : self .save_setting ("Light" ))
541
+ self .system_mode .toggled .connect (lambda : self .save_setting ("System" ))
542
+
543
+ def save_setting (self , value : str ):
544
+ self .settings .setValue (self .key , value )
545
+ self .settings .sync ()
546
+ self .main_window .apply_theme ()
547
+
490
548
class TopicStatusPanel (QStackedWidget ):
491
549
def __init__ (self , client : CommunicationClient ):
492
550
super ().__init__ ()
@@ -530,7 +588,7 @@ def set_data(self, data: str | None):
530
588
531
589
532
590
class Application (QMainWindow ):
533
- def __init__ (self ):
591
+ def __init__ (self , app : QApplication ):
534
592
super ().__init__ ()
535
593
self .setWindowTitle ("KevinbotLib Dashboard" )
536
594
@@ -581,6 +639,7 @@ def __init__(self):
581
639
grid_size = self .settings .value ("grid" , 48 , int ), # type: ignore
582
640
rows = self .settings .value ("rows" , 10 , int ), # type: ignore
583
641
cols = self .settings .value ("cols" , 10 , int ), # type: ignore
642
+ theme = GridThemes .Dark ,
584
643
)
585
644
palette = WidgetPalette (self .graphics_view , self .client )
586
645
self .model = palette .model
@@ -605,6 +664,26 @@ def __init__(self):
605
664
self .settings_window = SettingsWindow (self , self .settings )
606
665
self .settings_window .on_applied .connect (self .refresh_settings )
607
666
667
+ self .theme = Theme (ThemeStyle .System )
668
+ self .apply_theme ()
669
+
670
+ def apply_theme (self ):
671
+ theme_name = self .settings .value ("theme" , "Dark" )
672
+ if theme_name == "Dark" :
673
+ self .theme .set_style (ThemeStyle .Dark )
674
+ self .graphics_view .set_theme (GridThemes .Dark )
675
+ elif theme_name == "Light" :
676
+ self .theme .set_style (ThemeStyle .Light )
677
+ self .graphics_view .set_theme (GridThemes .Light )
678
+ else :
679
+ self .theme .set_style (ThemeStyle .System )
680
+ if self .theme .is_dark ():
681
+ self .graphics_view .set_theme (GridThemes .Dark )
682
+ else :
683
+ self .graphics_view .set_theme (GridThemes .Light )
684
+ self .theme .apply (self )
685
+
686
+
608
687
def update_latency (self ):
609
688
if self .client .websocket :
610
689
self .latency_status .setText (f"Latency: { self .client .websocket .latency * 1000 :.2f} ms" )
0 commit comments