11from asyncio import to_thread
2+ from traceback import print_exc
23import inject
34import win32gui
45from win32con import SW_HIDE , SW_SHOW
56import win32console
67from PIL import Image
78from pystray import Menu , MenuItem , Icon
89import _meta as app
10+ from active_window_checker import AppMode
11+ from tray .utils import ref , make_toggle , make_radiobutton
912from uac import has_admin_rights
1013from app_close import AppCloseManager
1114from auto_update import AutoUpdater
1215from interaction import InteractionManager
1316from inversion_rules import InversionRulesController
14- from settings import UserSettingsController
17+ from settings import UserSettingsController , UserSettings , OPTION_PATH , OPTION_CHANGE_HANDLER , T
1518from utils import explore , app_abs_path
1619
1720
18- def make_toggle (out_func = None , default_value = False ):
19- def decorator (func ):
20- def wrapper (self ):
21- value = [default_value ]
22-
23- def get_value (item ):
24- return value [0 ]
25-
26- def toggle ():
27- value [0 ] ^= True
28- func (self , value [0 ])
29-
30- return toggle , get_value
31- return wrapper
32- if out_func :
33- return decorator (out_func )
34- return decorator
35-
36-
3721class Tray :
3822 settings_controller = inject .attr (UserSettingsController )
3923 inversion_rules = inject .attr (InversionRulesController )
@@ -56,12 +40,16 @@ def setup(self):
5640 win32gui .ShowWindow (self .console_hwnd , SW_HIDE )
5741
5842 def run (self ):
59- self .tray = Icon (
60- app .__product_name__ ,
61- Image .open (app_abs_path (app .__icon__ )),
62- menu = self .build_menu ()
63- )
64- self .tray .run ()
43+ try :
44+ self .tray = Icon (
45+ app .__product_name__ ,
46+ Image .open (app_abs_path (app .__icon__ )),
47+ menu = self .build_menu ()
48+ )
49+ self .tray .run ()
50+ except :
51+ print_exc ()
52+ raise
6553
6654 async def run_async (self ):
6755 try :
@@ -82,14 +70,12 @@ def _wrapper(*ignore):
8270 def _open (path ):
8371 return callback (explore , path )
8472
85- def ref (text : str ):
86- """
87- Make first letter underscored, also
88- mark this letter as shortcut for system tray,
89- so you may press this letter on keyboard
90- to select corresponding menu item
91- """
92- return f'&{ text [0 ]} \u0332 { text [1 :]} '
73+ change_mode_menu , change_mode_setter = self .change_mode ()
74+
75+ self ._link_with_settings (
76+ lambda settings : settings .win_tracker .mode ,
77+ change_mode_setter
78+ )
9379
9480 im = self .im
9581 return Menu (
@@ -102,6 +88,10 @@ def ref(text: str):
10288 ref ("Show console" ),
10389 * self .toggle_console ()
10490 ),
91+ MenuItem (
92+ ref ("Mode" ),
93+ change_mode_menu
94+ ),
10595 Menu .SEPARATOR ,
10696 MenuItem (
10797 ref ('Open' ),
@@ -124,7 +114,7 @@ def ref(text: str):
124114 MenuItem (ref ('Settings file' ),
125115 callback (self .settings_controller .load )),
126116 MenuItem (ref ('Inversion rules file' ),
127- callback (self .settings_controller .load )),
117+ callback (self .inversion_rules .load )),
128118 )
129119 ),
130120 Menu .SEPARATOR ,
@@ -140,9 +130,29 @@ def ref(text: str):
140130 callback (self .close_manager .close )),
141131 )
142132
133+ def _link_with_settings (self ,
134+ path : OPTION_PATH ,
135+ handler : OPTION_CHANGE_HANDLER ,):
136+ def new_handler (value : T ):
137+ handler (value )
138+ if self .tray :
139+ self .tray .update_menu ()
140+
141+ self .settings_controller .add_option_change_handler (
142+ path , new_handler , True
143+ )
144+
143145 @make_toggle
144146 def toggle_console (self , value ):
145147 win32gui .ShowWindow (
146148 self .console_hwnd ,
147149 SW_SHOW if value else SW_HIDE
148150 )
151+
152+ @make_radiobutton ({
153+ AppMode .DISABLE : ref ("Ignore All" ),
154+ AppMode .RULES : ref ("According with rules" ),
155+ }, AppMode .RULES )
156+ def change_mode (self , value : AppMode ):
157+ self .settings_controller .settings .win_tracker .mode = value
158+ self .settings_controller .save ()
0 commit comments