frontengine 1.0.34__tar.gz → 1.0.35__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. {frontengine-1.0.34 → frontengine-1.0.35}/PKG-INFO +1 -1
  2. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/base_widget.py +25 -0
  3. frontengine-1.0.35/frontengine/show/toast/toast_widget.py +120 -0
  4. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/wallpaper/wallpaper_widget.py +16 -2
  5. frontengine-1.0.35/frontengine/ui/dialog/app_profile_dialog.py +115 -0
  6. frontengine-1.0.35/frontengine/ui/dialog/reminder_dialog.py +139 -0
  7. frontengine-1.0.35/frontengine/ui/dialog/smart_pause_dialog.py +87 -0
  8. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/main_ui.py +79 -9
  9. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/menu/settings_menu.py +37 -0
  10. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/control_center/control_center_ui.py +68 -3
  11. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/wallpaper/wallpaper_setting_ui.py +110 -24
  12. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/user_setting/user_setting_file.py +12 -0
  13. frontengine-1.0.35/frontengine/utils/app_profile/app_profile_service.py +102 -0
  14. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/multi_language/english.py +30 -1
  15. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/multi_language/traditional_chinese.py +30 -2
  16. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/platform_info/platform_info.py +85 -0
  17. frontengine-1.0.35/frontengine/utils/power_mode/power_mode.py +72 -0
  18. frontengine-1.0.35/frontengine/utils/reminder/reminder_service.py +181 -0
  19. frontengine-1.0.35/frontengine/utils/smart_pause/pause_rules.py +104 -0
  20. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/smart_pause/smart_pause_service.py +64 -9
  21. frontengine-1.0.35/frontengine/utils/weather/__init__.py +0 -0
  22. frontengine-1.0.35/frontengine/utils/workshop/__init__.py +0 -0
  23. frontengine-1.0.35/frontengine/worker/__init__.py +0 -0
  24. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine.egg-info/PKG-INFO +1 -1
  25. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine.egg-info/SOURCES.txt +10 -0
  26. {frontengine-1.0.34 → frontengine-1.0.35}/pyproject.toml +1 -1
  27. frontengine-1.0.34/frontengine/utils/power_mode/power_mode.py +0 -29
  28. {frontengine-1.0.34 → frontengine-1.0.35}/LICENSE +0 -0
  29. {frontengine-1.0.34 → frontengine-1.0.35}/README.md +0 -0
  30. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/__init__.py +0 -0
  31. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/__main__.py +0 -0
  32. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/__init__.py +0 -0
  33. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/focus_shield/__init__.py +0 -0
  34. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/focus_shield/focus_shield_widget.py +0 -0
  35. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/gif/__init__.py +0 -0
  36. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/gif/paint_gif.py +0 -0
  37. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/image/__init__.py +0 -0
  38. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/image/paint_image.py +0 -0
  39. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/load/__init__.py +0 -0
  40. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/load/load_someone_make_ui.py +0 -0
  41. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/overlay_factory.py +0 -0
  42. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/particle/__init__.py +0 -0
  43. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/particle/particle_ui.py +0 -0
  44. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/pet/__init__.py +0 -0
  45. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/pet/desktop_pet.py +0 -0
  46. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/presentation/__init__.py +0 -0
  47. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/presentation/annotation_overlay.py +0 -0
  48. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/presentation/cursor_effects.py +0 -0
  49. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/presentation/keystroke_display.py +0 -0
  50. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/presentation/magnifier.py +0 -0
  51. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/scene/__init__.py +0 -0
  52. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/scene/extend_graphic_scene.py +0 -0
  53. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/scene/extend_graphic_view.py +0 -0
  54. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/scene/scene.py +0 -0
  55. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/screen_care/__init__.py +0 -0
  56. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/screen_care/screen_filter.py +0 -0
  57. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/sound_player/__init__.py +0 -0
  58. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/sound_player/sound_effect.py +0 -0
  59. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/sound_player/sound_player.py +0 -0
  60. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/text/__init__.py +0 -0
  61. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/text/draw_text.py +0 -0
  62. {frontengine-1.0.34/frontengine/show/video → frontengine-1.0.35/frontengine/show/toast}/__init__.py +0 -0
  63. {frontengine-1.0.34/frontengine/show/wallpaper → frontengine-1.0.35/frontengine/show/video}/__init__.py +0 -0
  64. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/video/video_player.py +0 -0
  65. {frontengine-1.0.34/frontengine/show/web → frontengine-1.0.35/frontengine/show/wallpaper}/__init__.py +0 -0
  66. {frontengine-1.0.34/frontengine/system_tray → frontengine-1.0.35/frontengine/show/web}/__init__.py +0 -0
  67. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/web/webview.py +0 -0
  68. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/show/window_helpers.py +0 -0
  69. {frontengine-1.0.34/frontengine/ui → frontengine-1.0.35/frontengine/system_tray}/__init__.py +0 -0
  70. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/system_tray/extend_system_tray.py +0 -0
  71. {frontengine-1.0.34/frontengine/ui/color → frontengine-1.0.35/frontengine/ui}/__init__.py +0 -0
  72. {frontengine-1.0.34/frontengine/ui/dialog → frontengine-1.0.35/frontengine/ui/color}/__init__.py +0 -0
  73. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/color/global_color.py +0 -0
  74. {frontengine-1.0.34/frontengine/ui/menu → frontengine-1.0.35/frontengine/ui/dialog}/__init__.py +0 -0
  75. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/dialog/choose_file_dialog.py +0 -0
  76. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/dialog/hotkey_settings_dialog.py +0 -0
  77. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/dialog/save_file_dialog.py +0 -0
  78. {frontengine-1.0.34/frontengine/ui/page → frontengine-1.0.35/frontengine/ui/menu}/__init__.py +0 -0
  79. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/menu/help_menu.py +0 -0
  80. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/menu/how_to_menu.py +0 -0
  81. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/menu/language_menu.py +0 -0
  82. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/menu/preset_menu.py +0 -0
  83. {frontengine-1.0.34/frontengine/ui/page/control_center → frontengine-1.0.35/frontengine/ui/page}/__init__.py +0 -0
  84. {frontengine-1.0.34/frontengine/ui/page/focus → frontengine-1.0.35/frontengine/ui/page/control_center}/__init__.py +0 -0
  85. {frontengine-1.0.34/frontengine/ui/page/gif → frontengine-1.0.35/frontengine/ui/page/focus}/__init__.py +0 -0
  86. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/focus/focus_setting_ui.py +0 -0
  87. {frontengine-1.0.34/frontengine/ui/page/image → frontengine-1.0.35/frontengine/ui/page/gif}/__init__.py +0 -0
  88. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/gif/gif_setting_ui.py +0 -0
  89. {frontengine-1.0.34/frontengine/ui/page/particle → frontengine-1.0.35/frontengine/ui/page/image}/__init__.py +0 -0
  90. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/image/image_setting_ui.py +0 -0
  91. {frontengine-1.0.34/frontengine/ui/page/pet → frontengine-1.0.35/frontengine/ui/page/particle}/__init__.py +0 -0
  92. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/particle/particle_setting_ui.py +0 -0
  93. {frontengine-1.0.34/frontengine/ui/page/presentation → frontengine-1.0.35/frontengine/ui/page/pet}/__init__.py +0 -0
  94. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/pet/pet_setting_ui.py +0 -0
  95. {frontengine-1.0.34/frontengine/ui/page/scene_setting → frontengine-1.0.35/frontengine/ui/page/presentation}/__init__.py +0 -0
  96. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/presentation/presentation_setting_ui.py +0 -0
  97. {frontengine-1.0.34/frontengine/ui/page/scene_setting/scene_page → frontengine-1.0.35/frontengine/ui/page/scene_setting}/__init__.py +0 -0
  98. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/scene_setting/scene_manager.py +0 -0
  99. {frontengine-1.0.34/frontengine/ui/page/screen_care → frontengine-1.0.35/frontengine/ui/page/scene_setting/scene_page}/__init__.py +0 -0
  100. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py +0 -0
  101. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/scene_setting/scene_page/gif.py +0 -0
  102. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/scene_setting/scene_page/image.py +0 -0
  103. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/scene_setting/scene_page/registry.py +0 -0
  104. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/scene_setting/scene_page/sound.py +0 -0
  105. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/scene_setting/scene_page/text.py +0 -0
  106. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/scene_setting/scene_page/video.py +0 -0
  107. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/scene_setting/scene_page/web.py +0 -0
  108. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/scene_setting/scene_setting_ui.py +0 -0
  109. {frontengine-1.0.34/frontengine/ui/page/sound_player → frontengine-1.0.35/frontengine/ui/page/screen_care}/__init__.py +0 -0
  110. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/screen_care/screen_care_setting_ui.py +0 -0
  111. {frontengine-1.0.34/frontengine/ui/page/text → frontengine-1.0.35/frontengine/ui/page/sound_player}/__init__.py +0 -0
  112. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/sound_player/sound_player_setting_ui.py +0 -0
  113. {frontengine-1.0.34/frontengine/ui/page/video → frontengine-1.0.35/frontengine/ui/page/text}/__init__.py +0 -0
  114. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/text/text_setting_ui.py +0 -0
  115. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/utils.py +0 -0
  116. {frontengine-1.0.34/frontengine/ui/page/wallpaper → frontengine-1.0.35/frontengine/ui/page/video}/__init__.py +0 -0
  117. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/video/video_setting_ui.py +0 -0
  118. {frontengine-1.0.34/frontengine/ui/page/web → frontengine-1.0.35/frontengine/ui/page/wallpaper}/__init__.py +0 -0
  119. {frontengine-1.0.34/frontengine/user_setting → frontengine-1.0.35/frontengine/ui/page/web}/__init__.py +0 -0
  120. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/ui/page/web/web_setting_ui.py +0 -0
  121. {frontengine-1.0.34/frontengine/utils → frontengine-1.0.35/frontengine/user_setting}/__init__.py +0 -0
  122. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/user_setting/preset_repository.py +0 -0
  123. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/user_setting/scene_setting.py +0 -0
  124. {frontengine-1.0.34/frontengine/utils/audio_meter → frontengine-1.0.35/frontengine/utils}/__init__.py +0 -0
  125. {frontengine-1.0.34/frontengine/utils/autostart → frontengine-1.0.35/frontengine/utils/app_profile}/__init__.py +0 -0
  126. {frontengine-1.0.34/frontengine/utils/break_reminder → frontengine-1.0.35/frontengine/utils/audio_meter}/__init__.py +0 -0
  127. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/audio_meter/audio_envelope.py +0 -0
  128. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/audio_meter/screen_audio.py +0 -0
  129. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/audio_meter/system_audio_meter.py +0 -0
  130. {frontengine-1.0.34/frontengine/utils/browser → frontengine-1.0.35/frontengine/utils/autostart}/__init__.py +0 -0
  131. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/autostart/autostart_service.py +0 -0
  132. {frontengine-1.0.34/frontengine/utils/critical_exit → frontengine-1.0.35/frontengine/utils/break_reminder}/__init__.py +0 -0
  133. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/break_reminder/break_reminder.py +0 -0
  134. {frontengine-1.0.34/frontengine/utils/file → frontengine-1.0.35/frontengine/utils/browser}/__init__.py +0 -0
  135. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/browser/browser.py +0 -0
  136. {frontengine-1.0.34/frontengine/utils/focus_shield → frontengine-1.0.35/frontengine/utils/critical_exit}/__init__.py +0 -0
  137. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/critical_exit/check_key_is_press.py +0 -0
  138. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/critical_exit/critical_exit.py +0 -0
  139. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/critical_exit/win32_vk.py +0 -0
  140. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/exception/__init__.py +0 -0
  141. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/exception/exception_tags.py +0 -0
  142. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/exception/exceptions.py +0 -0
  143. {frontengine-1.0.34/frontengine/utils/focus_timer → frontengine-1.0.35/frontengine/utils/file}/__init__.py +0 -0
  144. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/file/open/__init__.py +0 -0
  145. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/file/open/open_file.py +0 -0
  146. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/file/save/__init__.py +0 -0
  147. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/file/save/save_file.py +0 -0
  148. {frontengine-1.0.34/frontengine/utils/hotkey → frontengine-1.0.35/frontengine/utils/focus_shield}/__init__.py +0 -0
  149. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/focus_shield/focus_shield.py +0 -0
  150. {frontengine-1.0.34/frontengine/utils/input_watch → frontengine-1.0.35/frontengine/utils/focus_timer}/__init__.py +0 -0
  151. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/focus_timer/focus_timer.py +0 -0
  152. {frontengine-1.0.34/frontengine/utils/json → frontengine-1.0.35/frontengine/utils/hotkey}/__init__.py +0 -0
  153. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/hotkey/hotkey_service.py +0 -0
  154. {frontengine-1.0.34/frontengine/utils/logging → frontengine-1.0.35/frontengine/utils/input_watch}/__init__.py +0 -0
  155. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/input_watch/input_watch_service.py +0 -0
  156. {frontengine-1.0.34/frontengine/utils/multi_language → frontengine-1.0.35/frontengine/utils/json}/__init__.py +0 -0
  157. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/json/json_file.py +0 -0
  158. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/json/json_repository.py +0 -0
  159. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/json_format/__init__.py +0 -0
  160. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/json_format/json_process.py +0 -0
  161. {frontengine-1.0.34/frontengine/utils/pet_chat → frontengine-1.0.35/frontengine/utils/logging}/__init__.py +0 -0
  162. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/logging/loggin_instance.py +0 -0
  163. {frontengine-1.0.34/frontengine/utils/platform_info → frontengine-1.0.35/frontengine/utils/multi_language}/__init__.py +0 -0
  164. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/multi_language/france.py +0 -0
  165. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/multi_language/germany.py +0 -0
  166. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/multi_language/italy.py +0 -0
  167. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/multi_language/language_wrapper.py +0 -0
  168. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/multi_language/russian.py +0 -0
  169. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/multi_language/simplified_chinese.py +0 -0
  170. {frontengine-1.0.34/frontengine/utils/playlist → frontengine-1.0.35/frontengine/utils/pet_chat}/__init__.py +0 -0
  171. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/pet_chat/pet_chat_service.py +0 -0
  172. {frontengine-1.0.34/frontengine/utils/plugins → frontengine-1.0.35/frontengine/utils/platform_info}/__init__.py +0 -0
  173. {frontengine-1.0.34/frontengine/utils/power_mode → frontengine-1.0.35/frontengine/utils/playlist}/__init__.py +0 -0
  174. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/playlist/playlist.py +0 -0
  175. {frontengine-1.0.34/frontengine/utils/preset_schedule → frontengine-1.0.35/frontengine/utils/plugins}/__init__.py +0 -0
  176. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/plugins/plugin_loader.py +0 -0
  177. {frontengine-1.0.34/frontengine/utils/redirect_manager → frontengine-1.0.35/frontengine/utils/power_mode}/__init__.py +0 -0
  178. {frontengine-1.0.34/frontengine/utils/smart_pause → frontengine-1.0.35/frontengine/utils/preset_schedule}/__init__.py +0 -0
  179. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/preset_schedule/preset_schedule_service.py +0 -0
  180. {frontengine-1.0.34/frontengine/utils/system_stats → frontengine-1.0.35/frontengine/utils/redirect_manager}/__init__.py +0 -0
  181. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/redirect_manager/redirect_manager_class.py +0 -0
  182. {frontengine-1.0.34/frontengine/utils/text_source → frontengine-1.0.35/frontengine/utils/reminder}/__init__.py +0 -0
  183. {frontengine-1.0.34/frontengine/utils/theme_schedule → frontengine-1.0.35/frontengine/utils/smart_pause}/__init__.py +0 -0
  184. {frontengine-1.0.34/frontengine/utils/weather → frontengine-1.0.35/frontengine/utils/system_stats}/__init__.py +0 -0
  185. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/system_stats/system_stats.py +0 -0
  186. {frontengine-1.0.34/frontengine/utils/workshop → frontengine-1.0.35/frontengine/utils/text_source}/__init__.py +0 -0
  187. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/text_source/text_source.py +0 -0
  188. {frontengine-1.0.34/frontengine/worker → frontengine-1.0.35/frontengine/utils/theme_schedule}/__init__.py +0 -0
  189. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/theme_schedule/theme_schedule_service.py +0 -0
  190. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/weather/weather_service.py +0 -0
  191. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/web_url.py +0 -0
  192. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/utils/workshop/workshop_content.py +0 -0
  193. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine/worker/qthread_worker.py +0 -0
  194. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine.egg-info/dependency_links.txt +0 -0
  195. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine.egg-info/entry_points.txt +0 -0
  196. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine.egg-info/requires.txt +0 -0
  197. {frontengine-1.0.34 → frontengine-1.0.35}/frontengine.egg-info/top_level.txt +0 -0
  198. {frontengine-1.0.34 → frontengine-1.0.35}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frontengine
3
- Version: 1.0.34
3
+ Version: 1.0.35
4
4
  Summary: FrontEngine is use-define frontview or only use like screen saver
5
5
  Author-email: JE-Chen <jechenmailman@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/Intergration-Automation-Testing/FrontEngine
@@ -8,6 +8,7 @@ from PySide6.QtWidgets import QWidget
8
8
  from frontengine.show.window_helpers import apply_overlay_window_flags, load_overlay_icon
9
9
  from frontengine.user_setting.user_setting_file import get_overlay_geometry, save_overlay_geometry
10
10
  from frontengine.utils.logging.loggin_instance import front_engine_logger
11
+ from frontengine.utils.power_mode.power_mode import DEFAULT_TIER, normalize_tier, tier_render_scale
11
12
 
12
13
 
13
14
  class BaseWidget(QWidget):
@@ -29,6 +30,9 @@ class BaseWidget(QWidget):
29
30
  # 綠幕背景色:設了就以不透明色填滿背景,方便 OBS 去背
30
31
  # Chroma key colour: fills the background opaquely so OBS can key it out.
31
32
  self.background_color: Optional[QColor] = None
33
+ # 畫質檔位:影響更新頻率上限與算圖縮放(見 utils/power_mode)
34
+ # Quality tier: caps the refresh rate and scales rendering (see utils/power_mode).
35
+ self.quality_tier: str = DEFAULT_TIER
32
36
  self._drag_origin = None
33
37
  self._geometry_restored = False
34
38
 
@@ -44,6 +48,27 @@ class BaseWidget(QWidget):
44
48
  front_engine_logger.info(f"{self.__class__.__name__} set_ui_variable | opacity: {opacity}")
45
49
  self.opacity = opacity
46
50
 
51
+ def set_quality_tier(self, tier: str) -> None:
52
+ """
53
+ 設定畫質檔位。基底類別只記下來並通知子類別,實際怎麼省由子類別決定
54
+ (例如放慢自己的計時器、用較低解析度算圖)。
55
+ Set the quality tier. The base class records it and tells the subclass;
56
+ what to actually give up - timer rate, render resolution - is the
57
+ subclass's call.
58
+ """
59
+ self.quality_tier = normalize_tier(tier)
60
+ front_engine_logger.info(
61
+ f"{self.__class__.__name__} set_quality_tier | tier: {self.quality_tier}")
62
+ self.apply_quality_tier()
63
+ self.update()
64
+
65
+ def apply_quality_tier(self) -> None:
66
+ """子類別覆寫這裡,把新的檔位套到自己的計時器/算圖上。"""
67
+
68
+ def render_scale(self) -> float:
69
+ """目前檔位的算圖縮放,1.0 表示原生解析度。"""
70
+ return tier_render_scale(self.quality_tier)
71
+
47
72
  def set_background_color(self, color) -> None:
48
73
  """
49
74
  設定綠幕背景色(傳 None 取消)。背景以不透明色填滿,內容再依原本的
@@ -0,0 +1,120 @@
1
+ """
2
+ 提示卡:在畫面上方短暫顯示一行字(提醒到期、規則觸發等),時間到自己關掉。
3
+ 點擊穿透,不會擋到底下的操作。
4
+
5
+ A toast: a line of text shown briefly near the top of the screen - a reminder
6
+ coming due, a rule firing - that closes itself. Click-through, so it never gets
7
+ in the way of what is underneath.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ from typing import Optional
12
+
13
+ from PySide6.QtCore import Qt, QTimer
14
+ from PySide6.QtGui import QColor, QFont, QFontMetrics, QGuiApplication, QPainter
15
+
16
+ from frontengine.show.base_widget import BaseWidget
17
+ from frontengine.utils.logging.loggin_instance import front_engine_logger
18
+
19
+ DEFAULT_DURATION_MS = 5000
20
+ MIN_DURATION_MS = 500
21
+ _PADDING = 18
22
+ _CORNER_RADIUS = 10
23
+
24
+
25
+ def clamp_duration(value, fallback: int = DEFAULT_DURATION_MS) -> int:
26
+ """顯示時間至少半秒,避免設成 0 讓提示閃一下就不見。"""
27
+ try:
28
+ return max(MIN_DURATION_MS, int(value))
29
+ except (TypeError, ValueError):
30
+ return fallback
31
+
32
+
33
+ class ToastWidget(BaseWidget):
34
+ """
35
+ 一張自動消失的提示卡。文字寬度決定卡片寬度,位置預設貼在主螢幕上方置中。
36
+ An auto-dismissing toast. The card is sized to its text and sits centred
37
+ near the top of the primary screen by default.
38
+ """
39
+
40
+ def __init__(self, message: str = "", duration_ms: int = DEFAULT_DURATION_MS,
41
+ font_size: int = 18) -> None:
42
+ front_engine_logger.info(f"[ToastWidget] Init | message={message!r}")
43
+ super().__init__()
44
+ self.message: str = str(message)
45
+ self.duration_ms: int = clamp_duration(duration_ms)
46
+ self.text_color = QColor("#ffffff")
47
+ self.card_color = QColor(20, 20, 20, 230)
48
+ self.opacity = 1.0
49
+ # 提示卡不該被拖曳擺位,也不接受點擊
50
+ # A toast is never dragged into place and never takes clicks.
51
+ self.overlay_lockable = False
52
+ self._font = QFont()
53
+ self._font.setPointSize(max(8, int(font_size)))
54
+ self._close_timer = QTimer(self)
55
+ self._close_timer.setSingleShot(True)
56
+ self._close_timer.timeout.connect(self.close)
57
+ self.set_ui_window_flag(show_on_bottom=False)
58
+ self.resize_to_message()
59
+
60
+ def set_message(self, message: str) -> None:
61
+ """換一則訊息並重新計算卡片大小。"""
62
+ self.message = str(message)
63
+ self.resize_to_message()
64
+ self.update()
65
+
66
+ def card_size(self) -> tuple:
67
+ """依文字算出卡片的寬高(含內距)。"""
68
+ metrics = QFontMetrics(self._font)
69
+ width = metrics.horizontalAdvance(self.message) + _PADDING * 2
70
+ height = metrics.height() + _PADDING
71
+ return (max(80, width), max(36, height))
72
+
73
+ def resize_to_message(self) -> None:
74
+ width, height = self.card_size()
75
+ self.resize(width, height)
76
+ self.move_to_top_centre()
77
+
78
+ def move_to_top_centre(self, screen=None) -> None:
79
+ """擺到螢幕上方置中(離頂端一小段距離,避開全螢幕程式的標題列)。"""
80
+ target = screen or QGuiApplication.primaryScreen()
81
+ if target is None: # pragma: no cover - no screen at all
82
+ return
83
+ available = target.availableGeometry()
84
+ self.move(
85
+ available.x() + (available.width() - self.width()) // 2,
86
+ available.y() + max(24, available.height() // 12),
87
+ )
88
+
89
+ def show_toast(self, screen=None) -> None:
90
+ """顯示並在時間到時自動關閉。"""
91
+ self.resize_to_message()
92
+ self.move_to_top_centre(screen)
93
+ self.show()
94
+ self._close_timer.start(self.duration_ms)
95
+
96
+ def draw_content(self, painter: QPainter) -> None:
97
+ painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
98
+ painter.setPen(Qt.PenStyle.NoPen)
99
+ painter.setBrush(self.card_color)
100
+ painter.drawRoundedRect(self.rect(), _CORNER_RADIUS, _CORNER_RADIUS)
101
+ painter.setFont(self._font)
102
+ painter.setPen(self.text_color)
103
+ painter.drawText(self.rect(), Qt.AlignmentFlag.AlignCenter, self.message)
104
+
105
+
106
+ def show_toast(message: str, duration_ms: int = DEFAULT_DURATION_MS,
107
+ screen=None) -> Optional[ToastWidget]:
108
+ """
109
+ 顯示一則提示卡並回傳它(訊息為空就不顯示,回傳 None)。呼叫端不必自己
110
+ 管生命週期:時間到會自己 close,而 BaseWidget 帶著 WA_DeleteOnClose。
111
+ Show a toast and hand it back (None for an empty message). Callers do not
112
+ have to manage its life: it closes itself, and BaseWidget carries
113
+ WA_DeleteOnClose.
114
+ """
115
+ text = str(message or "").strip()
116
+ if not text:
117
+ return None
118
+ toast = ToastWidget(text, duration_ms)
119
+ toast.show_toast(screen)
120
+ return toast
@@ -13,12 +13,13 @@ from __future__ import annotations
13
13
  from pathlib import Path
14
14
  from typing import Optional
15
15
 
16
- from PySide6.QtCore import QRect, QTimer
16
+ from PySide6.QtCore import QRect, Qt, QTimer
17
17
  from PySide6.QtGui import QMovie, QPainter, QPixmap
18
18
 
19
19
  from frontengine.show.base_widget import BaseWidget
20
20
  from frontengine.utils.audio_meter.audio_envelope import AudioEnvelope
21
21
  from frontengine.utils.logging.loggin_instance import front_engine_logger
22
+ from frontengine.utils.power_mode.power_mode import tier_interval
22
23
 
23
24
  _ANIMATED_SUFFIXES = (".gif", ".webp")
24
25
  MIN_REACT_SCALE = 1.0
@@ -105,12 +106,17 @@ class WallpaperWidget(BaseWidget):
105
106
  if strength is not None:
106
107
  self.react_strength = max(0, min(100, int(strength)))
107
108
  if self.audio_react:
108
- self._react_timer.start(self.REACT_INTERVAL_MS)
109
+ self._react_timer.start(tier_interval(self.REACT_INTERVAL_MS, self.quality_tier))
109
110
  else:
110
111
  self._react_timer.stop()
111
112
  self.scale = MIN_REACT_SCALE
112
113
  self.update()
113
114
 
115
+ def apply_quality_tier(self) -> None:
116
+ """畫質檔位改變時,跟著調整脈動的更新頻率(算圖縮放在繪製時套用)。"""
117
+ if self._react_timer.isActive():
118
+ self._react_timer.start(tier_interval(self.REACT_INTERVAL_MS, self.quality_tier))
119
+
114
120
  def _update_scale(self) -> None:
115
121
  """取一次音量、平滑後換成縮放比例。"""
116
122
  if not self.audio_react or self._level_provider is None:
@@ -141,6 +147,14 @@ class WallpaperWidget(BaseWidget):
141
147
  pixmap = self.current_pixmap()
142
148
  if pixmap is None or pixmap.isNull():
143
149
  return
150
+ # 低畫質檔位先把來源縮小再放大回來:算的像素少,看起來只是稍軟。
151
+ # Lower tiers shrink the source before scaling it back up: fewer pixels
152
+ # to push, at the cost of a slightly softer picture.
153
+ scale = self.render_scale()
154
+ if scale < 1.0:
155
+ pixmap = pixmap.scaled(
156
+ max(1, int(pixmap.width() * scale)), max(1, int(pixmap.height() * scale)),
157
+ Qt.AspectRatioMode.IgnoreAspectRatio, Qt.TransformationMode.FastTransformation)
144
158
  width = int(self.width() * self.scale)
145
159
  height = int(self.height() * self.scale)
146
160
  # 放大時往外溢出,維持置中,畫面才不會出現黑邊
@@ -0,0 +1,115 @@
1
+ """
2
+ 程式對應預設集:切到某個程式時自動套用一組覆蓋層設定(例如打開剪輯軟體
3
+ 就換成「工作」那組)。左欄填程式名稱,右欄挑一個已儲存的預設集。
4
+
5
+ Per-app profiles: apply a saved preset when a given app takes focus - the
6
+ "work" set when the editor comes up. The left column is the app name, the right
7
+ column picks one of your saved presets.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ from typing import Dict, Optional
12
+
13
+ from PySide6.QtWidgets import (
14
+ QAbstractItemView, QComboBox, QDialog, QDialogButtonBox, QGridLayout, QLabel, QPushButton,
15
+ QTableWidget, QTableWidgetItem, QWidget,
16
+ )
17
+
18
+ from frontengine.user_setting.preset_repository import PresetRepository
19
+ from frontengine.user_setting.user_setting_file import user_setting_dict, write_user_setting
20
+ from frontengine.utils.app_profile.app_profile_service import normalize_profiles
21
+ from frontengine.utils.logging.loggin_instance import front_engine_logger
22
+ from frontengine.utils.multi_language.language_wrapper import language_wrapper
23
+ from frontengine.utils.smart_pause.pause_rules import normalize_app_name
24
+
25
+
26
+ def _t(key: str, fallback: str) -> str:
27
+ return language_wrapper.language_word_dict.get(key, fallback)
28
+
29
+
30
+ def current_profiles() -> Dict[str, str]:
31
+ """目前設定裡的 {程式: 預設集} 對照表。"""
32
+ return normalize_profiles(user_setting_dict.get("app_profiles"))
33
+
34
+
35
+ class AppProfileDialog(QDialog):
36
+ """編輯「程式 → 預設集」對照表。"""
37
+
38
+ def __init__(self, parent: Optional[QWidget] = None) -> None:
39
+ front_engine_logger.info("[AppProfileDialog] Init")
40
+ super().__init__(parent)
41
+ self.setWindowTitle(_t("app_profile_title", "App profiles"))
42
+ self.presets = PresetRepository().list_presets()
43
+
44
+ self.table = QTableWidget(0, 2)
45
+ self.table.setHorizontalHeaderLabels([
46
+ _t("app_profile_app_column", "Application"),
47
+ _t("app_profile_preset_column", "Preset"),
48
+ ])
49
+ self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
50
+ self.table.horizontalHeader().setStretchLastSection(True)
51
+
52
+ self.add_button = QPushButton(_t("app_profile_add", "Add"))
53
+ self.add_button.clicked.connect(lambda: self.add_row("", ""))
54
+ self.remove_button = QPushButton(_t("app_profile_remove", "Remove"))
55
+ self.remove_button.clicked.connect(self.remove_selected_row)
56
+ self.hint_label = QLabel(
57
+ _t("app_profile_hint",
58
+ "Presets are saved from the Presets menu. Without any saved preset "
59
+ "there is nothing to apply."))
60
+ self.hint_label.setWordWrap(True)
61
+
62
+ self.button_box = QDialogButtonBox(
63
+ QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
64
+ self.button_box.accepted.connect(self.accept)
65
+ self.button_box.rejected.connect(self.reject)
66
+
67
+ layout = QGridLayout(self)
68
+ layout.addWidget(self.table, 0, 0, 1, 2)
69
+ layout.addWidget(self.add_button, 1, 0)
70
+ layout.addWidget(self.remove_button, 1, 1)
71
+ layout.addWidget(self.hint_label, 2, 0, 1, 2)
72
+ layout.addWidget(self.button_box, 3, 0, 1, 2)
73
+
74
+ for app, preset in current_profiles().items():
75
+ self.add_row(app, preset)
76
+
77
+ def add_row(self, app: str = "", preset: str = "") -> None:
78
+ """加一列(預設集下拉選單列出所有已儲存的預設集)。"""
79
+ row = self.table.rowCount()
80
+ self.table.insertRow(row)
81
+ self.table.setItem(row, 0, QTableWidgetItem(str(app)))
82
+ combobox = QComboBox()
83
+ combobox.addItems(self.presets)
84
+ # 設定裡指到已被刪掉的預設集時,仍把名稱留著讓使用者看得到
85
+ # Keep a name that points at a deleted preset visible instead of silently
86
+ # swapping it for another one.
87
+ if preset and preset not in self.presets:
88
+ combobox.addItem(str(preset))
89
+ if preset:
90
+ combobox.setCurrentText(str(preset))
91
+ self.table.setCellWidget(row, 1, combobox)
92
+
93
+ def remove_selected_row(self) -> None:
94
+ row = self.table.currentRow()
95
+ if row >= 0:
96
+ self.table.removeRow(row)
97
+
98
+ def profiles(self) -> Dict[str, str]:
99
+ """目前表格上的對照表(空白列會被略過)。"""
100
+ profiles: Dict[str, str] = {}
101
+ for row in range(self.table.rowCount()):
102
+ item = self.table.item(row, 0)
103
+ combobox = self.table.cellWidget(row, 1)
104
+ app = normalize_app_name(item.text() if item else "")
105
+ preset = combobox.currentText().strip() if combobox else ""
106
+ if app and preset:
107
+ profiles[app] = preset
108
+ return profiles
109
+
110
+ def accept(self) -> None:
111
+ profiles = self.profiles()
112
+ user_setting_dict["app_profiles"] = profiles
113
+ write_user_setting()
114
+ front_engine_logger.info(f"[AppProfileDialog] saved | {profiles}")
115
+ super().accept()
@@ -0,0 +1,139 @@
1
+ """
2
+ 自訂提醒設定:每隔一段時間提醒一次(喝水、起來走走),或每天在固定時間
3
+ 提醒一次(會議、吃藥)。提醒會以畫面上方的提示卡顯示。
4
+
5
+ Custom reminder settings: every N minutes (drink water, stand up) or once a day
6
+ at a set time (a meeting, a pill). Reminders appear as a toast near the top of
7
+ the screen.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ from typing import Any, Dict, List, Optional
12
+
13
+ from PySide6.QtCore import Qt
14
+ from PySide6.QtWidgets import (
15
+ QAbstractItemView, QComboBox, QDialog, QDialogButtonBox, QGridLayout, QLabel, QPushButton,
16
+ QTableWidget, QTableWidgetItem, QWidget,
17
+ )
18
+
19
+ from frontengine.user_setting.user_setting_file import user_setting_dict, write_user_setting
20
+ from frontengine.utils.logging.loggin_instance import front_engine_logger
21
+ from frontengine.utils.multi_language.language_wrapper import language_wrapper
22
+ from frontengine.utils.reminder.reminder_service import (
23
+ KIND_AT, KIND_EVERY, normalize_reminder, normalize_reminders,
24
+ )
25
+
26
+ _COLUMN_LABEL = 0
27
+ _COLUMN_KIND = 1
28
+ _COLUMN_VALUE = 2
29
+
30
+
31
+ def _t(key: str, fallback: str) -> str:
32
+ return language_wrapper.language_word_dict.get(key, fallback)
33
+
34
+
35
+ def current_reminders() -> List[Dict[str, Any]]:
36
+ """目前設定裡的提醒清單(壞掉的項目會被跳過)。"""
37
+ return normalize_reminders(user_setting_dict.get("reminders"))
38
+
39
+
40
+ class ReminderDialog(QDialog):
41
+ """編輯自訂提醒清單。"""
42
+
43
+ def __init__(self, parent: Optional[QWidget] = None) -> None:
44
+ front_engine_logger.info("[ReminderDialog] Init")
45
+ super().__init__(parent)
46
+ self.setWindowTitle(_t("reminder_title", "Reminders"))
47
+
48
+ self.table = QTableWidget(0, 3)
49
+ self.table.setHorizontalHeaderLabels([
50
+ _t("reminder_label_column", "Reminder"),
51
+ _t("reminder_kind_column", "When"),
52
+ _t("reminder_value_column", "Minutes / time"),
53
+ ])
54
+ self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
55
+ self.table.horizontalHeader().setStretchLastSection(True)
56
+
57
+ self.add_button = QPushButton(_t("reminder_add", "Add"))
58
+ self.add_button.clicked.connect(lambda: self.add_row())
59
+ self.remove_button = QPushButton(_t("reminder_remove", "Remove"))
60
+ self.remove_button.clicked.connect(self.remove_selected_row)
61
+ self.hint_label = QLabel(
62
+ _t("reminder_hint",
63
+ "Tick a row to keep it active. \"Every\" takes minutes, \"At\" takes a "
64
+ "24-hour time such as 14:30."))
65
+ self.hint_label.setWordWrap(True)
66
+
67
+ self.button_box = QDialogButtonBox(
68
+ QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
69
+ self.button_box.accepted.connect(self.accept)
70
+ self.button_box.rejected.connect(self.reject)
71
+
72
+ layout = QGridLayout(self)
73
+ layout.addWidget(self.table, 0, 0, 1, 2)
74
+ layout.addWidget(self.add_button, 1, 0)
75
+ layout.addWidget(self.remove_button, 1, 1)
76
+ layout.addWidget(self.hint_label, 2, 0, 1, 2)
77
+ layout.addWidget(self.button_box, 3, 0, 1, 2)
78
+
79
+ for reminder in current_reminders():
80
+ self.add_row(reminder)
81
+
82
+ def add_row(self, reminder: Optional[Dict[str, Any]] = None) -> None:
83
+ """加一列;沒給資料就給一筆空白的「每 45 分鐘」。"""
84
+ entry = reminder or {"label": "", "kind": KIND_EVERY, "minutes": 45, "enabled": True}
85
+ row = self.table.rowCount()
86
+ self.table.insertRow(row)
87
+
88
+ label_item = QTableWidgetItem(str(entry.get("label", "")))
89
+ label_item.setFlags(label_item.flags() | Qt.ItemFlag.ItemIsUserCheckable)
90
+ label_item.setCheckState(Qt.CheckState.Checked if entry.get("enabled", True)
91
+ else Qt.CheckState.Unchecked)
92
+ self.table.setItem(row, _COLUMN_LABEL, label_item)
93
+
94
+ kind_combobox = QComboBox()
95
+ kind_combobox.addItem(_t("reminder_kind_every", "Every"), KIND_EVERY)
96
+ kind_combobox.addItem(_t("reminder_kind_at", "At"), KIND_AT)
97
+ kind_index = kind_combobox.findData(entry.get("kind", KIND_EVERY))
98
+ kind_combobox.setCurrentIndex(max(0, kind_index))
99
+ self.table.setCellWidget(row, _COLUMN_KIND, kind_combobox)
100
+
101
+ value = entry.get("at") if entry.get("kind") == KIND_AT else entry.get("minutes", 45)
102
+ self.table.setItem(row, _COLUMN_VALUE, QTableWidgetItem(str(value)))
103
+
104
+ def remove_selected_row(self) -> None:
105
+ row = self.table.currentRow()
106
+ if row >= 0:
107
+ self.table.removeRow(row)
108
+
109
+ def _row_entry(self, row: int) -> Optional[Dict[str, Any]]:
110
+ label_item = self.table.item(row, _COLUMN_LABEL)
111
+ value_item = self.table.item(row, _COLUMN_VALUE)
112
+ kind_combobox = self.table.cellWidget(row, _COLUMN_KIND)
113
+ if label_item is None or kind_combobox is None:
114
+ return None
115
+ kind = kind_combobox.currentData()
116
+ value = value_item.text().strip() if value_item else ""
117
+ entry = {
118
+ "label": label_item.text().strip(),
119
+ "kind": kind,
120
+ "enabled": label_item.checkState() == Qt.CheckState.Checked,
121
+ }
122
+ entry["at" if kind == KIND_AT else "minutes"] = value
123
+ return normalize_reminder(entry)
124
+
125
+ def reminders(self) -> List[Dict[str, Any]]:
126
+ """目前表格上的提醒(格式不對的列會被略過)。"""
127
+ reminders = []
128
+ for row in range(self.table.rowCount()):
129
+ entry = self._row_entry(row)
130
+ if entry is not None:
131
+ reminders.append(entry)
132
+ return reminders
133
+
134
+ def accept(self) -> None:
135
+ reminders = self.reminders()
136
+ user_setting_dict["reminders"] = reminders
137
+ write_user_setting()
138
+ front_engine_logger.info(f"[ReminderDialog] saved | {len(reminders)} reminder(s)")
139
+ super().accept()
@@ -0,0 +1,87 @@
1
+ """
2
+ 智慧暫停設定:決定什麼時候該把覆蓋層暫時收起來——全螢幕程式在前景、
3
+ 改用電池供電,或指定的程式取得焦點。
4
+
5
+ Smart-pause settings: when should the overlays stand down - a fullscreen app in
6
+ front, the machine on battery, or one of your own apps taking focus.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ from typing import Any, Dict, Optional
11
+
12
+ from PySide6.QtWidgets import (
13
+ QCheckBox, QDialog, QDialogButtonBox, QGridLayout, QLabel, QLineEdit, QWidget,
14
+ )
15
+
16
+ from frontengine.user_setting.user_setting_file import user_setting_dict, write_user_setting
17
+ from frontengine.utils.logging.loggin_instance import front_engine_logger
18
+ from frontengine.utils.multi_language.language_wrapper import language_wrapper
19
+ from frontengine.utils.smart_pause.pause_rules import DEFAULT_RULES, parse_app_list
20
+
21
+
22
+ def _t(key: str, fallback: str) -> str:
23
+ return language_wrapper.language_word_dict.get(key, fallback)
24
+
25
+
26
+ def current_rules() -> Dict[str, Any]:
27
+ """從設定讀出目前的暫停規則(缺項目就補上預設值)。"""
28
+ stored = user_setting_dict.get("smart_pause_rules")
29
+ rules = dict(DEFAULT_RULES)
30
+ if isinstance(stored, dict):
31
+ rules.update({key: stored[key] for key in DEFAULT_RULES if key in stored})
32
+ rules["apps"] = parse_app_list(rules.get("apps"))
33
+ return rules
34
+
35
+
36
+ class SmartPauseDialog(QDialog):
37
+ """讓使用者挑選哪些情況要暫停覆蓋層。"""
38
+
39
+ def __init__(self, parent: Optional[QWidget] = None) -> None:
40
+ front_engine_logger.info("[SmartPauseDialog] Init")
41
+ super().__init__(parent)
42
+ self.setWindowTitle(_t("smart_pause_title", "Smart pause"))
43
+ rules = current_rules()
44
+
45
+ self.fullscreen_checkbox = QCheckBox(
46
+ _t("smart_pause_fullscreen", "Pause while a fullscreen app is running"))
47
+ self.fullscreen_checkbox.setChecked(bool(rules.get("fullscreen", True)))
48
+ self.battery_checkbox = QCheckBox(
49
+ _t("smart_pause_battery", "Pause while running on battery"))
50
+ self.battery_checkbox.setChecked(bool(rules.get("battery", False)))
51
+ self.apps_label = QLabel(
52
+ _t("smart_pause_apps_label", "Pause while these apps have focus:"))
53
+ self.apps_edit = QLineEdit(", ".join(rules.get("apps", [])))
54
+ self.apps_edit.setPlaceholderText("photoshop, premiere, blender")
55
+ self.hint_label = QLabel(
56
+ _t("smart_pause_hint",
57
+ "Names are matched without the folder or .exe, so \"photoshop\" is enough."))
58
+ self.hint_label.setWordWrap(True)
59
+
60
+ self.button_box = QDialogButtonBox(
61
+ QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
62
+ self.button_box.accepted.connect(self.accept)
63
+ self.button_box.rejected.connect(self.reject)
64
+
65
+ layout = QGridLayout(self)
66
+ layout.addWidget(self.fullscreen_checkbox, 0, 0, 1, 2)
67
+ layout.addWidget(self.battery_checkbox, 1, 0, 1, 2)
68
+ layout.addWidget(self.apps_label, 2, 0, 1, 2)
69
+ layout.addWidget(self.apps_edit, 3, 0, 1, 2)
70
+ layout.addWidget(self.hint_label, 4, 0, 1, 2)
71
+ layout.addWidget(self.button_box, 5, 0, 1, 2)
72
+
73
+ def rules(self) -> Dict[str, Any]:
74
+ """目前對話框上的規則。"""
75
+ return {
76
+ "fullscreen": self.fullscreen_checkbox.isChecked(),
77
+ "battery": self.battery_checkbox.isChecked(),
78
+ "apps": parse_app_list(self.apps_edit.text()),
79
+ }
80
+
81
+ def accept(self) -> None:
82
+ """寫回設定;服務每次輪詢都會重讀,不需要重啟。"""
83
+ rules = self.rules()
84
+ user_setting_dict["smart_pause_rules"] = rules
85
+ write_user_setting()
86
+ front_engine_logger.info(f"[SmartPauseDialog] saved | {rules}")
87
+ super().accept()