From c98912f31b27e88b7cfe0ec3362a42ac0da92a86 Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Wed, 1 Nov 2023 02:49:10 +0900 Subject: [PATCH] =?UTF-8?q?[Update]=20Mic=20Word=20Filter:=20UI=E6=94=B9?= =?UTF-8?q?=E5=96=84=E3=80=81=E3=83=AA=E3=82=B9=E3=83=88=E8=A1=A8=E8=A8=98?= =?UTF-8?q?=E3=81=AB=E3=81=97=E3=80=81=E8=BF=BD=E5=8A=A0=E3=82=84=E5=89=8A?= =?UTF-8?q?=E9=99=A4=E3=82=82=E7=9B=B4=E6=84=9F=E7=9A=84=E3=81=AB=E8=A1=8C?= =?UTF-8?q?=E3=81=88=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=80=82=E2=80=BB?= =?UTF-8?q?=5FSettingBoxGenerator.py=E5=86=85=E3=81=AB=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=9F=E9=96=A2=E6=95=B0=E3=81=8C=E3=80=81?= =?UTF-8?q?=E6=B1=8E=E7=94=A8=E7=9A=84=E3=81=A7=E3=81=AF=E3=81=AA=E3=81=8F?= =?UTF-8?q?=E3=80=81=E3=83=AF=E3=83=BC=E3=83=89=E3=83=95=E3=82=A3=E3=83=AB?= =?UTF-8?q?=E3=82=BF=E3=83=BC=E5=B0=82=E7=94=A8=E7=8A=B6=E6=85=8B=E3=81=A7?= =?UTF-8?q?=E3=81=99=E3=80=82=20config.py:=20=E7=99=BB=E9=8C=B2=E3=81=95?= =?UTF-8?q?=E3=82=8C=E3=81=9F=E5=8D=98=E8=AA=9E=E3=81=AF=E4=B8=80=E6=84=8F?= =?UTF-8?q?=E3=81=AB=E3=81=AA=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=80=81?= =?UTF-8?q?=E9=A0=86=E5=BA=8F=E3=82=92=E4=BF=9D=E6=8C=81=E3=81=97=E3=81=A4?= =?UTF-8?q?=E3=81=A4=E9=87=8D=E8=A4=87=E5=89=8A=E9=99=A4=E5=87=A6=E7=90=86?= =?UTF-8?q?=E3=80=82=20=E3=81=9D=E3=81=AE=E4=BB=96=E3=83=AF=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=83=95=E3=82=A3=E3=83=AB=E3=82=BF=E3=83=BC=E3=81=AE?= =?UTF-8?q?=E8=AA=AC=E6=98=8E=E6=96=87=E8=A8=80=E8=AA=BF=E6=95=B4=E3=81=AA?= =?UTF-8?q?=E3=81=A9=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.py | 2 +- controller.py | 42 ++- img/cancel_icon.png | Bin 0 -> 2064 bytes img/redo_white.png | Bin 0 -> 1351 bytes locales/en.yml | 4 +- locales/ja.yml | 4 +- view.py | 54 ++- .../_SettingBoxGenerator.py | 314 +++++++++++++++++- .../createSettingBox_Mic.py | 28 +- vrct_gui/ui_managers/Themes/_darkTheme.py | 21 ++ vrct_gui/ui_managers/UiScalingManager.py | 26 ++ 11 files changed, 474 insertions(+), 21 deletions(-) create mode 100644 img/cancel_icon.png create mode 100644 img/redo_white.png diff --git a/config.py b/config.py index afd25f43..90896694 100644 --- a/config.py +++ b/config.py @@ -346,7 +346,7 @@ class Config: @INPUT_MIC_WORD_FILTER.setter def INPUT_MIC_WORD_FILTER(self, value): if type(value) is list: - self._INPUT_MIC_WORD_FILTER = value + self._INPUT_MIC_WORD_FILTER = sorted(set(value), key=value.index) saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value) @property diff --git a/controller.py b/controller.py index f3ee030d..f3f2d7c1 100644 --- a/controller.py +++ b/controller.py @@ -487,19 +487,40 @@ def callbackSetMicMaxPhrases(value): except: view.showErrorMessage_MicMaxPhrases() -def callbackSetMicWordFilter(value): - print("callbackSetMicWordFilter", value) - word_filter = str(value) - word_filter = [w.strip() for w in word_filter.split(",") if len(w.strip()) > 0] - word_filter = ",".join(word_filter) - print("callbackSetMicWordFilter_afterSplitting", word_filter) - if len(word_filter) > 0: - config.INPUT_MIC_WORD_FILTER = word_filter.split(",") - else: - config.INPUT_MIC_WORD_FILTER = [] +def callbackSetMicWordFilter(values): + print("callbackSetMicWordFilter", values) + values = str(values) + values = [w.strip() for w in values.split(",") if len(w.strip()) > 0] + # Copy the list + new_input_mic_word_filter_list = config.INPUT_MIC_WORD_FILTER + new_added_value = [] + for value in values: + if value in new_input_mic_word_filter_list: + # If the value is already in the list, do nothing. + pass + else: + new_input_mic_word_filter_list.append(value) + new_added_value.append(value) + config.INPUT_MIC_WORD_FILTER = new_input_mic_word_filter_list + + view.addValueToList_WordFilter(new_added_value) + view.clearEntryBox_WordFilter() + view.setLatestConfigVariable("MicMicWordFilter") + model.resetKeywordProcessor() model.addKeywords() +def callbackDeleteMicWordFilter(value): + print("callbackDeleteMicWordFilter", value) + try: + new_input_mic_word_filter_list = config.INPUT_MIC_WORD_FILTER + new_input_mic_word_filter_list.remove(str(value)) + config.INPUT_MIC_WORD_FILTER = new_input_mic_word_filter_list + view.setLatestConfigVariable("MicMicWordFilter") + except: + print("There was no the target word in config.INPUT_MIC_WORD_FILTER") + + def callbackSetSpeakerEnergyThreshold(value): print("callbackSetSpeakerEnergyThreshold", value) if value == "": return @@ -718,6 +739,7 @@ def createMainWindow(): "callback_set_mic_phrase_timeout": callbackSetMicPhraseTimeout, "callback_set_mic_max_phrases": callbackSetMicMaxPhrases, "callback_set_mic_word_filter": callbackSetMicWordFilter, + "callback_delete_mic_word_filter": callbackDeleteMicWordFilter, # Transcription Tab (Speaker) "callback_set_speaker_energy_threshold": callbackSetSpeakerEnergyThreshold, diff --git a/img/cancel_icon.png b/img/cancel_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..aa6c386e7b0dbca0361d5250ac115f4e2809b023 GIT binary patch literal 2064 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 JPDHLkV1kn~dAk4r literal 0 HcmV?d00001 diff --git a/locales/en.yml b/locales/en.yml index 3af662cf..7eee5744 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -138,7 +138,9 @@ config_window: mic_word_filter: label: Mic Word Filter - desc: "It will not send the sentence if the word(s) included in the set list of words.\nHow to set: e.g. AAA,BBB,CCC" + desc: "If a registered word is detected, the text will not be sent. To add multiple words at once, separate them with a \",\" (comma). \n*Duplicate words will not be registered." + add_button_label: Add + count_desc: "Current registered word count: %{count}" speaker_dynamic_energy_threshold: diff --git a/locales/ja.yml b/locales/ja.yml index e608c2b2..b662a3eb 100644 --- a/locales/ja.yml +++ b/locales/ja.yml @@ -138,7 +138,9 @@ config_window: mic_word_filter: label: ワードフィルター - desc: "設定された単語を検出すると、その文章は送信されません。\n設定の例: AAA,BBB,CCC" + desc: "登録された単語を検出すると、その文章は送信されません。\n「,」カンマで区切ると、まとめて複数の単語を追加できます。\n※重複した単語は登録されません。" + add_button_label: 追加 + count_desc: "現在登録されている単語数: %{count}" speaker_dynamic_energy_threshold: diff --git a/view.py b/view.py index 1565aefa..ac1d0739 100644 --- a/view.py +++ b/view.py @@ -284,10 +284,15 @@ class View(): VAR_MIC_MAX_PHRASES=StringVar(value=config.INPUT_MIC_MAX_PHRASES), CALLBACK_FOCUS_OUT_MIC_MAX_PHRASES=self.callbackBindFocusOut_MicMaxPhrases, + CALLBACK_ARROW_SWITCH_MIC_WORD_FILTER_LIST_OPEN=self._openMicWordFilterList, + CALLBACK_ARROW_SWITCH_MIC_WORD_FILTER_LIST_CLOSE=self._closeMicWordFilterList, + 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")), + VAR_SWITCH_DESC_MIC_WORD_FILTER=StringVar(value=i18n.t("config_window.mic_word_filter.count_desc", count=len(config.INPUT_MIC_WORD_FILTER))), + VAR_LABEL_MIC_WORD_FILTER_ADD_BUTTON=StringVar(value=i18n.t("config_window.mic_word_filter.add_button_label")), CALLBACK_SET_MIC_WORD_FILTER=None, - VAR_MIC_WORD_FILTER=StringVar(value=",".join(config.INPUT_MIC_WORD_FILTER) if len(config.INPUT_MIC_WORD_FILTER) > 0 else ""), + MIC_WORD_FILTER_LIST=config.INPUT_MIC_WORD_FILTER, # Transcription Tab (Speaker) @@ -462,6 +467,7 @@ class View(): self.view_variable.CALLBACK_SET_MIC_PHRASE_TIMEOUT = config_window_registers.get("callback_set_mic_phrase_timeout", None) self.view_variable.CALLBACK_SET_MIC_MAX_PHRASES = config_window_registers.get("callback_set_mic_max_phrases", None) self.view_variable.CALLBACK_SET_MIC_WORD_FILTER = config_window_registers.get("callback_set_mic_word_filter", None) + self.view_variable.CALLBACK_DELETE_MIC_WORD_FILTER = config_window_registers.get("callback_delete_mic_word_filter", None) # Transcription Tab (Speaker) self.view_variable.CALLBACK_SET_SPEAKER_ENERGY_THRESHOLD = config_window_registers.get("callback_set_speaker_energy_threshold", None) @@ -603,10 +609,12 @@ class View(): def enableConfigWindowCompactMode(self): for additional_widget in vrct_gui.config_window.additional_widgets: additional_widget.grid_remove() + self._closeMicWordFilterList() def disableConfigWindowCompactMode(self): for additional_widget in vrct_gui.config_window.additional_widgets: additional_widget.grid() + self._closeMicWordFilterList() def showRestartButtonIfRequired(self, locale:Union[None,str]=None): @@ -783,6 +791,43 @@ class View(): + def _openMicWordFilterList(self): + target_widget = vrct_gui.config_window.sb__widgets["sb__arrow_switch_mic_word_filter"] + target_widget.arrow_switch_open.grid_remove() + target_widget.arrow_switch_close.grid() + + vrct_gui.config_window.sb__mic_word_filter_list.grid() + + def _closeMicWordFilterList(self): + target_widget = vrct_gui.config_window.sb__widgets["sb__arrow_switch_mic_word_filter"] + target_widget.arrow_switch_close.grid_remove() + target_widget.arrow_switch_open.grid() + + vrct_gui.config_window.sb__mic_word_filter_list.grid_remove() + + + def addValueToList_WordFilter(self, values:list): + target_widget = vrct_gui.config_window.sb__widgets["sb__add_and_delete_able_list_mic_word_filter_list"] + for t_item in target_widget.items: + if t_item.label in values: + values.remove(t_item.label) + t_item.redoFunction() + mic_word_filter_item_row_wrapper, accumulated_labels_width, last_row, last_column = target_widget.addValues( + values, + target_widget.mic_word_filter_item_row_wrapper, + target_widget.accumulated_labels_width, + target_widget.last_row, + target_widget.last_column + ) + target_widget.mic_word_filter_item_row_wrapper = mic_word_filter_item_row_wrapper + target_widget.accumulated_labels_width = accumulated_labels_width + target_widget.last_row = last_row + target_widget.last_column = last_column + + def clearEntryBox_WordFilter(self): + self._clearEntryBox(vrct_gui.config_window.sb__entry_mic_word_filter_list) + + # Widget Control (Whole) def foregroundOnIfForegroundEnabled(self): if config.ENABLE_FOREGROUND: @@ -924,6 +969,7 @@ class View(): def _closeConfigWindow(self): callFunctionIfCallable(self.view_variable.CALLBACK_CLOSE_CONFIG_WINDOW) + self._closeMicWordFilterList() vrct_gui._closeConfigWindow() # Window Control (Main Window Cover) @@ -981,7 +1027,8 @@ class View(): def setGuiVariable_MicMaxPhrases(self, value): self.view_variable.VAR_MIC_MAX_PHRASES.set(str(value)) - + def setGuiVariable_MicWordFilter_Length(self, value): + self.view_variable.VAR_SWITCH_DESC_MIC_WORD_FILTER.set(i18n.t("config_window.mic_word_filter.count_desc", count=value)) def setGuiVariable_SpeakerRecordTimeout(self, value): self.view_variable.VAR_SPEAKER_RECORD_TIMEOUT.set(str(value)) @@ -1011,6 +1058,9 @@ class View(): self.setGuiVariable_MicPhraseTimeout(config.INPUT_MIC_PHRASE_TIMEOUT) case "MicMaxPhrases": self.setGuiVariable_MicMaxPhrases(config.INPUT_MIC_MAX_PHRASES) + case "MicMicWordFilter": + self.setGuiVariable_MicWordFilter_Length(len(config.INPUT_MIC_WORD_FILTER)) + case "SpeakerRecordTimeout": self.setGuiVariable_SpeakerRecordTimeout(config.INPUT_SPEAKER_RECORD_TIMEOUT) case "SpeakerPhraseTimeout": diff --git a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/_SettingBoxGenerator.py b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/_SettingBoxGenerator.py index d996fb2e..8a7f3622 100644 --- a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/_SettingBoxGenerator.py +++ b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/_SettingBoxGenerator.py @@ -5,8 +5,9 @@ from typing import Union from customtkinter import CTkOptionMenu, CTkFont, CTkFrame, CTkLabel, CTkRadioButton, CTkEntry, CTkSlider, CTkSwitch, CTkCheckBox, CTkProgressBar from CTkToolTip import * -from vrct_gui.ui_utils import createButtonWithImage, getLatestWidth, createOptionMenuBox +from vrct_gui.ui_utils import createButtonWithImage, getLatestWidth, createOptionMenuBox, getLatestHeight, bindButtonFunctionAndColor from vrct_gui import vrct_gui +from utils import isEven, callFunctionIfCallable SETTING_BOX_COLUMN = 1 @@ -17,6 +18,8 @@ class _SettingBoxGenerator(): self.parent_widget = parent_widget self.settings = settings + self.MAIN_INNER_AREA_MIN_WIDTH = int(self.settings.uism.MAIN_AREA_MIN_WIDTH - self.settings.uism.SB__IPADX) + self.dropdown_menu_window = vrct_gui.vrct_gui.dropdown_menu_window def _createSettingBoxFrame(self, sb__attr_name, for_var_label_text=None, for_var_desc_text=None): @@ -449,6 +452,315 @@ class _SettingBoxGenerator(): return setting_box_frame + def createSettingBoxArrowSwitch( + self, + for_var_label_text, for_var_desc_text, + arrow_switch_attr_name, + open_command, + close_command, + var_switch_desc=None, + ): + + (setting_box_frame, setting_box_item_frame) = self._createSettingBoxFrame(arrow_switch_attr_name, for_var_label_text, for_var_desc_text) + + ARROW_BUTTON_COLUMN = SETTING_BOX_COLUMN + + if var_switch_desc is not None: + label_widget = CTkLabel( + setting_box_item_frame, + textvariable=var_switch_desc, + height=0, + corner_radius=0, + font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__ARROW_SWITCH_DESC_FONT_SIZE, weight="normal"), + anchor="w", + text_color=self.settings.ctm.LABELS_DESC_TEXT_COLOR, + ) + + label_widget.grid(row=1, column=SETTING_BOX_COLUMN) + ARROW_BUTTON_COLUMN = SETTING_BOX_COLUMN + 1 + + + for_opening_button_wrapper = createButtonWithImage( + parent_widget=setting_box_item_frame, + button_fg_color=self.settings.ctm.SB__ARROW_SWITCH_BUTTON_COLOR, + button_enter_color=self.settings.ctm.SB__ARROW_SWITCH_BUTTON_HOVERED_COLOR, + button_clicked_color=self.settings.ctm.SB__ARROW_SWITCH_BUTTON_CLICKED_COLOR, + button_image_file=self.settings.image_file.ARROW_LEFT.rotate(270), + button_image_size=self.settings.uism.SB__ARROW_SWITCH_BUTTON_ICON_SIZE, + button_ipadxy=self.settings.uism.SB__ARROW_SWITCH_BUTTON_IPADXY, + button_command=open_command, + ) + for_opening_button_wrapper.grid(row=1, column=ARROW_BUTTON_COLUMN, padx=self.settings.uism.SB__ARROW_SWITCH_LEFT_PADX, sticky="e") + + self.config_window.sb__widgets[arrow_switch_attr_name].arrow_switch_open = for_opening_button_wrapper + + for_closing_button_wrapper = createButtonWithImage( + parent_widget=setting_box_item_frame, + button_fg_color=self.settings.ctm.SB__ARROW_SWITCH_BUTTON_COLOR, + button_enter_color=self.settings.ctm.SB__ARROW_SWITCH_BUTTON_HOVERED_COLOR, + button_clicked_color=self.settings.ctm.SB__ARROW_SWITCH_BUTTON_CLICKED_COLOR, + button_image_file=self.settings.image_file.ARROW_LEFT.rotate(90), + button_image_size=self.settings.uism.SB__ARROW_SWITCH_BUTTON_ICON_SIZE, + button_ipadxy=self.settings.uism.SB__ARROW_SWITCH_BUTTON_IPADXY, + button_command=close_command, + ) + for_closing_button_wrapper.grid(row=1, column=ARROW_BUTTON_COLUMN, padx=self.settings.uism.SB__ARROW_SWITCH_LEFT_PADX, sticky="e") + for_closing_button_wrapper.grid_remove() + + self.config_window.sb__widgets[arrow_switch_attr_name].arrow_switch_close = for_closing_button_wrapper + + + return setting_box_frame + + + + # I've added it for the word filter, but it's not currently generalized. If you want to use it in the same way elsewhere, it will require refactoring. + def createSettingBoxAddAndDeleteAbleList( + self, + add_and_delete_able_list_attr_name, + entry_attr_name, + entry_width, + mic_word_filter_list, + ): + + (setting_box_frame, setting_box_item_frame) = self._createSettingBoxFrame(add_and_delete_able_list_attr_name) + + self.config_window.sb__widgets[add_and_delete_able_list_attr_name].items = [] + + + list_container = CTkFrame(setting_box_item_frame, corner_radius=0, fg_color=self.settings.ctm.SB__BG_COLOR, width=0, height=0) + list_container.grid(row=1, column=0, sticky="nsew") + + + max_width = int(self.MAIN_INNER_AREA_MIN_WIDTH - (self.settings.uism.SB__IPADX*2)) + + def addValues(mic_word_filter_list, mic_word_filter_item_row_wrapper, accumulated_labels_width, row, column): + for mic_word_filter_item in mic_word_filter_list: + mic_word_filter_item_wrapper = self._createValue(add_and_delete_able_list_attr_name, mic_word_filter_item_row_wrapper, row, column, mic_word_filter_item) + + if int(accumulated_labels_width + getLatestWidth(mic_word_filter_item_wrapper) + self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_LEFT_PADX[1]) >= max_width: + accumulated_labels_width = 0 + column = 0 + row += 1 + mic_word_filter_item_wrapper.destroy() + mic_word_filter_item_row_wrapper = self._createRowFrame(list_container, row) + mic_word_filter_item_wrapper = self._createValue(add_and_delete_able_list_attr_name, mic_word_filter_item_row_wrapper, row, column, mic_word_filter_item) + column += 1 + else: + column += 1 + + accumulated_labels_width += int(getLatestWidth(mic_word_filter_item_wrapper) + self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_LEFT_PADX[1]) + + + + return mic_word_filter_item_row_wrapper, accumulated_labels_width, row, column + + accumulated_labels_width = 0 + row=0 + column=0 + mic_word_filter_item_row_wrapper = self._createRowFrame(list_container, row) + + + mic_word_filter_list = self.view_variable.MIC_WORD_FILTER_LIST + + mic_word_filter_item_row_wrapper, accumulated_labels_width, row, column = addValues(mic_word_filter_list, mic_word_filter_item_row_wrapper, accumulated_labels_width, row, column) + + + self.config_window.sb__widgets[add_and_delete_able_list_attr_name].mic_word_filter_item_row_wrapper = mic_word_filter_item_row_wrapper + self.config_window.sb__widgets[add_and_delete_able_list_attr_name].accumulated_labels_width = accumulated_labels_width + self.config_window.sb__widgets[add_and_delete_able_list_attr_name].last_row = row + self.config_window.sb__widgets[add_and_delete_able_list_attr_name].last_column = column + self.config_window.sb__widgets[add_and_delete_able_list_attr_name].addValues = lambda values, mic_word_filter_item_row_wrapper, accumulated_labels_width, last_row, last_column: addValues(values, mic_word_filter_item_row_wrapper, accumulated_labels_width, last_row, last_column) + + + entry_and_add_button_wrapper = CTkFrame(setting_box_item_frame, corner_radius=0, fg_color=self.settings.ctm.SB__BG_COLOR) + entry_and_add_button_wrapper.grid(row=2, column=0, pady=(self.settings.uism.SB__IPADY, 0), sticky="ew") + + entry_and_add_button_wrapper.grid_columnconfigure((0,3), weight=1) + + + + entry_widget = CTkEntry( + entry_and_add_button_wrapper, + text_color=self.settings.ctm.SB__ENTRY_TEXT_COLOR, + fg_color=self.settings.ctm.SB__ENTRY_BG_COLOR, + border_color=self.settings.ctm.SB__ENTRY_BORDER_COLOR, + width=entry_width, + placeholder_text="AAA or AAA,BBB,CCC", + height=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__ENTRY_HEIGHT, + font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__ENTRY_FONT_SIZE, weight="normal"), + ) + setattr(self.config_window, entry_attr_name, entry_widget) + + entry_widget.grid(row=0, column=1, sticky="ew") + + + + add_button = CTkFrame(entry_and_add_button_wrapper, corner_radius=self.settings.uism.BUTTONS_CORNER_RADIUS, fg_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_COLOR, cursor="hand2") + add_button.grid(row=0, column=2, padx=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_LEFT_PADX, sticky="ew") + + + add_button.grid_columnconfigure(0, weight=1) + add_button_label_wrapper = CTkFrame(add_button, corner_radius=0, fg_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_COLOR) + add_button_label_wrapper.grid(row=0, column=0, padx=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_IPADX, pady=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_IPADY, sticky="ew") + + add_button_label_wrapper.grid_columnconfigure((0,2), weight=1) + add_button_label = CTkLabel( + add_button_label_wrapper, + textvariable=self.view_variable.VAR_LABEL_MIC_WORD_FILTER_ADD_BUTTON, + height=0, + corner_radius=0, + font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_FONT_SIZE, weight="normal"), + anchor="w", + text_color=self.settings.ctm.LABELS_TEXT_COLOR, + ) + add_button_label.grid(row=0, column=1) + + + def adjustedCommand(): + callFunctionIfCallable(self.view_variable.CALLBACK_SET_MIC_WORD_FILTER, entry_widget.get()) + entry_widget.focus_set() + + bindButtonFunctionAndColor( + target_widgets=[ + add_button, + add_button_label_wrapper, + add_button_label, + ], + enter_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_HOVERED_COLOR, + leave_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_COLOR, + clicked_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_CLICKED_COLOR, + buttonReleasedFunction=lambda _e: adjustedCommand(), + ) + + + return setting_box_frame + + + def _createRowFrame(self, parent_widget, row): + mic_word_filter_item_row_wrapper = CTkFrame(parent_widget, corner_radius=0, fg_color=self.settings.ctm.SB__BG_COLOR, width=0, height=0) + mic_word_filter_item_row_wrapper.grid(row=row, column=0, pady=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_BOTTOM_PADY, sticky="nsew") + + return mic_word_filter_item_row_wrapper + + + + def _createValue(self, add_and_delete_able_list_attr_name, parent_row_frame, row, column, mic_word_filter_item): + mic_word_filter_item_wrapper = CTkFrame(parent_row_frame, corner_radius=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_CORNER_RADIUS, fg_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST_BG_COLOR, width=0, height=0) + mic_word_filter_item_wrapper.grid(row=0, column=column, padx=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_LEFT_PADX, sticky="nsew") + setattr(self, f"{row}_{column}", mic_word_filter_item_wrapper) + + + + mic_word_filter_item_wrapper.grid_rowconfigure((0,2), weight=1) + label_widget = CTkLabel( + mic_word_filter_item_wrapper, + text=mic_word_filter_item, + height=0, + corner_radius=0, + font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_FONT_SIZE, weight="normal"), + anchor="w", + text_color=self.settings.ctm.BASIC_TEXT_COLOR, + ) + + label_widget.grid(row=1, column=0, padx=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_IPADX, pady=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_IPADY) + + + if isEven(getLatestHeight(label_widget)) is False: + label_widget.grid( + pady=( + self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_IPADY, + self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_IPADY + 1 + ) + ) + + + if isEven(getLatestWidth(label_widget)) is False: + label_widget.grid( + padx=( + self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_IPADX[0], + self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_IPADX[1] + 1 + ) + ) + + + + def pressedDeleteButtonCommand(_e, delete_button, redo_button): + # overstrike true + label_widget.configure(font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_FONT_SIZE, weight="normal", overstrike=True)) + # change fg_color + mic_word_filter_item_wrapper.configure(fg_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST_DELETED_BG_COLOR) + # change button img to redo button + delete_button.grid_remove() + redo_button.grid() + # callback delete function + callFunctionIfCallable(self.view_variable.CALLBACK_DELETE_MIC_WORD_FILTER, mic_word_filter_item) + + def pressedRedoButtonCommand(_e, delete_button, redo_button): + # overstrike false + label_widget.configure(font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_FONT_SIZE, weight="normal", overstrike=False)) + # change fg_color + mic_word_filter_item_wrapper.configure(fg_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST_BG_COLOR) + # change button img to delete button + redo_button.grid_remove() + delete_button.grid() + # callback add function + callFunctionIfCallable(self.view_variable.CALLBACK_SET_MIC_WORD_FILTER, mic_word_filter_item) + + + + delete_button = createButtonWithImage( + parent_widget=mic_word_filter_item_wrapper, + button_fg_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST_BG_COLOR, + button_enter_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_HOVERED_BG_COLOR, + button_clicked_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_CLICKED_BG_COLOR, + button_image_file=self.settings.image_file.CANCEL_ICON, + button_image_size=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_IMG_SIZE, + button_ipadxy=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_IPADXY, + button_command=lambda _e: pressedDeleteButtonCommand(_e, delete_button, redo_button), + ) + delete_button.grid(row=1, column=1, padx=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_PADX, sticky="e") + + redo_button = createButtonWithImage( + parent_widget=mic_word_filter_item_wrapper, + button_fg_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST_DELETED_BG_COLOR, + button_enter_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST__VALUES_DELETED_BUTTON_HOVERED_BG_COLOR, + button_clicked_color=self.settings.ctm.SB__ADD_AND_DELETE_ABLE_LIST__VALUES_DELETED_BUTTON_CLICKED_BG_COLOR, + button_image_file=self.settings.image_file.REDO_ICON, + button_image_size=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_IMG_SIZE, + button_ipadxy=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_IPADXY, + button_command=lambda _e: pressedRedoButtonCommand(_e, delete_button, redo_button), + ) + redo_button.grid(row=1, column=1, padx=self.settings.uism.ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_PADX, sticky="e") + redo_button.grid_remove() + + + partial_pressedRedoButtonCommand = partial(pressedRedoButtonCommand, _e=None, delete_button=delete_button, redo_button=redo_button) + item_data = SimpleNamespace( + label = mic_word_filter_item, + redoFunction = lambda: partial_pressedRedoButtonCommand(), + ) + + + items = self.config_window.sb__widgets[add_and_delete_able_list_attr_name].items + if len(items) == 0: + items.append(item_data) + else: + is_replaced = False + for i, item in enumerate(items): + if item.label == mic_word_filter_item: + items[i] = item_data + is_replaced = True + break + if is_replaced is False: items.append(item_data) + + + return mic_word_filter_item_wrapper + + + + + # if setting_box_type == "dropdown_menu_x_dropdown_menu": # self.setting_box_dropdown_menu_x_dropdown_menu = CTkFrame(self.setting_box, corner_radius=0, fg_color=self.settings.ctm.SB__BG_COLOR, width=0, height=0) diff --git a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_transcription/createSettingBox_Mic.py b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_transcription/createSettingBox_Mic.py index 472e5baa..d5ece1b6 100644 --- a/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_transcription/createSettingBox_Mic.py +++ b/vrct_gui/config_window/widgets/createSideMenuAndSettingsBoxContainers/setting_box_containers/setting_box_transcription/createSettingBox_Mic.py @@ -8,6 +8,8 @@ def createSettingBox_Mic(setting_box_wrapper, config_window, settings, view_vari createSettingBoxSwitch = sbg.createSettingBoxSwitch createSettingBoxProgressbarXSlider = sbg.createSettingBoxProgressbarXSlider createSettingBoxEntry = sbg.createSettingBoxEntry + createSettingBoxArrowSwitch = sbg.createSettingBoxArrowSwitch + createSettingBoxAddAndDeleteAbleList = sbg.createSettingBoxAddAndDeleteAbleList def checkbox_input_mic_threshold_check_callback(is_turned_on): @@ -36,6 +38,11 @@ def createSettingBox_Mic(setting_box_wrapper, config_window, settings, view_vari def entry_input_mic_max_phrases_callback(value): callFunctionIfCallable(view_variable.CALLBACK_SET_MIC_MAX_PHRASES, value) + def arrow_switch_mic_word_filter_list_open_callback(value): + callFunctionIfCallable(view_variable.CALLBACK_ARROW_SWITCH_MIC_WORD_FILTER_LIST_OPEN) + def arrow_switch_mic_word_filter_list_close_callback(value): + callFunctionIfCallable(view_variable.CALLBACK_ARROW_SWITCH_MIC_WORD_FILTER_LIST_CLOSE) + def entry_input_mic_word_filters_callback(value): callFunctionIfCallable(view_variable.CALLBACK_SET_MIC_WORD_FILTER, value) @@ -140,13 +147,24 @@ def createSettingBox_Mic(setting_box_wrapper, config_window, settings, view_vari # # __________ - config_window.sb__mic_word_filter = createSettingBoxEntry( + config_window.sb__mic_word_filter = createSettingBoxArrowSwitch( for_var_label_text=view_variable.VAR_LABEL_MIC_WORD_FILTER, for_var_desc_text=view_variable.VAR_DESC_MIC_WORD_FILTER, - entry_attr_name="sb__entry_mic_word_filter", - entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_300, - entry_bind__Any_KeyRelease=lambda value: entry_input_mic_word_filters_callback(value), - entry_textvariable=view_variable.VAR_MIC_WORD_FILTER, + arrow_switch_attr_name="sb__arrow_switch_mic_word_filter", + open_command=lambda value: arrow_switch_mic_word_filter_list_open_callback(value), + close_command=lambda value: arrow_switch_mic_word_filter_list_close_callback(value), + var_switch_desc=view_variable.VAR_SWITCH_DESC_MIC_WORD_FILTER, ) config_window.sb__mic_word_filter.grid(row=row, pady=0) + row+=1 + + config_window.sb__mic_word_filter_list = createSettingBoxAddAndDeleteAbleList( + add_and_delete_able_list_attr_name="sb__add_and_delete_able_list_mic_word_filter_list", + entry_attr_name="sb__entry_mic_word_filter_list", + entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_300, + mic_word_filter_list=view_variable.MIC_WORD_FILTER_LIST, + ) + config_window.sb__mic_word_filter_list.grid(row=row, pady=0) + # Default, close the list. + config_window.sb__mic_word_filter_list.grid_remove() row+=1 \ No newline at end of file diff --git a/vrct_gui/ui_managers/Themes/_darkTheme.py b/vrct_gui/ui_managers/Themes/_darkTheme.py index 8cadde2c..2522608a 100644 --- a/vrct_gui/ui_managers/Themes/_darkTheme.py +++ b/vrct_gui/ui_managers/Themes/_darkTheme.py @@ -229,6 +229,24 @@ def _darkTheme(base_color): SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_CLICKED_COLOR = base_color.PRIMARY_800_COLOR, + SB__ARROW_SWITCH_BUTTON_COLOR = base_color.DARK_888_COLOR, + SB__ARROW_SWITCH_BUTTON_HOVERED_COLOR = base_color.DARK_800_COLOR, + SB__ARROW_SWITCH_BUTTON_CLICKED_COLOR = base_color.DARK_900_COLOR, + + SB__ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_COLOR = base_color.PRIMARY_600_COLOR, + SB__ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_HOVERED_COLOR = base_color.PRIMARY_500_COLOR, + SB__ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_CLICKED_COLOR = base_color.PRIMARY_700_COLOR, + SB__ADD_AND_DELETE_ABLE_LIST_BG_COLOR = base_color.DARK_800_COLOR, + + SB__ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_HOVERED_BG_COLOR = base_color.DARK_750_COLOR, + SB__ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_CLICKED_BG_COLOR = base_color.DARK_850_COLOR, + + SB__ADD_AND_DELETE_ABLE_LIST_DELETED_BG_COLOR = base_color.DARK_850_COLOR, + SB__ADD_AND_DELETE_ABLE_LIST__VALUES_DELETED_BUTTON_HOVERED_BG_COLOR = base_color.DARK_800_COLOR, + SB__ADD_AND_DELETE_ABLE_LIST__VALUES_DELETED_BUTTON_CLICKED_BG_COLOR = base_color.DARK_900_COLOR, + + + # Side menu SIDE_MENU_BG_COLOR = base_color.DARK_950_COLOR, @@ -273,6 +291,9 @@ def _darkTheme(base_color): REFRESH_ICON = getImageFileFromUiUtils("refresh_icon.png"), HELP_ICON = getImageFileFromUiUtils("help_icon_white.png"), + + CANCEL_ICON = getImageFileFromUiUtils("cancel_icon.png"), + REDO_ICON = getImageFileFromUiUtils("redo_white.png"), ), ) diff --git a/vrct_gui/ui_managers/UiScalingManager.py b/vrct_gui/ui_managers/UiScalingManager.py index fae26c79..9a1ad1c2 100644 --- a/vrct_gui/ui_managers/UiScalingManager.py +++ b/vrct_gui/ui_managers/UiScalingManager.py @@ -217,6 +217,10 @@ class UiScalingManager(): self.config_window.SB__DESC_TOP_PADY = self._calculateUiSize(2) + self.config_window.BUTTONS_CORNER_RADIUS = self._calculateUiSize(6) + # self.config_window.BUTTONS_IPADX = self._calculateUiSize(10) + # self.config_window.BUTTONS_IPADY = self._calculateUiSize(6) + self.config_window.SB__ERROR_MESSAGE_IPADX = (self._calculateUiSize(10), self._calculateUiSize(10)) self.config_window.SB__ERROR_MESSAGE_IPADY = (self._calculateUiSize(6), self._calculateUiSize(6)) self.config_window.SB__ERROR_MESSAGE_FONT_SIZE = self._calculateUiSize(14) @@ -276,6 +280,28 @@ class UiScalingManager(): + self.config_window.SB__ARROW_SWITCH_BUTTON_IPADXY = self._calculateUiSize(16) + self.config_window.SB__ARROW_SWITCH_BUTTON_ICON_SIZE = self._calculateUiSize(24) + self.config_window.SB__ARROW_SWITCH_DESC_FONT_SIZE = self._calculateUiSize(16) + self.config_window.SB__ARROW_SWITCH_LEFT_PADX = (self._calculateUiSize(20), 0) + + self.config_window.ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_IPADX = self._calculateUiSize(16) + self.config_window.ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_IPADY = self._calculateUiSize(6) + + self.config_window.ADD_AND_DELETE_ABLE_LIST__VALUES_CORNER_RADIUS = self._calculateUiSize(2) + self.config_window.ADD_AND_DELETE_ABLE_LIST__VALUES_LEFT_PADX = (0, self._calculateUiSize(4)) + self.config_window.ADD_AND_DELETE_ABLE_LIST__VALUES_BOTTOM_PADY = (0, self._calculateUiSize(4)) + + self.config_window.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_FONT_SIZE = self._calculateUiSize(14) + self.config_window.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_IPADX = (self._calculateUiSize(8), 0) + self.config_window.ADD_AND_DELETE_ABLE_LIST__VALUES_TEXT_IPADY = self._calculateUiSize(6) + self.config_window.ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_IMG_SIZE = self._calculateUiSize(14) + self.config_window.ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_IPADXY = self._calculateUiSize(6) + self.config_window.ADD_AND_DELETE_ABLE_LIST__VALUES_ACTION_BUTTON_PADX = (self._calculateUiSize(6), self._calculateUiSize(8)) + + self.config_window.ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_LEFT_PADX = (self._calculateUiSize(20), 0) + self.config_window.ADD_AND_DELETE_ABLE_LIST__ADD_BUTTON_FONT_SIZE = self._calculateUiSize(14) + def _calculateUiSize(self, default_size, is_allowed_odd:bool=False, is_zero_allowed:bool=False): size = calculateUiSize(default_size, self.SCALING_FLOAT, is_allowed_odd, is_zero_allowed) return size