92
92
hw_lib_map = {"AUTO" : "Automatic" , "LHM" : "LibreHardwareMonitor (admin.)" , "PYTHON" : "Python libraries" ,
93
93
"STUB" : "Fake random data" , "STATIC" : "Fake static data" }
94
94
reverse_map = {False : "classic" , True : "reverse" }
95
+ weather_unit_map = {"metric" : "metric - °C" , "imperial" : "imperial - °F" , "standard" : "standard - °K" }
96
+ weather_lang_map = {"sq" : "Albanian" , "af" : "Afrikaans" , "ar" : "Arabic" , "az" : "Azerbaijani" , "eu" : "Basque" ,
97
+ "be" : "Belarusian" , "bg" : "Bulgarian" , "ca" : "Catalan" , "zh_cn" : "Chinese Simplified" ,
98
+ "zh_tw" : "Chinese Traditional" , "hr" : "Croatian" , "cz" : "Czech" , "da" : "Danish" , "nl" : "Dutch" ,
99
+ "en" : "English" , "fi" : "Finnish" , "fr" : "French" , "gl" : "Galician" , "de" : "German" , "el" : "Greek" ,
100
+ "he" : "Hebrew" , "hi" : "Hindi" , "hu" : "Hungarian" , "is" : "Icelandic" , "id" : "Indonesian" ,
101
+ "it" : "Italian" , "ja" : "Japanese" , "kr" : "Korean" , "ku" : "Kurmanji (Kurdish)" , "la" : "Latvian" ,
102
+ "lt" : "Lithuanian" , "mk" : "Macedonian" , "no" : "Norwegian" , "fa" : "Persian (Farsi)" , "pl" : "Polish" ,
103
+ "pt" : "Portuguese" , "pt_br" : "Português Brasil" , "ro" : "Romanian" , "ru" : "Russian" , "sr" : "Serbian" ,
104
+ "sk" : "Slovak" , "sl" : "Slovenian" , "sp" : "Spanish" , "sv" : "Swedish" , "th" : "Thai" , "tr" : "Turkish" ,
105
+ "ua" : "Ukrainian" , "vi" : "Vietnamese" , "zu" : "Zulu" }
95
106
96
107
MAIN_DIRECTORY = str (Path (__file__ ).parent .resolve ()) + "/"
97
108
THEMES_DIR = MAIN_DIRECTORY + 'res/themes'
@@ -162,6 +173,9 @@ def __init__(self):
162
173
self .window .bind ("<FocusIn>" , self .on_theme_change )
163
174
self .window .after (0 , self .on_fan_speed_update )
164
175
176
+ # Subwindow for weather/ping config.
177
+ self .more_config_window = MoreConfigWindow (self )
178
+
165
179
# Make TK look better with Sun Valley ttk theme
166
180
sv_ttk .set_theme ("light" )
167
181
@@ -251,6 +265,10 @@ def __init__(self):
251
265
"Fans missing from the list? Install lm-sensors package\n "
252
266
"and run 'sudo sensors-detect' command, then reboot." )
253
267
268
+ self .edit_theme_btn = ttk .Button (self .window , text = "Weather & ping" ,
269
+ command = lambda : self .on_weatherping_click ())
270
+ self .edit_theme_btn .place (x = 170 , y = 510 , height = 50 , width = 130 )
271
+
254
272
self .edit_theme_btn = ttk .Button (self .window , text = "Edit theme" , command = lambda : self .on_theme_editor_click ())
255
273
self .edit_theme_btn .place (x = 310 , y = 510 , height = 50 , width = 130 )
256
274
@@ -375,6 +393,9 @@ def load_config_values(self):
375
393
self .on_brightness_change ()
376
394
self .on_hwlib_change ()
377
395
396
+ # Load configuration to sub-window as well
397
+ self .more_config_window .load_config_values (self .config )
398
+
378
399
def save_config_values (self ):
379
400
self .config ['config' ]['THEME' ] = self .theme_cb .get ()
380
401
self .config ['config' ]['HW_SENSORS' ] = [k for k , v in hw_lib_map .items () if v == self .hwlib_cb .get ()][0 ]
@@ -401,9 +422,23 @@ def save_config_values(self):
401
422
with open ("config.yaml" , "w" , encoding = 'utf-8' ) as file :
402
423
ruamel .yaml .YAML ().dump (self .config , file )
403
424
425
+ def save_additional_config (self , ping : str , api_key : str , lat : str , long : str , unit : str , lang : str ):
426
+ self .config ['config' ]['PING' ] = ping
427
+ self .config ['config' ]['WEATHER_API_KEY' ] = api_key
428
+ self .config ['config' ]['WEATHER_LATITUDE' ] = lat
429
+ self .config ['config' ]['WEATHER_LONGITUDE' ] = long
430
+ self .config ['config' ]['WEATHER_UNITS' ] = unit
431
+ self .config ['config' ]['WEATHER_LANGUAGE' ] = lang
432
+
433
+ with open ("config.yaml" , "w" , encoding = 'utf-8' ) as file :
434
+ ruamel .yaml .YAML ().dump (self .config , file )
435
+
404
436
def on_theme_change (self , e = None ):
405
437
self .load_theme_preview ()
406
438
439
+ def on_weatherping_click (self ):
440
+ self .more_config_window .show ()
441
+
407
442
def on_theme_editor_click (self ):
408
443
subprocess .Popen (MAIN_DIRECTORY + "theme-editor.py" + " \" " + self .theme_cb .get () + "\" " , shell = True )
409
444
@@ -486,6 +521,139 @@ def on_fan_speed_update(self):
486
521
self .window .after (500 , self .on_fan_speed_update )
487
522
488
523
524
+ class MoreConfigWindow :
525
+ def __init__ (self , main_window : TuringConfigWindow ):
526
+ self .window = Toplevel ()
527
+ self .window .withdraw ()
528
+ self .window .title ('Configure weather & ping' )
529
+ self .window .geometry ("750x400" )
530
+
531
+ self .main_window = main_window
532
+
533
+ # Make TK look better with Sun Valley ttk theme
534
+ sv_ttk .set_theme ("light" )
535
+
536
+ self .ping_label = ttk .Label (self .window , text = 'Hostname / IP to ping' )
537
+ self .ping_label .place (x = 10 , y = 10 )
538
+ self .ping_entry = ttk .Entry (self .window )
539
+ self .ping_entry .place (x = 190 , y = 5 , width = 250 )
540
+
541
+ weather_label = ttk .Label (self .window , text = 'Weather forecast (OpenWeatherMap API)' , font = 'bold' )
542
+ weather_label .place (x = 10 , y = 70 )
543
+
544
+ weather_info_label = ttk .Label (self .window ,
545
+ text = "To display weather forecast on themes that support it, you need an OpenWeatherMap \" One Call API 3.0\" key.\n "
546
+ "You will get 1,000 API calls per day for free. This program is configured to stay under this threshold (~300 calls/day)." )
547
+ weather_info_label .place (x = 10 , y = 100 )
548
+ weather_api_link_label = ttk .Label (self .window ,
549
+ text = "Click here to subscribe to OpenWeatherMap One Call API 3.0." )
550
+ weather_api_link_label .place (x = 10 , y = 140 )
551
+ weather_api_link_label .config (foreground = "#a3a3ff" , cursor = "hand2" )
552
+ weather_api_link_label .bind ("<Button-1>" ,
553
+ lambda e : webbrowser .open_new_tab ("https://openweathermap.org/api" ))
554
+
555
+ self .api_label = ttk .Label (self .window , text = 'OpenWeatherMap API key' )
556
+ self .api_label .place (x = 10 , y = 170 )
557
+ self .api_entry = ttk .Entry (self .window )
558
+ self .api_entry .place (x = 190 , y = 165 , width = 250 )
559
+
560
+ latlong_label = ttk .Label (self .window ,
561
+ text = "You can use online services to get your latitude/longitude e.g. latlong.net (click here)" )
562
+ latlong_label .place (x = 10 , y = 210 )
563
+ latlong_label .config (foreground = "#a3a3ff" , cursor = "hand2" )
564
+ latlong_label .bind ("<Button-1>" ,
565
+ lambda e : webbrowser .open_new_tab ("https://www.latlong.net/" ))
566
+
567
+ self .lat_label = ttk .Label (self .window , text = 'Latitude' )
568
+ self .lat_label .place (x = 10 , y = 250 )
569
+ self .lat_entry = ttk .Entry (self .window , validate = 'key' ,
570
+ validatecommand = (self .window .register (self .validateCoord ), '%P' ))
571
+ self .lat_entry .place (x = 80 , y = 245 , width = 100 )
572
+
573
+ self .long_label = ttk .Label (self .window , text = 'Longitude' )
574
+ self .long_label .place (x = 270 , y = 250 )
575
+ self .long_entry = ttk .Entry (self .window , validate = 'key' ,
576
+ validatecommand = (self .window .register (self .validateCoord ), '%P' ))
577
+ self .long_entry .place (x = 340 , y = 245 , width = 100 )
578
+
579
+ self .unit_label = ttk .Label (self .window , text = 'Units' )
580
+ self .unit_label .place (x = 10 , y = 290 )
581
+ self .unit_cb = ttk .Combobox (self .window , values = list (weather_unit_map .values ()), state = 'readonly' )
582
+ self .unit_cb .place (x = 190 , y = 285 , width = 250 )
583
+
584
+ self .lang_label = ttk .Label (self .window , text = 'Language' )
585
+ self .lang_label .place (x = 10 , y = 330 )
586
+ self .lang_cb = ttk .Combobox (self .window , values = list (weather_lang_map .values ()), state = 'readonly' )
587
+ self .lang_cb .place (x = 190 , y = 325 , width = 250 )
588
+
589
+ self .save_btn = ttk .Button (self .window , text = "Save settings" , command = lambda : self .on_save_click ())
590
+ self .save_btn .place (x = 590 , y = 340 , height = 50 , width = 130 )
591
+
592
+ self .window .protocol ("WM_DELETE_WINDOW" , self .on_closing )
593
+
594
+ def validateCoord (self , coord : str ):
595
+ if not coord :
596
+ return True
597
+ try :
598
+ float (coord )
599
+ except :
600
+ return False
601
+ return True
602
+
603
+ def show (self ):
604
+ self .window .deiconify ()
605
+
606
+ def on_closing (self ):
607
+ self .window .withdraw ()
608
+
609
+ def load_config_values (self , config ):
610
+ self .config = config
611
+
612
+ try :
613
+ self .ping_entry .insert (0 , self .config ['config' ]['PING' ])
614
+ except :
615
+ self .ping_entry .insert (0 , "8.8.8.8" )
616
+
617
+ try :
618
+ self .api_entry .insert (0 , self .config ['config' ]['WEATHER_API_KEY' ])
619
+ except :
620
+ pass
621
+
622
+ try :
623
+ self .lat_entry .insert (0 , self .config ['config' ]['WEATHER_LATITUDE' ])
624
+ except :
625
+ self .lat_entry .insert (0 , "45.75" )
626
+
627
+ try :
628
+ self .long_entry .insert (0 , self .config ['config' ]['WEATHER_LONGITUDE' ])
629
+ except :
630
+ self .long_entry .insert (0 , "45.75" )
631
+
632
+ try :
633
+ self .unit_cb .set (weather_unit_map [self .config ['config' ]['WEATHER_UNITS' ]])
634
+ except :
635
+ self .unit_cb .set (0 )
636
+
637
+ try :
638
+ self .lang_cb .set (weather_lang_map [self .config ['config' ]['WEATHER_LANGUAGE' ]])
639
+ except :
640
+ self .lang_cb .set (weather_lang_map ["en" ])
641
+
642
+ def on_save_click (self ):
643
+ self .save_config_values ()
644
+ self .on_closing ()
645
+
646
+ def save_config_values (self ):
647
+ ping = self .ping_entry .get ()
648
+ api_key = self .api_entry .get ()
649
+ lat = self .lat_entry .get ()
650
+ long = self .long_entry .get ()
651
+ unit = [k for k , v in weather_unit_map .items () if v == self .unit_cb .get ()][0 ]
652
+ lang = [k for k , v in weather_lang_map .items () if v == self .lang_cb .get ()][0 ]
653
+
654
+ self .main_window .save_additional_config (ping , api_key , lat , long , unit , lang )
655
+
656
+
489
657
if __name__ == "__main__" :
490
658
configurator = TuringConfigWindow ()
491
659
configurator .run ()
0 commit comments