11import subprocess
22import time
33import os
4- from PySide6 .QtWidgets import QMainWindow , QLabel , QPushButton , QGridLayout , QVBoxLayout , QWidget , QHBoxLayout , QComboBox , QCheckBox , QLineEdit , QScrollArea , QMessageBox
4+ from PySide6 .QtWidgets import QMainWindow , QLabel , QPushButton , QGridLayout , QVBoxLayout , QWidget , QHBoxLayout , QComboBox , QCheckBox , QLineEdit , QScrollArea , QMessageBox , QSlider
55from PySide6 .QtGui import QFont
66from PySide6 .QtCore import Qt , QPropertyAnimation , QRect , QEasingCurve , QTimer
77from utils import get_text , set_gaming_tool , set_language , logging , lang
8-
98is_dark_mode = True
109is_muted = False
1110wifi_enabled = True
1211selected_wifi = None
1312selected_bluetooth = None
14-
1513class SettingsWindow (QMainWindow ):
1614 def __init__ (self , parent = None ):
1715 super ().__init__ (parent )
@@ -23,24 +21,21 @@ def __init__(self, parent=None):
2321 self .layout .setAlignment (Qt .AlignCenter )
2422 self .layout .setSpacing (70 )
2523 self .layout .setContentsMargins (80 , 80 , 80 , 80 )
26-
2724 self .title = QLabel (get_text ('settings' ))
2825 self .title .setFont (QFont ('Hack' , 55 , QFont .Bold ))
2926 self .title .setObjectName ('neon-text' )
3027 self .layout .addWidget (self .title , alignment = Qt .AlignCenter )
31-
3228 self .grid_layout = QGridLayout ()
3329 self .grid_layout .setSpacing (60 )
3430 self .grid_layout .setContentsMargins (60 , 60 , 60 , 60 )
3531 self .layout .addLayout (self .grid_layout )
36-
3732 self .add_audio_panel ()
3833 self .add_display_panel ()
3934 self .add_network_panel ()
4035 self .add_power_panel ()
4136 self .add_general_panel ()
4237 self .add_gaming_tools_panel ()
43-
38+ self . add_updates_panel () # Nowa sekcja ulepszająca ustawienia
4439 self .wifi_panel = QWidget (objectName = 'setting-panel' )
4540 self .wifi_layout = QVBoxLayout (self .wifi_panel )
4641 self .wifi_layout .setSpacing (30 )
@@ -66,7 +61,6 @@ def __init__(self, parent=None):
6661 self .wifi_layout .addWidget (self .connect_btn )
6762 self .wifi_panel .setHidden (True )
6863 self .layout .addWidget (self .wifi_panel )
69-
7064 self .bluetooth_panel = QWidget (objectName = 'setting-panel' )
7165 self .bluetooth_layout = QVBoxLayout (self .bluetooth_panel )
7266 self .bluetooth_layout .setSpacing (30 )
@@ -92,7 +86,6 @@ def __init__(self, parent=None):
9286 self .bluetooth_layout .addWidget (self .pair_btn )
9387 self .bluetooth_panel .setHidden (True )
9488 self .layout .addWidget (self .bluetooth_panel )
95-
9689 self .bottom_layout = QHBoxLayout ()
9790 self .bottom_layout .setAlignment (Qt .AlignRight )
9891 self .bottom_layout .setSpacing (50 )
@@ -112,15 +105,12 @@ def __init__(self, parent=None):
112105 self .bottom_layout .addWidget (self .close_btn )
113106 self .layout .addLayout (self .bottom_layout )
114107 self .layout .addStretch ()
115-
116108 self .update_texts ()
117109 QTimer .singleShot (100 , self .animate_panels )
118110 QTimer .singleShot (500 , self .log_button_visibility )
119111 logging .info ('SettingsWindow initialized successfully' )
120-
121112 def log_button_visibility (self ):
122113 logging .info (f'Back button visible: { self .back_btn .isVisible ()} , geometry: { self .back_btn .geometry ().getRect ()} ' )
123-
124114 def back_to_main (self ):
125115 try :
126116 if self .parent ():
@@ -131,68 +121,49 @@ def back_to_main(self):
131121 QMessageBox .warning (self , "Warning" , get_text ('error_returning_to_main' , {'error' : 'No parent window' }))
132122 self .close ()
133123 except Exception as e :
134- logging .error (f'Error returning to main window: { e } ' )
135- QMessageBox .warning (self , "Warning" , get_text ('error_returning_to_main' , {'error' : str (e )}))
136-
137- def animate_panels (self ):
138- panels = self .central_widget .findChildren (QWidget , 'setting-panel' )
139- for i , panel in enumerate (panels ):
140- anim = QPropertyAnimation (panel , b"geometry" )
141- rect = panel .geometry ()
142- anim .setStartValue (QRect (rect .x (), rect .y () + 300 , rect .width (), rect .height ()))
143- anim .setEndValue (rect )
144- anim .setDuration (2000 )
145- anim .setEasingCurve (QEasingCurve .OutQuint )
146- QTimer .singleShot (i * 400 , anim .start )
147-
124+ logging .error (f'Error returning to main: { e } ' )
148125 def add_audio_panel (self ):
149126 panel = QWidget (objectName = 'setting-panel' )
150127 layout = QVBoxLayout (panel )
151128 layout .setSpacing (30 )
152129 title = QLabel (get_text ('audio' ))
153130 title .setFont (QFont ('Hack' , 22 , QFont .Bold ))
154131 layout .addWidget (title )
155- inc_vol = QPushButton (get_text ('increase_volume' ))
156- inc_vol .setObjectName ('setting-btn' )
157- inc_vol .setFixedHeight (70 )
158- inc_vol .clicked .connect (lambda : self .audio_action ('increaseVolume' ))
159- layout .addWidget (inc_vol )
160- dec_vol = QPushButton (get_text ('decrease_volume' ))
161- dec_vol .setObjectName ('setting-btn' )
162- dec_vol .setFixedHeight (70 )
163- dec_vol .clicked .connect (lambda : self .audio_action ('decreaseVolume' ))
164- layout .addWidget (dec_vol )
132+ self .volume_slider = QSlider (Qt .Horizontal )
133+ self .volume_slider .setRange (0 , 100 )
134+ self .volume_slider .setValue (50 ) # Domyślna wartość
135+ self .volume_slider .valueChanged .connect (self .set_volume )
136+ layout .addWidget (self .volume_slider )
165137 toggle_mute = QPushButton (get_text ('toggle_mute' ))
166138 toggle_mute .setObjectName ('setting-btn' )
167139 toggle_mute .setFixedHeight (70 )
168140 toggle_mute .clicked .connect (lambda : self .audio_action ('toggleMute' ))
169141 layout .addWidget (toggle_mute )
170142 self .grid_layout .addWidget (panel , 0 , 0 )
171-
143+ def set_volume (self , value ):
144+ logging .info (f'Setting volume to { value } %' )
145+ subprocess .run (['pactl' , 'set-sink-volume' , '@DEFAULT_SINK@' , f'{ value } %' ])
172146 def add_display_panel (self ):
173147 panel = QWidget (objectName = 'setting-panel' )
174148 layout = QVBoxLayout (panel )
175149 layout .setSpacing (30 )
176150 title = QLabel (get_text ('display' ))
177151 title .setFont (QFont ('Hack' , 22 , QFont .Bold ))
178152 layout .addWidget (title )
179- inc_bright = QPushButton (get_text ('increase_brightness' ))
180- inc_bright .setObjectName ('setting-btn' )
181- inc_bright .setFixedHeight (70 )
182- inc_bright .clicked .connect (lambda : self .display_action ('increaseBrightness' ))
183- layout .addWidget (inc_bright )
184- dec_bright = QPushButton (get_text ('decrease_brightness' ))
185- dec_bright .setObjectName ('setting-btn' )
186- dec_bright .setFixedHeight (70 )
187- dec_bright .clicked .connect (lambda : self .display_action ('decreaseBrightness' ))
188- layout .addWidget (dec_bright )
153+ self .brightness_slider = QSlider (Qt .Horizontal )
154+ self .brightness_slider .setRange (0 , 100 )
155+ self .brightness_slider .setValue (50 ) # Domyślna wartość
156+ self .brightness_slider .valueChanged .connect (self .set_brightness )
157+ layout .addWidget (self .brightness_slider )
189158 toggle_theme = QPushButton (get_text ('toggle_theme' ))
190159 toggle_theme .setObjectName ('setting-btn' )
191160 toggle_theme .setFixedHeight (70 )
192161 toggle_theme .clicked .connect (lambda : self .display_action ('toggleTheme' ))
193162 layout .addWidget (toggle_theme )
194163 self .grid_layout .addWidget (panel , 0 , 1 )
195-
164+ def set_brightness (self , value ):
165+ logging .info (f'Setting brightness to { value } %' )
166+ subprocess .run (['brightnessctl' , 'set' , f'{ value } %' ])
196167 def add_network_panel (self ):
197168 panel = QWidget (objectName = 'setting-panel' )
198169 layout = QVBoxLayout (panel )
@@ -216,7 +187,6 @@ def add_network_panel(self):
216187 bluetooth .clicked .connect (lambda : self .network_action ('showBluetooth' ))
217188 layout .addWidget (bluetooth )
218189 self .grid_layout .addWidget (panel , 1 , 0 )
219-
220190 def add_power_panel (self ):
221191 panel = QWidget (objectName = 'setting-panel' )
222192 layout = QVBoxLayout (panel )
@@ -240,7 +210,6 @@ def add_power_panel(self):
240210 performance .clicked .connect (lambda : self .power_action ('performance' ))
241211 layout .addWidget (performance )
242212 self .grid_layout .addWidget (panel , 1 , 1 )
243-
244213 def add_general_panel (self ):
245214 panel = QWidget (objectName = 'setting-panel' )
246215 layout = QVBoxLayout (panel )
@@ -260,7 +229,6 @@ def add_general_panel(self):
260229 apply_lang .clicked .connect (lambda : self .set_language (self .lang_select .currentText ()))
261230 layout .addWidget (apply_lang )
262231 self .grid_layout .addWidget (panel , 2 , 0 )
263-
264232 def add_gaming_tools_panel (self ):
265233 panel = QWidget (objectName = 'setting-panel' )
266234 layout = QVBoxLayout (panel )
@@ -281,7 +249,57 @@ def add_gaming_tools_panel(self):
281249 vkbasalt_check .stateChanged .connect (lambda state : set_gaming_tool ('vkbasalt' , state == Qt .Checked ))
282250 layout .addWidget (vkbasalt_check )
283251 self .grid_layout .addWidget (panel , 2 , 1 )
284-
252+ def add_updates_panel (self ):
253+ panel = QWidget (objectName = 'setting-panel' )
254+ layout = QVBoxLayout (panel )
255+ layout .setSpacing (30 )
256+ title = QLabel (get_text ('updates' ))
257+ title .setFont (QFont ('Hack' , 22 , QFont .Bold ))
258+ layout .addWidget (title )
259+ check_updates = QPushButton (get_text ('check_updates' ))
260+ check_updates .setObjectName ('setting-btn' )
261+ check_updates .setFixedHeight (70 )
262+ check_updates .clicked .connect (self .check_updates )
263+ layout .addWidget (check_updates )
264+ apply_updates = QPushButton (get_text ('apply_updates' ))
265+ apply_updates .setObjectName ('setting-btn' )
266+ apply_updates .setFixedHeight (70 )
267+ apply_updates .clicked .connect (self .apply_updates )
268+ layout .addWidget (apply_updates )
269+ self .grid_layout .addWidget (panel , 3 , 0 )
270+ def check_updates (self ):
271+ logging .info ('Checking for updates' )
272+ try :
273+ result = subprocess .run (['apt' , 'update' ], capture_output = True , text = True )
274+ if result .returncode == 0 :
275+ QMessageBox .information (self , "Info" , get_text ('updates_checked' ))
276+ else :
277+ QMessageBox .warning (self , "Warning" , get_text ('updates_check_failed' , {'error' : result .stderr }))
278+ except Exception as e :
279+ logging .error (f'Error checking updates: { e } ' )
280+ QMessageBox .warning (self , "Warning" , get_text ('updates_check_failed' , {'error' : str (e )}))
281+ def apply_updates (self ):
282+ logging .info ('Applying updates' )
283+ try :
284+ result = subprocess .run (['apt' , 'upgrade' , '-y' ], capture_output = True , text = True )
285+ if result .returncode == 0 :
286+ QMessageBox .information (self , "Info" , get_text ('updates_applied' ))
287+ else :
288+ QMessageBox .warning (self , "Warning" , get_text ('updates_apply_failed' , {'error' : result .stderr }))
289+ except Exception as e :
290+ logging .error (f'Error applying updates: { e } ' )
291+ QMessageBox .warning (self , "Warning" , get_text ('updates_apply_failed' , {'error' : str (e )}))
292+ def animate_panels (self ):
293+ for i in range (self .grid_layout .count ()):
294+ panel = self .grid_layout .itemAt (i ).widget ()
295+ if panel :
296+ anim = QPropertyAnimation (panel , b"geometry" )
297+ rect = panel .geometry ()
298+ anim .setStartValue (QRect (rect .x (), rect .y () + 300 , rect .width (), rect .height ()))
299+ anim .setEndValue (rect )
300+ anim .setDuration (2000 )
301+ anim .setEasingCurve (QEasingCurve .OutQuint )
302+ QTimer .singleShot (i * 200 , lambda a = anim : a .start ())
285303 def update_texts (self ):
286304 self .setWindowTitle (get_text ('settings' ))
287305 self .title .setText (get_text ('settings' ))
@@ -306,32 +324,16 @@ def update_texts(self):
306324 for cb in checkboxes :
307325 key = cb .text ().lower ().replace (' ' , '_' )
308326 cb .setText (get_text (key ))
309-
310327 def audio_action (self , action ):
311328 global is_muted
312- if action == 'increaseVolume' :
313- logging .info ('Increasing volume' )
314- is_muted = False
315- subprocess .run (['pactl' , 'set-sink-volume' , '@DEFAULT_SINK@' , '+5%' ])
316- elif action == 'decreaseVolume' :
317- logging .info ('Decreasing volume' )
318- is_muted = False
319- subprocess .run (['pactl' , 'set-sink-volume' , '@DEFAULT_SINK@' , '-5%' ])
320- elif action == 'toggleMute' :
329+ if action == 'toggleMute' :
321330 logging .info ('Toggling mute' )
322331 is_muted = not is_muted
323332 subprocess .run (['pactl' , 'set-sink-mute' , '@DEFAULT_SINK@' , 'toggle' ])
324-
325333 def display_action (self , action ):
326334 global is_dark_mode
327335 config_path = os .path .join (os .path .expanduser ('~' ), '.hackeros/Hacker-Mode/wayfire.ini' )
328- if action == 'increaseBrightness' :
329- logging .info ('Increasing brightness' )
330- subprocess .run (['brightnessctl' , 'set' , '+5%' ])
331- elif action == 'decreaseBrightness' :
332- logging .info ('Decreasing brightness' )
333- subprocess .run (['brightnessctl' , 'set' , '5%-' ])
334- elif action == 'toggleTheme' :
336+ if action == 'toggleTheme' :
335337 logging .info ('Toggling theme' )
336338 is_dark_mode = not is_dark_mode
337339 theme = 'dark' if is_dark_mode else 'light'
@@ -344,7 +346,6 @@ def display_action(self, action):
344346 subprocess .run (['wayfire' , '-c' , config_path , '--replace' ])
345347 except Exception as e :
346348 logging .error (f'Error toggling theme: { e } ' )
347-
348349 def network_action (self , action ):
349350 global wifi_enabled
350351 if action == 'showWifiSettings' :
@@ -369,17 +370,14 @@ def network_action(self, action):
369370 logging .info ('Showing Bluetooth' )
370371 self .bluetooth_panel .setHidden (False )
371372 self .wifi_panel .setHidden (True )
372-
373373 def power_action (self , profile ):
374374 logging .info (f'Setting power profile to { profile } ' )
375375 subprocess .run (['powerprofilesctl' , 'set' , profile ])
376-
377376 def set_language (self , new_lang ):
378377 set_language (new_lang )
379378 self .update_texts ()
380379 if self .parent ():
381380 self .parent ().update_texts ()
382-
383381 def update_wifi_list (self ):
384382 while self .wifi_list_layout .count ():
385383 child = self .wifi_list_layout .takeAt (0 )
@@ -404,7 +402,6 @@ def update_wifi_list(self):
404402 label = QLabel (get_text ('no_networks' ))
405403 label .setObjectName ('list-label' )
406404 self .wifi_list_layout .addWidget (label )
407-
408405 def select_wifi (self , ssid ):
409406 global selected_wifi
410407 selected_wifi = ssid
@@ -414,7 +411,6 @@ def select_wifi(self, ssid):
414411 btn .setStyleSheet ("background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #3d3d3d, stop:1 #2a2a2a);" )
415412 else :
416413 btn .setStyleSheet ("" )
417-
418414 def connect_wifi (self ):
419415 global selected_wifi
420416 if not selected_wifi :
@@ -434,7 +430,6 @@ def connect_wifi(self):
434430 except Exception as e :
435431 QMessageBox .warning (self , "Warning" , get_text ('connection_failed' , {'error' : str (e )}))
436432 logging .error (f'Error connecting to Wi-Fi: { e } ' )
437-
438433 def scan_bluetooth (self ):
439434 while self .bluetooth_list_layout .count ():
440435 child = self .bluetooth_list_layout .takeAt (0 )
@@ -463,7 +458,6 @@ def scan_bluetooth(self):
463458 label = QLabel ('No devices found' )
464459 label .setObjectName ('list-label' )
465460 self .bluetooth_list_layout .addWidget (label )
466-
467461 def select_bluetooth (self , device_id ):
468462 global selected_bluetooth
469463 selected_bluetooth = device_id
@@ -473,7 +467,6 @@ def select_bluetooth(self, device_id):
473467 btn .setStyleSheet ("background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #3d3d3d, stop:1 #2a2a2a);" )
474468 else :
475469 btn .setStyleSheet ("" )
476-
477470 def pair_bluetooth (self ):
478471 global selected_bluetooth
479472 if not selected_bluetooth :
@@ -494,7 +487,6 @@ def pair_bluetooth(self):
494487 except Exception as e :
495488 QMessageBox .warning (self , "Warning" , get_text ('pairing_failed' , {'error' : str (e )}))
496489 logging .error (f'Error pairing Bluetooth: { e } ' )
497-
498490 def closeEvent (self , event ):
499491 try :
500492 if self .parent ():
0 commit comments