[Update] Main Window: (WIP UI) CTranslate2、内部翻訳機能などの追加により、メイン画面にUI追加。デザインは確定ではなく、UI Scaling未対応などテスト状態です。

This commit is contained in:
Sakamoto Shiina
2024-01-13 12:37:37 +09:00
parent 017963bb0b
commit 8c64b91839
8 changed files with 202 additions and 20 deletions

View File

@@ -250,6 +250,9 @@ def messageBoxFocusOut(e):
model.oscStopSendTyping()
# func select languages
def getLatestSelectableTranslationEngines():
return model.findTranslationEngines(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
def initSetTranslateEngine():
engine = config.SELECTED_TAB_YOUR_TRANSLATOR_ENGINES[config.SELECTED_TAB_NO]
config.CHOICE_INPUT_TRANSLATOR = engine
@@ -285,6 +288,8 @@ def setYourLanguageAndCountry(select):
language, country = model.getLanguageAndCountry(select)
config.SOURCE_LANGUAGE = language
config.SOURCE_COUNTRY = country
view.updateSelectableTranslationEngineList(getLatestSelectableTranslationEngines())
view.setGuiVariable_SelectedTranslationEngine(config.CHOICE_OUTPUT_TRANSLATOR)
view.printToTextbox_selectedYourLanguages(select)
def setTargetLanguageAndCountry(select):
@@ -294,6 +299,8 @@ def setTargetLanguageAndCountry(select):
language, country = model.getLanguageAndCountry(select)
config.TARGET_LANGUAGE = language
config.TARGET_COUNTRY = country
view.updateSelectableTranslationEngineList(getLatestSelectableTranslationEngines())
view.setGuiVariable_SelectedTranslationEngine(config.CHOICE_OUTPUT_TRANSLATOR)
view.printToTextbox_selectedTargetLanguages(select)
def swapYourLanguageAndTargetLanguage():
@@ -329,6 +336,14 @@ def callbackSelectedLanguagePresetTab(selected_tab_no):
config.TARGET_LANGUAGE = language
config.TARGET_COUNTRY = country
view.printToTextbox_changedLanguagePresetTab(config.SELECTED_TAB_NO)
view.updateSelectableTranslationEngineList(getLatestSelectableTranslationEngines())
view.setGuiVariable_SelectedTranslationEngine(config.CHOICE_OUTPUT_TRANSLATOR)
def callbackSelectedTranslationEngine(selected_translation_engine):
print("callbackSelectedTranslationEngine", selected_translation_engine)
setYourTranslateEngine(selected_translation_engine)
setTargetTranslateEngine(selected_translation_engine)
view.setGuiVariable_SelectedTranslationEngine(config.CHOICE_OUTPUT_TRANSLATOR)
# command func
def callbackToggleTranslation(is_turned_on):
@@ -825,6 +840,7 @@ def createMainWindow():
initSetConfigByExeArguments()
initSetTranslateEngine()
initSetLanguageAndCountry()
view.updateSelectableTranslationEngineList(getLatestSelectableTranslationEngines())
if config.AUTH_KEYS["DeepL_API"] is not None:
if model.authenticationTranslatorDeepLAuthKey("DeepL_API", config.AUTH_KEYS["DeepL_API"]) is False:
@@ -876,6 +892,9 @@ def createMainWindow():
"callback_swap_languages": swapYourLanguageAndTargetLanguage,
"callback_selected_language_preset_tab": callbackSelectedLanguagePresetTab,
"callback_selected_translation_engine": callbackSelectedTranslationEngine,
"message_box_bind_Return": messageBoxPressKeyEnter,
"message_box_bind_Any_KeyPress": messageBoxPressKeyAny,
"message_box_bind_FocusIn": messageBoxFocusIn,

View File

@@ -9,6 +9,8 @@ main_window:
both_direction_desc: Translate Each Other
swap_button_label: Swap Languages
target_language: Target Language
translator: Translator
translator_ctranslate2: Internal
textbox_tab_all: All
textbox_tab_sent: Sent

View File

@@ -9,6 +9,8 @@ main_window:
both_direction_desc: 双方向に翻訳
swap_button_label: 言語を入れ替え
target_language: 相手の言語
translator: 翻訳エンジン
translator_ctranslate2: オフライン翻訳
textbox_tab_all: 全て
textbox_tab_sent: 送信

21
view.py
View File

@@ -35,6 +35,8 @@ class View():
else:
VERSION_TEXT=i18n.t("config_window.version", version=config.VERSION) + " (Speaker2Chatbox)"
self.TEXT_TRANSLATOR_CTRANSLATE2 = i18n.t("main_window.translator") + ": " + i18n.t("main_window.translator_ctranslate2")
self.settings = SimpleNamespace()
theme = get_appearance_mode() if config.APPEARANCE_THEME == "System" else config.APPEARANCE_THEME
all_ctm = ColorThemeManager(theme)
@@ -163,6 +165,8 @@ class View():
IS_OPENED_SELECTABLE_TARGET_LANGUAGE_WINDOW=False,
CALLBACK_SELECTED_TARGET_LANGUAGE=None,
VAR_SELECTED_TRANSLATION_ENGINE = StringVar(value="Translator: INIT"),
CALLBACK_SELECTED_TRANSLATION_ENGINE = None,
VAR_LABEL_TEXTBOX_ALL=StringVar(value=i18n.t("main_window.textbox_tab_all")),
VAR_LABEL_TEXTBOX_SENT=StringVar(value=i18n.t("main_window.textbox_tab_sent")),
@@ -515,6 +519,7 @@ class View():
self.view_variable.CALLBACK_SELECTED_LANGUAGE_PRESET_TAB = main_window_registers.get("callback_selected_language_preset_tab", None)
self.view_variable.CALLBACK_SELECTED_TRANSLATION_ENGINE = main_window_registers.get("callback_selected_translation_engine", None)
def adjustedMessageBoxReturnFunction(_e):
if self.view_variable.IS_ENTRY_MESSAGE_BOX_DISABLED is True:
@@ -899,6 +904,15 @@ class View():
case "SPEAKER_OFF":
vrct_gui.sls__box_target_language_speaker_status__enabled.place_forget()
def updateSelectableTranslationEngineList(self, selectable_translation_engines_list):
translation_dict = {item: item for item in selectable_translation_engines_list}
translation_dict["CTranslate2"] = self.TEXT_TRANSLATOR_CTRANSLATE2
vrct_gui.translation_engine_dropdown_menu_window.updateDropdownMenuValues(
dropdown_menu_widget_id="translation_engine_dropdown_menu",
dropdown_menu_values=translation_dict,
)
# Config Window
def enableConfigWindowCompactMode(self):
@@ -1332,6 +1346,13 @@ class View():
# Set GuiVariable (view_variable)
def setGuiVariable_SelectedTranslationEngine(self, value):
if value == "CTranslate2":
self.view_variable.VAR_SELECTED_TRANSLATION_ENGINE.set(self.TEXT_TRANSLATOR_CTRANSLATE2)
value = self.TEXT_TRANSLATOR_CTRANSLATE2
else:
self.view_variable.VAR_SELECTED_TRANSLATION_ENGINE.set(i18n.t("main_window.translator") + ": " + value)
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))

View File

@@ -1,9 +1,10 @@
from typing import Union
from types import SimpleNamespace
from customtkinter import CTkToplevel, CTkFrame, CTkLabel, CTkFont
from time import sleep
from .ui_utils import bindButtonReleaseFunction, bindEnterAndLeaveColor, bindButtonPressColor, getLatestHeight, applyUiScalingAndFixTheBugScrollBar, getLatestWidth, getLongestText, CustomizedCTkScrollableFrame
from .ui_utils import bindButtonReleaseFunction, bindEnterAndLeaveColor, bindButtonPressColor, getLatestHeight, applyUiScalingAndFixTheBugScrollBar, getLatestWidth, getLongestText, getLongestText_Dict, CustomizedCTkScrollableFrame
from functools import partial
from utils import isEven, makeEven
@@ -90,7 +91,7 @@ class _CreateDropdownMenuWindow(CTkToplevel):
def updateDropdownMenuValues(self, dropdown_menu_widget_id, dropdown_menu_values):
def updateDropdownMenuValues(self, dropdown_menu_widget_id, dropdown_menu_values:Union[dict, list],):
self.dropdown_menu_widgets[dropdown_menu_widget_id].widget.destroy()
self.createDropdownMenuBox(
dropdown_menu_widget_id=dropdown_menu_widget_id,
@@ -105,7 +106,7 @@ class _CreateDropdownMenuWindow(CTkToplevel):
)
def createDropdownMenuBox(self, dropdown_menu_widget_id, dropdown_menu_values, command, wrapper_widget, attach_widget, dropdown_menu_min_width=None, dropdown_menu_height=None, max_display_length=None):
def createDropdownMenuBox(self, dropdown_menu_widget_id, dropdown_menu_values:Union[dict, list], command, wrapper_widget, attach_widget, dropdown_menu_min_width=None, dropdown_menu_height=None, max_display_length=None):
self.attach_widget = attach_widget
self.wrapper_widget = wrapper_widget
@@ -166,9 +167,12 @@ class _CreateDropdownMenuWindow(CTkToplevel):
self.dropdown_menu_container.grid_remove()
def _createDropdownMenuValues(self, dropdown_menu_widget_id, dropdown_menu_values, command):
def _createDropdownMenuValues(self, dropdown_menu_widget_id, dropdown_menu_values:Union[dict, list], command):
if isinstance(dropdown_menu_values, list):
longest_text = getLongestText(dropdown_menu_values)
elif isinstance(dropdown_menu_values, dict):
longest_text = getLongestText_Dict(dropdown_menu_values)
longest_text = getLongestText(dropdown_menu_values)
self.dropdown_menu_values_wrapper = CTkFrame(self.scroll_frame_container, corner_radius=0, fg_color=self.window_bg_color)
self.dropdown_menu_values_wrapper.grid(row=0, column=0, sticky="nsew")
self.dropdown_menu_values_wrapper.grid_columnconfigure(0, weight=1)
@@ -220,19 +224,31 @@ class _CreateDropdownMenuWindow(CTkToplevel):
row=0
for dropdown_menu_value in dropdown_menu_values:
IS_LIST_TYPE = False
if isinstance(dropdown_menu_values, list):
for_in_values = dropdown_menu_values
IS_LIST_TYPE = True
elif isinstance(dropdown_menu_values, dict):
for_in_values = dropdown_menu_values.keys()
IS_LIST_TYPE = False
row=0
for dropdown_menu_value in for_in_values:
dropdown_menu_value_wrapper = CTkFrame(self.dropdown_menu_values_wrapper, corner_radius=0, fg_color=self.values_bg_color, width=0, height=0, cursor="hand2")
dropdown_menu_value_wrapper.grid(row=row, column=0, pady=self.value_pady, sticky="nsew")
setattr(self, f"{dropdown_menu_widget_id}__{row}", dropdown_menu_value_wrapper)
if IS_LIST_TYPE is True:
dropdown_menu_value_text = dropdown_menu_value
else:
dropdown_menu_value_text = dropdown_menu_values[dropdown_menu_value]
dropdown_menu_value_wrapper.grid_rowconfigure((0,2), weight=1)
label_widget = CTkLabel(
dropdown_menu_value_wrapper,
text=dropdown_menu_value,
text=dropdown_menu_value_text,
height=0,
corner_radius=0,
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.value_font_size, weight="normal"),
@@ -252,7 +268,11 @@ class _CreateDropdownMenuWindow(CTkToplevel):
command(value)
self._withdraw()
callback = partial(optimizedCommand, dropdown_menu_value)
if IS_LIST_TYPE is True:
callback = partial(optimizedCommand, dropdown_menu_value_text)
else:
callback = partial(optimizedCommand, dropdown_menu_value)
bindButtonReleaseFunction([dropdown_menu_value_wrapper, label_widget], callback)
row+=1
@@ -267,7 +287,10 @@ class _CreateDropdownMenuWindow(CTkToplevel):
if self.active_dropdown_menu_widget is not None:
self.active_dropdown_menu_widget.grid_remove()
try:
self.active_dropdown_menu_widget.grid_remove()
except:
pass
target_data = self.dropdown_menu_widgets[dropdown_menu_widget_id]
self.attach_widget = target_data.attach_widget

View File

@@ -1,5 +1,7 @@
from customtkinter import CTkFont, CTkFrame, CTkLabel, CTkImage
from ...._CreateDropdownMenuWindow import _CreateDropdownMenuWindow
from ....ui_utils import bindEnterAndLeaveColor, bindButtonPressColor, bindButtonReleaseFunction, switchActiveTabAndPassiveTab, switchTabsColor, createOptionMenuBox, bindButtonFunctionAndColor, bindEnterAndLeaveFunction
from utils import callFunctionIfCallable
@@ -336,4 +338,106 @@ def createSidebarLanguagesSettings(settings, main_window, view_variable):
height=0,
corner_radius=0,
image=CTkImage(settings.image_file.HEADPHONES_ICON_DISABLED, size=settings.uism.SLS__BOX_TRANSCRIPTION_STATUS_IMAGE_SIZE),
)
)
sls__box_translation_optionmenu_wrapper = CTkFrame(main_window.sls__box_frame, corner_radius=0, fg_color=settings.ctm.SLS__BG_COLOR, width=0, height=0)
sls__box_translation_optionmenu_wrapper.grid(row=5, column=0, sticky="ew")
sls__box_translation_optionmenu_wrapper.grid_columnconfigure((0,2), weight=1, minsize=settings.uism.SLS__BOX_ARROWS_SWAP_BUTTON_PADX)
sls__box_translation_optionmenu_wrapper.grid_columnconfigure(1, weight=1)
main_window.translation_engine_dropdown_menu_window = _CreateDropdownMenuWindow(
settings=settings,
view_variable=main_window._view_variable,
window_additional_y_pos=4,
window_border_width=1,
scrollbar_ipadx=(2,2),
scrollbar_width=16,
value_ipadx=(8,0),
value_ipady=(6,6),
value_pady=0,
value_font_size=14,
dropdown_menu_default_min_width=200,
window_bg_color="#1f2022",
window_border_color="#7f8084",
values_bg_color="#323336",
values_hovered_bg_color="#4b4c4f",
values_clicked_bg_color="#292a2d",
values_text_color=settings.ctm.BASIC_TEXT_COLOR,
)
# main_window.translation_engine_dropdown_menu_window = _CreateDropdownMenuWindow(
# settings=settings.config_window,
# view_variable=main_window._view_variable,
# window_additional_y_pos=settings.config_window.uism.SB__DROPDOWN_MENU_WINDOW_ADDITIONAL_Y_POS,
# window_border_width=settings.config_window.uism.SB__DROPDOWN_MENU_WINDOW_BORDER_WIDTH,
# scrollbar_ipadx=settings.config_window.uism.SB__DROPDOWN_MENU_SCROLLBAR_IPADX,
# scrollbar_width=settings.config_window.uism.SB__DROPDOWN_MENU_SCROLLBAR_WIDTH,
# value_ipadx=settings.config_window.uism.SB__DROPDOWN_MENU_VALUE_IPADX,
# value_ipady=settings.config_window.uism.SB__DROPDOWN_MENU_VALUE_IPADY,
# value_pady=settings.config_window.uism.SB__DROPDOWN_MENU_VALUE_PADY,
# value_font_size=settings.config_window.uism.SB__DROPDOWN_MENU_VALUE_FONT_SIZE,
# dropdown_menu_default_min_width=settings.config_window.uism.SB__DROPDOWN_MENU_VALUE_DEFAULT_MIN_WIDTH,
# window_bg_color=settings.config_window.ctm.SB__DROPDOWN_MENU_WINDOW_BG_COLOR,
# window_border_color=settings.config_window.ctm.SB__DROPDOWN_MENU_WINDOW_BORDER_COLOR,
# values_bg_color=settings.config_window.ctm.SB__DROPDOWN_MENU_BG_COLOR,
# values_hovered_bg_color=settings.config_window.ctm.SB__DROPDOWN_MENU_HOVERED_BG_COLOR,
# values_clicked_bg_color=settings.config_window.ctm.SB__DROPDOWN_MENU_CLICKED_BG_COLOR,
# values_text_color=settings.config_window.ctm.BASIC_TEXT_COLOR,
# )
def adjustedCommand(value):
callFunctionIfCallable(view_variable.CALLBACK_SELECTED_TRANSLATION_ENGINE, value)
main_window.translation_engine_dropdown_menu_window.createDropdownMenuBox(
dropdown_menu_widget_id="translation_engine_dropdown_menu",
dropdown_menu_values=[],
command=adjustedCommand,
wrapper_widget=main_window,
attach_widget=sls__box_translation_optionmenu_wrapper,
dropdown_menu_min_width=200,
)
(sls__selected_translation_engine_box, optionmenu_label_widget, optionmenu_img_widget) = createOptionMenuBox(
parent_widget=sls__box_translation_optionmenu_wrapper,
optionmenu_bg_color=settings.ctm.SLS__BG_COLOR,
optionmenu_hovered_bg_color=settings.ctm.SLS__OPTIONMENU_HOVERED_BG_COLOR,
optionmenu_clicked_bg_color=settings.ctm.SLS__OPTIONMENU_CLICKED_BG_COLOR,
optionmenu_ipadx=(0,10),
optionmenu_ipady=6,
variable=view_variable.VAR_SELECTED_TRANSLATION_ENGINE,
font_family=settings.FONT_FAMILY,
font_size=12,
text_color=settings.ctm.LABELS_TEXT_COLOR,
image_file=settings.image_file.REFRESH_ICON.rotate(45),
image_size=(14,14),
# image_size=settings.uism.SLS__BOX_OPTION_MENU_ARROW_IMAGE_SIZE,
optionmenu_clicked_command=lambda _e: main_window.translation_engine_dropdown_menu_window.show(
dropdown_menu_widget_id="translation_engine_dropdown_menu"
),
optionmenu_position="center",
setattr_widget=main_window,
image_widget_attr_name="sls__arrow_img_select",
)
sls__selected_translation_engine_box.grid(row=0, column=1, sticky="ew")
optionmenu_img_widget.grid_remove()

View File

@@ -66,7 +66,7 @@ class UiScalingManager():
# Sidebar
# Sidebar Features
self.main.SF__LOGO_MAX_SIZE = self._calculateUiSize(120)
self.main.SF__LOGO_PADY = (self._calculateUiSize(12),self._calculateUiSize(8))
self.main.SF__LOGO_PADY = (self._calculateUiSize(10),self._calculateUiSize(6))
self.main.SF__LOGO_HEIGHT_FOR_ADJUSTMENT = (self._calculateUiSize(6))
self.main.SF__LABELS_IPADY = self._calculateUiSize(16)
@@ -84,34 +84,34 @@ class UiScalingManager():
# Sidebar Quick Language Settings, SQLS
self.main.SLS__TITLE_FONT_SIZE = self._calculateUiSize(16)
self.main.SLS__TITLE_PADY = (self._calculateUiSize(12), self._calculateUiSize(6))
self.main.SLS__TITLE_FONT_SIZE = self._calculateUiSize(14)
self.main.SLS__TITLE_PADY = (self._calculateUiSize(10), self._calculateUiSize(4))
self.main.SLS__PRESET_TAB_NUMBER_FONT_SIZE = self._calculateUiSize(16)
self.main.SLS__PRESET_TAB_NUMBER_HEIGHT = self._calculateUiSize(30)
self.main.SLS__PRESET_TAB_NUMBER_CORNER_RADIUS = self._calculateUiSize(6)
self.main.SLS__PRESET_TAB_NUMBER_ADJUSTED_HEIGHT = self._calculateUiSize(36)
self.main.SLS__BOX_TRANSCRIPTION_STATUS_IMAGE_SIZE = self.dupTuple(self._calculateUiSize(14))
self.main.SLS__BOX_TOP_PADY = self._calculateUiSize(12)
self.main.SLS__BOX_TRANSCRIPTION_STATUS_IMAGE_SIZE = self.dupTuple(self._calculateUiSize(14))
self.main.SLS__BOX_SECTION_TITLE_FONT_SIZE = self._calculateUiSize(16)
self.main.SLS__BOX_SECTION_TITLE_BOTTOM_PADY = self._calculateUiSize(10)
self.main.SLS__BOX_IPADX = self._calculateUiSize(10)
self.main.SLS__BOX_IPADY = (self._calculateUiSize(8),self._calculateUiSize(18))
self.main.SLS__BOX_IPADY = (self._calculateUiSize(8),self._calculateUiSize(14))
self.main.SLS__BOX_OPTION_MENU_FONT_SIZE = self._calculateUiSize(14)
self.main.SLS__BOX_OPTION_MENU_IPADY = self._calculateUiSize(2)
self.main.SLS__BOX_OPTION_MENU_ARROW_IMAGE_SIZE = (self._calculateUiSize(20), self._calculateUiSize(20))
self.main.SLS__BOX_OPTION_MENU_ARROW_IMAGE_SIZE = self.dupTuple(self._calculateUiSize(20))
# self.main.SLS__BOX_OPTION_MENU_WIDTH = self._calculateUiSize(200)
self.main.SLS__BOX_ARROWS_PADY = self._calculateUiSize(4)
self.main.SLS__BOX_ARROWS_PADY = self._calculateUiSize(6)
self.main.SLS__BOX_ARROWS_SWAP_BUTTON_CORNER_RADIUS = self._calculateUiSize(6)
self.main.SLS__BOX_ARROWS_SWAP_BUTTON_PADX = self._calculateUiSize(20)
self.main.SLS__BOX_ARROWS_SWAP_BUTTON_IPADX = self._calculateUiSize(8)
self.main.SLS__BOX_ARROWS_SWAP_BUTTON_IPADY = self._calculateUiSize(6)
self.main.SLS__BOX_ARROWS_SWAP_BUTTON_IPADY = self._calculateUiSize(4)
self.main.SLS__BOX_ARROWS_IMAGE_SIZE = self.dupTuple(self._calculateUiSize(16))
self.main.SLS__BOX_ARROWS_DESC_FONT_SIZE = self._calculateUiSize(12)
self.main.SLS__BOX_ARROWS_DESC_PADX = self._calculateUiSize(6)
self.main.SLS__BOX_TOP_PADY = self._calculateUiSize(16)
self.main.SIDEBAR_CONFIG_BUTTON_CORNER_RADIUS = self._calculateUiSize(6)
self.main.SIDEBAR_CONFIG_BUTTON_IMAGE_SIZE = self.main.SF__COMPACT_MODE_IMAGE_SIZE

View File

@@ -42,6 +42,17 @@ def getLongestText(text_list:list):
longest_text = text
return longest_text
def getLongestText_Dict(text_dict:dict):
max_length = 0
longest_text = ""
for key, text in text_dict.items():
if len(text) > max_length:
max_length = len(text)
longest_text = text
return longest_text
def calculateUiSize(default_size, scaling_float, is_allowed_odd:bool=False, is_zero_allowed:bool=False):
size = int(default_size * scaling_float)
size += 1 if not is_allowed_odd and size % 2 != 0 else 0