frontengine 1.0.64__tar.gz → 1.0.66__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.
- {frontengine-1.0.64 → frontengine-1.0.66}/PKG-INFO +1 -1
- frontengine-1.0.66/frontengine/show/replica/replica_widget.py +118 -0
- frontengine-1.0.66/frontengine/ui/dialog/screensaver_dialog.py +113 -0
- frontengine-1.0.66/frontengine/ui/dialog/window_replica_dialog.py +124 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/main_ui.py +85 -1
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/menu/settings_menu.py +7 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/tools/tools_setting_ui.py +22 -1
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/multi_language/english.py +13 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/multi_language/france.py +13 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/multi_language/germany.py +13 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/multi_language/italy.py +13 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/multi_language/russian.py +13 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/multi_language/simplified_chinese.py +13 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/multi_language/traditional_chinese.py +13 -0
- frontengine-1.0.66/frontengine/utils/screensaver/screensaver_service.py +177 -0
- frontengine-1.0.66/frontengine/utils/window_pin/__init__.py +0 -0
- frontengine-1.0.66/frontengine/utils/window_replica/__init__.py +0 -0
- frontengine-1.0.66/frontengine/utils/window_replica/dwm_thumbnail.py +189 -0
- frontengine-1.0.66/frontengine/utils/workshop/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine.egg-info/PKG-INFO +1 -1
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine.egg-info/SOURCES.txt +8 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/pyproject.toml +1 -1
- {frontengine-1.0.64 → frontengine-1.0.66}/LICENSE +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/README.md +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/__main__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/base_widget.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/camera/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/camera/camera_widget.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/canvas/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/canvas/whiteboard_widget.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/capture/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/capture/region_capture.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/focus_shield/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/focus_shield/focus_shield_widget.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/gif/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/gif/paint_gif.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/image/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/image/paint_image.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/load/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/load/load_someone_make_ui.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/measure/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/measure/measure_widget.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/monitor/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/monitor/monitor_widget.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/notes/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/notes/sticky_note_widget.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/overlay_factory.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/particle/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/particle/particle_ui.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/pet/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/pet/desktop_pet.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/presentation/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/presentation/annotation_overlay.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/presentation/cursor_effects.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/presentation/keystroke_display.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/presentation/magnifier.py +0 -0
- {frontengine-1.0.64/frontengine/show/scene → frontengine-1.0.66/frontengine/show/replica}/__init__.py +0 -0
- {frontengine-1.0.64/frontengine/show/screen_care → frontengine-1.0.66/frontengine/show/scene}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/scene/extend_graphic_scene.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/scene/extend_graphic_view.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/scene/scene.py +0 -0
- {frontengine-1.0.64/frontengine/show/sound_player → frontengine-1.0.66/frontengine/show/screen_care}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/screen_care/color_vision_widget.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/screen_care/screen_filter.py +0 -0
- {frontengine-1.0.64/frontengine/show/spectrum → frontengine-1.0.66/frontengine/show/sound_player}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/sound_player/sound_effect.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/sound_player/sound_player.py +0 -0
- {frontengine-1.0.64/frontengine/show/text → frontengine-1.0.66/frontengine/show/spectrum}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/spectrum/spectrum_widget.py +0 -0
- {frontengine-1.0.64/frontengine/show/toast → frontengine-1.0.66/frontengine/show/text}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/text/draw_text.py +0 -0
- {frontengine-1.0.64/frontengine/show/video → frontengine-1.0.66/frontengine/show/toast}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/toast/toast_widget.py +0 -0
- {frontengine-1.0.64/frontengine/show/wallpaper → frontengine-1.0.66/frontengine/show/video}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/video/video_player.py +0 -0
- {frontengine-1.0.64/frontengine/show/web → frontengine-1.0.66/frontengine/show/wallpaper}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/wallpaper/wallpaper_widget.py +0 -0
- {frontengine-1.0.64/frontengine/system_tray → frontengine-1.0.66/frontengine/show/web}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/web/webview.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/show/window_helpers.py +0 -0
- {frontengine-1.0.64/frontengine/ui → frontengine-1.0.66/frontengine/system_tray}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/system_tray/extend_system_tray.py +0 -0
- {frontengine-1.0.64/frontengine/ui/color → frontengine-1.0.66/frontengine/ui}/__init__.py +0 -0
- {frontengine-1.0.64/frontengine/ui/dialog → frontengine-1.0.66/frontengine/ui/color}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/color/global_color.py +0 -0
- {frontengine-1.0.64/frontengine/ui/menu → frontengine-1.0.66/frontengine/ui/dialog}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/app_profile_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/choose_file_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/clipboard_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/hotkey_settings_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/how_to_use_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/reminder_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/remote_control_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/screen_privacy_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/screen_text_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/signage_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/smart_pause_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/usage_report_dialog.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/dialog/window_pin_dialog.py +0 -0
- {frontengine-1.0.64/frontengine/ui/nav → frontengine-1.0.66/frontengine/ui/menu}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/menu/help_menu.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/menu/how_to_menu.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/menu/language_menu.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/menu/preset_menu.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page → frontengine-1.0.66/frontengine/ui/nav}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/nav/sidebar.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/control_center → frontengine-1.0.66/frontengine/ui/page}/__init__.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/focus → frontengine-1.0.66/frontengine/ui/page/control_center}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/control_center/control_center_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/gif → frontengine-1.0.66/frontengine/ui/page/focus}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/focus/focus_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/image → frontengine-1.0.66/frontengine/ui/page/gif}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/gif/gif_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/particle → frontengine-1.0.66/frontengine/ui/page/image}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/image/image_setting_ui.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/layout_kit.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/pet → frontengine-1.0.66/frontengine/ui/page/particle}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/particle/particle_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/presentation → frontengine-1.0.66/frontengine/ui/page/pet}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/pet/pet_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/scene_setting → frontengine-1.0.66/frontengine/ui/page/presentation}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/presentation/presentation_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/scene_setting/scene_page → frontengine-1.0.66/frontengine/ui/page/scene_setting}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/scene_setting/scene_manager.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/screen_care → frontengine-1.0.66/frontengine/ui/page/scene_setting/scene_page}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/scene_setting/scene_page/base_scene_page.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/scene_setting/scene_page/gif.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/scene_setting/scene_page/image.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/scene_setting/scene_page/registry.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/scene_setting/scene_page/sound.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/scene_setting/scene_page/text.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/scene_setting/scene_page/video.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/scene_setting/scene_page/web.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/scene_setting/scene_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/sound_player → frontengine-1.0.66/frontengine/ui/page/screen_care}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/screen_care/screen_care_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/text → frontengine-1.0.66/frontengine/ui/page/sound_player}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/sound_player/sound_player_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/tools → frontengine-1.0.66/frontengine/ui/page/text}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/text/text_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/video → frontengine-1.0.66/frontengine/ui/page/tools}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/utils.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/wallpaper → frontengine-1.0.66/frontengine/ui/page/video}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/video/video_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/web → frontengine-1.0.66/frontengine/ui/page/wallpaper}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/wallpaper/wallpaper_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/page/widgets → frontengine-1.0.66/frontengine/ui/page/web}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/web/web_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/ui/style → frontengine-1.0.66/frontengine/ui/page/widgets}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/page/widgets/widgets_setting_ui.py +0 -0
- {frontengine-1.0.64/frontengine/user_setting → frontengine-1.0.66/frontengine/ui/style}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/ui/style/app_style.py +0 -0
- {frontengine-1.0.64/frontengine/utils → frontengine-1.0.66/frontengine/user_setting}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/user_setting/preset_repository.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/user_setting/scene_setting.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/user_setting/user_setting_file.py +0 -0
- {frontengine-1.0.64/frontengine/utils/app_profile → frontengine-1.0.66/frontengine/utils}/__init__.py +0 -0
- {frontengine-1.0.64/frontengine/utils/audio_meter → frontengine-1.0.66/frontengine/utils/app_profile}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/app_profile/app_profile_service.py +0 -0
- {frontengine-1.0.64/frontengine/utils/autostart → frontengine-1.0.66/frontengine/utils/audio_meter}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/audio_meter/audio_envelope.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/audio_meter/loopback_capture.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/audio_meter/microphone_meter.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/audio_meter/screen_audio.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/audio_meter/spectrum_analyzer.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/audio_meter/system_audio_meter.py +0 -0
- {frontengine-1.0.64/frontengine/utils/break_reminder → frontengine-1.0.66/frontengine/utils/autostart}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/autostart/autostart_service.py +0 -0
- {frontengine-1.0.64/frontengine/utils/browser → frontengine-1.0.66/frontengine/utils/break_reminder}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/break_reminder/break_reminder.py +0 -0
- {frontengine-1.0.64/frontengine/utils/clipboard → frontengine-1.0.66/frontengine/utils/browser}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/browser/browser.py +0 -0
- {frontengine-1.0.64/frontengine/utils/color_vision → frontengine-1.0.66/frontengine/utils/clipboard}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/clipboard/clipboard_history.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/clipboard/clipboard_watcher.py +0 -0
- {frontengine-1.0.64/frontengine/utils/critical_exit → frontengine-1.0.66/frontengine/utils/color_vision}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/color_vision/color_vision.py +0 -0
- {frontengine-1.0.64/frontengine/utils/focus_shield → frontengine-1.0.66/frontengine/utils/critical_exit}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/critical_exit/check_key_is_press.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/critical_exit/critical_exit.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/critical_exit/win32_vk.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/exception/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/exception/exception_tags.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/exception/exceptions.py +0 -0
- {frontengine-1.0.64/frontengine/utils/focus_timer → frontengine-1.0.66/frontengine/utils/focus_shield}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/focus_shield/focus_shield.py +0 -0
- {frontengine-1.0.64/frontengine/utils/hotkey → frontengine-1.0.66/frontengine/utils/focus_timer}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/focus_timer/focus_timer.py +0 -0
- {frontengine-1.0.64/frontengine/utils/input_watch → frontengine-1.0.66/frontengine/utils/hotkey}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/hotkey/hotkey_service.py +0 -0
- {frontengine-1.0.64/frontengine/utils/json → frontengine-1.0.66/frontengine/utils/input_watch}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/input_watch/input_watch_service.py +0 -0
- {frontengine-1.0.64/frontengine/utils/logging → frontengine-1.0.66/frontengine/utils/json}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/json/json_file.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/json/json_repository.py +0 -0
- {frontengine-1.0.64/frontengine/utils/measure → frontengine-1.0.66/frontengine/utils/logging}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/logging/loggin_instance.py +0 -0
- {frontengine-1.0.64/frontengine/utils/midi → frontengine-1.0.66/frontengine/utils/measure}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/measure/measure.py +0 -0
- {frontengine-1.0.64/frontengine/utils/multi_language → frontengine-1.0.66/frontengine/utils/midi}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/midi/midi_input.py +0 -0
- {frontengine-1.0.64/frontengine/utils/now_playing → frontengine-1.0.66/frontengine/utils/multi_language}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/multi_language/language_wrapper.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/multi_language/retranslate.py +0 -0
- {frontengine-1.0.64/frontengine/utils/pet_chat → frontengine-1.0.66/frontengine/utils/now_playing}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/now_playing/now_playing.py +0 -0
- {frontengine-1.0.64/frontengine/utils/platform_info → frontengine-1.0.66/frontengine/utils/pet_chat}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/pet_chat/pet_chat_service.py +0 -0
- {frontengine-1.0.64/frontengine/utils/playlist → frontengine-1.0.66/frontengine/utils/platform_info}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/platform_info/platform_info.py +0 -0
- {frontengine-1.0.64/frontengine/utils/plugins → frontengine-1.0.66/frontengine/utils/playlist}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/playlist/playlist.py +0 -0
- {frontengine-1.0.64/frontengine/utils/power_mode → frontengine-1.0.66/frontengine/utils/plugins}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/plugins/plugin_loader.py +0 -0
- {frontengine-1.0.64/frontengine/utils/preset_schedule → frontengine-1.0.66/frontengine/utils/power_mode}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/power_mode/power_mode.py +0 -0
- {frontengine-1.0.64/frontengine/utils/recording → frontengine-1.0.66/frontengine/utils/preset_schedule}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/preset_schedule/preset_schedule_service.py +0 -0
- {frontengine-1.0.64/frontengine/utils/redirect_manager → frontengine-1.0.66/frontengine/utils/recording}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/recording/frame_recorder.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/recording/gif_writer.py +0 -0
- {frontengine-1.0.64/frontengine/utils/reminder → frontengine-1.0.66/frontengine/utils/redirect_manager}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/redirect_manager/redirect_manager_class.py +0 -0
- {frontengine-1.0.64/frontengine/utils/remote → frontengine-1.0.66/frontengine/utils/reminder}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/reminder/reminder_service.py +0 -0
- {frontengine-1.0.64/frontengine/utils/screen_privacy → frontengine-1.0.66/frontengine/utils/remote}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/remote/remote_server.py +0 -0
- {frontengine-1.0.64/frontengine/utils/screen_text → frontengine-1.0.66/frontengine/utils/screen_privacy}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/screen_privacy/capture_affinity.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/screen_privacy/share_watch.py +0 -0
- {frontengine-1.0.64/frontengine/utils/signage → frontengine-1.0.66/frontengine/utils/screen_text}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/screen_text/screen_text_service.py +0 -0
- {frontengine-1.0.64/frontengine/utils/smart_pause → frontengine-1.0.66/frontengine/utils/screensaver}/__init__.py +0 -0
- {frontengine-1.0.64/frontengine/utils/steam → frontengine-1.0.66/frontengine/utils/signage}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/signage/signage_service.py +0 -0
- {frontengine-1.0.64/frontengine/utils/system_stats → frontengine-1.0.66/frontengine/utils/smart_pause}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/smart_pause/pause_rules.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/smart_pause/smart_pause_service.py +0 -0
- {frontengine-1.0.64/frontengine/utils/text_source → frontengine-1.0.66/frontengine/utils/steam}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/steam/steam_language.py +0 -0
- {frontengine-1.0.64/frontengine/utils/theme_schedule → frontengine-1.0.66/frontengine/utils/system_stats}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/system_stats/system_stats.py +0 -0
- {frontengine-1.0.64/frontengine/utils/usage_tracking → frontengine-1.0.66/frontengine/utils/text_source}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/text_source/text_source.py +0 -0
- {frontengine-1.0.64/frontengine/utils/virtual_camera → frontengine-1.0.66/frontengine/utils/theme_schedule}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/theme_schedule/theme_schedule_service.py +0 -0
- {frontengine-1.0.64/frontengine/utils/weather → frontengine-1.0.66/frontengine/utils/usage_tracking}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/usage_tracking/usage_service.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/usage_tracking/usage_tracker.py +0 -0
- {frontengine-1.0.64/frontengine/utils/window_pin → frontengine-1.0.66/frontengine/utils/virtual_camera}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/virtual_camera/camera_feed.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/virtual_camera/virtual_camera.py +0 -0
- {frontengine-1.0.64/frontengine/utils/workshop → frontengine-1.0.66/frontengine/utils/weather}/__init__.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/weather/weather_service.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/web_url.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/window_pin/window_layout.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/window_pin/window_pin.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine/utils/workshop/workshop_content.py +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine.egg-info/dependency_links.txt +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine.egg-info/entry_points.txt +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine.egg-info/requires.txt +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/frontengine.egg-info/top_level.txt +0 -0
- {frontengine-1.0.64 → frontengine-1.0.66}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frontengine
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.66
|
|
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
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""
|
|
2
|
+
視窗複本覆蓋層:一個小視窗,裡面是另一個視窗的即時畫面。
|
|
3
|
+
|
|
4
|
+
和其他覆蓋層不同,這一個**不能點擊穿透**:使用者要能把它拖到順手的位置、拉大縮小、
|
|
5
|
+
關掉。所以它是一個可以拖曳的無邊框視窗,而不是一層蓋在畫面上的東西。
|
|
6
|
+
|
|
7
|
+
A window replica overlay: a small window showing another window, live.
|
|
8
|
+
|
|
9
|
+
Unlike the other overlays this one must **not** pass clicks through: the user has
|
|
10
|
+
to be able to drag it somewhere convenient, resize it and close it. So it is a
|
|
11
|
+
draggable frameless window rather than a sheet laid over the screen.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from typing import Optional
|
|
16
|
+
|
|
17
|
+
from PySide6.QtCore import QPoint, Qt
|
|
18
|
+
from PySide6.QtGui import QColor, QPainter
|
|
19
|
+
from PySide6.QtWidgets import QWidget
|
|
20
|
+
|
|
21
|
+
from frontengine.utils.logging.loggin_instance import front_engine_logger
|
|
22
|
+
from frontengine.utils.window_replica.dwm_thumbnail import (
|
|
23
|
+
DEFAULT_REPLICA_WIDTH, MIN_REPLICA_SIZE, DwmThumbnail, available, fit_within,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class WindowReplicaWidget(QWidget):
|
|
28
|
+
"""顯示另一個視窗即時畫面的小視窗。"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, source_handle: int, title: str = "",
|
|
31
|
+
opacity_percent: int = 100, parent: Optional[QWidget] = None) -> None:
|
|
32
|
+
front_engine_logger.info(f"[WindowReplicaWidget] Init | source={source_handle}")
|
|
33
|
+
super().__init__(parent)
|
|
34
|
+
self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
|
|
35
|
+
self.setWindowFlags(
|
|
36
|
+
Qt.WindowType.FramelessWindowHint
|
|
37
|
+
| Qt.WindowType.WindowStaysOnTopHint
|
|
38
|
+
| Qt.WindowType.Tool)
|
|
39
|
+
self.setWindowTitle(title or "FrontEngine")
|
|
40
|
+
self.setMinimumSize(MIN_REPLICA_SIZE, MIN_REPLICA_SIZE)
|
|
41
|
+
|
|
42
|
+
self.source_handle = int(source_handle)
|
|
43
|
+
self.source_title = title
|
|
44
|
+
self.opacity_percent = max(1, min(100, int(opacity_percent)))
|
|
45
|
+
self.thumbnail = DwmThumbnail()
|
|
46
|
+
self._drag_origin: Optional[QPoint] = None
|
|
47
|
+
|
|
48
|
+
self.resize(DEFAULT_REPLICA_WIDTH, int(DEFAULT_REPLICA_WIDTH * 9 / 16))
|
|
49
|
+
|
|
50
|
+
def start(self) -> bool:
|
|
51
|
+
"""
|
|
52
|
+
接上來源視窗並依它的長寬比調整大小。接不上就回 False,呼叫端不要把一個
|
|
53
|
+
空視窗留在畫面上。
|
|
54
|
+
Attach to the source and take its aspect ratio. False when it could not
|
|
55
|
+
attach, so the caller does not leave an empty window on screen.
|
|
56
|
+
"""
|
|
57
|
+
if not available():
|
|
58
|
+
front_engine_logger.info("[WindowReplicaWidget] not supported on this platform")
|
|
59
|
+
return False
|
|
60
|
+
# 縮圖要接在「這個視窗的 handle」上,所以必須先讓它有 handle。
|
|
61
|
+
# The thumbnail attaches to this window's handle, so it needs one first.
|
|
62
|
+
self.show()
|
|
63
|
+
if not self.thumbnail.register(int(self.winId()), self.source_handle):
|
|
64
|
+
return False
|
|
65
|
+
source_size = self.thumbnail.source_size()
|
|
66
|
+
width, height = fit_within(source_size, (DEFAULT_REPLICA_WIDTH,
|
|
67
|
+
int(DEFAULT_REPLICA_WIDTH * 9 / 16)))
|
|
68
|
+
self.resize(width, height)
|
|
69
|
+
self._refresh()
|
|
70
|
+
return True
|
|
71
|
+
|
|
72
|
+
def _refresh(self) -> None:
|
|
73
|
+
self.thumbnail.update(self.width(), self.height(),
|
|
74
|
+
opacity=int(self.opacity_percent * 255 / 100))
|
|
75
|
+
|
|
76
|
+
def set_opacity_percent(self, percent: int) -> None:
|
|
77
|
+
self.opacity_percent = max(1, min(100, int(percent)))
|
|
78
|
+
self._refresh()
|
|
79
|
+
|
|
80
|
+
def resizeEvent(self, event) -> None:
|
|
81
|
+
super().resizeEvent(event)
|
|
82
|
+
self._refresh()
|
|
83
|
+
|
|
84
|
+
def paintEvent(self, event) -> None:
|
|
85
|
+
# DWM 把縮圖合成上來之前,先鋪一層不透明底色。少了這一步,來源還沒畫上來的
|
|
86
|
+
# 那一瞬間會透出後面的東西,看起來像破圖。
|
|
87
|
+
# An opaque backing before DWM composites the thumbnail. Without it the
|
|
88
|
+
# moment before the source arrives shows whatever is behind, which reads
|
|
89
|
+
# as a rendering fault.
|
|
90
|
+
painter = QPainter(self)
|
|
91
|
+
painter.fillRect(self.rect(), QColor(0, 0, 0))
|
|
92
|
+
|
|
93
|
+
def mousePressEvent(self, event) -> None:
|
|
94
|
+
if event.button() == Qt.MouseButton.LeftButton:
|
|
95
|
+
self._drag_origin = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
|
|
96
|
+
event.accept()
|
|
97
|
+
|
|
98
|
+
def mouseMoveEvent(self, event) -> None:
|
|
99
|
+
if self._drag_origin is not None and event.buttons() & Qt.MouseButton.LeftButton:
|
|
100
|
+
self.move(event.globalPosition().toPoint() - self._drag_origin)
|
|
101
|
+
event.accept()
|
|
102
|
+
|
|
103
|
+
def mouseReleaseEvent(self, event) -> None:
|
|
104
|
+
self._drag_origin = None
|
|
105
|
+
event.accept()
|
|
106
|
+
|
|
107
|
+
def mouseDoubleClickEvent(self, event) -> None:
|
|
108
|
+
"""雙擊關掉——沒有標題列,總得有一個看得懂的出口。"""
|
|
109
|
+
self.close()
|
|
110
|
+
event.accept()
|
|
111
|
+
|
|
112
|
+
def closeEvent(self, event) -> None:
|
|
113
|
+
# 縮圖是系統資源,視窗沒了也不會自己消失。從標題列以外的任何路徑關閉時
|
|
114
|
+
# closeEvent 是唯一會被呼叫到的地方,所以收尾放這裡。
|
|
115
|
+
# The thumbnail is a system resource and does not go away with the
|
|
116
|
+
# window. closeEvent is the one place every close path reaches.
|
|
117
|
+
self.thumbnail.unregister()
|
|
118
|
+
super().closeEvent(event)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""
|
|
2
|
+
螢幕保護設定:閒置多久之後,把哪一頁的覆蓋層放上來。
|
|
3
|
+
|
|
4
|
+
Screensaver settings: how long idle, and which page's overlay to put on screen.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any, Dict, Optional
|
|
9
|
+
|
|
10
|
+
from PySide6.QtWidgets import (
|
|
11
|
+
QCheckBox, QComboBox, QDialog, QDialogButtonBox, QGridLayout, QLabel, QSpinBox, QWidget,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from frontengine.user_setting.user_setting_file import user_setting_dict, write_user_setting
|
|
15
|
+
from frontengine.utils.logging.loggin_instance import front_engine_logger
|
|
16
|
+
from frontengine.utils.multi_language.language_wrapper import language_wrapper
|
|
17
|
+
from frontengine.utils.multi_language.retranslate import tr
|
|
18
|
+
from frontengine.utils.screensaver.screensaver_service import (
|
|
19
|
+
DEFAULT_SCREENSAVER, MAX_IDLE_MINUTES, MIN_IDLE_MINUTES, SOURCES, clamp_idle_minutes,
|
|
20
|
+
normalize_source,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
SETTING_KEY = "screensaver"
|
|
24
|
+
|
|
25
|
+
# 下拉選單的文字用各分頁既有的鍵,省得同一個詞在七種語言裡再翻一次。
|
|
26
|
+
# The dropdown reuses each page's existing key rather than translating the same
|
|
27
|
+
# word a second time in seven languages.
|
|
28
|
+
SOURCE_LABEL_KEYS = {
|
|
29
|
+
"video": ("tab_video_text", "Video"),
|
|
30
|
+
"image": ("tab_image_text", "Image"),
|
|
31
|
+
"gif": ("tab_gif_text", "GIF and WEBP"),
|
|
32
|
+
"particle": ("tab_particle_text", "Particle"),
|
|
33
|
+
"web": ("tab_web_text", "Web"),
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _t(key: str, fallback: str) -> str:
|
|
38
|
+
return language_wrapper.language_word_dict.get(key, fallback)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def current_settings() -> Dict[str, Any]:
|
|
42
|
+
"""目前的螢幕保護設定(缺項目補預設值)。"""
|
|
43
|
+
stored = user_setting_dict.get(SETTING_KEY)
|
|
44
|
+
settings = dict(DEFAULT_SCREENSAVER)
|
|
45
|
+
if isinstance(stored, dict):
|
|
46
|
+
settings.update({key: stored[key] for key in DEFAULT_SCREENSAVER if key in stored})
|
|
47
|
+
settings["idle_minutes"] = clamp_idle_minutes(settings.get("idle_minutes"))
|
|
48
|
+
settings["source"] = normalize_source(settings.get("source"))
|
|
49
|
+
settings["enabled"] = bool(settings.get("enabled"))
|
|
50
|
+
return settings
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class ScreensaverDialog(QDialog):
|
|
54
|
+
"""設定閒置多久、顯示哪一頁。"""
|
|
55
|
+
|
|
56
|
+
def __init__(self, parent: Optional[QWidget] = None) -> None:
|
|
57
|
+
front_engine_logger.info("[ScreensaverDialog] Init")
|
|
58
|
+
super().__init__(parent)
|
|
59
|
+
self.setWindowTitle(_t("screensaver_title", "Screensaver"))
|
|
60
|
+
settings = current_settings()
|
|
61
|
+
|
|
62
|
+
self.enable_checkbox = tr(QCheckBox(), "screensaver_enable", "Show something when idle")
|
|
63
|
+
self.enable_checkbox.setChecked(settings["enabled"])
|
|
64
|
+
|
|
65
|
+
self.idle_label = tr(QLabel(), "screensaver_idle_minutes", "Idle for (minutes)")
|
|
66
|
+
self.idle_spinbox = QSpinBox()
|
|
67
|
+
self.idle_spinbox.setRange(MIN_IDLE_MINUTES, MAX_IDLE_MINUTES)
|
|
68
|
+
self.idle_spinbox.setValue(settings["idle_minutes"])
|
|
69
|
+
|
|
70
|
+
self.source_label = tr(QLabel(), "screensaver_source", "Show")
|
|
71
|
+
self.source_combobox = QComboBox()
|
|
72
|
+
for name in SOURCES:
|
|
73
|
+
key, fallback = SOURCE_LABEL_KEYS[name]
|
|
74
|
+
self.source_combobox.addItem(_t(key, fallback), name)
|
|
75
|
+
index = self.source_combobox.findData(settings["source"])
|
|
76
|
+
if index >= 0:
|
|
77
|
+
self.source_combobox.setCurrentIndex(index)
|
|
78
|
+
|
|
79
|
+
self.hint_label = tr(
|
|
80
|
+
QLabel(), "screensaver_hint",
|
|
81
|
+
"It uses that page as you have it set up, so choose the file there first. "
|
|
82
|
+
"Nothing appears while the page has nothing to show. Moving the mouse or "
|
|
83
|
+
"pressing a key takes it away again, and anything you opened yourself stays.")
|
|
84
|
+
self.hint_label.setWordWrap(True)
|
|
85
|
+
|
|
86
|
+
buttons = QDialogButtonBox(
|
|
87
|
+
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
|
|
88
|
+
buttons.accepted.connect(self.accept)
|
|
89
|
+
buttons.rejected.connect(self.reject)
|
|
90
|
+
|
|
91
|
+
layout = QGridLayout(self)
|
|
92
|
+
layout.addWidget(self.enable_checkbox, 0, 0, 1, 2)
|
|
93
|
+
layout.addWidget(self.idle_label, 1, 0)
|
|
94
|
+
layout.addWidget(self.idle_spinbox, 1, 1)
|
|
95
|
+
layout.addWidget(self.source_label, 2, 0)
|
|
96
|
+
layout.addWidget(self.source_combobox, 2, 1)
|
|
97
|
+
layout.addWidget(self.hint_label, 3, 0, 1, 2)
|
|
98
|
+
layout.addWidget(buttons, 4, 0, 1, 2)
|
|
99
|
+
|
|
100
|
+
def collect(self) -> Dict[str, Any]:
|
|
101
|
+
"""把畫面上的選擇讀成設定。"""
|
|
102
|
+
return {
|
|
103
|
+
"enabled": self.enable_checkbox.isChecked(),
|
|
104
|
+
"idle_minutes": clamp_idle_minutes(self.idle_spinbox.value()),
|
|
105
|
+
"source": normalize_source(self.source_combobox.currentData()),
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
def accept(self) -> None:
|
|
109
|
+
user_setting_dict[SETTING_KEY] = self.collect()
|
|
110
|
+
write_user_setting()
|
|
111
|
+
front_engine_logger.info(
|
|
112
|
+
f"[ScreensaverDialog] saved | {user_setting_dict[SETTING_KEY]}")
|
|
113
|
+
super().accept()
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""
|
|
2
|
+
挑一個視窗,開一個顯示它即時畫面的小視窗。
|
|
3
|
+
|
|
4
|
+
和「釘選視窗」的差別在於原視窗動不動:釘選會把它搬到最上層,複本讓它留在原地。
|
|
5
|
+
Pick a window and open a small one showing it live. The difference from pinning
|
|
6
|
+
is whether the original moves: pinning brings it to the top, a replica leaves it
|
|
7
|
+
where it is.
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import List, Optional, Tuple
|
|
12
|
+
|
|
13
|
+
from PySide6.QtCore import Qt
|
|
14
|
+
from PySide6.QtWidgets import (
|
|
15
|
+
QAbstractItemView, QDialog, QDialogButtonBox, QGridLayout, QLabel, QListWidget,
|
|
16
|
+
QListWidgetItem, QPushButton, QSlider, QWidget,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from frontengine.show.replica.replica_widget import WindowReplicaWidget
|
|
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.multi_language.retranslate import retranslator, tr
|
|
23
|
+
from frontengine.utils.window_pin import window_pin
|
|
24
|
+
from frontengine.utils.window_replica.dwm_thumbnail import available
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _t(key: str, fallback: str) -> str:
|
|
28
|
+
return language_wrapper.language_word_dict.get(key, fallback)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class WindowReplicaDialog(QDialog):
|
|
32
|
+
"""列出目前的視窗,讓使用者挑一個做成即時複本。"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, parent: Optional[QWidget] = None, lister=None,
|
|
35
|
+
replica_factory=WindowReplicaWidget) -> None:
|
|
36
|
+
front_engine_logger.info("[WindowReplicaDialog] Init")
|
|
37
|
+
super().__init__(parent)
|
|
38
|
+
self.setWindowTitle(_t("window_replica_title", "Replicate a window"))
|
|
39
|
+
self._lister = lister or window_pin.list_windows
|
|
40
|
+
self._replica_factory = replica_factory
|
|
41
|
+
self.replica_widget_list: List[WindowReplicaWidget] = []
|
|
42
|
+
|
|
43
|
+
self.window_list = QListWidget()
|
|
44
|
+
self.window_list.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
|
45
|
+
self.refresh_button = tr(QPushButton(), "window_replica_refresh", "Refresh")
|
|
46
|
+
self.refresh_button.clicked.connect(self.reload_windows)
|
|
47
|
+
self.show_button = tr(QPushButton(), "window_replica_show", "Show replica")
|
|
48
|
+
self.show_button.clicked.connect(self.start_replica)
|
|
49
|
+
|
|
50
|
+
self.opacity_label = tr(QLabel(), "window_replica_opacity", "Opacity")
|
|
51
|
+
self.opacity_slider = QSlider(Qt.Orientation.Horizontal)
|
|
52
|
+
self.opacity_slider.setRange(10, 100)
|
|
53
|
+
self.opacity_slider.setValue(100)
|
|
54
|
+
|
|
55
|
+
hint_key, hint_fallback = (
|
|
56
|
+
("window_replica_hint",
|
|
57
|
+
"A second window showing the chosen one live; the original stays where it "
|
|
58
|
+
"is. Drag the replica to move it, double-click it to close it. Windows only.")
|
|
59
|
+
if available() else
|
|
60
|
+
("window_replica_unsupported", "Window replicas are Windows only."))
|
|
61
|
+
self.hint_label = QLabel(_t(hint_key, hint_fallback))
|
|
62
|
+
retranslator.bind(self.hint_label, hint_key, hint_fallback)
|
|
63
|
+
self.hint_label.setWordWrap(True)
|
|
64
|
+
|
|
65
|
+
self.button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
|
|
66
|
+
self.button_box.rejected.connect(self.reject)
|
|
67
|
+
|
|
68
|
+
layout = QGridLayout(self)
|
|
69
|
+
layout.addWidget(self.window_list, 0, 0, 1, 2)
|
|
70
|
+
layout.addWidget(self.refresh_button, 1, 0)
|
|
71
|
+
layout.addWidget(self.show_button, 1, 1)
|
|
72
|
+
layout.addWidget(self.opacity_label, 2, 0)
|
|
73
|
+
layout.addWidget(self.opacity_slider, 2, 1)
|
|
74
|
+
layout.addWidget(self.hint_label, 3, 0, 1, 2)
|
|
75
|
+
layout.addWidget(self.button_box, 4, 0, 1, 2)
|
|
76
|
+
|
|
77
|
+
self.show_button.setEnabled(available())
|
|
78
|
+
self.reload_windows()
|
|
79
|
+
|
|
80
|
+
def reload_windows(self) -> List[Tuple[int, str]]:
|
|
81
|
+
"""重新抓一次視窗清單。"""
|
|
82
|
+
self.window_list.clear()
|
|
83
|
+
windows = self._lister() or []
|
|
84
|
+
for handle, title in windows:
|
|
85
|
+
item = QListWidgetItem(title)
|
|
86
|
+
item.setData(Qt.ItemDataRole.UserRole, int(handle))
|
|
87
|
+
self.window_list.addItem(item)
|
|
88
|
+
return windows
|
|
89
|
+
|
|
90
|
+
def selected(self) -> Optional[Tuple[int, str]]:
|
|
91
|
+
"""目前選到的 (handle, 標題);沒選就是 None。"""
|
|
92
|
+
item = self.window_list.currentItem()
|
|
93
|
+
if item is None:
|
|
94
|
+
return None
|
|
95
|
+
return int(item.data(Qt.ItemDataRole.UserRole)), item.text()
|
|
96
|
+
|
|
97
|
+
def start_replica(self) -> Optional[WindowReplicaWidget]:
|
|
98
|
+
"""
|
|
99
|
+
對選到的視窗開一個複本。接不上就把它收掉再回 None——留一個永遠黑著的
|
|
100
|
+
小視窗在畫面上,比什麼都不做更糟。
|
|
101
|
+
Open a replica of the selected window. If it cannot attach, the widget is
|
|
102
|
+
closed and this returns None: leaving a permanently black window on
|
|
103
|
+
screen is worse than doing nothing.
|
|
104
|
+
"""
|
|
105
|
+
chosen = self.selected()
|
|
106
|
+
if chosen is None:
|
|
107
|
+
return None
|
|
108
|
+
handle, title = chosen
|
|
109
|
+
replica = self._replica_factory(handle, title, self.opacity_slider.value(), None)
|
|
110
|
+
if not replica.start():
|
|
111
|
+
front_engine_logger.info(f"[WindowReplicaDialog] could not replicate {title!r}")
|
|
112
|
+
replica.close()
|
|
113
|
+
return None
|
|
114
|
+
self.replica_widget_list.append(replica)
|
|
115
|
+
return replica
|
|
116
|
+
|
|
117
|
+
def close_all(self) -> None:
|
|
118
|
+
"""關掉這個對話框開過的所有複本。"""
|
|
119
|
+
for replica in list(self.replica_widget_list):
|
|
120
|
+
try:
|
|
121
|
+
replica.close()
|
|
122
|
+
except RuntimeError: # pragma: no cover - 底層物件已消失
|
|
123
|
+
pass
|
|
124
|
+
self.replica_widget_list.clear()
|
|
@@ -67,6 +67,7 @@ from frontengine.utils.midi.midi_input import MidiInput, binding_key
|
|
|
67
67
|
from frontengine.utils.remote.remote_server import RemoteServer
|
|
68
68
|
from frontengine.ui.dialog.smart_pause_dialog import current_rules
|
|
69
69
|
from frontengine.utils.screen_privacy.share_watch import ShareWatchService
|
|
70
|
+
from frontengine.utils.screensaver.screensaver_service import ScreensaverService
|
|
70
71
|
from frontengine.utils.app_profile.app_profile_service import AppProfileService
|
|
71
72
|
from frontengine.utils.clipboard.clipboard_history import DEFAULT_LIMIT, ClipboardHistory
|
|
72
73
|
from frontengine.utils.clipboard.clipboard_watcher import ClipboardWatcher
|
|
@@ -329,6 +330,15 @@ class FrontEngineMainUI(QMainWindow):
|
|
|
329
330
|
)
|
|
330
331
|
self.preset_schedule_service.start()
|
|
331
332
|
|
|
333
|
+
# 閒置夠久就把選定的覆蓋層放上來 / Show the chosen overlay once idle
|
|
334
|
+
self._screensaver_overlays: list = []
|
|
335
|
+
self.screensaver_service = ScreensaverService(
|
|
336
|
+
config_provider=lambda: user_setting_dict.get("screensaver", {})
|
|
337
|
+
)
|
|
338
|
+
self.screensaver_service.screensaver_started.connect(self._start_screensaver)
|
|
339
|
+
self.screensaver_service.screensaver_stopped.connect(self._stop_screensaver)
|
|
340
|
+
self.screensaver_service.start()
|
|
341
|
+
|
|
332
342
|
# 還原上次工作階段(若有開啟),再套用啟動預設集
|
|
333
343
|
# Restore the last session when enabled, then apply the startup preset.
|
|
334
344
|
if user_setting_dict.get("restore_last_session"):
|
|
@@ -383,6 +393,76 @@ class FrontEngineMainUI(QMainWindow):
|
|
|
383
393
|
self.control_center_ui.register_overlay_source(
|
|
384
394
|
lambda attribute=attribute: getattr(self.tools_setting_ui, attribute, []))
|
|
385
395
|
|
|
396
|
+
# 螢幕保護能顯示哪些分頁:來源名稱 -> (頁面屬性, 啟動方法, 覆蓋層清單屬性)
|
|
397
|
+
# What the screensaver can show: source -> (page attribute, start method,
|
|
398
|
+
# the page's overlay list).
|
|
399
|
+
_SCREENSAVER_SOURCES = {
|
|
400
|
+
"video": ("video_setting_ui", "start_play_video", "video_widget_list"),
|
|
401
|
+
"image": ("image_setting_ui", "start_play_image", "image_widget_list"),
|
|
402
|
+
"gif": ("gif_setting_ui", "start_play_gif", "gif_widget_list"),
|
|
403
|
+
"particle": ("particle_setting_ui", "start_play_particle", "particle_list"),
|
|
404
|
+
"web": ("web_setting_ui", "start_open_web_with_url", "web_widget_list"),
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
@staticmethod
|
|
408
|
+
def _screensaver_ready(source: str, page: Any) -> bool:
|
|
409
|
+
"""
|
|
410
|
+
這一頁現在按下開始會不會出東西。
|
|
411
|
+
|
|
412
|
+
非問不可:每個分頁在沒選檔案時都會跳一個 modal 訊息框,而螢幕保護正好是
|
|
413
|
+
在沒有人的時候啟動的——那個對話框會擋在畫面上直到有人回來按掉。
|
|
414
|
+
Whether pressing start on this page would actually show something.
|
|
415
|
+
|
|
416
|
+
This has to be asked: every page opens a modal message box when no file
|
|
417
|
+
is chosen, and the screensaver fires precisely when nobody is there - the
|
|
418
|
+
dialog would sit on screen until someone came back and dismissed it.
|
|
419
|
+
"""
|
|
420
|
+
if source == "web":
|
|
421
|
+
field = getattr(page, "web_url_input", None)
|
|
422
|
+
return bool(field is not None and field.text().strip())
|
|
423
|
+
return bool(getattr(page, "ready_to_play", False))
|
|
424
|
+
|
|
425
|
+
def _start_screensaver(self, source: str) -> None:
|
|
426
|
+
"""閒置夠久了:把選定分頁的覆蓋層放上來,並記住是哪幾個。"""
|
|
427
|
+
entry = self._SCREENSAVER_SOURCES.get(source)
|
|
428
|
+
if entry is None:
|
|
429
|
+
return
|
|
430
|
+
attribute, start_method, list_name = entry
|
|
431
|
+
page = getattr(self, attribute, None)
|
|
432
|
+
overlays = getattr(page, list_name, None) if page is not None else None
|
|
433
|
+
if page is None or overlays is None:
|
|
434
|
+
return
|
|
435
|
+
if not self._screensaver_ready(source, page):
|
|
436
|
+
front_engine_logger.info(
|
|
437
|
+
f"[FrontEngineMainUI] screensaver source '{source}' has nothing set up")
|
|
438
|
+
return
|
|
439
|
+
before = len(overlays)
|
|
440
|
+
try:
|
|
441
|
+
getattr(page, start_method)()
|
|
442
|
+
except Exception as error: # pragma: no cover - defensive boundary
|
|
443
|
+
front_engine_logger.warning(f"[FrontEngineMainUI] screensaver start failed: {error!r}")
|
|
444
|
+
return
|
|
445
|
+
# 只記下這次新增的那幾個。人回來時關掉的就只有這些,使用者自己開著的
|
|
446
|
+
# 覆蓋層不會跟著被收走。
|
|
447
|
+
# Only what this call added. Coming back closes these and nothing else,
|
|
448
|
+
# so overlays the user opened themselves survive.
|
|
449
|
+
self._screensaver_overlays = [(overlays, widget) for widget in overlays[before:]]
|
|
450
|
+
|
|
451
|
+
def _stop_screensaver(self) -> None:
|
|
452
|
+
"""人回來了:關掉螢幕保護開的那幾個覆蓋層,其他的留著。"""
|
|
453
|
+
for overlays, widget in self._screensaver_overlays:
|
|
454
|
+
try:
|
|
455
|
+
# 先 close() 再從清單移除:只丟掉參考不會跑 closeEvent,計時器與
|
|
456
|
+
# 媒體都停不下來。
|
|
457
|
+
# close() before dropping the reference: dropping it alone never
|
|
458
|
+
# runs closeEvent, so timers and media keep going.
|
|
459
|
+
widget.close()
|
|
460
|
+
except RuntimeError: # pragma: no cover - 底層物件已消失
|
|
461
|
+
pass
|
|
462
|
+
if widget in overlays:
|
|
463
|
+
overlays.remove(widget)
|
|
464
|
+
self._screensaver_overlays = []
|
|
465
|
+
|
|
386
466
|
@staticmethod
|
|
387
467
|
def _startup_language() -> str:
|
|
388
468
|
"""
|
|
@@ -741,7 +821,7 @@ class FrontEngineMainUI(QMainWindow):
|
|
|
741
821
|
# The background services to stop on close, outermost first.
|
|
742
822
|
_CLOSING_SERVICES = (
|
|
743
823
|
"preset_schedule_service", "theme_schedule_service", "usage_service",
|
|
744
|
-
"signage_service",
|
|
824
|
+
"signage_service", "screensaver_service",
|
|
745
825
|
"remote_server", "midi_input", "share_watch_service", "reminder_service",
|
|
746
826
|
"app_profile_service", "smart_pause_service", "hotkey_service",
|
|
747
827
|
)
|
|
@@ -808,6 +888,10 @@ class FrontEngineMainUI(QMainWindow):
|
|
|
808
888
|
self.widgets_setting_ui.stop_spectrum()
|
|
809
889
|
if getattr(self, "tools_setting_ui", None) is not None:
|
|
810
890
|
self.tools_setting_ui.release_pinned_windows()
|
|
891
|
+
# 複本註冊的是 DWM 縮圖,那是系統資源:視窗沒了也不會自己消失。
|
|
892
|
+
# A replica holds a DWM thumbnail, a system resource that does not
|
|
893
|
+
# go away just because the process is closing.
|
|
894
|
+
self.tools_setting_ui.close_replicas()
|
|
811
895
|
self.tools_setting_ui.stop_camera()
|
|
812
896
|
self.tools_setting_ui.stop_virtual_camera()
|
|
813
897
|
|
|
@@ -12,6 +12,7 @@ from frontengine.ui.dialog.hotkey_settings_dialog import HotkeySettingsDialog
|
|
|
12
12
|
from frontengine.ui.dialog.reminder_dialog import ReminderDialog
|
|
13
13
|
from frontengine.ui.dialog.remote_control_dialog import RemoteControlDialog
|
|
14
14
|
from frontengine.ui.dialog.screen_privacy_dialog import ScreenPrivacyDialog
|
|
15
|
+
from frontengine.ui.dialog.screensaver_dialog import ScreensaverDialog
|
|
15
16
|
from frontengine.ui.dialog.signage_dialog import SignageDialog
|
|
16
17
|
from frontengine.ui.dialog.smart_pause_dialog import SmartPauseDialog
|
|
17
18
|
from frontengine.ui.dialog.usage_report_dialog import UsageReportDialog
|
|
@@ -107,6 +108,12 @@ def build_settings_menu(ui: "FrontEngineMainUI") -> None:
|
|
|
107
108
|
menu.addAction(reminder_action)
|
|
108
109
|
ui.reminder_action = reminder_action
|
|
109
110
|
|
|
111
|
+
screensaver_action = QAction(_t("settings_menu_screensaver", "Screensaver..."), menu)
|
|
112
|
+
retranslator.bind(screensaver_action, "settings_menu_screensaver", "Screensaver...")
|
|
113
|
+
screensaver_action.triggered.connect(lambda: ScreensaverDialog(ui).exec())
|
|
114
|
+
menu.addAction(screensaver_action)
|
|
115
|
+
ui.screensaver_action = screensaver_action
|
|
116
|
+
|
|
110
117
|
signage_action = QAction(_t("settings_menu_signage", "Signage mode..."), menu)
|
|
111
118
|
retranslator.bind(signage_action, "settings_menu_signage", "Signage mode...")
|
|
112
119
|
signage_action.triggered.connect(lambda: _open_signage_dialog(ui))
|
|
@@ -25,6 +25,7 @@ from frontengine.ui.dialog.screen_text_dialog import (
|
|
|
25
25
|
ScreenTextDialog, ask_for_consent, has_consent,
|
|
26
26
|
)
|
|
27
27
|
from frontengine.ui.dialog.window_pin_dialog import WindowPinDialog
|
|
28
|
+
from frontengine.ui.dialog.window_replica_dialog import WindowReplicaDialog
|
|
28
29
|
from frontengine.user_setting.user_setting_file import user_setting_dict, write_user_setting
|
|
29
30
|
from frontengine.ui.page.utils import coerce_int
|
|
30
31
|
from frontengine.ui.page.layout_kit import SettingPage
|
|
@@ -85,6 +86,7 @@ class ToolsSettingUI(SettingPage):
|
|
|
85
86
|
# raises RuntimeError on touch and "copy last" was a silent no-op.
|
|
86
87
|
self.last_capture: Optional[QPixmap] = None
|
|
87
88
|
self.pin_dialog: Optional[WindowPinDialog] = None
|
|
89
|
+
self.replica_dialog: Optional[WindowReplicaDialog] = None
|
|
88
90
|
|
|
89
91
|
self._build_measure_row()
|
|
90
92
|
self._build_capture_row()
|
|
@@ -95,6 +97,11 @@ class ToolsSettingUI(SettingPage):
|
|
|
95
97
|
self.pin_button = tr(QPushButton(), "tools_pin_window", "Pin a window...")
|
|
96
98
|
self.pin_button.clicked.connect(self.open_pin_dialog)
|
|
97
99
|
|
|
100
|
+
# 視窗複本:原視窗留在原地,另外開一個小視窗顯示它的即時畫面
|
|
101
|
+
# Window replica: the original stays put, a small window shows it live
|
|
102
|
+
self.replica_button = tr(QPushButton(), "tools_replicate_window", "Replicate a window...")
|
|
103
|
+
self.replica_button.clicked.connect(self.open_replica_dialog)
|
|
104
|
+
|
|
98
105
|
# 視窗版面:記下每個視窗的位置,之後一鍵擺回去
|
|
99
106
|
# Window layouts: remember where the windows are and put them back later.
|
|
100
107
|
self.layout_label = tr(QLabel(), "tools_layout_label", "Window layout")
|
|
@@ -154,7 +161,7 @@ class ToolsSettingUI(SettingPage):
|
|
|
154
161
|
windows.add_row("tools_name", self.layout_name_edit, "Name")
|
|
155
162
|
windows.add_inline(self.layout_save_button)
|
|
156
163
|
windows.add_row("tools_saved", self.layout_combobox, "Saved")
|
|
157
|
-
windows.add_inline(self.layout_restore_button, self.pin_button)
|
|
164
|
+
windows.add_inline(self.layout_restore_button, self.pin_button, self.replica_button)
|
|
158
165
|
|
|
159
166
|
self.add_body_widget(self.hint_label)
|
|
160
167
|
self.finish_body()
|
|
@@ -366,6 +373,20 @@ class ToolsSettingUI(SettingPage):
|
|
|
366
373
|
self.pin_dialog.exec()
|
|
367
374
|
return self.pin_dialog
|
|
368
375
|
|
|
376
|
+
def open_replica_dialog(self) -> WindowReplicaDialog:
|
|
377
|
+
"""開視窗複本對話框(關掉主程式時會把開過的複本收乾淨)。"""
|
|
378
|
+
self.replica_dialog = WindowReplicaDialog(self)
|
|
379
|
+
self.replica_dialog.exec()
|
|
380
|
+
return self.replica_dialog
|
|
381
|
+
|
|
382
|
+
def close_replicas(self) -> None:
|
|
383
|
+
"""關掉開過的視窗複本(主程式關閉時呼叫)。"""
|
|
384
|
+
if self.replica_dialog is not None:
|
|
385
|
+
try:
|
|
386
|
+
self.replica_dialog.close_all()
|
|
387
|
+
except RuntimeError:
|
|
388
|
+
self.replica_dialog = None
|
|
389
|
+
|
|
369
390
|
def release_pinned_windows(self) -> None:
|
|
370
391
|
"""把釘過的別人視窗放開(主程式關閉時呼叫)。"""
|
|
371
392
|
if self.pin_dialog is not None:
|
|
@@ -46,6 +46,19 @@ english_word_dict = {
|
|
|
46
46
|
"tools_shape": "Shape",
|
|
47
47
|
"tools_name": "Name",
|
|
48
48
|
"tools_saved": "Saved",
|
|
49
|
+
"tools_replicate_window": "Replicate a window...",
|
|
50
|
+
"window_replica_title": "Replicate a window",
|
|
51
|
+
"window_replica_refresh": "Refresh",
|
|
52
|
+
"window_replica_show": "Show replica",
|
|
53
|
+
"window_replica_opacity": "Opacity",
|
|
54
|
+
"window_replica_hint": "A second window showing the chosen one live; the original stays where it is. Drag the replica to move it, double-click it to close it. Windows only.",
|
|
55
|
+
"window_replica_unsupported": "Window replicas are Windows only.",
|
|
56
|
+
"settings_menu_screensaver": "Screensaver...",
|
|
57
|
+
"screensaver_title": "Screensaver",
|
|
58
|
+
"screensaver_enable": "Show something when idle",
|
|
59
|
+
"screensaver_idle_minutes": "Idle for (minutes)",
|
|
60
|
+
"screensaver_source": "Show",
|
|
61
|
+
"screensaver_hint": "It uses that page as you have it set up, so choose the file there first. Nothing appears while the page has nothing to show. Moving the mouse or pressing a key takes it away again, and anything you opened yourself stays.",
|
|
49
62
|
"section_close": "CLOSE",
|
|
50
63
|
"section_everything": "EVERYTHING AT ONCE",
|
|
51
64
|
"section_log": "MESSAGES",
|
|
@@ -47,6 +47,19 @@ french_word_dict = {
|
|
|
47
47
|
"tools_shape": "Forme",
|
|
48
48
|
"tools_name": "Nom",
|
|
49
49
|
"tools_saved": "Enregistrés",
|
|
50
|
+
"tools_replicate_window": "Dupliquer une fenêtre...",
|
|
51
|
+
"window_replica_title": "Dupliquer une fenêtre",
|
|
52
|
+
"window_replica_refresh": "Actualiser",
|
|
53
|
+
"window_replica_show": "Afficher le duplicata",
|
|
54
|
+
"window_replica_opacity": "Opacité",
|
|
55
|
+
"window_replica_hint": "Une seconde fenêtre affiche la fenêtre choisie en direct ; l'originale reste à sa place. Faites glisser pour la déplacer, double-cliquez pour la fermer. Windows uniquement.",
|
|
56
|
+
"window_replica_unsupported": "Les duplicatas de fenêtre sont réservés à Windows.",
|
|
57
|
+
"settings_menu_screensaver": "Économiseur d'écran...",
|
|
58
|
+
"screensaver_title": "Économiseur d'écran",
|
|
59
|
+
"screensaver_enable": "Afficher quelque chose en cas d'inactivité",
|
|
60
|
+
"screensaver_idle_minutes": "Inactif depuis (minutes)",
|
|
61
|
+
"screensaver_source": "Afficher",
|
|
62
|
+
"screensaver_hint": "Il affiche la page telle que vous l'avez réglée : choisissez-y d'abord un fichier. Tant que la page n'a rien à montrer, rien n'apparaît. Un mouvement de souris ou une touche le retire, et ce que vous avez ouvert vous-même reste.",
|
|
50
63
|
"section_close": "FERMER",
|
|
51
64
|
"section_everything": "TOUT À LA FOIS",
|
|
52
65
|
"section_log": "MESSAGES",
|
|
@@ -47,6 +47,19 @@ germany_word_dict = {
|
|
|
47
47
|
"tools_shape": "Form",
|
|
48
48
|
"tools_name": "Name",
|
|
49
49
|
"tools_saved": "Gespeichert",
|
|
50
|
+
"tools_replicate_window": "Fenster duplizieren...",
|
|
51
|
+
"window_replica_title": "Fenster duplizieren",
|
|
52
|
+
"window_replica_refresh": "Aktualisieren",
|
|
53
|
+
"window_replica_show": "Duplikat anzeigen",
|
|
54
|
+
"window_replica_opacity": "Deckkraft",
|
|
55
|
+
"window_replica_hint": "Ein zweites Fenster zeigt das gewählte live; das Original bleibt, wo es ist. Ziehen zum Verschieben, Doppelklick zum Schließen. Nur Windows.",
|
|
56
|
+
"window_replica_unsupported": "Fensterduplikate gibt es nur unter Windows.",
|
|
57
|
+
"settings_menu_screensaver": "Bildschirmschoner...",
|
|
58
|
+
"screensaver_title": "Bildschirmschoner",
|
|
59
|
+
"screensaver_enable": "Bei Untätigkeit etwas anzeigen",
|
|
60
|
+
"screensaver_idle_minutes": "Untätig seit (Minuten)",
|
|
61
|
+
"screensaver_source": "Anzeigen",
|
|
62
|
+
"screensaver_hint": "Es zeigt die gewählte Seite so, wie Sie sie eingerichtet haben - wählen Sie dort also zuerst eine Datei. Solange die Seite nichts zu zeigen hat, erscheint nichts. Eine Mausbewegung oder ein Tastendruck nimmt es wieder weg, und was Sie selbst geöffnet haben, bleibt.",
|
|
50
63
|
"section_close": "SCHLIESSEN",
|
|
51
64
|
"section_everything": "ALLES AUF EINMAL",
|
|
52
65
|
"section_log": "MELDUNGEN",
|
|
@@ -47,6 +47,19 @@ italian_word_dict = {
|
|
|
47
47
|
"tools_shape": "Forma",
|
|
48
48
|
"tools_name": "Nome",
|
|
49
49
|
"tools_saved": "Salvati",
|
|
50
|
+
"tools_replicate_window": "Duplica una finestra...",
|
|
51
|
+
"window_replica_title": "Duplica una finestra",
|
|
52
|
+
"window_replica_refresh": "Aggiorna",
|
|
53
|
+
"window_replica_show": "Mostra il duplicato",
|
|
54
|
+
"window_replica_opacity": "Opacità",
|
|
55
|
+
"window_replica_hint": "Una seconda finestra mostra quella scelta in diretta; l'originale resta dov'è. Trascina per spostarla, doppio clic per chiuderla. Solo Windows.",
|
|
56
|
+
"window_replica_unsupported": "I duplicati di finestra sono solo per Windows.",
|
|
57
|
+
"settings_menu_screensaver": "Salvaschermo...",
|
|
58
|
+
"screensaver_title": "Salvaschermo",
|
|
59
|
+
"screensaver_enable": "Mostra qualcosa quando sei inattivo",
|
|
60
|
+
"screensaver_idle_minutes": "Inattivo da (minuti)",
|
|
61
|
+
"screensaver_source": "Mostra",
|
|
62
|
+
"screensaver_hint": "Mostra quella pagina così come l'hai impostata, quindi scegli prima un file lì. Finché la pagina non ha nulla da mostrare, non compare niente. Muovere il mouse o premere un tasto lo toglie, e ciò che hai aperto tu resta.",
|
|
50
63
|
"section_close": "CHIUDI",
|
|
51
64
|
"section_everything": "TUTTO IN UNA VOLTA",
|
|
52
65
|
"section_log": "MESSAGGI",
|