From 38edeaebf326e805bc5bcf59d948dbdcf6ef396a Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Sat, 30 Dec 2023 17:25:29 +0900 Subject: [PATCH] =?UTF-8?q?[Update]=20Main=20Window:=20Add=20Restore=20the?= =?UTF-8?q?=20main=20window=20position=20feature.=20VRCT=E7=B5=82=E4=BA=86?= =?UTF-8?q?=E6=99=82=EF=BC=88=E3=83=A1=E3=82=A4=E3=83=B3=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E3=81=AEX=E3=82=92=E6=8A=BC=E3=81=97=E3=81=9F=E6=99=82?= =?UTF-8?q?=EF=BC=89=E3=81=AE=E7=94=BB=E9=9D=A2=E4=BD=8D=E7=BD=AE=E3=81=A8?= =?UTF-8?q?=E3=82=B5=E3=82=A4=E3=82=BA=E3=82=92=E8=A8=98=E9=8C=B2=E3=81=97?= =?UTF-8?q?=E3=80=81=E6=AC=A1=E5=9B=9E=E8=B5=B7=E5=8B=95=E6=99=82=E3=81=AB?= =?UTF-8?q?=E5=90=8C=E3=81=98=E5=A0=B4=E6=89=80=E5=90=8C=E3=81=98=E3=82=B5?= =?UTF-8?q?=E3=82=A4=E3=82=BA=E3=81=A7=E8=A1=A8=E7=A4=BA=E3=81=95=E3=81=9B?= =?UTF-8?q?=E3=82=8B=E6=A9=9F=E8=83=BD=E3=82=92=E8=BF=BD=E5=8A=A0=E3=80=82?= =?UTF-8?q?=E3=83=87=E3=83=95=E3=82=A9=E3=83=AB=E3=83=88=E3=81=A7=E3=82=AA?= =?UTF-8?q?=E3=83=B3=E3=81=A7=E3=81=99=E3=80=82=20=E2=80=BB=E6=AC=A1?= =?UTF-8?q?=E5=9B=9E=E3=82=A2=E3=83=97=E3=83=87=E5=BE=8C=E3=81=AE=E5=88=9D?= =?UTF-8?q?=E6=9C=9F=E8=B5=B7=E5=8B=95=E6=99=82=E3=81=AF=E3=81=BF=E3=82=93?= =?UTF-8?q?=E3=81=AA=E3=80=81=E4=B8=80=E7=95=AA=E5=B7=A6=E4=B8=8A=E7=AB=AF?= =?UTF-8?q?=E5=BA=A7=E6=A8=99x-0=20y-0=E3=81=A7=E8=A1=A8=E7=A4=BA=E3=81=95?= =?UTF-8?q?=E3=82=8C=E3=81=BE=E3=81=99=E3=80=82=E3=81=93=E3=81=AE=E8=A8=AD?= =?UTF-8?q?=E5=AE=9A=E3=82=92=E3=82=AA=E3=83=95=E3=81=AB=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=81=A8=E5=B8=B8=E3=81=AB=E7=94=BB=E9=9D=A2=E4=B8=AD=E5=A4=AE?= =?UTF-8?q?=EF=BC=88=E4=BB=8A=E3=81=BE=E3=81=A7=E9=80=9A=E3=82=8A=EF=BC=89?= =?UTF-8?q?=E3=81=AB=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C=E3=81=BE=E3=81=99?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.py | 31 +++++++++++++++++++ controller.py | 9 ++++++ locales/en.yml | 4 +++ locales/ja.yml | 4 +++ view.py | 29 +++++++++++++++-- .../createSettingBox_Appearance.py | 15 ++++++++- .../main_window/createMainWindowWidgets.py | 2 +- vrct_gui/vrct_gui.py | 20 +++++++++--- 8 files changed, 105 insertions(+), 9 deletions(-) diff --git a/config.py b/config.py index aac57a8d..8c3398ef 100644 --- a/config.py +++ b/config.py @@ -280,6 +280,30 @@ class Config: self._UI_LANGUAGE = value saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + @property + @json_serializable('ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY') + def ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY(self): + return self._ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY + + @ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY.setter + def ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY(self, value): + if isinstance(value, bool): + self._ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY = value + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) + + @property + @json_serializable('MAIN_WINDOW_GEOMETRY') + def MAIN_WINDOW_GEOMETRY(self): + return self._MAIN_WINDOW_GEOMETRY + + @MAIN_WINDOW_GEOMETRY.setter + def MAIN_WINDOW_GEOMETRY(self, value): + if isinstance(value, dict) and set(value.keys()) == set(self.MAIN_WINDOW_GEOMETRY.keys()): + for key, value in value.items(): + if isinstance(value, str): + self._MAIN_WINDOW_GEOMETRY[key] = value + saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, self.MAIN_WINDOW_GEOMETRY) + @property @json_serializable('CHOICE_MIC_HOST') def CHOICE_MIC_HOST(self): @@ -640,6 +664,13 @@ class Config: self._MESSAGE_BOX_RATIO = 10 self._FONT_FAMILY = "Yu Gothic UI" self._UI_LANGUAGE = "en" + self._ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY = True + self._MAIN_WINDOW_GEOMETRY = { + "x_pos": "0", + "y_pos": "0", + "width": "870", + "height": "640", + } self._CHOICE_MIC_HOST = getDefaultInputDevice()["host"]["name"] self._CHOICE_MIC_DEVICE = getDefaultInputDevice()["device"]["name"] self._INPUT_MIC_ENERGY_THRESHOLD = 300 diff --git a/controller.py b/controller.py index 9096dcd8..0f505099 100644 --- a/controller.py +++ b/controller.py @@ -23,6 +23,10 @@ def callbackFilepathConfigFile(): print("callbackFilepathConfigFile", config.LOCAL_PATH.replace('/', '\\')) Popen(['explorer', config.LOCAL_PATH.replace('/', '\\')], shell=True) +def callbackQuitVrct(): + main_window_geometry = view.getMainWindowGeometry() + config.MAIN_WINDOW_GEOMETRY = main_window_geometry + def messageFormatter(format_type:str, translation, message): if format_type == "RECEIVED": FORMAT_WITH_T = config.RECEIVED_MESSAGE_FORMAT_WITH_T @@ -420,6 +424,9 @@ def callbackSetUiLanguage(value): config.UI_LANGUAGE = value view.showRestartButtonIfRequired(locale=config.UI_LANGUAGE) +def callbackSetEnableRestoreMainWindowGeometry(value): + print("callbackSetEnableAutoClearMessageBox", value) + config.ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY = value # Translation Tab def callbackSetDeeplAuthkey(value): @@ -803,6 +810,7 @@ def createMainWindow(): "callback_restart_software": callbackRestartSoftware, "callback_filepath_logs": callbackFilepathLogs, "callback_filepath_config_file": callbackFilepathConfigFile, + "callback_quit_vrct": callbackQuitVrct, }, window_action_registers={ @@ -844,6 +852,7 @@ def createMainWindow(): "callback_set_message_box_ratio": callbackSetMessageBoxRatio, "callback_set_font_family": callbackSetFontFamily, "callback_set_ui_language": callbackSetUiLanguage, + "callback_set_enable_restore_main_window_geometry": callbackSetEnableRestoreMainWindowGeometry, # Translation Tab "callback_set_deepl_authkey": callbackSetDeeplAuthkey, diff --git a/locales/en.yml b/locales/en.yml index dbfc39c6..fd159673 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -113,6 +113,10 @@ config_window: ui_language: label: UI Language + to_restore_main_window_geometry: + label: Remember The Main Window Position + desc: Restore the position and size of the previous window upon startup. + deepl_auth_key: label: DeepL Auth Key diff --git a/locales/ja.yml b/locales/ja.yml index cca4e254..73337446 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -110,6 +110,10 @@ config_window: ui_language: label: UIの言語 / UI Language + to_restore_main_window_geometry: + label: メイン画面の位置を記憶する + desc: 起動時、前回の画面の位置とサイズを復元します。 + deepl_auth_key: label: DeepL 認証キー diff --git a/view.py b/view.py index b105ffd6..712821e7 100644 --- a/view.py +++ b/view.py @@ -45,6 +45,13 @@ class View(): self.settings.main = SimpleNamespace( ctm=all_ctm.main, uism=all_uism.main, + geometry=SimpleNamespace( + width=config.MAIN_WINDOW_GEOMETRY["width"], + height=config.MAIN_WINDOW_GEOMETRY["height"], + x_pos=config.MAIN_WINDOW_GEOMETRY["x_pos"], + y_pos=config.MAIN_WINDOW_GEOMETRY["y_pos"], + ), + to_restore_main_window_geometry=config.ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY, **common_args ) @@ -84,7 +91,8 @@ class View(): CALLBACK_OPEN_FILEPATH_LOGS=None, CALLBACK_OPEN_FILEPATH_CONFIG_FILE=None, - CALLBACK_QUIT_VRCT=vrct_gui._quitVRCT, + CALLBACK_DELETE_MAIN_WINDOW=self.quitVRCT, + CALLBACK_QUIT_VRCT=None, CALLBACK_WHEN_DETECT_WINDOW_OVERED_SIZE=self._showDisplayOverUiSizeConfirmationModal, @@ -240,6 +248,10 @@ class View(): CALLBACK_SET_UI_LANGUAGE=None, VAR_UI_LANGUAGE=StringVar(value=selectable_languages[config.UI_LANGUAGE]), + VAR_LABEL_ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY=StringVar(value=i18n.t("config_window.to_restore_main_window_geometry.label")), + VAR_DESC_ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY=StringVar(value=i18n.t("config_window.to_restore_main_window_geometry.desc")), + CALLBACK_SET_ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY=None, + VAR_ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY=BooleanVar(value=config.ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY), # Translation Tab VAR_LABEL_DEEPL_AUTH_KEY=StringVar(value=i18n.t("config_window.deepl_auth_key.label")), @@ -463,6 +475,7 @@ class View(): self.view_variable.CALLBACK_RESTART_SOFTWARE=common_registers.get("callback_restart_software", None) self.view_variable.CALLBACK_OPEN_FILEPATH_LOGS=common_registers.get("callback_filepath_logs", None) self.view_variable.CALLBACK_OPEN_FILEPATH_CONFIG_FILE=common_registers.get("callback_filepath_config_file", None) + self.view_variable.CALLBACK_QUIT_VRCT=common_registers.get("callback_quit_vrct", None) if window_action_registers is not None: @@ -527,6 +540,7 @@ class View(): self.view_variable.CALLBACK_SET_MESSAGE_BOX_RATIO = config_window_registers.get("callback_set_message_box_ratio", None) self.view_variable.CALLBACK_SET_FONT_FAMILY = config_window_registers.get("callback_set_font_family", None) self.view_variable.CALLBACK_SET_UI_LANGUAGE = config_window_registers.get("callback_set_ui_language", None) + self.view_variable.CALLBACK_SET_ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY = config_window_registers.get("callback_set_enable_restore_main_window_geometry", None) # Translation Tab @@ -760,7 +774,9 @@ class View(): vrct_gui._showGUI() vrct_gui._startMainLoop() - + def quitVRCT(self): + callFunctionIfCallable(self.view_variable.CALLBACK_QUIT_VRCT) + vrct_gui._quitVRCT() # Common @staticmethod @@ -774,6 +790,15 @@ class View(): def openWebPage(url:str): webbrowser.open_new_tab(url) + @staticmethod + def getMainWindowGeometry(): + result = { + "width": str(vrct_gui.winfo_toplevel().winfo_width()), + "height": str(vrct_gui.winfo_toplevel().winfo_height()), + "x_pos": str(vrct_gui.winfo_toplevel().winfo_x()), + "y_pos": str(vrct_gui.winfo_toplevel().winfo_y()), + } + return result # Open Webpage Functions def openWebPage_Booth(self): diff --git a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_appearance/createSettingBox_Appearance.py b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_appearance/createSettingBox_Appearance.py index a228e5a1..615c0e4e 100644 --- a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_appearance/createSettingBox_Appearance.py +++ b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_appearance/createSettingBox_Appearance.py @@ -6,6 +6,7 @@ def createSettingBox_Appearance(setting_box_wrapper, config_window, settings, vi sbg = _SettingBoxGenerator(setting_box_wrapper, config_window, settings, view_variable) createSettingBoxDropdownMenu = sbg.createSettingBoxDropdownMenu createSettingBoxSlider = sbg.createSettingBoxSlider + createSettingBoxCheckbox = sbg.createSettingBoxCheckbox # 関数名は変えるかもしれない。 # テーマ変更、フォント変更時、 Widget再生成か再起動かは検討中 @@ -30,6 +31,8 @@ def createSettingBox_Appearance(setting_box_wrapper, config_window, settings, vi def optionmenu_ui_language_callback(value): callFunctionIfCallable(view_variable.CALLBACK_SET_UI_LANGUAGE, value) + def checkbox_enable_restore_main_window_geometry_callback(checkbox_box_widget): + callFunctionIfCallable(view_variable.CALLBACK_SET_ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY, checkbox_box_widget.get()) row=0 config_window.sb__transparency = createSettingBoxSlider( @@ -119,5 +122,15 @@ def createSettingBox_Appearance(setting_box_wrapper, config_window, settings, vi command=lambda value: optionmenu_ui_language_callback(value), variable=view_variable.VAR_UI_LANGUAGE, ) - config_window.sb__ui_language.grid(row=row, pady=0) + config_window.sb__ui_language.grid(row=row) + row+=1 + + config_window.sb__enable_restore_main_window_geometry = createSettingBoxCheckbox( + for_var_label_text=view_variable.VAR_LABEL_ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY, + for_var_desc_text=view_variable.VAR_DESC_ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY, + checkbox_attr_name="sb__checkbox_enable_restore_main_window_geometry", + command=lambda: checkbox_enable_restore_main_window_geometry_callback(config_window.sb__checkbox_enable_restore_main_window_geometry), + variable=view_variable.VAR_ENABLE_RESTORE_MAIN_WINDOW_GEOMETRY, + ) + config_window.sb__enable_restore_main_window_geometry.grid(row=row, pady=0) row+=1 \ No newline at end of file diff --git a/vrct_gui/main_window/createMainWindowWidgets.py b/vrct_gui/main_window/createMainWindowWidgets.py index 8e8c96b6..16a402d7 100644 --- a/vrct_gui/main_window/createMainWindowWidgets.py +++ b/vrct_gui/main_window/createMainWindowWidgets.py @@ -6,7 +6,7 @@ from utils import callFunctionIfCallable from ..ui_utils import createButtonWithImage, getImagePath, bindButtonFunctionAndColor def createMainWindowWidgets(vrct_gui, settings, view_variable): - vrct_gui.protocol("WM_DELETE_WINDOW", lambda: callFunctionIfCallable(view_variable.CALLBACK_QUIT_VRCT)) + vrct_gui.protocol("WM_DELETE_WINDOW", lambda: callFunctionIfCallable(view_variable.CALLBACK_DELETE_MAIN_WINDOW)) vrct_gui.iconbitmap(getImagePath("vrct_logo_mark_black.ico")) diff --git a/vrct_gui/vrct_gui.py b/vrct_gui/vrct_gui.py index a0926150..7c0bdc7f 100644 --- a/vrct_gui/vrct_gui.py +++ b/vrct_gui/vrct_gui.py @@ -43,11 +43,21 @@ class VRCT_GUI(CTk): def _showGUI(self): self.attributes("-alpha", 0) self.deiconify() - self.geometry("{}x{}".format( - self.settings.main.uism.MAIN_AREA_MIN_WIDTH + self.settings.main.uism.SIDEBAR_MIN_WIDTH, - self.winfo_height() - )) - setGeometryToCenterOfScreen(root_widget=self) + if self.settings.main.to_restore_main_window_geometry is True: + self.geometry("{}x{}+{}+{}".format( + self.settings.main.geometry.width, + self.settings.main.geometry.height, + self.settings.main.geometry.x_pos, + self.settings.main.geometry.y_pos, + )) + else: + self.geometry("{}x{}".format( + self.settings.main.uism.MAIN_AREA_MIN_WIDTH + self.settings.main.uism.SIDEBAR_MIN_WIDTH, + self.winfo_height() + )) + setGeometryToCenterOfScreen(root_widget=self) + + if self._view_variable.IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE is True: self._enableMainWindowSidebarCompactMode() fadeInAnimation(self, steps=5, interval=0.008)