diff --git a/view.py b/view.py index 3e348a96..6a5ff860 100644 --- a/view.py +++ b/view.py @@ -16,21 +16,15 @@ from config import config class View(): def __init__(self): - self.settings = SimpleNamespace() - # theme = get_appearance_mode() if config.APPEARANCE_THEME == "System" else config.APPEARANCE_THEME - theme = "Dark" - all_ctm = ColorThemeManager(theme) - all_uism = UiScalingManager(config.UI_SCALING) - image_file = ImageFileManager(theme) - + # Localization i18n.load_path.append(os_path.join(os_path.dirname(__file__), "locales")) i18n.set("fallback", "en") # The fallback language is English. i18n.set("skip_locale_root_data", True) i18n.set("filename_format", "{locale}.{format}") i18n.set("enable_memoization", True) - i18n.set("locale", config.UI_LANGUAGE) + # Save settings at startup for items that require a restart VRCT for the changes to apply self.restart_required_configs_pre_data = SimpleNamespace( appearance_theme=config.APPEARANCE_THEME, ui_scaling=config.UI_SCALING, @@ -38,6 +32,12 @@ class View(): ui_language=config.UI_LANGUAGE, ) + self.settings = SimpleNamespace() + # theme = get_appearance_mode() if config.APPEARANCE_THEME == "System" else config.APPEARANCE_THEME + theme = "Dark" + all_ctm = ColorThemeManager(theme) + all_uism = UiScalingManager(config.UI_SCALING) + image_file = ImageFileManager(theme) common_args = { "image_file": image_file, @@ -85,6 +85,8 @@ class View(): CALLBACK_RESTART_SOFTWARE=None, CALLBACK_UPDATE_SOFTWARE=None, + CALLBACK_QUIT_VRCT=vrct_gui._quitVRCT, + CALLBACK_WHEN_DETECT_WINDOW_OVERED_SIZE=self._showDisplayOverUiSizeConfirmationModal, # Confirmation Modal @@ -95,7 +97,7 @@ class View(): VAR_LABEL_CONFIRMATION_MODAL_DENY_BUTTON=StringVar(value=""), VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON=StringVar(value=""), - # Open Config Window + # Window Control (Config Window) CALLBACK_CLICKED_OPEN_CONFIG_WINDOW_BUTTON=self._openConfigWindow, CALLBACK_CLICKED_CLOSE_CONFIG_WINDOW_BUTTON=self._closeConfigWindow, CALLBACK_OPEN_CONFIG_WINDOW=None, @@ -253,26 +255,26 @@ class View(): CALLBACK_CHECK_MIC_THRESHOLD=None, VAR_MIC_ENERGY_THRESHOLD__SLIDER=IntVar(value=config.INPUT_MIC_ENERGY_THRESHOLD), VAR_MIC_ENERGY_THRESHOLD__ENTRY=StringVar(value=config.INPUT_MIC_ENERGY_THRESHOLD), - CALLBACK_FOCUS_OUT_MIC_ENERGY_THRESHOLD=self.setLatestConfigVariable_MicEnergyThreshold, + CALLBACK_FOCUS_OUT_MIC_ENERGY_THRESHOLD=self.callbackBindFocusOut_MicEnergyThreshold, VAR_LABEL_MIC_RECORD_TIMEOUT=StringVar(value=i18n.t("config_window.mic_record_timeout.label")), VAR_DESC_MIC_RECORD_TIMEOUT=StringVar(value=i18n.t("config_window.mic_record_timeout.desc")), CALLBACK_SET_MIC_RECORD_TIMEOUT=None, VAR_MIC_RECORD_TIMEOUT=StringVar(value=config.INPUT_MIC_RECORD_TIMEOUT), - CALLBACK_FOCUS_OUT_MIC_RECORD_TIMEOUT=self.setLatestConfigVariable_MicRecordTimeout, + CALLBACK_FOCUS_OUT_MIC_RECORD_TIMEOUT=self.callbackBindFocusOut_MicRecordTimeout, VAR_LABEL_MIC_PHRASE_TIMEOUT=StringVar(value=i18n.t("config_window.mic_phrase_timeout.label")), VAR_DESC_MIC_PHRASE_TIMEOUT=StringVar(value=i18n.t("config_window.mic_phrase_timeout.desc")), CALLBACK_SET_MIC_PHRASE_TIMEOUT=None, VAR_MIC_PHRASE_TIMEOUT=StringVar(value=config.INPUT_MIC_PHRASE_TIMEOUT), - CALLBACK_FOCUS_OUT_MIC_PHRASE_TIMEOUT=self.setLatestConfigVariable_MicPhraseTimeout, + CALLBACK_FOCUS_OUT_MIC_PHRASE_TIMEOUT=self.callbackBindFocusOut_MicPhraseTimeout, VAR_LABEL_MIC_MAX_PHRASES=StringVar(value=i18n.t("config_window.mic_max_phrase.label")), VAR_DESC_MIC_MAX_PHRASES=StringVar(value=i18n.t("config_window.mic_max_phrase.desc")), CALLBACK_SET_MIC_MAX_PHRASES=None, VAR_MIC_MAX_PHRASES=StringVar(value=config.INPUT_MIC_MAX_PHRASES), - CALLBACK_FOCUS_OUT_MIC_MAX_PHRASES=self.setLatestConfigVariable_MicMaxPhrases, + CALLBACK_FOCUS_OUT_MIC_MAX_PHRASES=self.callbackBindFocusOut_MicMaxPhrases, VAR_LABEL_MIC_WORD_FILTER=StringVar(value=i18n.t("config_window.mic_word_filter.label")), VAR_DESC_MIC_WORD_FILTER=StringVar(value=i18n.t("config_window.mic_word_filter.desc")), @@ -290,26 +292,26 @@ class View(): CALLBACK_CHECK_SPEAKER_THRESHOLD=None, VAR_SPEAKER_ENERGY_THRESHOLD__SLIDER=IntVar(value=config.INPUT_SPEAKER_ENERGY_THRESHOLD), VAR_SPEAKER_ENERGY_THRESHOLD__ENTRY=StringVar(value=config.INPUT_SPEAKER_ENERGY_THRESHOLD), - CALLBACK_FOCUS_OUT_SPEAKER_ENERGY_THRESHOLD=self.setLatestConfigVariable_SpeakerEnergyThreshold, + CALLBACK_FOCUS_OUT_SPEAKER_ENERGY_THRESHOLD=self.callbackBindFocusOut_SpeakerEnergyThreshold, VAR_LABEL_SPEAKER_RECORD_TIMEOUT=StringVar(value=i18n.t("config_window.speaker_record_timeout.label")), VAR_DESC_SPEAKER_RECORD_TIMEOUT=StringVar(value=i18n.t("config_window.speaker_record_timeout.desc")), CALLBACK_SET_SPEAKER_RECORD_TIMEOUT=None, VAR_SPEAKER_RECORD_TIMEOUT=StringVar(value=config.INPUT_SPEAKER_RECORD_TIMEOUT), - CALLBACK_FOCUS_OUT_SPEAKER_RECORD_TIMEOUT=self.setLatestConfigVariable_SpeakerRecordTimeout, + CALLBACK_FOCUS_OUT_SPEAKER_RECORD_TIMEOUT=self.callbackBindFocusOut_SpeakerRecordTimeout, VAR_LABEL_SPEAKER_PHRASE_TIMEOUT=StringVar(value=i18n.t("config_window.speaker_phrase_timeout.label")), VAR_DESC_SPEAKER_PHRASE_TIMEOUT=StringVar(value=i18n.t("config_window.speaker_phrase_timeout.desc")), CALLBACK_SET_SPEAKER_PHRASE_TIMEOUT=None, VAR_SPEAKER_PHRASE_TIMEOUT=StringVar(value=config.INPUT_SPEAKER_PHRASE_TIMEOUT), - CALLBACK_FOCUS_OUT_SPEAKER_PHRASE_TIMEOUT=self.setLatestConfigVariable_SpeakerPhraseTimeout, + CALLBACK_FOCUS_OUT_SPEAKER_PHRASE_TIMEOUT=self.callbackBindFocusOut_SpeakerPhraseTimeout, VAR_LABEL_SPEAKER_MAX_PHRASES=StringVar(value=i18n.t("config_window.speaker_max_phrase.label")), VAR_DESC_SPEAKER_MAX_PHRASES=StringVar(value=i18n.t("config_window.speaker_max_phrase.desc")), CALLBACK_SET_SPEAKER_MAX_PHRASES=None, VAR_SPEAKER_MAX_PHRASES=StringVar(value=config.INPUT_SPEAKER_MAX_PHRASES), - CALLBACK_FOCUS_OUT_SPEAKER_MAX_PHRASES=self.setLatestConfigVariable_SpeakerMaxPhrases, + CALLBACK_FOCUS_OUT_SPEAKER_MAX_PHRASES=self.callbackBindFocusOut_SpeakerMaxPhrases, # Others Tab @@ -518,6 +520,23 @@ class View(): # self._insertSampleConversationToTextbox() + +# GUI process + def createGUI(self): + vrct_gui._createGUI(settings=self.settings, view_variable=self.view_variable) + + @staticmethod + def showGUI(): + vrct_gui._showGUI() + + @staticmethod + def startMainLoop(): + vrct_gui._showGUI() + vrct_gui._startMainLoop() + + + +# Common @staticmethod def getAvailableFonts(): available_fonts = list(tk_font.families()) @@ -529,6 +548,8 @@ class View(): def openWebPage(url:str): webbrowser.open_new_tab(url) + +# Open Webpage Functions def openWebPage_Booth(self): self.openWebPage(config.BOOTH_URL) self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.opened_web_page_booth")) @@ -537,6 +558,16 @@ class View(): self.openWebPage(config.DOCUMENTS_URL) self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.opened_web_page_vrct_documents")) +# Widget Control + # Common + @staticmethod + def _clearEntryBox(entry_widget): + entry_widget.delete(0, CTK_END) + + def clearErrorMessage(self): + vrct_gui._clearErrorMessage() + + @staticmethod def showUpdateAvailableButton(): vrct_gui.update_available_container.grid() @@ -550,154 +581,6 @@ class View(): vrct_gui._changeMainWindowWidgetsStatus("disabled", "All") - - def foregroundOnIfForegroundEnabled(self): - if config.ENABLE_FOREGROUND: - self.foregroundOn() - - def foregroundOffIfForegroundEnabled(self): - if config.ENABLE_FOREGROUND: - self.foregroundOff() - - - @staticmethod - def foregroundOn(): - vrct_gui.attributes("-topmost", True) - - @staticmethod - def foregroundOff(): - vrct_gui.attributes("-topmost", False) - - - def _adjustUiSizeAndRestart(self): - current_percentage = int(config.UI_SCALING.replace("%","")) - target_percentage = current_percentage - 20 - if target_percentage >= 40 and str(target_percentage) + "%" in self.view_variable.LIST_UI_SCALING: - index = self.view_variable.LIST_UI_SCALING.index(str(target_percentage) + "%") - callFunctionIfCallable(self.view_variable.CALLBACK_SET_UI_SCALING, self.view_variable.LIST_UI_SCALING[index]) - callFunctionIfCallable(self.view_variable.CALLBACK_RESTART_SOFTWARE) - else: - self._hideConfirmationModal() - # ※Below 40% of the UI size is not supported, and we cannot handle it at this time. - - - - - - def _showDisplayOverUiSizeConfirmationModal(self): - self.foregroundOffIfForegroundEnabled() - - self.view_variable.VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE.set("") - vrct_gui.main_window_cover.show() - - self.view_variable.CALLBACK_HIDE_CONFIRMATION_MODAL=self._hideConfirmationModal - self.view_variable.CALLBACK_ACCEPTED_CONFIRMATION_MODAL=self._adjustUiSizeAndRestart - self.view_variable.CALLBACK_DENIED_CONFIRMATION_MODAL=self._hideConfirmationModal - - self.view_variable.VAR_MESSAGE_CONFIRMATION_MODAL.set(i18n.t("main_window.confirmation_message.detected_over_ui_size", current_ui_size=config.UI_SCALING)) - self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_DENY_BUTTON.set(i18n.t("main_window.confirmation_message.deny_adjust_ui_size")) - self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON.set(i18n.t("main_window.confirmation_message.accept_adjust_ui_size")) - - vrct_gui.confirmation_modal.show(hide_title_bar=False, close_when_focusout=False) - - - - def _showUpdateSoftwareConfirmationModal(self): - self.foregroundOffIfForegroundEnabled() - - self.view_variable.VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE.set("") - vrct_gui.main_window_cover.show() - - self.view_variable.CALLBACK_HIDE_CONFIRMATION_MODAL=self._hideConfirmationModal - self.view_variable.CALLBACK_ACCEPTED_CONFIRMATION_MODAL=self._startUpdateSoftware - self.view_variable.CALLBACK_DENIED_CONFIRMATION_MODAL=self._hideConfirmationModal - - self.view_variable.VAR_MESSAGE_CONFIRMATION_MODAL.set(i18n.t("main_window.confirmation_message.update_software")) - self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_DENY_BUTTON.set(i18n.t("main_window.confirmation_message.deny_update_software")) - self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON.set(i18n.t("main_window.confirmation_message.accept_update_software")) - vrct_gui.confirmation_modal.show() - - - - - - def showTheLimitOfTranslationEngineConfirmationModal(self): - self.foregroundOffIfForegroundEnabled() - - self.view_variable.VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE.set("") - vrct_gui.main_window_cover.show() - - self.view_variable.CALLBACK_HIDE_CONFIRMATION_MODAL=self._hideInformationModal - self.view_variable.CALLBACK_ACCEPTED_CONFIRMATION_MODAL=self._hideInformationModal - # self.view_variable.CALLBACK_DENIED_CONFIRMATION_MODAL=self._hideConfirmationModal - - self.view_variable.VAR_MESSAGE_CONFIRMATION_MODAL.set(i18n.t("main_window.confirmation_message.translation_engine_limit_error")) - # self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_DENY_BUTTON.set(i18n.t("main_window.confirmation_message.deny_update_software")) - self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON.set(i18n.t("main_window.confirmation_message.accept_translation_engine_limit_error")) - vrct_gui.information_modal.show(hide_title_bar=False, close_when_focusout=False) - - - - def translationEngineLimitErrorProcess(self): - # turn off translation switch. - vrct_gui.translation_switch_box.deselect() - vrct_gui.translation_frame.markToggleManually(False) - - # disable translation feature. - vrct_gui._changeMainWindowWidgetsStatus("disabled", ["translation_switch"], to_hold_state=True) - - # print system message that mention to stopped translation feature. - view.printToTextbox_TranslationEngineLimitError() - view.showTheLimitOfTranslationEngineConfirmationModal() - - - - - - - - def _hideInformationModal(self): - vrct_gui.information_modal.hide() - vrct_gui.main_window_cover.hide() - self.foregroundOnIfForegroundEnabled() - - - def _hideConfirmationModal(self): - vrct_gui.confirmation_modal.hide() - vrct_gui.main_window_cover.hide() - self.foregroundOnIfForegroundEnabled() - - # def _deniedUpdateSoftware(self): - # self._hideConfirmationModal() - - def _startUpdateSoftware(self): - self.view_variable.VAR_MESSAGE_CONFIRMATION_MODAL.set(i18n.t("main_window.confirmation_message.updating")) - vrct_gui.confirmation_modal.hide_buttons() - vrct_gui.update() - vrct_gui.confirmation_modal.update() - callFunctionIfCallable(self.view_variable.CALLBACK_UPDATE_SOFTWARE) - - - - def _openConfigWindow(self): - self.view_variable.VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE.set(i18n.t("main_window.cover_message")) - callFunctionIfCallable(self.view_variable.CALLBACK_OPEN_CONFIG_WINDOW) - vrct_gui._openConfigWindow() - - def _closeConfigWindow(self): - callFunctionIfCallable(self.view_variable.CALLBACK_CLOSE_CONFIG_WINDOW) - vrct_gui._closeConfigWindow() - - - - def _openTheCoverOfMainWindow(self): - vrct_gui.main_window_cover.show() - vrct_gui.config_window.lift() - - @staticmethod - def _closeTheCoverOfMainWindow(): - vrct_gui.main_window_cover.withdraw() - def enableMainWindowSidebarCompactMode(self): self.view_variable.IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE = True vrct_gui._enableMainWindowSidebarCompactMode() @@ -706,134 +589,8 @@ class View(): self.view_variable.IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE = False vrct_gui._disableMainWindowSidebarCompactMode() - def openSelectableLanguagesWindow_YourLanguage(self, _e): - self.view_variable.VAR_TITLE_LABEL_SELECTABLE_LANGUAGE.set(i18n.t("selectable_language_window.title_your_language")) - vrct_gui._openSelectableLanguagesWindow("your_language") - - def openSelectableLanguagesWindow_TargetLanguage(self, _e): - self.view_variable.VAR_TITLE_LABEL_SELECTABLE_LANGUAGE.set(i18n.t("selectable_language_window.title_target_language")) - vrct_gui._openSelectableLanguagesWindow("target_language") - - - def updateGuiVariableByPresetTabNo(self, tab_no:str): - self.view_variable.VAR_YOUR_LANGUAGE.set(config.SELECTED_TAB_YOUR_LANGUAGES[tab_no]) - self.view_variable.VAR_TARGET_LANGUAGE.set(config.SELECTED_TAB_TARGET_LANGUAGES[tab_no]) - - - def updateList_selectableLanguages(self, new_selectable_language_list:list): - self.view_variable.LIST_SELECTABLE_LANGUAGES = new_selectable_language_list - - - def printToTextbox_enableTranslation(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.enabled_translation")) - def printToTextbox_disableTranslation(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.disabled_translation")) - - def printToTextbox_enableTranscriptionSend(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.enabled_voice2chatbox")) - def printToTextbox_disableTranscriptionSend(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.disabled_voice2chatbox")) - - def printToTextbox_enableTranscriptionReceive(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.enabled_speaker2log")) - def printToTextbox_disableTranscriptionReceive(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.disabled_speaker2log")) - - def printToTextbox_enableForeground(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.enabled_foreground")) - def printToTextbox_disableForeground(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.disabled_foreground")) - - def printToTextbox_AuthenticationSuccess(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.auth_key_success")) - def printToTextbox_AuthenticationError(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.auth_key_error")) - - - def printToTextbox_TranscriptionSendNoDeviceError(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.no_mic_device_detected_error")) - - def printToTextbox_TranscriptionReceiveNoDeviceError(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.no_speaker_device_detected_error")) - - - def printToTextbox_TranslationEngineLimitError(self): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.translation_engine_limit_error")) - - - # def printToTextbox_OSCError(self): [Deprecated] - # self._printToTextbox_Info("OSC is not enabled, please enable OSC and rejoin. or turn off the \"Send Message To VRChat\" setting") - - def printToTextbox_DetectedByWordFilter(self, detected_message): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.detected_by_word_filter"), detected_message=detected_message) - - - - def printToTextbox_selectedYourLanguages(self, selected_your_language): - your_language = selected_your_language.replace("\n", " ") - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.selected_your_language", your_language=your_language)) - - def printToTextbox_selectedTargetLanguages(self, selected_target_language): - target_language = selected_target_language.replace("\n", " ") - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.selected_target_language", target_language=target_language)) - - def printToTextbox_changedLanguagePresetTab(self, tab_no:str): - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.switched_language_preset_tab", tab_no=tab_no)) - self.printToTextbox_latestSelectedLanguages() - - def printToTextbox_latestSelectedLanguages(self): - your_language = self.view_variable.VAR_YOUR_LANGUAGE.get().replace("\n", " ") - target_language = self.view_variable.VAR_TARGET_LANGUAGE.get().replace("\n", " ") - self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.latest_language_setting", your_language=your_language, target_language=target_language)) - - - @staticmethod - def _printToTextbox_Info(info_message): - vrct_gui._printToTextbox( - target_type="SYSTEM", - original_message=info_message, - # translated_message="", - ) - - - - def printToTextbox_SentMessage(self, original_message, translated_message): - self._printToTextbox_Sent(original_message, translated_message) - - @staticmethod - def _printToTextbox_Sent(original_message, translated_message): - vrct_gui._printToTextbox( - target_type="SENT", - original_message=original_message, - translated_message=translated_message, - ) - - - def printToTextbox_ReceivedMessage(self, original_message, translated_message): - self._printToTextbox_Received(original_message, translated_message) - - @staticmethod - def _printToTextbox_Received(original_message, translated_message): - vrct_gui._printToTextbox( - target_type="RECEIVED", - original_message=original_message, - translated_message=translated_message, - ) - - - @staticmethod - def getTextFromMessageBox(): - return vrct_gui.entry_message_box.get() - - @staticmethod - def clearMessageBox(): - vrct_gui.entry_message_box.delete(0, CTK_END) - - @staticmethod - def setMainWindowTransparency(transparency:float): - vrct_gui.wm_attributes("-alpha", transparency) - + # Config Window def enableConfigWindowCompactMode(self): for additional_widget in vrct_gui.config_window.additional_widgets: additional_widget.grid_remove() @@ -843,21 +600,6 @@ class View(): additional_widget.grid() - - def createGUI(self): - vrct_gui._createGUI(settings=self.settings, view_variable=self.view_variable) - - @staticmethod - def showGUI(): - vrct_gui._showGUI() - - @staticmethod - def startMainLoop(): - vrct_gui._showGUI() - vrct_gui._startMainLoop() - - - # Config Window def showRestartButtonIfRequired(self, locale:Union[None,str]=None): is_restart_required = not ( self.restart_required_configs_pre_data.appearance_theme == config.APPEARANCE_THEME and @@ -881,8 +623,7 @@ class View(): def _hideRestartButton(self): vrct_gui.config_window.restart_button_container.grid_remove() - def _updateActiveSettingBoxTabNo(self, active_setting_box_tab_attr_name:str): - self.view_variable.ACTIVE_SETTING_BOX_TAB_ATTR_NAME = active_setting_box_tab_attr_name + @staticmethod def setWidgetsStatus_ConfigWindowCompactModeSwitch_Disabled(): @@ -892,6 +633,8 @@ class View(): def setWidgetsStatus_ConfigWindowCompactModeSwitch_Normal(): vrct_gui.config_window.setting_box_compact_mode_switch_box.configure(state="normal") + + def openMicEnergyThresholdWidget(self): self.view_variable.VAR_LABEL_MIC_DYNAMIC_ENERGY_THRESHOLD.set(i18n.t("config_window.mic_dynamic_energy_threshold.label_for_manual")) self.view_variable.VAR_DESC_MIC_DYNAMIC_ENERGY_THRESHOLD.set(i18n.t("config_window.mic_dynamic_energy_threshold.desc_for_manual")) @@ -967,6 +710,7 @@ class View(): + def updateList_MicHost(self, new_mic_host_list:list): self.view_variable.LIST_MIC_HOST = new_mic_host_list vrct_gui.dropdown_menu_window.updateDropdownMenuValues( @@ -1007,85 +751,395 @@ class View(): + + +# Widget Control (Whole) + def foregroundOnIfForegroundEnabled(self): + if config.ENABLE_FOREGROUND: + self.foregroundOn() + + def foregroundOffIfForegroundEnabled(self): + if config.ENABLE_FOREGROUND: + self.foregroundOff() + + + @staticmethod + def foregroundOn(): + vrct_gui.attributes("-topmost", True) + + @staticmethod + def foregroundOff(): + vrct_gui.attributes("-topmost", False) + + + @staticmethod + def setMainWindowTransparency(transparency:float): + vrct_gui.wm_attributes("-alpha", transparency) + + +# Function + def _adjustUiSizeAndRestart(self): + current_percentage = int(config.UI_SCALING.replace("%","")) + target_percentage = current_percentage - 20 + if target_percentage >= 40 and str(target_percentage) + "%" in self.view_variable.LIST_UI_SCALING: + index = self.view_variable.LIST_UI_SCALING.index(str(target_percentage) + "%") + callFunctionIfCallable(self.view_variable.CALLBACK_SET_UI_SCALING, self.view_variable.LIST_UI_SCALING[index]) + callFunctionIfCallable(self.view_variable.CALLBACK_RESTART_SOFTWARE) + else: + self._hideConfirmationModal() + # ※Below 40% of the UI size is not supported, and we cannot handle it at this time. + + + + def translationEngineLimitErrorProcess(self): + # turn off translation switch. + vrct_gui.translation_switch_box.deselect() + vrct_gui.translation_frame.markToggleManually(False) + + # disable translation feature. + vrct_gui._changeMainWindowWidgetsStatus("disabled", ["translation_switch"], to_hold_state=True) + + # print system message that mention to stopped translation feature. + view.printToTextbox_TranslationEngineLimitError() + view.showTheLimitOfTranslationEngineConfirmationModal() + + + + +# Show Modal + def _showDisplayOverUiSizeConfirmationModal(self): + self.foregroundOffIfForegroundEnabled() + + self.view_variable.VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE.set("") + vrct_gui.main_window_cover.show() + + self.view_variable.CALLBACK_HIDE_CONFIRMATION_MODAL=self._hideConfirmationModal + self.view_variable.CALLBACK_ACCEPTED_CONFIRMATION_MODAL=self._adjustUiSizeAndRestart + self.view_variable.CALLBACK_DENIED_CONFIRMATION_MODAL=self._hideConfirmationModal + + self.view_variable.VAR_MESSAGE_CONFIRMATION_MODAL.set(i18n.t("main_window.confirmation_message.detected_over_ui_size", current_ui_size=config.UI_SCALING)) + self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_DENY_BUTTON.set(i18n.t("main_window.confirmation_message.deny_adjust_ui_size")) + self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON.set(i18n.t("main_window.confirmation_message.accept_adjust_ui_size")) + + vrct_gui.confirmation_modal.show(hide_title_bar=False, close_when_focusout=False) + + + + def _showUpdateSoftwareConfirmationModal(self): + self.foregroundOffIfForegroundEnabled() + + self.view_variable.VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE.set("") + vrct_gui.main_window_cover.show() + + self.view_variable.CALLBACK_HIDE_CONFIRMATION_MODAL=self._hideConfirmationModal + self.view_variable.CALLBACK_ACCEPTED_CONFIRMATION_MODAL=self._startUpdateSoftware + self.view_variable.CALLBACK_DENIED_CONFIRMATION_MODAL=self._hideConfirmationModal + + self.view_variable.VAR_MESSAGE_CONFIRMATION_MODAL.set(i18n.t("main_window.confirmation_message.update_software")) + self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_DENY_BUTTON.set(i18n.t("main_window.confirmation_message.deny_update_software")) + self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON.set(i18n.t("main_window.confirmation_message.accept_update_software")) + vrct_gui.confirmation_modal.show() + + + + + + def showTheLimitOfTranslationEngineConfirmationModal(self): + self.foregroundOffIfForegroundEnabled() + + self.view_variable.VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE.set("") + vrct_gui.main_window_cover.show() + + self.view_variable.CALLBACK_HIDE_CONFIRMATION_MODAL=self._hideInformationModal + self.view_variable.CALLBACK_ACCEPTED_CONFIRMATION_MODAL=self._hideInformationModal + + self.view_variable.VAR_MESSAGE_CONFIRMATION_MODAL.set(i18n.t("main_window.confirmation_message.translation_engine_limit_error")) + self.view_variable.VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON.set(i18n.t("main_window.confirmation_message.accept_translation_engine_limit_error")) + vrct_gui.information_modal.show(hide_title_bar=False, close_when_focusout=False) + + + + +# Hide Modal + def _hideInformationModal(self): + vrct_gui.information_modal.hide() + vrct_gui.main_window_cover.hide() + self.foregroundOnIfForegroundEnabled() + + + def _hideConfirmationModal(self): + vrct_gui.confirmation_modal.hide() + vrct_gui.main_window_cover.hide() + self.foregroundOnIfForegroundEnabled() + + +# Process + def _startUpdateSoftware(self): + self.view_variable.VAR_MESSAGE_CONFIRMATION_MODAL.set(i18n.t("main_window.confirmation_message.updating")) + vrct_gui.confirmation_modal.hide_buttons() + vrct_gui.update() + vrct_gui.confirmation_modal.update() + callFunctionIfCallable(self.view_variable.CALLBACK_UPDATE_SOFTWARE) + + + +# Window Control + def _openConfigWindow(self): + self.view_variable.VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE.set(i18n.t("main_window.cover_message")) + callFunctionIfCallable(self.view_variable.CALLBACK_OPEN_CONFIG_WINDOW) + vrct_gui._openConfigWindow() + + def _closeConfigWindow(self): + callFunctionIfCallable(self.view_variable.CALLBACK_CLOSE_CONFIG_WINDOW) + vrct_gui._closeConfigWindow() + +# Window Control (Main Window Cover) + def _openTheCoverOfMainWindow(self): + vrct_gui.main_window_cover.show() + vrct_gui.config_window.lift() + + @staticmethod + def _closeTheCoverOfMainWindow(): + vrct_gui.main_window_cover.withdraw() + +# Window Control (Selectable Languages Window) + def openSelectableLanguagesWindow_YourLanguage(self, _e): + self.view_variable.VAR_TITLE_LABEL_SELECTABLE_LANGUAGE.set(i18n.t("selectable_language_window.title_your_language")) + vrct_gui._openSelectableLanguagesWindow("your_language") + + def openSelectableLanguagesWindow_TargetLanguage(self, _e): + self.view_variable.VAR_TITLE_LABEL_SELECTABLE_LANGUAGE.set(i18n.t("selectable_language_window.title_target_language")) + vrct_gui._openSelectableLanguagesWindow("target_language") + + +# Update GuiVariable (view_variable) + def updateGuiVariableByPresetTabNo(self, tab_no:str): + self.view_variable.VAR_YOUR_LANGUAGE.set(config.SELECTED_TAB_YOUR_LANGUAGES[tab_no]) + self.view_variable.VAR_TARGET_LANGUAGE.set(config.SELECTED_TAB_TARGET_LANGUAGES[tab_no]) + + + def updateList_selectableLanguages(self, new_selectable_language_list:list): + self.view_variable.LIST_SELECTABLE_LANGUAGES = new_selectable_language_list + + # (Config Window Setting Box Tab) + def _updateActiveSettingBoxTabNo(self, active_setting_box_tab_attr_name:str): + self.view_variable.ACTIVE_SETTING_BOX_TAB_ATTR_NAME = active_setting_box_tab_attr_name + + +# Set GuiVariable (view_variable) def setGuiVariable_MicEnergyThreshold(self, value): self.view_variable.VAR_MIC_ENERGY_THRESHOLD__SLIDER.set(int(value)) self.view_variable.VAR_MIC_ENERGY_THRESHOLD__ENTRY.set(str(value)) - def setLatestConfigVariable_MicEnergyThreshold(self, _e=None): - self.setGuiVariable_MicEnergyThreshold(config.INPUT_MIC_ENERGY_THRESHOLD) - self.clearErrorMessage() - def setGuiVariable_SpeakerEnergyThreshold(self, value): self.view_variable.VAR_SPEAKER_ENERGY_THRESHOLD__SLIDER.set(int(value)) self.view_variable.VAR_SPEAKER_ENERGY_THRESHOLD__ENTRY.set(str(value)) - def setLatestConfigVariable_SpeakerEnergyThreshold(self, _e=None): - self.setGuiVariable_SpeakerEnergyThreshold(config.INPUT_SPEAKER_ENERGY_THRESHOLD) - self.clearErrorMessage() - - - def setGuiVariable_MicRecordTimeout(self, value, delete=False): - if delete is True: self._clearEntryBox(vrct_gui.config_window.sb__entry_mic_record_timeout) + def setGuiVariable_MicRecordTimeout(self, value): self.view_variable.VAR_MIC_RECORD_TIMEOUT.set(str(value)) - def setLatestConfigVariable_MicRecordTimeout(self, _e=None): - self.setGuiVariable_MicRecordTimeout(config.INPUT_MIC_RECORD_TIMEOUT) - self.clearErrorMessage() - - def setGuiVariable_MicPhraseTimeout(self, value, delete=False): - if delete is True: self._clearEntryBox(vrct_gui.config_window.sb__entry_mic_phrase_timeout) + def setGuiVariable_MicPhraseTimeout(self, value): self.view_variable.VAR_MIC_PHRASE_TIMEOUT.set(str(value)) - def setLatestConfigVariable_MicPhraseTimeout(self, _e=None): - self.setGuiVariable_MicPhraseTimeout(config.INPUT_MIC_PHRASE_TIMEOUT) - self.clearErrorMessage() - - def setGuiVariable_MicMaxPhrases(self, value, delete=False): - if delete is True: self._clearEntryBox(vrct_gui.config_window.sb__entry_mic_max_phrases) + def setGuiVariable_MicMaxPhrases(self, value): self.view_variable.VAR_MIC_MAX_PHRASES.set(str(value)) - def setLatestConfigVariable_MicMaxPhrases(self, _e=None): - self.setGuiVariable_MicMaxPhrases(config.INPUT_MIC_MAX_PHRASES) - self.clearErrorMessage() - - def setGuiVariable_SpeakerRecordTimeout(self, value, delete=False): - if delete is True: self._clearEntryBox(vrct_gui.config_window.sb__entry_speaker_record_timeout) + def setGuiVariable_SpeakerRecordTimeout(self, value): self.view_variable.VAR_SPEAKER_RECORD_TIMEOUT.set(str(value)) - def setLatestConfigVariable_SpeakerRecordTimeout(self, _e=None): - self.setGuiVariable_SpeakerRecordTimeout(config.INPUT_SPEAKER_RECORD_TIMEOUT) - self.clearErrorMessage() - - def setGuiVariable_SpeakerPhraseTimeout(self, value, delete=False): - if delete is True: self._clearEntryBox(vrct_gui.config_window.sb__entry_speaker_phrase_timeout) + def setGuiVariable_SpeakerPhraseTimeout(self, value): self.view_variable.VAR_SPEAKER_PHRASE_TIMEOUT.set(str(value)) - def setLatestConfigVariable_SpeakerPhraseTimeout(self, _e=None): - self.setGuiVariable_SpeakerPhraseTimeout(config.INPUT_SPEAKER_PHRASE_TIMEOUT) - self.clearErrorMessage() - - def setGuiVariable_SpeakerMaxPhrases(self, value, delete=False): - if delete is True: self._clearEntryBox(vrct_gui.config_window.sb__entry_speaker_max_phrases) + def setGuiVariable_SpeakerMaxPhrases(self, value): self.view_variable.VAR_SPEAKER_MAX_PHRASES.set(str(value)) - def setLatestConfigVariable_SpeakerMaxPhrases(self, _e=None): - self.setGuiVariable_SpeakerMaxPhrases(config.INPUT_SPEAKER_MAX_PHRASES) - self.clearErrorMessage() + + + + + + def setLatestConfigVariable(self, target_name:str): + match (target_name): + case "MicEnergyThreshold": + self.setGuiVariable_MicEnergyThreshold(config.INPUT_MIC_ENERGY_THRESHOLD) + case "SpeakerEnergyThreshold": + self.setGuiVariable_SpeakerEnergyThreshold(config.INPUT_SPEAKER_ENERGY_THRESHOLD) + case "MicRecordTimeout": + self.setGuiVariable_MicRecordTimeout(config.INPUT_MIC_RECORD_TIMEOUT) + case "MicPhraseTimeout": + self.setGuiVariable_MicPhraseTimeout(config.INPUT_MIC_PHRASE_TIMEOUT) + case "MicMaxPhrases": + self.setGuiVariable_MicMaxPhrases(config.INPUT_MIC_MAX_PHRASES) + case "SpeakerRecordTimeout": + self.setGuiVariable_SpeakerRecordTimeout(config.INPUT_SPEAKER_RECORD_TIMEOUT) + case "SpeakerPhraseTimeout": + self.setGuiVariable_SpeakerPhraseTimeout(config.INPUT_SPEAKER_PHRASE_TIMEOUT) + case "SpeakerMaxPhrases": + self.setGuiVariable_SpeakerMaxPhrases(config.INPUT_SPEAKER_MAX_PHRASES) + + case _: + raise ValueError(f"No matching case for target_name: {target_name}") + + +# Print To Textbox. + def printToTextbox_enableTranslation(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.enabled_translation")) + def printToTextbox_disableTranslation(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.disabled_translation")) + + def printToTextbox_enableTranscriptionSend(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.enabled_voice2chatbox")) + def printToTextbox_disableTranscriptionSend(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.disabled_voice2chatbox")) + + def printToTextbox_enableTranscriptionReceive(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.enabled_speaker2log")) + def printToTextbox_disableTranscriptionReceive(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.disabled_speaker2log")) + + def printToTextbox_enableForeground(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.enabled_foreground")) + def printToTextbox_disableForeground(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.disabled_foreground")) + + def printToTextbox_AuthenticationSuccess(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.auth_key_success")) + def printToTextbox_AuthenticationError(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.auth_key_error")) + + + def printToTextbox_TranscriptionSendNoDeviceError(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.no_mic_device_detected_error")) + + def printToTextbox_TranscriptionReceiveNoDeviceError(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.no_speaker_device_detected_error")) + + + def printToTextbox_TranslationEngineLimitError(self): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.translation_engine_limit_error")) + + + # def printToTextbox_OSCError(self): [Deprecated] + # self._printToTextbox_Info("OSC is not enabled, please enable OSC and rejoin. or turn off the \"Send Message To VRChat\" setting") + + def printToTextbox_DetectedByWordFilter(self, detected_message): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.detected_by_word_filter", detected_message=detected_message)) + + + + def printToTextbox_selectedYourLanguages(self, selected_your_language): + your_language = selected_your_language.replace("\n", " ") + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.selected_your_language", your_language=your_language)) + + def printToTextbox_selectedTargetLanguages(self, selected_target_language): + target_language = selected_target_language.replace("\n", " ") + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.selected_target_language", target_language=target_language)) + + def printToTextbox_changedLanguagePresetTab(self, tab_no:str): + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.switched_language_preset_tab", tab_no=tab_no)) + self.printToTextbox_latestSelectedLanguages() + + def printToTextbox_latestSelectedLanguages(self): + your_language = self.view_variable.VAR_YOUR_LANGUAGE.get().replace("\n", " ") + target_language = self.view_variable.VAR_TARGET_LANGUAGE.get().replace("\n", " ") + self._printToTextbox_Info(i18n.t("main_window.textbox_system_message.latest_language_setting", your_language=your_language, target_language=target_language)) @staticmethod - def _clearEntryBox(entry_widget): - entry_widget.delete(0, CTK_END) + def _printToTextbox_Info(info_message): + vrct_gui._printToTextbox( + target_type="SYSTEM", + original_message=info_message, + # translated_message="", + ) + + def printToTextbox_SentMessage(self, original_message, translated_message): + self._printToTextbox_Sent(original_message, translated_message) + + @staticmethod + def _printToTextbox_Sent(original_message, translated_message): + vrct_gui._printToTextbox( + target_type="SENT", + original_message=original_message, + translated_message=translated_message, + ) + + + def printToTextbox_ReceivedMessage(self, original_message, translated_message): + self._printToTextbox_Received(original_message, translated_message) + + @staticmethod + def _printToTextbox_Received(original_message, translated_message): + vrct_gui._printToTextbox( + target_type="RECEIVED", + original_message=original_message, + translated_message=translated_message, + ) + + +# Message Box + @staticmethod + def getTextFromMessageBox(): + return vrct_gui.entry_message_box.get() + + def clearMessageBox(self): + self._clearEntryBox(vrct_gui.entry_message_box) + + + + +# Callback Bind FocusOut + def callbackBindFocusOut_MicEnergyThreshold(self, _e=None): + self.setLatestConfigVariable("MicEnergyThreshold") + self.clearErrorMessage() + + def callbackBindFocusOut_SpeakerEnergyThreshold(self, _e=None): + self.setLatestConfigVariable("SpeakerEnergyThreshold") + self.clearErrorMessage() + + + def callbackBindFocusOut_MicRecordTimeout(self, _e=None): + self.setLatestConfigVariable("MicRecordTimeout") + self.clearErrorMessage() + + def callbackBindFocusOut_MicPhraseTimeout(self, _e=None): + self.setLatestConfigVariable("MicPhraseTimeout") + self.clearErrorMessage() + + def callbackBindFocusOut_MicMaxPhrases(self, _e=None): + self.setLatestConfigVariable("MicMaxPhrases") + self.clearErrorMessage() + + + def callbackBindFocusOut_SpeakerRecordTimeout(self, _e=None): + self.setLatestConfigVariable("SpeakerRecordTimeout") + self.clearErrorMessage() + + def callbackBindFocusOut_SpeakerPhraseTimeout(self, _e=None): + self.setLatestConfigVariable("SpeakerPhraseTimeout") + self.clearErrorMessage() + + def callbackBindFocusOut_SpeakerMaxPhrases(self, _e=None): + self.setLatestConfigVariable("SpeakerMaxPhrases") + self.clearErrorMessage() + + + + + + + +# Show Error Message (Config Window) def showErrorMessage_MicEnergyThreshold(self): self._showErrorMessage( vrct_gui.config_window.sb__progressbar_x_slider__entry_mic_energy_threshold, @@ -1162,27 +1216,17 @@ class View(): self._makeInvalidValueErrorMessage(i18n.t("config_window.speaker_dynamic_energy_threshold.no_device_error_message")) ) - def _showErrorMessage(self, target_widget, message): - self.view_variable.VAR_ERROR_MESSAGE.set(message) - vrct_gui._showErrorMessage(target_widget=target_widget) - @staticmethod def _makeInvalidValueErrorMessage(error_message): return i18n.t("config_window.common_error_message.invalid_value") + "\n" + error_message - def clearErrorMessage(self): - vrct_gui._clearErrorMessage() + def _showErrorMessage(self, target_widget, message): + self.view_variable.VAR_ERROR_MESSAGE.set(message) + vrct_gui._showErrorMessage(target_widget=target_widget) - @staticmethod - def showSplash(): - vrct_gui.showSplash() - - @staticmethod - def destroySplash(): - vrct_gui.destroySplash() # These conversations are generated by ChatGPT def _insertSampleConversationToTextbox(self): diff --git a/vrct_gui/main_window/createMainWindowWidgets.py b/vrct_gui/main_window/createMainWindowWidgets.py index 2bcea306..088a3075 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", vrct_gui._quitVRCT) + vrct_gui.protocol("WM_DELETE_WINDOW", lambda: callFunctionIfCallable(view_variable.CALLBACK_QUIT_VRCT)) vrct_gui.iconbitmap(getImagePath("vrct_logo_mark_black.ico")) diff --git a/vrct_gui/vrct_gui.py b/vrct_gui/vrct_gui.py index 73e3d805..06f5f4f5 100644 --- a/vrct_gui/vrct_gui.py +++ b/vrct_gui/vrct_gui.py @@ -134,9 +134,6 @@ class VRCT_GUI(CTk): ) - # self.update() - # self.geometry("{}x{}".format(self.winfo_width(), self.winfo_height())) - def _startMainLoop(self): self.mainloop() @@ -174,9 +171,6 @@ class VRCT_GUI(CTk): def _openSelectableLanguagesWindow(self, selectable_language_window_type): - # print("___________________________________open____________________________________________________") - # print("your", self._view_variable.IS_OPENED_SELECTABLE_YOUR_LANGUAGE_WINDOW) - # print("target", self._view_variable.IS_OPENED_SELECTABLE_TARGET_LANGUAGE_WINDOW) if selectable_language_window_type == "your_language": if self._view_variable.IS_OPENED_SELECTABLE_YOUR_LANGUAGE_WINDOW is False: self.sls__arrow_img_your_language.configure(image=CTkImage(self.settings.main.image_file.ARROW_LEFT, size=self.settings.main.uism.SLS__BOX_OPTION_MENU_ARROW_IMAGE_SIZE)) @@ -208,9 +202,6 @@ class VRCT_GUI(CTk): self.selectable_languages_window.withdraw() - # print("______________________________________close_________________________________________________") - # print("your", self._view_variable.IS_OPENED_SELECTABLE_YOUR_LANGUAGE_WINDOW) - # print("target", self._view_variable.IS_OPENED_SELECTABLE_TARGET_LANGUAGE_WINDOW) if self._view_variable.IS_OPENED_SELECTABLE_TARGET_LANGUAGE_WINDOW is not False or self._view_variable.IS_OPENED_SELECTABLE_YOUR_LANGUAGE_WINDOW is not False: def callback(): self._view_variable.IS_OPENED_SELECTABLE_TARGET_LANGUAGE_WINDOW = False