Merge branch 'UI_2.0' into develop
14
.gitignore
vendored
@@ -1,19 +1,7 @@
|
||||
build/
|
||||
dist/
|
||||
config.json
|
||||
VRC_ChatBox_translator.spec
|
||||
memo.txt
|
||||
app/
|
||||
booth/
|
||||
pyinstaller/
|
||||
VRCT.build/
|
||||
VRCT.dist/
|
||||
VRCT.onefile-build/
|
||||
VRCT.exe
|
||||
VRCT.spec
|
||||
deepl-translate/
|
||||
translators/
|
||||
test/
|
||||
*.pyc
|
||||
.vscode/
|
||||
lib/
|
||||
logs/
|
||||
65
README.jp.md
Normal file
@@ -0,0 +1,65 @@
|
||||
<div align="center">
|
||||
|
||||

|
||||
[](https://github.com/misyaguziya/VRCT/releases)
|
||||
[](https://github.com/misyaguziya/VRCT/releases)
|
||||
[](https://github.com/misyaguziya/VRCT/blob/master/LICENSE)
|
||||
[](https://misyaguziya.booth.pm/items/5155325)
|
||||
|
||||
| [English](./README.md) | **日本語** |
|
||||
|
||||
<h3>
|
||||
VRCTは翻訳や文字起こしでVRChatの会話をサポートするソフトウェアです。
|
||||
</h3>
|
||||
|
||||

|
||||
|
||||
<div align="left">
|
||||
|
||||
# ダウンロード&インストール
|
||||
好きな場所からダウンロードしてください。
|
||||
- [Github.com](https://github.com/misyaguziya/VRCT/releases/)
|
||||
- [BOOTH.pm](https://misyaguziya.booth.pm/items/5155325)
|
||||
|
||||
ダウンロードしてexeを起動するだけです。
|
||||
|
||||
# VRCTってなに?
|
||||
VRCTは話す言語の異なる人同士が会話を行うためにチャットもしくは音声の翻訳を行うことで会話をサポートするソフトウェアです。
|
||||
これらの機能はVRChat内で使用するために設計されています。
|
||||
※サポート対象外ですがその他の用途として映画鑑賞等でも使用されています。
|
||||
|
||||
VRCTはあなたの会話を以下でサポートをします。
|
||||
- 💬 **VRChatへのチャット送信機能**
|
||||
- 🌐 **翻訳機能**
|
||||
- 🎙 **マイクの文字起こし機能**
|
||||
- 🔈 **スピーカーの文字起こし機能**
|
||||
|
||||
# ドキュメント
|
||||
初期設定や基本機能、その他の機能についても記載してあります。
|
||||
- [Documents Link](https://mzsoftware.notion.site/VRCT-Documents-be79b7a165f64442ad8f326d86c22246?pvs=4)
|
||||
|
||||
# 使い方(Youtube)
|
||||
<div align="center">
|
||||
|
||||
[](https://www.youtube.com/watch?v=rUTad037n8Q)
|
||||
|
||||
<div align="left">
|
||||
|
||||
# pythonで実行したい場合
|
||||
1. 以下のバージョンのpythonをインストールしてください。
|
||||
`python version 3.11.5`
|
||||
2. packageのインストールとmain.pyを起動してください。
|
||||
```bash
|
||||
./install.bat
|
||||
python main.py
|
||||
```
|
||||
|
||||
## Author
|
||||
- [みしゃ(misyaguzi)](https://github.com/misyaguziya) (メイン開発)
|
||||
- [しいな(Shiina_12siy)](https://twitter.com/Shiina_12siy) (UI/UX, UI多言語対応)
|
||||
- [レラ](https://github.com/soumt-r) (翻訳:韓国語)
|
||||
- [どね]() (ロゴデザイン)
|
||||
|
||||
---
|
||||
|
||||
VRCT は VRChat によって承認されておらず、VRChat または VRChat の開発もしくは管理に公式に関与する者の見解や意見が反映されたものではありません。VRChat および関連するすべての財産は 米国VRChat, Incの商標または登録商標です。
|
||||
143
README.md
@@ -1,116 +1,65 @@
|
||||
<div align="center">
|
||||
|
||||

|
||||
[](https://github.com/misyaguziya/VRCT/releases)
|
||||
[](https://github.com/misyaguziya/VRCT/releases)
|
||||
[](https://github.com/misyaguziya/VRCT/blob/master/LICENSE)
|
||||
[](https://misyaguziya.booth.pm/items/5155325)
|
||||
|
||||
# VRCT (VRChat Chatbox Translator & Transcription)
|
||||
| **English** | [日本語](./README.jp.md) |
|
||||
|
||||
<h3>
|
||||
VRCT is software that supports VRChat conversations with translation and transcription.
|
||||
</h3>
|
||||
|
||||

|
||||
|
||||
<div align="left">
|
||||
|
||||
## Overview
|
||||
VRChatのChatBoxにOSC経由でメッセージを送信するツール
|
||||
翻訳エンジンを使用してメッセージとその翻訳部分を同時に送信することができる
|
||||
# Download & Install
|
||||
Download from anywhere you like.
|
||||
- [Github.com](https://github.com/misyaguziya/VRCT/releases/)
|
||||
- [BOOTH.pm](https://misyaguziya.booth.pm/items/5155325)
|
||||
|
||||
## Requirement
|
||||
- python 3.9.13
|
||||
- pillow
|
||||
- PyAudioWPatch
|
||||
- python-osc
|
||||
- customtkinter
|
||||
- deepl
|
||||
- deepl-translate(https://github.com/misyaguziya/deepl-translate)
|
||||
- translators(https://github.com/misyaguziya/translators)
|
||||
- custom_speech_recognition(https://github.com/misyaguziya/custom_speech_recognition)
|
||||
Just download and run the exe.
|
||||
|
||||
**deepl-translate/translators/custom_speech_recognitionについては追加実装をしています**
|
||||
**`pip install`でinstallした場合、動かないので注意**
|
||||
# What is VRCT?
|
||||
VRCT is software that supports conversations between people who speak different languages by providing chat or voice translation.
|
||||
These features are designed for use within VRChat.
|
||||
*Although not supported, it is also used for other purposes such as watching movies.
|
||||
|
||||
## install
|
||||
```bash
|
||||
./install.bat
|
||||
```
|
||||
VRCT supports your conversations with
|
||||
- 💬 **Send chat to VRChat**
|
||||
- 🌐 **Translation**
|
||||
- 🎙 **Transcription of audio from microphone**
|
||||
- 🔈 **Transcription of audio from Speaker**
|
||||
|
||||
## Usage
|
||||
```bash
|
||||
python VRCT.py
|
||||
```
|
||||
# Documents
|
||||
Initial setup, basic functions, and other features are also described.
|
||||
- [Documents Link](https://mzsoftware.notion.site/VRCT-Documents-be79b7a165f64442ad8f326d86c22246?pvs=4)
|
||||
|
||||
## Features
|
||||
# How to Use (YouTube)
|
||||
<div align="center">
|
||||
|
||||
### init
|
||||
0. VRChatのOSCを有効にする(重要)
|
||||
[](https://www.youtube.com/watch?v=rUTad037n8Q)
|
||||
|
||||
(任意)
|
||||
1. DeepLのAPIを使用するためにアカウント登録し、認証キーを取得する
|
||||
2. ギアアイコンのボタンでconfigウィンドウを開く
|
||||
3. ParameterタブのDeepL Auth Keyに認証キーを記載
|
||||
4. configウィンドウを閉じる
|
||||
<div align="left">
|
||||
|
||||
### Normal use
|
||||
1. メッセージボックスにメッセージを記入
|
||||
2. Enterキーを押し、メッセージを送信する
|
||||
|
||||
### About Checkboxes
|
||||
- translation: 翻訳の有効無効
|
||||
- voice2chatbox: マイクの音声を文字起こししてチャットボックスに送信する
|
||||
- speaker2log: スピーカーの音声から文字起こししてログに表示する
|
||||
- foreground: 最前面表示の有効無効
|
||||
|
||||
### About Textbox
|
||||
- log tab: すべてのログを表示
|
||||
- send tab: 送信したメッセージを表示
|
||||
- receive tab: 受信したメッセージを表示
|
||||
- system tab: 機能についてのメッセージを表示
|
||||
|
||||
### About Config Window
|
||||
- UI tab
|
||||
- Transparency: ウィンドウの透過度の調整
|
||||
- Appearance Theme: ウィンドウテーマを選択
|
||||
- UI Scaling: UIサイズを調整
|
||||
- Font Family: 表示フォントを選択
|
||||
- UI Language: UIの表示言語を選択
|
||||
- Translation tab
|
||||
- Select Translator: 翻訳エンジンの変更
|
||||
- Send Language: 送信するメッセージに対して翻訳する言語[source, target]を選択
|
||||
- Receive Language: 受信したメッセージに対して翻訳する言語[source, target]を選択
|
||||
- Transcription tab
|
||||
- Input Mic Host: マイクのホストAPIを選択
|
||||
- Input Mic Device: マイクを選択
|
||||
- Input Mic Voice Language: 入力する音声の言語
|
||||
- Input Mic Energy Threshold: 音声取得のしきい値
|
||||
- Check threshold point: Input Mic Energy Thresholdのしきい値を視覚化
|
||||
- Input Mic Dynamic Energy Threshold: 音声取得のしきい値の自動調整
|
||||
- Input Mic Phase Timeout: 文字起こしする音声時間の上限
|
||||
- Input Mic Record Timeout: 音声の区切りの無音時間
|
||||
- Input Mic Max Phrases: 保留する単語の上限
|
||||
- Input Mic Word Filter: MICの文字起こし時にWord Filterで設定した文字が入っていた場合にChatboxに表示しない (ex AAA,BBB,CCC)
|
||||
- Input Speaker Device: スピーカーを選択
|
||||
- Input Speaker Voice Language: 受信する音声の言語
|
||||
- Input Speaker Energy Threshold: 音声取得のしきい値
|
||||
- Check threshold point: Input Speaker Energy Thresholdのしきい値を視覚化
|
||||
- Input Speaker Dynamic Energy Threshold: 音声取得のしきい値の自動調整
|
||||
- Input Speaker Record Timeout: 音声の区切りの無音時間
|
||||
- Input Speaker Phase Timeout: 文字起こしする音声時間の上限
|
||||
- Input Speaker Max Phrases: 保留する単語の上限
|
||||
- Parameter tab
|
||||
- OSC IP address: 変更不要
|
||||
- OSC port: 変更不要
|
||||
- DeepL Auth key: DeepLの認証キーの設定
|
||||
- Message Format: 送信するメッセージのデコレーションの設定
|
||||
- [message]がメッセージボックスに記入したメッセージに置換される
|
||||
- [translation]が翻訳されたメッセージに置換される
|
||||
- 初期フォーマット:`[message]([translation])`
|
||||
- Others tab
|
||||
- Auto clear chat box: メッセージ送信後に書き込んだメッセージを空にする
|
||||
- **(New!) Notification XSOverlay: XSOverlayの通知機能を有効(VR only)**
|
||||
# If you want to run it in python
|
||||
1. Install the following version of python.
|
||||
`python version 3.11.5`
|
||||
2. Install package and run main.py.
|
||||
```bash
|
||||
./install.bat
|
||||
python main.py
|
||||
```
|
||||
|
||||
## Author
|
||||
みしゃ(misyaguzi)
|
||||
- Main開発
|
||||
- twitter: https://twitter.com/misya_ai
|
||||
- booth: https://misyaguziya.booth.pm/items/4814313
|
||||
- [みしゃ(misyaguzi)](https://github.com/misyaguziya) (Main Development)
|
||||
- [しいな(Shiina_12siy)](https://twitter.com/Shiina_12siy) (UI/UX, UI multilingual support)
|
||||
- [レラ](https://github.com/soumt-r) (Translation:Korean)
|
||||
- [どね]() (Logo Design)
|
||||
|
||||
しいな(Shiina_12siy)
|
||||
- Main開発, 翻訳(英語)
|
||||
---
|
||||
|
||||
レラ
|
||||
- 翻訳(韓国語)
|
||||
VRCT is not endorsed by VRChat and does not reflect the views or opinions of VRChat or anyone officially involved in producing or managing VRChat properties. VRChat and all associated properties are trademarks or registered trademarks of VRChat Inc. VRChat © VRChat Inc.
|
||||
125
README.txt
@@ -4,129 +4,14 @@
|
||||
# 概要
|
||||
VRChatで使用されるChatBoxをOSC経由でメッセージを送信するツールになります。
|
||||
翻訳エンジンを使用してメッセージとその翻訳部分を同時に送信することができます。
|
||||
(翻訳エンジンはDeepL,Google,Bingに対応)
|
||||
|
||||
# 使用方法
|
||||
初期設定時
|
||||
0. VRChatのOSCを有効にする(重要)
|
||||
|
||||
(任意)
|
||||
1. DeepLのAPIを使用するためにアカウント登録し、認証キーを取得する
|
||||
2. ギアアイコンのボタンでconfigウィンドウを開く
|
||||
3. ParameterタブのDeepL Auth Keyに認証キーを記載
|
||||
4. configウィンドウを閉じる
|
||||
|
||||
通常使用時
|
||||
1. メッセージボックスにメッセージを記入
|
||||
2. Enterキーを押し、メッセージを送信する
|
||||
|
||||
# その他の設定
|
||||
translation チェックボックス: 翻訳の有効無効
|
||||
voice2chatbox チェックボックス : マイクの音声を文字起こししてチャットボックスに送信する
|
||||
speaker2log チェックボックス : スピーカーの音声から文字起こししてログに表示する
|
||||
foreground チェックボックス: 最前面表示の有効無効
|
||||
|
||||
テキストボックス
|
||||
logタブ
|
||||
すべてのログを表示
|
||||
sendタブ
|
||||
送信したメッセージを表示
|
||||
receiveタブ
|
||||
受信したメッセージを表示
|
||||
systemタブ
|
||||
機能についてのメッセージを表示
|
||||
|
||||
configウィンドウ
|
||||
UIタブ
|
||||
Transparency: ウィンドウの透過度の調整
|
||||
Appearance Theme: ウィンドウテーマを選択
|
||||
UI Scaling: UIサイズを調整
|
||||
Font Family: 表示フォントを選択
|
||||
UI Language: UIの表示言語を選択
|
||||
Translationタブ
|
||||
Select Translator: 翻訳エンジンの変更
|
||||
Send Language: 送信するメッセージに対して翻訳する言語[source, target]を選択
|
||||
Receive Language: 受信したメッセージに対して翻訳する言語[source, target]を選択
|
||||
Transcriptionタブ
|
||||
Input Mic Host: マイクのホストAPIを選択
|
||||
Input Mic Device: マイクを選択
|
||||
Input Mic Voice Language: 入力する音声の言語
|
||||
Input Mic Energy Threshold: 音声取得のしきい値
|
||||
Check threshold point: Input Mic Energy Thresholdのしきい値を視覚化
|
||||
Input Mic Dynamic Energy Threshold: 音声取得のしきい値の自動調整
|
||||
Input Mic Record Timeout: 音声の区切りの無音時間
|
||||
Input Mic Phase Timeout: 文字起こしする音声時間の上限
|
||||
Input Mic Max Phrases: 保留する単語の上限
|
||||
Input Mic Word Filter: MICの文字起こし時にWord Filterで設定した文字が入っていた場合にChatboxに表示しない (ex AAA,BBB,CCC)
|
||||
Input Speaker Device: スピーカーを選択
|
||||
Input Speaker Voice Language: 受信する音声の言語
|
||||
Input Speaker Energy Threshold: 音声取得のしきい値
|
||||
Check threshold point: Input Speaker Energy Thresholdのしきい値を視覚化
|
||||
Input Speaker Dynamic Energy Threshold: 音声取得のしきい値の自動調整
|
||||
Input Speaker Record Timeout: 音声の区切りの無音時間
|
||||
Input Speaker Phase Timeout: 文字起こしする音声時間の上限
|
||||
Input Speaker Max Phrases: 保留する単語の上限
|
||||
Parameterタブ
|
||||
OSC IP address: 変更不要
|
||||
OSC port: 変更不要
|
||||
DeepL Auth key: DeepLの認証キーの設定
|
||||
Message Format: 送信するメッセージのデコレーションの設定
|
||||
[message]がメッセージボックスに記入したメッセージに置換される
|
||||
[translation]が翻訳されたメッセージに置換される
|
||||
初期フォーマット:"[message]([translation])"
|
||||
Othersタブ
|
||||
Auto clear chat box: メッセージ送信後に書き込んだメッセージを空にする
|
||||
(New!) Notification XSOverlay: XSOverlayの通知機能を有効(VR only)
|
||||
|
||||
設定の初期化
|
||||
config.jsonを削除
|
||||
ドキュメント(JP):https://mzsoftware.notion.site/VRCT-Documents-be79b7a165f64442ad8f326d86c22246?pvs=4
|
||||
|
||||
# お問い合わせ
|
||||
要望などはTwitterまで
|
||||
https://twitter.com/misya_ai
|
||||
Googleフォーム:https://t.co/lSlo4brZwm
|
||||
Twitter:https://twitter.com/misya_ai
|
||||
Github:https://github.com/misyaguziya/VRCT
|
||||
|
||||
# アップデート履歴
|
||||
[2023-05-29: v0.1b] v0.1b リリース
|
||||
[2023-05-30: v0.2b]
|
||||
- configボタンをギアアイコンに変更
|
||||
- 詳細情報のボタンを追加
|
||||
- 翻訳機能有効無効のチェックボックスを追加
|
||||
- 最前面表示の有効無効のチェックボックスを追加
|
||||
- いくつかのバグを修正
|
||||
[2023-06-03: v0.3b]
|
||||
- 全体的にUIを刷新
|
||||
- 透過機能を追加
|
||||
- テーマのLight/Dark/Systemのモードの変更機能を追加
|
||||
- UIのスケール変更機能を追加
|
||||
- フォントの変更機能を追加
|
||||
[2023-06-06: v0.4b]
|
||||
- 翻訳エンジンを追加
|
||||
- 入力と出力の翻訳言語を選択できるように変更
|
||||
[2023-06-20: v1.0]
|
||||
- マイクからの音声の文字起こし機能を追加
|
||||
- スピーカーからの音声の文字起こし機能を追加
|
||||
[2023-06-28: v1.1]
|
||||
- いくつかのバクを修正
|
||||
- 翻訳/文字起こし言語の表記を略称からわかりやすい文字に変更
|
||||
- 文字起こしの処理の軽量化
|
||||
[2023-07-05: v1.2]
|
||||
- 文字起こし精度の向上
|
||||
[2023-07-21: v1.3]
|
||||
- UIの表示言語を日本語/英語を選択できる機能を追加
|
||||
- Energy Thresholdの視覚化機能を追加
|
||||
- 文字起こしの誤認識対策のため、Word Filterを追加
|
||||
- WASAPI以外のHostAPIでもマイクとして使用できるようにHostAPIを選択できる機能を追加
|
||||
- メッセージ送信後に書き込んだメッセージを空にするか選択できる機能を追加
|
||||
- バグ対策のため、translation/voice2chatbox/speaker2log/foregroundは起動時はOFFになるように変更
|
||||
- バグ対策のため、スピーカーについて既定デバイス以外を選択した時にERRORが出るように変更
|
||||
- 半角入力時に一部の文字が書き込めないバグを修正
|
||||
[2023-07-22: v1.3.1]
|
||||
- UIの表示言語選択に韓国語を追加
|
||||
[2023-07-30: v1.3.2]
|
||||
- 試験的にXSOverlayへの通知機能を追加
|
||||
- checkbox ONの状態でもConfigを開けるように変更
|
||||
- 文字起こし言語の表示を修正
|
||||
- いくつかのバグを修正
|
||||
|
||||
# 注意事項
|
||||
再配布とかはやめてね
|
||||
[2023-10-21: 2.0.0] v2.0.0 リリース
|
||||
499
VRCT.py
@@ -1,499 +0,0 @@
|
||||
from time import sleep
|
||||
from os import path as os_path
|
||||
|
||||
import customtkinter
|
||||
from customtkinter import CTk, CTkFrame, CTkCheckBox, CTkFont, CTkButton, CTkImage, CTkTabview, CTkTextbox, CTkEntry
|
||||
from PIL.Image import open as Image_open
|
||||
|
||||
from threading import Thread
|
||||
from utils import print_textbox, get_localized_text, widget_main_window_label_setter
|
||||
from window_config import ToplevelWindowConfig
|
||||
from window_information import ToplevelWindowInformation
|
||||
from config import config
|
||||
from model import model
|
||||
|
||||
class App(CTk):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
## set UI theme
|
||||
customtkinter.set_appearance_mode(config.APPEARANCE_THEME)
|
||||
customtkinter.set_default_color_theme("blue")
|
||||
|
||||
# init main window
|
||||
self.iconbitmap(os_path.join(os_path.dirname(__file__), "img", "app.ico"))
|
||||
self.title("VRCT")
|
||||
self.geometry(f"{400}x{175}")
|
||||
self.minsize(400, 175)
|
||||
self.grid_columnconfigure(1, weight=1)
|
||||
self.grid_rowconfigure(0, weight=1)
|
||||
self.wm_attributes("-alpha", config.TRANSPARENCY/100)
|
||||
customtkinter.set_widget_scaling(int(config.UI_SCALING.replace("%", "")) / 100)
|
||||
self.protocol("WM_DELETE_WINDOW", self.delete_window)
|
||||
|
||||
# add sidebar
|
||||
self.add_sidebar()
|
||||
|
||||
# add entry message box
|
||||
self.entry_message_box = CTkEntry(
|
||||
self,
|
||||
placeholder_text="message",
|
||||
font=CTkFont(family=config.FONT_FAMILY),
|
||||
)
|
||||
self.entry_message_box.grid(row=1, column=1, columnspan=2, padx=5, pady=(5, 10), sticky="nsew")
|
||||
self.entry_message_box.bind("<Return>", self.entry_message_box_press_key_enter)
|
||||
self.entry_message_box.bind("<Any-KeyPress>", self.entry_message_box_press_key_any)
|
||||
self.entry_message_box.bind("<Leave>", self.entry_message_box_leave)
|
||||
|
||||
# add tabview textbox
|
||||
self.add_tabview_logs(get_localized_text(f"{config.UI_LANGUAGE}"))
|
||||
|
||||
self.config_window = ToplevelWindowConfig(self)
|
||||
self.information_window = ToplevelWindowInformation(self)
|
||||
self.init_process()
|
||||
|
||||
def init_process(self):
|
||||
# set translator
|
||||
if model.authenticationTranslator() is False:
|
||||
# error update Auth key
|
||||
self.printLogAuthenticationError()
|
||||
|
||||
# set word filter
|
||||
model.addKeywords()
|
||||
|
||||
# check OSC started
|
||||
model.checkOSCStarted()
|
||||
|
||||
# check Software Updated
|
||||
model.checkSoftwareUpdated()
|
||||
|
||||
def button_config_callback(self):
|
||||
self.foreground_stop()
|
||||
self.transcription_stop()
|
||||
self.checkbox_translation.configure(state="disabled")
|
||||
self.checkbox_transcription_send.configure(state="disabled")
|
||||
self.checkbox_transcription_receive.configure(state="disabled")
|
||||
self.checkbox_foreground.configure(state="disabled")
|
||||
self.tabview_logs.configure(state="disabled")
|
||||
self.textbox_message_log.configure(state="disabled")
|
||||
self.textbox_message_send_log.configure(state="disabled")
|
||||
self.textbox_message_receive_log.configure(state="disabled")
|
||||
self.textbox_message_system_log.configure(state="disabled")
|
||||
self.entry_message_box.configure(state="disabled")
|
||||
self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"])
|
||||
self.button_information.configure(state="disabled", fg_color=["gray92", "gray14"])
|
||||
self.config_window.deiconify()
|
||||
self.config_window.focus_set()
|
||||
self.config_window.focus()
|
||||
self.config_window.grab_set()
|
||||
|
||||
def button_information_callback(self):
|
||||
self.information_window.deiconify()
|
||||
self.information_window.focus_set()
|
||||
self.information_window.focus()
|
||||
|
||||
def checkbox_translation_callback(self):
|
||||
config.ENABLE_TRANSLATION = self.checkbox_translation.get()
|
||||
if config.ENABLE_TRANSLATION is True:
|
||||
self.printLogStartTranslation()
|
||||
else:
|
||||
self.printLogStopTranslation()
|
||||
|
||||
def transcription_send_start(self):
|
||||
model.startMicTranscript(self.sendMicMessage)
|
||||
self.printLogStartVoice2chatbox()
|
||||
self.checkbox_transcription_send.configure(state="normal")
|
||||
self.checkbox_transcription_receive.configure(state="normal")
|
||||
self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
|
||||
def transcription_send_stop(self):
|
||||
model.stopMicTranscript()
|
||||
self.printLogStopVoice2chatbox()
|
||||
self.checkbox_transcription_send.configure(state="normal")
|
||||
self.checkbox_transcription_receive.configure(state="normal")
|
||||
self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
|
||||
def transcription_send_stop_for_config(self):
|
||||
model.stopMicTranscript()
|
||||
self.printLogStopVoice2chatbox()
|
||||
|
||||
def checkbox_transcription_send_callback(self):
|
||||
config.ENABLE_TRANSCRIPTION_SEND = self.checkbox_transcription_send.get()
|
||||
self.checkbox_transcription_send.configure(state="disabled")
|
||||
self.checkbox_transcription_receive.configure(state="disabled")
|
||||
self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"])
|
||||
if config.ENABLE_TRANSCRIPTION_SEND is True:
|
||||
th_transcription_send_start = Thread(target=self.transcription_send_start)
|
||||
th_transcription_send_start.daemon = True
|
||||
th_transcription_send_start.start()
|
||||
else:
|
||||
th_transcription_send_stop = Thread(target=self.transcription_send_stop)
|
||||
th_transcription_send_stop.daemon = True
|
||||
th_transcription_send_stop.start()
|
||||
|
||||
def transcription_receive_start(self):
|
||||
model.startSpeakerTranscript(self.receiveSpeakerMessage)
|
||||
self.printLogStartSpeaker2log()
|
||||
self.checkbox_transcription_send.configure(state="normal")
|
||||
self.checkbox_transcription_receive.configure(state="normal")
|
||||
self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
|
||||
def transcription_receive_stop(self):
|
||||
model.stopSpeakerTranscript()
|
||||
self.printLogStopSpeaker2log()
|
||||
self.checkbox_transcription_send.configure(state="normal")
|
||||
self.checkbox_transcription_receive.configure(state="normal")
|
||||
self.button_config.configure(state="normal", fg_color=["#3B8ED0", "#1F6AA5"])
|
||||
|
||||
def transcription_receive_stop_for_config(self):
|
||||
model.stopSpeakerTranscript()
|
||||
self.printLogStopSpeaker2log()
|
||||
|
||||
def checkbox_transcription_receive_callback(self):
|
||||
config.ENABLE_TRANSCRIPTION_RECEIVE = self.checkbox_transcription_receive.get()
|
||||
self.checkbox_transcription_send.configure(state="disabled")
|
||||
self.checkbox_transcription_receive.configure(state="disabled")
|
||||
self.button_config.configure(state="disabled", fg_color=["gray92", "gray14"])
|
||||
if config.ENABLE_TRANSCRIPTION_RECEIVE is True:
|
||||
th_transcription_receive_start = Thread(target=self.transcription_receive_start)
|
||||
th_transcription_receive_start.daemon = True
|
||||
th_transcription_receive_start.start()
|
||||
else:
|
||||
th_transcription_receive_stop = Thread(target=self.transcription_receive_stop)
|
||||
th_transcription_receive_stop.daemon = True
|
||||
th_transcription_receive_stop.start()
|
||||
|
||||
def transcription_start(self):
|
||||
if config.ENABLE_TRANSCRIPTION_SEND is True:
|
||||
th_transcription_send_start = Thread(target=self.transcription_send_start)
|
||||
th_transcription_send_start.daemon = True
|
||||
th_transcription_send_start.start()
|
||||
sleep(2)
|
||||
if config.ENABLE_TRANSCRIPTION_RECEIVE is True:
|
||||
th_transcription_receive_start = Thread(target=self.transcription_receive_start)
|
||||
th_transcription_receive_start.daemon = True
|
||||
th_transcription_receive_start.start()
|
||||
|
||||
def transcription_stop(self):
|
||||
if config.ENABLE_TRANSCRIPTION_SEND is True:
|
||||
th_transcription_send_stop = Thread(target=self.transcription_send_stop_for_config)
|
||||
th_transcription_send_stop.daemon = True
|
||||
th_transcription_send_stop.start()
|
||||
if config.ENABLE_TRANSCRIPTION_RECEIVE is True:
|
||||
th_transcription_receive_stop = Thread(target=self.transcription_receive_stop_for_config)
|
||||
th_transcription_receive_stop.daemon = True
|
||||
th_transcription_receive_stop.start()
|
||||
|
||||
def checkbox_foreground_callback(self):
|
||||
config.ENABLE_FOREGROUND = self.checkbox_foreground.get()
|
||||
if config.ENABLE_FOREGROUND:
|
||||
self.attributes("-topmost", True)
|
||||
self.printLogStartForeground()
|
||||
else:
|
||||
self.attributes("-topmost", False)
|
||||
self.printLogStopForeground()
|
||||
|
||||
def foreground_start(self):
|
||||
if config.ENABLE_FOREGROUND:
|
||||
self.attributes("-topmost", True)
|
||||
self.printLogStartForeground()
|
||||
|
||||
def foreground_stop(self):
|
||||
if config.ENABLE_FOREGROUND:
|
||||
self.attributes("-topmost", False)
|
||||
self.printLogStopForeground()
|
||||
|
||||
def entry_message_box_press_key_enter(self, event):
|
||||
# osc stop send typing
|
||||
model.oscStopSendTyping()
|
||||
|
||||
if config.ENABLE_FOREGROUND:
|
||||
self.attributes("-topmost", True)
|
||||
|
||||
message = self.entry_message_box.get()
|
||||
self.sendChatMessage(message)
|
||||
|
||||
def entry_message_box_press_key_any(self, event):
|
||||
# osc start send typing
|
||||
model.oscStartSendTyping()
|
||||
if config.ENABLE_FOREGROUND:
|
||||
self.attributes("-topmost", False)
|
||||
|
||||
if event.keysym != "??":
|
||||
if len(event.char) != 0 and event.keysym in config.BREAK_KEYSYM_LIST:
|
||||
self.entry_message_box.insert("end", event.char)
|
||||
return "break"
|
||||
|
||||
def entry_message_box_leave(self, event):
|
||||
# osc stop send typing
|
||||
model.oscStopSendTyping()
|
||||
if config.ENABLE_FOREGROUND:
|
||||
self.attributes("-topmost", True)
|
||||
|
||||
def delete_window(self):
|
||||
self.quit()
|
||||
self.destroy()
|
||||
|
||||
def add_sidebar(self):
|
||||
init_lang_text = "Loading..."
|
||||
self.sidebar_frame = CTkFrame(master=self, corner_radius=0)
|
||||
|
||||
# add checkbox translation
|
||||
self.checkbox_translation = CTkCheckBox(
|
||||
self.sidebar_frame,
|
||||
text=init_lang_text,
|
||||
onvalue=True,
|
||||
offvalue=False,
|
||||
command=self.checkbox_translation_callback,
|
||||
font=CTkFont(family=config.FONT_FAMILY)
|
||||
)
|
||||
|
||||
# add checkbox transcription send
|
||||
self.checkbox_transcription_send = CTkCheckBox(
|
||||
self.sidebar_frame,
|
||||
text=init_lang_text,
|
||||
onvalue=True,
|
||||
offvalue=False,
|
||||
command=self.checkbox_transcription_send_callback,
|
||||
font=CTkFont(family=config.FONT_FAMILY)
|
||||
)
|
||||
|
||||
# add checkbox transcription receive
|
||||
self.checkbox_transcription_receive = CTkCheckBox(
|
||||
self.sidebar_frame,
|
||||
text=init_lang_text,
|
||||
onvalue=True,
|
||||
offvalue=False,
|
||||
command=self.checkbox_transcription_receive_callback,
|
||||
font=CTkFont(family=config.FONT_FAMILY)
|
||||
)
|
||||
|
||||
# add checkbox foreground
|
||||
self.checkbox_foreground = CTkCheckBox(
|
||||
self.sidebar_frame,
|
||||
text=init_lang_text,
|
||||
onvalue=True,
|
||||
offvalue=False,
|
||||
command=self.checkbox_foreground_callback,
|
||||
font=CTkFont(family=config.FONT_FAMILY)
|
||||
)
|
||||
|
||||
# add button information
|
||||
self.button_information = CTkButton(
|
||||
self.sidebar_frame,
|
||||
text=None,
|
||||
width=36,
|
||||
command=self.button_information_callback,
|
||||
image=CTkImage(Image_open(os_path.join(os_path.dirname(__file__), "img", "info-icon-white.png")))
|
||||
)
|
||||
|
||||
# add button config
|
||||
self.button_config = CTkButton(
|
||||
self.sidebar_frame,
|
||||
text=None,
|
||||
width=36,
|
||||
command=self.button_config_callback,
|
||||
image=CTkImage(Image_open(os_path.join(os_path.dirname(__file__), "img", "config-icon-white.png")))
|
||||
)
|
||||
|
||||
self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsw")
|
||||
self.sidebar_frame.grid_rowconfigure(5, weight=1)
|
||||
self.checkbox_translation.grid(row=0, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we")
|
||||
self.checkbox_transcription_send.grid(row=1, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we")
|
||||
self.checkbox_transcription_receive.grid(row=2, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we")
|
||||
self.checkbox_foreground.grid(row=3, column=0, columnspan=2, padx=10, pady=(5, 5), sticky="we")
|
||||
self.button_information.grid(row=5, column=0, padx=(10, 5), pady=(5, 5), sticky="wse")
|
||||
self.button_config.grid(row=5, column=1, padx=(5, 10), pady=(5, 5), sticky="wse")
|
||||
|
||||
def delete_tabview_logs(self, pre_language_yaml_data):
|
||||
self.tabview_logs.delete(pre_language_yaml_data["main_tab_title_log"])
|
||||
self.tabview_logs.delete(pre_language_yaml_data["main_tab_title_send"])
|
||||
self.tabview_logs.delete(pre_language_yaml_data["main_tab_title_receive"])
|
||||
self.tabview_logs.delete(pre_language_yaml_data["main_tab_title_system"])
|
||||
|
||||
def add_tabview_logs(self, language_yaml_data):
|
||||
main_tab_title_log = language_yaml_data["main_tab_title_log"]
|
||||
main_tab_title_send = language_yaml_data["main_tab_title_send"]
|
||||
main_tab_title_receive = language_yaml_data["main_tab_title_receive"]
|
||||
main_tab_title_system = language_yaml_data["main_tab_title_system"]
|
||||
|
||||
# add tabview textbox
|
||||
self.tabview_logs = CTkTabview(master=self)
|
||||
self.tabview_logs.add(main_tab_title_log)
|
||||
self.tabview_logs.add(main_tab_title_send)
|
||||
self.tabview_logs.add(main_tab_title_receive)
|
||||
self.tabview_logs.add(main_tab_title_system)
|
||||
self.tabview_logs.grid(row=0, column=1, padx=0, pady=0, sticky="nsew")
|
||||
self.tabview_logs._segmented_button.configure(font=CTkFont(family=config.FONT_FAMILY))
|
||||
self.tabview_logs._segmented_button.grid(sticky="W")
|
||||
self.tabview_logs.tab(main_tab_title_log).grid_rowconfigure(0, weight=1)
|
||||
self.tabview_logs.tab(main_tab_title_log).grid_columnconfigure(0, weight=1)
|
||||
self.tabview_logs.tab(main_tab_title_send).grid_rowconfigure(0, weight=1)
|
||||
self.tabview_logs.tab(main_tab_title_send).grid_columnconfigure(0, weight=1)
|
||||
self.tabview_logs.tab(main_tab_title_receive).grid_rowconfigure(0, weight=1)
|
||||
self.tabview_logs.tab(main_tab_title_receive).grid_columnconfigure(0, weight=1)
|
||||
self.tabview_logs.tab(main_tab_title_system).grid_rowconfigure(0, weight=1)
|
||||
self.tabview_logs.tab(main_tab_title_system).grid_columnconfigure(0, weight=1)
|
||||
self.tabview_logs.configure(fg_color="transparent")
|
||||
|
||||
# add textbox message log
|
||||
self.textbox_message_log = CTkTextbox(
|
||||
self.tabview_logs.tab(main_tab_title_log),
|
||||
font=CTkFont(family=config.FONT_FAMILY)
|
||||
)
|
||||
|
||||
# add textbox message send log
|
||||
self.textbox_message_send_log = CTkTextbox(
|
||||
self.tabview_logs.tab(main_tab_title_send),
|
||||
font=CTkFont(family=config.FONT_FAMILY)
|
||||
)
|
||||
|
||||
# add textbox message receive log
|
||||
self.textbox_message_receive_log = CTkTextbox(
|
||||
self.tabview_logs.tab(main_tab_title_receive),
|
||||
font=CTkFont(family=config.FONT_FAMILY)
|
||||
)
|
||||
|
||||
# add textbox message system log
|
||||
self.textbox_message_system_log = CTkTextbox(
|
||||
self.tabview_logs.tab(main_tab_title_system),
|
||||
font=CTkFont(family=config.FONT_FAMILY)
|
||||
)
|
||||
|
||||
self.textbox_message_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew")
|
||||
self.textbox_message_send_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew")
|
||||
self.textbox_message_receive_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew")
|
||||
self.textbox_message_system_log.grid(row=0, column=0, padx=0, pady=0, sticky="nsew")
|
||||
self.textbox_message_log.configure(state='disabled')
|
||||
self.textbox_message_send_log.configure(state='disabled')
|
||||
self.textbox_message_receive_log.configure(state='disabled')
|
||||
self.textbox_message_system_log.configure(state='disabled')
|
||||
|
||||
widget_main_window_label_setter(self, language_yaml_data)
|
||||
|
||||
def printLogAuthenticationError(self):
|
||||
print_textbox(self.textbox_message_log, "Auth Key or language setting is incorrect", "ERROR")
|
||||
print_textbox(self.textbox_message_system_log, "Auth Key or language setting is incorrect", "ERROR")
|
||||
|
||||
def printLogStartTranslation(self):
|
||||
print_textbox(self.textbox_message_log, "Start translation", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Start translation", "INFO")
|
||||
|
||||
def printLogStopTranslation(self):
|
||||
print_textbox(self.textbox_message_log, "Stop translation", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Stop translation", "INFO")
|
||||
|
||||
def printLogStartVoice2chatbox(self):
|
||||
print_textbox(self.textbox_message_log, "Start voice2chatbox", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Start voice2chatbox", "INFO")
|
||||
|
||||
def printLogStopVoice2chatbox(self):
|
||||
print_textbox(self.textbox_message_log, "Stop voice2chatbox", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Stop voice2chatbox", "INFO")
|
||||
|
||||
def printLogStartSpeaker2log(self):
|
||||
print_textbox(self.textbox_message_log, "Start speaker2log", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Start speaker2log", "INFO")
|
||||
|
||||
def printLogStopSpeaker2log(self):
|
||||
print_textbox(self.textbox_message_log, "Stop speaker2log", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Stop speaker2log", "INFO")
|
||||
|
||||
def printLogStartForeground(self):
|
||||
print_textbox(self.textbox_message_log, "Start foreground", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Start foreground", "INFO")
|
||||
|
||||
def printLogStopForeground(self):
|
||||
print_textbox(self.textbox_message_log, "Stop foreground", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, "Stop foreground", "INFO")
|
||||
|
||||
def printLogDetectWordFilter(self, message):
|
||||
print_textbox(self.textbox_message_log, f"Detect WordFilter :{message}", "INFO")
|
||||
print_textbox(self.textbox_message_system_log, f"Detect WordFilter :{message}", "INFO")
|
||||
|
||||
def printLogOSCError(self):
|
||||
print_textbox(self.textbox_message_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR")
|
||||
print_textbox(self.textbox_message_system_log, "OSC is not enabled, please enable OSC and rejoin.", "ERROR")
|
||||
|
||||
def printLogSendMessage(self, message):
|
||||
print_textbox(self.textbox_message_log, f"{message}", "SEND")
|
||||
print_textbox(self.textbox_message_send_log, f"{message}", "SEND")
|
||||
|
||||
def printLogReceiveMessage(self, message):
|
||||
print_textbox(self.textbox_message_log, f"{message}", "RECEIVE")
|
||||
print_textbox(self.textbox_message_receive_log, f"{message}", "RECEIVE")
|
||||
|
||||
def sendChatMessage(self, message):
|
||||
if len(message) > 0:
|
||||
# translate
|
||||
if config.ENABLE_TRANSLATION is False:
|
||||
chat_message = f"{message}"
|
||||
elif model.getTranslatorStatus() is False:
|
||||
self.printLogAuthenticationError()
|
||||
chat_message = f"{message}"
|
||||
else:
|
||||
chat_message = model.getInputTranslate(message)
|
||||
|
||||
# send OSC message
|
||||
if config.ENABLE_OSC is True:
|
||||
model.oscSendMessage(chat_message)
|
||||
else:
|
||||
self.printLogOSCError()
|
||||
|
||||
# update textbox message log
|
||||
self.printLogSendMessage(chat_message)
|
||||
|
||||
# delete message in entry message box
|
||||
if config.ENABLE_AUTO_CLEAR_CHATBOX is True:
|
||||
self.entry_message_box.delete(0, customtkinter.END)
|
||||
|
||||
def sendMicMessage(self, message):
|
||||
if len(message) > 0:
|
||||
# word filter
|
||||
if model.checkKeywords(message):
|
||||
self.printLogDetectWordFilter(message)
|
||||
return
|
||||
|
||||
# translate
|
||||
if config.ENABLE_TRANSLATION is False:
|
||||
voice_message = f"{message}"
|
||||
elif model.getTranslatorStatus() is False:
|
||||
self.printLogAuthenticationError()
|
||||
voice_message = f"{message}"
|
||||
else:
|
||||
voice_message = model.getInputTranslate(message)
|
||||
|
||||
if config.ENABLE_TRANSCRIPTION_SEND is True:
|
||||
if config.ENABLE_OSC is True:
|
||||
# osc send message
|
||||
model.oscSendMessage(voice_message)
|
||||
else:
|
||||
self.printLogOSCError()
|
||||
# update textbox message log
|
||||
self.printLogSendMessage(voice_message)
|
||||
|
||||
def receiveSpeakerMessage(self, message):
|
||||
if len(message) > 0:
|
||||
# translate
|
||||
if config.ENABLE_TRANSLATION is False:
|
||||
voice_message = f"{message}"
|
||||
elif model.getTranslatorStatus() is False:
|
||||
self.printLogAuthenticationError()
|
||||
voice_message = f"{message}"
|
||||
else:
|
||||
voice_message = model.getOutputTranslate(message)
|
||||
|
||||
if config.ENABLE_TRANSCRIPTION_RECEIVE is True:
|
||||
# update textbox message receive log
|
||||
self.printLogReceiveMessage(voice_message)
|
||||
if config.ENABLE_NOTICE_XSOVERLAY is True:
|
||||
model.notificationXsoverlay(voice_message)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
app = App()
|
||||
app.mainloop()
|
||||
except Exception as e:
|
||||
import traceback
|
||||
with open('error.log', 'a') as f:
|
||||
traceback.print_exc(file=f)
|
||||
4
batch/restart.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
@if not "%~0"=="%~dp0.\%~nx0" start /min cmd /c,"%~dp0.\%~nx0" %* & goto :eof
|
||||
|
||||
taskkill /im %1 /F
|
||||
START "" %1
|
||||
11
batch/update.bat
Normal file
@@ -0,0 +1,11 @@
|
||||
@if not "%~0"=="%~dp0.\%~nx0" start /min cmd /c,"%~dp0.\%~nx0" %* & goto :eof
|
||||
|
||||
taskkill /im %1 /F
|
||||
ping -n 2 127.0.0.1 > nul
|
||||
del /f %1
|
||||
ping -n 2 127.0.0.1 > nul
|
||||
rename %2 %1
|
||||
ping -n 2 127.0.0.1 > nul
|
||||
if %3 == True (
|
||||
START "" %1
|
||||
)
|
||||
1
build.bat
Normal file
@@ -0,0 +1 @@
|
||||
pyinstaller --onedir --onefile --windowed --clean --icon="./img/vrct_logo_mark_black.ico" --add-data "./img;img/" --add-data "./locales;locales/" --add-data "./batch;batch/" --name VRCT --exclude-module numpy --exclude-module pandas --exclude-module matplotlib --exclude-module PyQt5 main.py
|
||||
395
config.py
@@ -1,4 +1,4 @@
|
||||
from json import load, dump
|
||||
import sys
|
||||
import inspect
|
||||
from os import path as os_path
|
||||
from json import load as json_load
|
||||
@@ -6,16 +6,23 @@ from json import dump as json_dump
|
||||
import tkinter as tk
|
||||
from tkinter import font
|
||||
from languages import selectable_languages
|
||||
from models.translation.translation_languages import translatorEngine, translation_lang
|
||||
from models.transcription.transcription_languages import transcription_lang
|
||||
from models.transcription.transcription_utils import getInputDevices, getOutputDevices, getDefaultInputDevice, getDefaultOutputDevice
|
||||
from models.translation.translation_languages import translatorEngine
|
||||
from models.transcription.transcription_utils import getInputDevices, getDefaultInputDevice
|
||||
from utils import generatePercentageStringsList
|
||||
|
||||
json_serializable_vars = {}
|
||||
def json_serializable(var_name):
|
||||
def decorator(func):
|
||||
json_serializable_vars[var_name] = func
|
||||
return func
|
||||
return decorator
|
||||
|
||||
def saveJson(path, key, value):
|
||||
with open(path, "r") as fp:
|
||||
json_data = load(fp)
|
||||
with open(path, "r", encoding="utf-8") as fp:
|
||||
json_data = json_load(fp)
|
||||
json_data[key] = value
|
||||
with open(path, "w") as fp:
|
||||
dump(json_data, fp, indent=4)
|
||||
with open(path, "w", encoding="utf-8") as fp:
|
||||
json_dump(json_data, fp, indent=4, ensure_ascii=False)
|
||||
|
||||
class Config:
|
||||
_instance = None
|
||||
@@ -27,6 +34,7 @@ class Config:
|
||||
cls._instance.load_config()
|
||||
return cls._instance
|
||||
|
||||
# Read Only
|
||||
@property
|
||||
def VERSION(self):
|
||||
return self._VERSION
|
||||
@@ -35,6 +43,27 @@ class Config:
|
||||
def PATH_CONFIG(self):
|
||||
return self._PATH_CONFIG
|
||||
|
||||
@property
|
||||
def GITHUB_URL(self):
|
||||
return self._GITHUB_URL
|
||||
|
||||
@property
|
||||
def BOOTH_URL(self):
|
||||
return self._BOOTH_URL
|
||||
|
||||
@property
|
||||
def DOCUMENTS_URL(self):
|
||||
return self._DOCUMENTS_URL
|
||||
|
||||
@property
|
||||
def MAX_MIC_ENERGY_THRESHOLD(self):
|
||||
return self._MAX_MIC_ENERGY_THRESHOLD
|
||||
|
||||
@property
|
||||
def MAX_SPEAKER_ENERGY_THRESHOLD(self):
|
||||
return self._MAX_SPEAKER_ENERGY_THRESHOLD
|
||||
|
||||
# Read Write
|
||||
@property
|
||||
def ENABLE_TRANSLATION(self):
|
||||
return self._ENABLE_TRANSLATION
|
||||
@@ -72,6 +101,99 @@ class Config:
|
||||
self._ENABLE_FOREGROUND = value
|
||||
|
||||
@property
|
||||
def SOURCE_COUNTRY(self):
|
||||
return self._SOURCE_COUNTRY
|
||||
|
||||
@SOURCE_COUNTRY.setter
|
||||
def SOURCE_COUNTRY(self, value):
|
||||
if type(value) is str:
|
||||
self._SOURCE_COUNTRY = value
|
||||
|
||||
@property
|
||||
def SOURCE_LANGUAGE(self):
|
||||
return self._SOURCE_LANGUAGE
|
||||
|
||||
@SOURCE_LANGUAGE.setter
|
||||
def SOURCE_LANGUAGE(self, value):
|
||||
if type(value) is str:
|
||||
self._SOURCE_LANGUAGE = value
|
||||
|
||||
@property
|
||||
def TARGET_COUNTRY(self):
|
||||
return self._TARGET_COUNTRY
|
||||
|
||||
@TARGET_COUNTRY.setter
|
||||
def TARGET_COUNTRY(self, value):
|
||||
if type(value) is str:
|
||||
self._TARGET_COUNTRY = value
|
||||
|
||||
@property
|
||||
def TARGET_LANGUAGE(self):
|
||||
return self._TARGET_LANGUAGE
|
||||
|
||||
@TARGET_LANGUAGE.setter
|
||||
def TARGET_LANGUAGE(self, value):
|
||||
if type(value) is str:
|
||||
self._TARGET_LANGUAGE = value
|
||||
|
||||
@property
|
||||
def CHOICE_TRANSLATOR(self):
|
||||
return self._CHOICE_TRANSLATOR
|
||||
|
||||
@CHOICE_TRANSLATOR.setter
|
||||
def CHOICE_TRANSLATOR(self, value):
|
||||
if value in translatorEngine:
|
||||
self._CHOICE_TRANSLATOR = value
|
||||
|
||||
# Save Json Data
|
||||
## Main Window
|
||||
@property
|
||||
@json_serializable('SELECTED_TAB_NO')
|
||||
def SELECTED_TAB_NO(self):
|
||||
return self._SELECTED_TAB_NO
|
||||
|
||||
@SELECTED_TAB_NO.setter
|
||||
def SELECTED_TAB_NO(self, value):
|
||||
if type(value) is str:
|
||||
self._SELECTED_TAB_NO = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('SELECTED_TAB_YOUR_LANGUAGES')
|
||||
def SELECTED_TAB_YOUR_LANGUAGES(self):
|
||||
return self._SELECTED_TAB_YOUR_LANGUAGES
|
||||
|
||||
@SELECTED_TAB_YOUR_LANGUAGES.setter
|
||||
def SELECTED_TAB_YOUR_LANGUAGES(self, value):
|
||||
if type(value) is dict:
|
||||
self._SELECTED_TAB_YOUR_LANGUAGES = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('SELECTED_TAB_TARGET_LANGUAGES')
|
||||
def SELECTED_TAB_TARGET_LANGUAGES(self):
|
||||
return self._SELECTED_TAB_TARGET_LANGUAGES
|
||||
|
||||
@SELECTED_TAB_TARGET_LANGUAGES.setter
|
||||
def SELECTED_TAB_TARGET_LANGUAGES(self, value):
|
||||
if type(value) is dict:
|
||||
self._SELECTED_TAB_TARGET_LANGUAGES = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE')
|
||||
def IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE(self):
|
||||
return self._IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE
|
||||
|
||||
@IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE.setter
|
||||
def IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE(self, value):
|
||||
if type(value) is bool:
|
||||
self._IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
## Config Window
|
||||
@property
|
||||
@json_serializable('TRANSPARENCY')
|
||||
def TRANSPARENCY(self):
|
||||
return self._TRANSPARENCY
|
||||
|
||||
@@ -82,6 +204,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('APPEARANCE_THEME')
|
||||
def APPEARANCE_THEME(self):
|
||||
return self._APPEARANCE_THEME
|
||||
|
||||
@@ -92,16 +215,18 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('UI_SCALING')
|
||||
def UI_SCALING(self):
|
||||
return self._UI_SCALING
|
||||
|
||||
@UI_SCALING.setter
|
||||
def UI_SCALING(self, value):
|
||||
if value in ["80%", "90%", "100%", "110%", "120%"]:
|
||||
if value in generatePercentageStringsList(start=40,end=200, step=10):
|
||||
self._UI_SCALING = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('FONT_FAMILY')
|
||||
def FONT_FAMILY(self):
|
||||
return self._FONT_FAMILY
|
||||
|
||||
@@ -115,6 +240,7 @@ class Config:
|
||||
root.destroy()
|
||||
|
||||
@property
|
||||
@json_serializable('UI_LANGUAGE')
|
||||
def UI_LANGUAGE(self):
|
||||
return self._UI_LANGUAGE
|
||||
|
||||
@@ -125,56 +251,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def CHOICE_TRANSLATOR(self):
|
||||
return self._CHOICE_TRANSLATOR
|
||||
|
||||
@CHOICE_TRANSLATOR.setter
|
||||
def CHOICE_TRANSLATOR(self, value):
|
||||
if value in translatorEngine:
|
||||
self._CHOICE_TRANSLATOR = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def INPUT_SOURCE_LANG(self):
|
||||
return self._INPUT_SOURCE_LANG
|
||||
|
||||
@INPUT_SOURCE_LANG.setter
|
||||
def INPUT_SOURCE_LANG(self, value):
|
||||
if value in list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys()):
|
||||
self._INPUT_SOURCE_LANG = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def INPUT_TARGET_LANG(self):
|
||||
return self._INPUT_TARGET_LANG
|
||||
|
||||
@INPUT_TARGET_LANG.setter
|
||||
def INPUT_TARGET_LANG(self, value):
|
||||
if value in list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys()):
|
||||
self._INPUT_TARGET_LANG = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def OUTPUT_SOURCE_LANG(self):
|
||||
return self._OUTPUT_SOURCE_LANG
|
||||
|
||||
@OUTPUT_SOURCE_LANG.setter
|
||||
def OUTPUT_SOURCE_LANG(self, value):
|
||||
if value in list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys()):
|
||||
self._OUTPUT_SOURCE_LANG = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def OUTPUT_TARGET_LANG(self):
|
||||
return self._OUTPUT_TARGET_LANG
|
||||
|
||||
@OUTPUT_TARGET_LANG.setter
|
||||
def OUTPUT_TARGET_LANG(self, value):
|
||||
if value in list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys()):
|
||||
self._OUTPUT_TARGET_LANG = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('CHOICE_MIC_HOST')
|
||||
def CHOICE_MIC_HOST(self):
|
||||
return self._CHOICE_MIC_HOST
|
||||
|
||||
@@ -185,6 +262,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('CHOICE_MIC_DEVICE')
|
||||
def CHOICE_MIC_DEVICE(self):
|
||||
return self._CHOICE_MIC_DEVICE
|
||||
|
||||
@@ -195,16 +273,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def INPUT_MIC_VOICE_LANGUAGE(self):
|
||||
return self._INPUT_MIC_VOICE_LANGUAGE
|
||||
|
||||
@INPUT_MIC_VOICE_LANGUAGE.setter
|
||||
def INPUT_MIC_VOICE_LANGUAGE(self, value):
|
||||
if value in list(transcription_lang.keys()):
|
||||
self._INPUT_MIC_VOICE_LANGUAGE = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('INPUT_MIC_ENERGY_THRESHOLD')
|
||||
def INPUT_MIC_ENERGY_THRESHOLD(self):
|
||||
return self._INPUT_MIC_ENERGY_THRESHOLD
|
||||
|
||||
@@ -215,6 +284,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD')
|
||||
def INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD(self):
|
||||
return self._INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD
|
||||
|
||||
@@ -225,6 +295,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('INPUT_MIC_RECORD_TIMEOUT')
|
||||
def INPUT_MIC_RECORD_TIMEOUT(self):
|
||||
return self._INPUT_MIC_RECORD_TIMEOUT
|
||||
|
||||
@@ -235,6 +306,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('INPUT_MIC_PHRASE_TIMEOUT')
|
||||
def INPUT_MIC_PHRASE_TIMEOUT(self):
|
||||
return self._INPUT_MIC_PHRASE_TIMEOUT
|
||||
|
||||
@@ -245,6 +317,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('INPUT_MIC_MAX_PHRASES')
|
||||
def INPUT_MIC_MAX_PHRASES(self):
|
||||
return self._INPUT_MIC_MAX_PHRASES
|
||||
|
||||
@@ -255,6 +328,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('INPUT_MIC_WORD_FILTER')
|
||||
def INPUT_MIC_WORD_FILTER(self):
|
||||
return self._INPUT_MIC_WORD_FILTER
|
||||
|
||||
@@ -265,28 +339,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def CHOICE_SPEAKER_DEVICE(self):
|
||||
return self._CHOICE_SPEAKER_DEVICE
|
||||
|
||||
@CHOICE_SPEAKER_DEVICE.setter
|
||||
def CHOICE_SPEAKER_DEVICE(self, value):
|
||||
if value in [device["name"] for device in getOutputDevices()]:
|
||||
speaker_device = [device for device in getOutputDevices() if device["name"] == value][0]
|
||||
if getDefaultOutputDevice()["index"] == speaker_device["index"]:
|
||||
self._CHOICE_SPEAKER_DEVICE = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def INPUT_SPEAKER_VOICE_LANGUAGE(self):
|
||||
return self._INPUT_SPEAKER_VOICE_LANGUAGE
|
||||
|
||||
@INPUT_SPEAKER_VOICE_LANGUAGE.setter
|
||||
def INPUT_SPEAKER_VOICE_LANGUAGE(self, value):
|
||||
if value in list(transcription_lang.keys()):
|
||||
self._INPUT_SPEAKER_VOICE_LANGUAGE = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('INPUT_SPEAKER_ENERGY_THRESHOLD')
|
||||
def INPUT_SPEAKER_ENERGY_THRESHOLD(self):
|
||||
return self._INPUT_SPEAKER_ENERGY_THRESHOLD
|
||||
|
||||
@@ -297,6 +350,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD')
|
||||
def INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD(self):
|
||||
return self._INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD
|
||||
|
||||
@@ -307,6 +361,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('INPUT_SPEAKER_RECORD_TIMEOUT')
|
||||
def INPUT_SPEAKER_RECORD_TIMEOUT(self):
|
||||
return self._INPUT_SPEAKER_RECORD_TIMEOUT
|
||||
|
||||
@@ -317,6 +372,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('INPUT_SPEAKER_PHRASE_TIMEOUT')
|
||||
def INPUT_SPEAKER_PHRASE_TIMEOUT(self):
|
||||
return self._INPUT_SPEAKER_PHRASE_TIMEOUT
|
||||
|
||||
@@ -327,6 +383,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('INPUT_SPEAKER_MAX_PHRASES')
|
||||
def INPUT_SPEAKER_MAX_PHRASES(self):
|
||||
return self._INPUT_SPEAKER_MAX_PHRASES
|
||||
|
||||
@@ -337,6 +394,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('OSC_IP_ADDRESS')
|
||||
def OSC_IP_ADDRESS(self):
|
||||
return self._OSC_IP_ADDRESS
|
||||
|
||||
@@ -347,6 +405,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('OSC_PORT')
|
||||
def OSC_PORT(self):
|
||||
return self._OSC_PORT
|
||||
|
||||
@@ -357,6 +416,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('AUTH_KEYS')
|
||||
def AUTH_KEYS(self):
|
||||
return self._AUTH_KEYS
|
||||
|
||||
@@ -369,6 +429,7 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, self.AUTH_KEYS)
|
||||
|
||||
@property
|
||||
@json_serializable('MESSAGE_FORMAT')
|
||||
def MESSAGE_FORMAT(self):
|
||||
return self._MESSAGE_FORMAT
|
||||
|
||||
@@ -379,16 +440,18 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def ENABLE_AUTO_CLEAR_CHATBOX(self):
|
||||
return self._ENABLE_AUTO_CLEAR_CHATBOX
|
||||
@json_serializable('ENABLE_AUTO_CLEAR_MESSAGE_BOX')
|
||||
def ENABLE_AUTO_CLEAR_MESSAGE_BOX(self):
|
||||
return self._ENABLE_AUTO_CLEAR_MESSAGE_BOX
|
||||
|
||||
@ENABLE_AUTO_CLEAR_CHATBOX.setter
|
||||
def ENABLE_AUTO_CLEAR_CHATBOX(self, value):
|
||||
@ENABLE_AUTO_CLEAR_MESSAGE_BOX.setter
|
||||
def ENABLE_AUTO_CLEAR_MESSAGE_BOX(self, value):
|
||||
if type(value) is bool:
|
||||
self._ENABLE_AUTO_CLEAR_CHATBOX = value
|
||||
self._ENABLE_AUTO_CLEAR_MESSAGE_BOX = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
@json_serializable('ENABLE_NOTICE_XSOVERLAY')
|
||||
def ENABLE_NOTICE_XSOVERLAY(self):
|
||||
return self._ENABLE_NOTICE_XSOVERLAY
|
||||
|
||||
@@ -399,109 +462,133 @@ class Config:
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def ENABLE_OSC(self):
|
||||
return self._ENABLE_OSC
|
||||
@json_serializable('ENABLE_SEND_MESSAGE_TO_VRC')
|
||||
def ENABLE_SEND_MESSAGE_TO_VRC(self):
|
||||
return self._ENABLE_SEND_MESSAGE_TO_VRC
|
||||
|
||||
@ENABLE_OSC.setter
|
||||
def ENABLE_OSC(self, value):
|
||||
@ENABLE_SEND_MESSAGE_TO_VRC.setter
|
||||
def ENABLE_SEND_MESSAGE_TO_VRC(self, value):
|
||||
if type(value) is bool:
|
||||
self._ENABLE_OSC = value
|
||||
self._ENABLE_SEND_MESSAGE_TO_VRC = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
# [deprecated]
|
||||
# @property
|
||||
# @json_serializable('STARTUP_OSC_ENABLED_CHECK')
|
||||
# def STARTUP_OSC_ENABLED_CHECK(self):
|
||||
# return self._STARTUP_OSC_ENABLED_CHECK
|
||||
|
||||
# @STARTUP_OSC_ENABLED_CHECK.setter
|
||||
# def STARTUP_OSC_ENABLED_CHECK(self, value):
|
||||
# if type(value) is bool:
|
||||
# self._STARTUP_OSC_ENABLED_CHECK = value
|
||||
# saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def UPDATE_FLAG(self):
|
||||
return self._UPDATE_FLAG
|
||||
@json_serializable('ENABLE_LOGGER')
|
||||
def ENABLE_LOGGER(self):
|
||||
return self._ENABLE_LOGGER
|
||||
|
||||
@UPDATE_FLAG.setter
|
||||
def UPDATE_FLAG(self, value):
|
||||
@ENABLE_LOGGER.setter
|
||||
def ENABLE_LOGGER(self, value):
|
||||
if type(value) is bool:
|
||||
self._UPDATE_FLAG = value
|
||||
self._ENABLE_LOGGER = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
@property
|
||||
def GITHUB_URL(self):
|
||||
return self._GITHUB_URL
|
||||
@json_serializable('IS_CONFIG_WINDOW_COMPACT_MODE')
|
||||
def IS_CONFIG_WINDOW_COMPACT_MODE(self):
|
||||
return self._IS_CONFIG_WINDOW_COMPACT_MODE
|
||||
|
||||
@property
|
||||
def BREAK_KEYSYM_LIST(self):
|
||||
return self._BREAK_KEYSYM_LIST
|
||||
|
||||
@property
|
||||
def MAX_MIC_ENERGY_THRESHOLD(self):
|
||||
return self._MAX_MIC_ENERGY_THRESHOLD
|
||||
|
||||
@property
|
||||
def MAX_SPEAKER_ENERGY_THRESHOLD(self):
|
||||
return self._MAX_SPEAKER_ENERGY_THRESHOLD
|
||||
@IS_CONFIG_WINDOW_COMPACT_MODE.setter
|
||||
def IS_CONFIG_WINDOW_COMPACT_MODE(self, value):
|
||||
if type(value) is bool:
|
||||
self._IS_CONFIG_WINDOW_COMPACT_MODE = value
|
||||
saveJson(self.PATH_CONFIG, inspect.currentframe().f_code.co_name, value)
|
||||
|
||||
def init_config(self):
|
||||
self._VERSION = "1.3.2"
|
||||
self._PATH_CONFIG = "./config.json"
|
||||
# Read Only
|
||||
self._VERSION = "2.0.0"
|
||||
self._PATH_CONFIG = os_path.join(os_path.dirname(sys.argv[0]), "config.json")
|
||||
self._GITHUB_URL = "https://api.github.com/repos/misyaguziya/VRCT/releases/latest"
|
||||
self._BOOTH_URL = "https://misyaguziya.booth.pm/"
|
||||
self._DOCUMENTS_URL = "https://mzsoftware.notion.site/VRCT-Documents-be79b7a165f64442ad8f326d86c22246"
|
||||
self._MAX_MIC_ENERGY_THRESHOLD = 2000
|
||||
self._MAX_SPEAKER_ENERGY_THRESHOLD = 4000
|
||||
|
||||
# Read Write
|
||||
self._ENABLE_TRANSLATION = False
|
||||
self._ENABLE_TRANSCRIPTION_SEND = False
|
||||
self._ENABLE_TRANSCRIPTION_RECEIVE = False
|
||||
self._ENABLE_FOREGROUND = False
|
||||
self._CHOICE_TRANSLATOR = translatorEngine[0]
|
||||
self._SOURCE_LANGUAGE = "Japanese"
|
||||
self._SOURCE_COUNTRY = "Japan"
|
||||
self._TARGET_LANGUAGE = "English"
|
||||
self._TARGET_COUNTRY = "United States"
|
||||
|
||||
# Save Json Data
|
||||
## Main Window
|
||||
self._SELECTED_TAB_NO = "1"
|
||||
self._SELECTED_TAB_YOUR_LANGUAGES = {
|
||||
"1":"Japanese\n(Japan)",
|
||||
"2":"Japanese\n(Japan)",
|
||||
"3":"Japanese\n(Japan)",
|
||||
}
|
||||
self._SELECTED_TAB_TARGET_LANGUAGES = {
|
||||
"1":"English\n(United States)",
|
||||
"2":"English\n(United States)",
|
||||
"3":"English\n(United States)",
|
||||
}
|
||||
self._IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE = False
|
||||
|
||||
## Config Window
|
||||
self._TRANSPARENCY = 100
|
||||
self._APPEARANCE_THEME = "System"
|
||||
self._UI_SCALING = "100%"
|
||||
self._FONT_FAMILY = "Yu Gothic UI"
|
||||
self._UI_LANGUAGE = "en"
|
||||
self._CHOICE_TRANSLATOR = translatorEngine[0]
|
||||
self._INPUT_SOURCE_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys())[0]
|
||||
self._INPUT_TARGET_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys())[1]
|
||||
self._OUTPUT_SOURCE_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["source"].keys())[1]
|
||||
self._OUTPUT_TARGET_LANG = list(translation_lang[self.CHOICE_TRANSLATOR]["target"].keys())[0]
|
||||
self._CHOICE_MIC_HOST = getDefaultInputDevice()["host"]["name"]
|
||||
self._CHOICE_MIC_DEVICE = getDefaultInputDevice()["device"]["name"]
|
||||
self._INPUT_MIC_VOICE_LANGUAGE = list(transcription_lang.keys())[0]
|
||||
self._INPUT_MIC_ENERGY_THRESHOLD = 300
|
||||
self._INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD = True
|
||||
self._INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD = False
|
||||
self._INPUT_MIC_RECORD_TIMEOUT = 3
|
||||
self._INPUT_MIC_PHRASE_TIMEOUT = 3
|
||||
self._INPUT_MIC_MAX_PHRASES = 10
|
||||
self._INPUT_MIC_WORD_FILTER = []
|
||||
self._CHOICE_SPEAKER_DEVICE = getDefaultOutputDevice()["name"]
|
||||
self._INPUT_SPEAKER_VOICE_LANGUAGE = list(transcription_lang.keys())[1]
|
||||
self._INPUT_SPEAKER_ENERGY_THRESHOLD = 300
|
||||
self._INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD = True
|
||||
self._INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD = False
|
||||
self._INPUT_SPEAKER_RECORD_TIMEOUT = 3
|
||||
self._INPUT_SPEAKER_PHRASE_TIMEOUT = 3
|
||||
self._INPUT_SPEAKER_MAX_PHRASES = 10
|
||||
self._OSC_IP_ADDRESS = "127.0.0.1"
|
||||
self._OSC_PORT = 9000
|
||||
self._AUTH_KEYS = {
|
||||
"DeepL(web)": None,
|
||||
"DeepL(auth)": None,
|
||||
"Bing(web)": None,
|
||||
"Google(web)": None,
|
||||
"DeepL_API": None,
|
||||
"DeepL": None,
|
||||
"Bing": None,
|
||||
"Google": None,
|
||||
}
|
||||
self._MESSAGE_FORMAT = "[message]([translation])"
|
||||
self._ENABLE_AUTO_CLEAR_CHATBOX = False
|
||||
self._ENABLE_AUTO_CLEAR_MESSAGE_BOX = True
|
||||
self._ENABLE_NOTICE_XSOVERLAY = False
|
||||
self._ENABLE_OSC = False
|
||||
self._UPDATE_FLAG = False
|
||||
self._GITHUB_URL = "https://api.github.com/repos/misyaguziya/VRCT/releases/latest"
|
||||
self._BREAK_KEYSYM_LIST = [
|
||||
"Delete", "Select", "Up", "Down", "Next", "End", "Print",
|
||||
"Prior","Insert","Home", "Left", "Clear", "Right", "Linefeed"
|
||||
]
|
||||
self._MAX_MIC_ENERGY_THRESHOLD = 2000
|
||||
self._MAX_SPEAKER_ENERGY_THRESHOLD = 4000
|
||||
self._ENABLE_SEND_MESSAGE_TO_VRC = True
|
||||
# self._STARTUP_OSC_ENABLED_CHECK = True # [deprecated]
|
||||
self._ENABLE_LOGGER = False
|
||||
self._IS_CONFIG_WINDOW_COMPACT_MODE = False
|
||||
|
||||
def load_config(self):
|
||||
if os_path.isfile(self.PATH_CONFIG) is not False:
|
||||
with open(self.PATH_CONFIG, 'r') as fp:
|
||||
with open(self.PATH_CONFIG, 'r', encoding="utf-8") as fp:
|
||||
config = json_load(fp)
|
||||
|
||||
for key in config.keys():
|
||||
setattr(self, key, config[key])
|
||||
|
||||
with open(self.PATH_CONFIG, 'w') as fp:
|
||||
setter_methods = [
|
||||
name for name, obj in vars(type(self)).items()
|
||||
if isinstance(obj, property) and obj.fset is not None
|
||||
]
|
||||
with open(self.PATH_CONFIG, 'w', encoding="utf-8") as fp:
|
||||
config = {}
|
||||
for method in setter_methods:
|
||||
config[method] = getattr(self, method)
|
||||
json_dump(config, fp, indent=4)
|
||||
for var_name, var_func in json_serializable_vars.items():
|
||||
config[var_name] = var_func(self)
|
||||
json_dump(config, fp, indent=4, ensure_ascii=False)
|
||||
|
||||
config = Config()
|
||||
739
controller.py
Normal file
@@ -0,0 +1,739 @@
|
||||
from time import sleep
|
||||
from threading import Thread
|
||||
from config import config
|
||||
from model import model
|
||||
from view import view
|
||||
from utils import get_key_by_value
|
||||
from languages import selectable_languages
|
||||
|
||||
# Common
|
||||
def callbackUpdateSoftware():
|
||||
model.updateSoftware()
|
||||
|
||||
def callbackRestartSoftware():
|
||||
model.reStartSoftware()
|
||||
|
||||
# func transcription send message
|
||||
def sendMicMessage(message):
|
||||
if len(message) > 0:
|
||||
translation = ""
|
||||
if model.checkKeywords(message):
|
||||
view.printToTextbox_DetectedByWordFilter(detected_message=message)
|
||||
return
|
||||
elif config.ENABLE_TRANSLATION is False:
|
||||
pass
|
||||
else:
|
||||
translation = model.getInputTranslate(message)
|
||||
if translation == False:
|
||||
config.ENABLE_TRANSLATION = False
|
||||
translation = ""
|
||||
view.translationEngineLimitErrorProcess()
|
||||
|
||||
if config.ENABLE_TRANSCRIPTION_SEND is True:
|
||||
if config.ENABLE_SEND_MESSAGE_TO_VRC is True:
|
||||
if len(translation) > 0:
|
||||
osc_message = config.MESSAGE_FORMAT.replace("[message]", message)
|
||||
osc_message = osc_message.replace("[translation]", translation)
|
||||
else:
|
||||
osc_message = message
|
||||
model.oscSendMessage(osc_message)
|
||||
|
||||
view.printToTextbox_SentMessage(message, translation)
|
||||
if config.ENABLE_LOGGER is True:
|
||||
if len(translation) > 0:
|
||||
translation = f" ({translation})"
|
||||
model.logger.info(f"[SENT] {message}{translation}")
|
||||
|
||||
def startTranscriptionSendMessage():
|
||||
model.startMicTranscript(sendMicMessage, view.printToTextbox_TranscriptionSendNoDeviceError)
|
||||
view.setMainWindowAllWidgetsStatusToNormal()
|
||||
|
||||
def stopTranscriptionSendMessage():
|
||||
model.stopMicTranscript()
|
||||
view.setMainWindowAllWidgetsStatusToNormal()
|
||||
|
||||
def startThreadingTranscriptionSendMessage():
|
||||
view.printToTextbox_enableTranscriptionSend()
|
||||
th_startTranscriptionSendMessage = Thread(target=startTranscriptionSendMessage)
|
||||
th_startTranscriptionSendMessage.daemon = True
|
||||
th_startTranscriptionSendMessage.start()
|
||||
|
||||
def stopThreadingTranscriptionSendMessage():
|
||||
view.printToTextbox_disableTranscriptionSend()
|
||||
th_stopTranscriptionSendMessage = Thread(target=stopTranscriptionSendMessage)
|
||||
th_stopTranscriptionSendMessage.daemon = True
|
||||
th_stopTranscriptionSendMessage.start()
|
||||
|
||||
def startTranscriptionSendMessageOnCloseConfigWindow():
|
||||
model.startMicTranscript(sendMicMessage, view.printToTextbox_TranscriptionSendNoDeviceError)
|
||||
|
||||
def stopTranscriptionSendMessageOnOpenConfigWindow():
|
||||
model.stopMicTranscript()
|
||||
|
||||
def startThreadingTranscriptionSendMessageOnCloseConfigWindow():
|
||||
th_startTranscriptionSendMessage = Thread(target=startTranscriptionSendMessageOnCloseConfigWindow)
|
||||
th_startTranscriptionSendMessage.daemon = True
|
||||
th_startTranscriptionSendMessage.start()
|
||||
|
||||
def stopThreadingTranscriptionSendMessageOnOpenConfigWindow():
|
||||
th_stopTranscriptionSendMessage = Thread(target=stopTranscriptionSendMessageOnOpenConfigWindow)
|
||||
th_stopTranscriptionSendMessage.daemon = True
|
||||
th_stopTranscriptionSendMessage.start()
|
||||
|
||||
# func transcription receive message
|
||||
def receiveSpeakerMessage(message):
|
||||
if len(message) > 0:
|
||||
translation = ""
|
||||
if config.ENABLE_TRANSLATION is False:
|
||||
pass
|
||||
else:
|
||||
translation = model.getOutputTranslate(message)
|
||||
if translation == False:
|
||||
config.ENABLE_TRANSLATION = False
|
||||
translation = ""
|
||||
view.translationEngineLimitErrorProcess()
|
||||
|
||||
if config.ENABLE_TRANSCRIPTION_RECEIVE is True:
|
||||
if config.ENABLE_NOTICE_XSOVERLAY is True:
|
||||
if len(translation) > 0:
|
||||
xsoverlay_message = config.MESSAGE_FORMAT.replace("[message]", message)
|
||||
xsoverlay_message = xsoverlay_message.replace("[translation]", translation)
|
||||
else:
|
||||
xsoverlay_message = message
|
||||
model.notificationXSOverlay(xsoverlay_message)
|
||||
|
||||
# update textbox message log (Received)
|
||||
view.printToTextbox_ReceivedMessage(message, translation)
|
||||
if config.ENABLE_LOGGER is True:
|
||||
if len(translation) > 0:
|
||||
translation = f" ({translation})"
|
||||
model.logger.info(f"[RECEIVED] {message}{translation}")
|
||||
|
||||
def startTranscriptionReceiveMessage():
|
||||
model.startSpeakerTranscript(receiveSpeakerMessage, view.printToTextbox_TranscriptionReceiveNoDeviceError)
|
||||
view.setMainWindowAllWidgetsStatusToNormal()
|
||||
|
||||
def stopTranscriptionReceiveMessage():
|
||||
model.stopSpeakerTranscript()
|
||||
view.setMainWindowAllWidgetsStatusToNormal()
|
||||
|
||||
def startThreadingTranscriptionReceiveMessage():
|
||||
view.printToTextbox_enableTranscriptionReceive()
|
||||
th_startTranscriptionReceiveMessage = Thread(target=startTranscriptionReceiveMessage)
|
||||
th_startTranscriptionReceiveMessage.daemon = True
|
||||
th_startTranscriptionReceiveMessage.start()
|
||||
|
||||
def stopThreadingTranscriptionReceiveMessage():
|
||||
view.printToTextbox_disableTranscriptionReceive()
|
||||
th_stopTranscriptionReceiveMessage = Thread(target=stopTranscriptionReceiveMessage)
|
||||
th_stopTranscriptionReceiveMessage.daemon = True
|
||||
th_stopTranscriptionReceiveMessage.start()
|
||||
|
||||
def startTranscriptionReceiveMessageOnCloseConfigWindow():
|
||||
model.startSpeakerTranscript(receiveSpeakerMessage, view.printToTextbox_TranscriptionReceiveNoDeviceError)
|
||||
|
||||
|
||||
def stopTranscriptionReceiveMessageOnOpenConfigWindow():
|
||||
model.stopSpeakerTranscript()
|
||||
|
||||
def startThreadingTranscriptionReceiveMessageOnCloseConfigWindow():
|
||||
th_startTranscriptionReceiveMessage = Thread(target=startTranscriptionReceiveMessageOnCloseConfigWindow)
|
||||
th_startTranscriptionReceiveMessage.daemon = True
|
||||
th_startTranscriptionReceiveMessage.start()
|
||||
|
||||
def stopThreadingTranscriptionReceiveMessageOnOpenConfigWindow():
|
||||
th_stopTranscriptionReceiveMessage = Thread(target=stopTranscriptionReceiveMessageOnOpenConfigWindow)
|
||||
th_stopTranscriptionReceiveMessage.daemon = True
|
||||
th_stopTranscriptionReceiveMessage.start()
|
||||
|
||||
# func message box
|
||||
def sendChatMessage(message):
|
||||
if len(message) > 0:
|
||||
translation = ""
|
||||
if config.ENABLE_TRANSLATION is False:
|
||||
pass
|
||||
else:
|
||||
translation = model.getInputTranslate(message)
|
||||
if translation == False:
|
||||
config.ENABLE_TRANSLATION = False
|
||||
translation = ""
|
||||
view.translationEngineLimitErrorProcess()
|
||||
|
||||
# send OSC message
|
||||
if config.ENABLE_SEND_MESSAGE_TO_VRC is True:
|
||||
if len(translation) > 0:
|
||||
osc_message = config.MESSAGE_FORMAT.replace("[message]", message)
|
||||
osc_message = osc_message.replace("[translation]", translation)
|
||||
else:
|
||||
osc_message = message
|
||||
model.oscSendMessage(osc_message)
|
||||
|
||||
# update textbox message log (Sent)
|
||||
view.printToTextbox_SentMessage(message, translation)
|
||||
if config.ENABLE_LOGGER is True:
|
||||
if len(translation) > 0:
|
||||
translation = f" ({translation})"
|
||||
model.logger.info(f"[SENT] {message}{translation}")
|
||||
|
||||
# delete message in entry message box
|
||||
if config.ENABLE_AUTO_CLEAR_MESSAGE_BOX is True:
|
||||
view.clearMessageBox()
|
||||
|
||||
def messageBoxPressKeyEnter(e):
|
||||
model.oscStopSendTyping()
|
||||
message = view.getTextFromMessageBox()
|
||||
sendChatMessage(message)
|
||||
|
||||
def messageBoxPressKeyAny(e):
|
||||
if config.ENABLE_SEND_MESSAGE_TO_VRC is True:
|
||||
model.oscStartSendTyping()
|
||||
else:
|
||||
model.oscStopSendTyping()
|
||||
|
||||
def messageBoxFocusIn(e):
|
||||
view.foregroundOffIfForegroundEnabled()
|
||||
|
||||
def messageBoxFocusOut(e):
|
||||
view.foregroundOnIfForegroundEnabled()
|
||||
if config.ENABLE_SEND_MESSAGE_TO_VRC is True:
|
||||
model.oscStopSendTyping()
|
||||
|
||||
# func select languages
|
||||
def initSetLanguageAndCountry():
|
||||
select = config.SELECTED_TAB_YOUR_LANGUAGES[config.SELECTED_TAB_NO]
|
||||
language, country = model.getLanguageAndCountry(select)
|
||||
config.SOURCE_LANGUAGE = language
|
||||
config.SOURCE_COUNTRY = country
|
||||
select = config.SELECTED_TAB_TARGET_LANGUAGES[config.SELECTED_TAB_NO]
|
||||
language, country = model.getLanguageAndCountry(select)
|
||||
config.TARGET_LANGUAGE = language
|
||||
config.TARGET_COUNTRY = country
|
||||
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
|
||||
|
||||
def setYourLanguageAndCountry(select):
|
||||
languages = config.SELECTED_TAB_YOUR_LANGUAGES
|
||||
languages[config.SELECTED_TAB_NO] = select
|
||||
config.SELECTED_TAB_YOUR_LANGUAGES = languages
|
||||
language, country = model.getLanguageAndCountry(select)
|
||||
config.SOURCE_LANGUAGE = language
|
||||
config.SOURCE_COUNTRY = country
|
||||
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
|
||||
view.printToTextbox_selectedYourLanguages(select)
|
||||
|
||||
def setTargetLanguageAndCountry(select):
|
||||
languages = config.SELECTED_TAB_TARGET_LANGUAGES
|
||||
languages[config.SELECTED_TAB_NO] = select
|
||||
config.SELECTED_TAB_TARGET_LANGUAGES = languages
|
||||
language, country = model.getLanguageAndCountry(select)
|
||||
config.TARGET_LANGUAGE = language
|
||||
config.TARGET_COUNTRY = country
|
||||
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
|
||||
view.printToTextbox_selectedTargetLanguages(select)
|
||||
|
||||
def callbackSelectedLanguagePresetTab(selected_tab_no):
|
||||
config.SELECTED_TAB_NO = selected_tab_no
|
||||
view.updateGuiVariableByPresetTabNo(config.SELECTED_TAB_NO)
|
||||
languages = config.SELECTED_TAB_YOUR_LANGUAGES
|
||||
select = languages[config.SELECTED_TAB_NO]
|
||||
language, country = model.getLanguageAndCountry(select)
|
||||
config.SOURCE_LANGUAGE = language
|
||||
config.SOURCE_COUNTRY = country
|
||||
languages = config.SELECTED_TAB_TARGET_LANGUAGES
|
||||
select = languages[config.SELECTED_TAB_NO]
|
||||
language, country = model.getLanguageAndCountry(select)
|
||||
config.TARGET_LANGUAGE = language
|
||||
config.TARGET_COUNTRY = country
|
||||
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
|
||||
view.printToTextbox_changedLanguagePresetTab(config.SELECTED_TAB_NO)
|
||||
|
||||
# command func
|
||||
def callbackToggleTranslation(is_turned_on):
|
||||
config.ENABLE_TRANSLATION = is_turned_on
|
||||
if config.ENABLE_TRANSLATION is True:
|
||||
view.printToTextbox_enableTranslation()
|
||||
else:
|
||||
view.printToTextbox_disableTranslation()
|
||||
|
||||
def callbackToggleTranscriptionSend(is_turned_on):
|
||||
view.setMainWindowAllWidgetsStatusToDisabled()
|
||||
config.ENABLE_TRANSCRIPTION_SEND = is_turned_on
|
||||
if config.ENABLE_TRANSCRIPTION_SEND is True:
|
||||
startThreadingTranscriptionSendMessage()
|
||||
else:
|
||||
stopThreadingTranscriptionSendMessage()
|
||||
|
||||
def callbackToggleTranscriptionReceive(is_turned_on):
|
||||
view.setMainWindowAllWidgetsStatusToDisabled()
|
||||
config.ENABLE_TRANSCRIPTION_RECEIVE = is_turned_on
|
||||
if config.ENABLE_TRANSCRIPTION_RECEIVE is True:
|
||||
startThreadingTranscriptionReceiveMessage()
|
||||
else:
|
||||
stopThreadingTranscriptionReceiveMessage()
|
||||
|
||||
def callbackToggleForeground(is_turned_on):
|
||||
config.ENABLE_FOREGROUND = is_turned_on
|
||||
if config.ENABLE_FOREGROUND is True:
|
||||
view.printToTextbox_enableForeground()
|
||||
view.foregroundOn()
|
||||
else:
|
||||
view.printToTextbox_disableForeground()
|
||||
view.foregroundOff()
|
||||
|
||||
def callbackEnableMainWindowSidebarCompactMode():
|
||||
config.IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE = True
|
||||
view.enableMainWindowSidebarCompactMode()
|
||||
|
||||
def callbackDisableMainWindowSidebarCompactMode():
|
||||
config.IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE = False
|
||||
view.disableMainWindowSidebarCompactMode()
|
||||
|
||||
# Config Window
|
||||
def callbackOpenConfigWindow():
|
||||
view.setMainWindowAllWidgetsStatusToDisabled()
|
||||
if config.ENABLE_TRANSCRIPTION_SEND is True:
|
||||
stopThreadingTranscriptionSendMessageOnOpenConfigWindow()
|
||||
if config.ENABLE_TRANSCRIPTION_RECEIVE is True:
|
||||
stopThreadingTranscriptionReceiveMessageOnOpenConfigWindow()
|
||||
if config.ENABLE_FOREGROUND is True:
|
||||
view.foregroundOff()
|
||||
|
||||
def callbackCloseConfigWindow():
|
||||
model.stopCheckMicEnergy()
|
||||
model.stopCheckSpeakerEnergy()
|
||||
view.initMicThresholdCheckButton()
|
||||
# view.initProgressBar_MicEnergy() # ProgressBarに0をセットしたい
|
||||
view.initSpeakerThresholdCheckButton()
|
||||
# view.initProgressBar_SpeakerEnergy() # ProgressBarに0をセットしたい
|
||||
|
||||
if config.ENABLE_TRANSCRIPTION_SEND is True:
|
||||
startThreadingTranscriptionSendMessageOnCloseConfigWindow()
|
||||
if config.ENABLE_TRANSCRIPTION_RECEIVE is True:
|
||||
sleep(2)
|
||||
if config.ENABLE_TRANSCRIPTION_RECEIVE is True:
|
||||
startThreadingTranscriptionReceiveMessageOnCloseConfigWindow()
|
||||
if config.ENABLE_FOREGROUND is True:
|
||||
view.foregroundOn()
|
||||
view.setMainWindowAllWidgetsStatusToNormal()
|
||||
|
||||
# Compact Mode Switch
|
||||
def callbackEnableConfigWindowCompactMode():
|
||||
config.IS_CONFIG_WINDOW_COMPACT_MODE = True
|
||||
model.stopCheckMicEnergy()
|
||||
view.initMicThresholdCheckButton()
|
||||
model.stopCheckSpeakerEnergy()
|
||||
view.initSpeakerThresholdCheckButton()
|
||||
|
||||
view.enableConfigWindowCompactMode()
|
||||
|
||||
def callbackDisableConfigWindowCompactMode():
|
||||
config.IS_CONFIG_WINDOW_COMPACT_MODE = False
|
||||
model.stopCheckMicEnergy()
|
||||
view.initMicThresholdCheckButton()
|
||||
model.stopCheckSpeakerEnergy()
|
||||
view.initSpeakerThresholdCheckButton()
|
||||
|
||||
view.disableConfigWindowCompactMode()
|
||||
|
||||
# Appearance Tab
|
||||
def callbackSetTransparency(value):
|
||||
print("callbackSetTransparency", int(value))
|
||||
config.TRANSPARENCY = int(value)
|
||||
view.setMainWindowTransparency(config.TRANSPARENCY/100)
|
||||
|
||||
def callbackSetAppearance(value):
|
||||
print("callbackSetAppearance", value)
|
||||
config.APPEARANCE_THEME = value
|
||||
view.showRestartButtonIfRequired()
|
||||
|
||||
def callbackSetUiScaling(value):
|
||||
print("callbackSetUiScaling", value)
|
||||
config.UI_SCALING = value
|
||||
new_scaling_float = int(value.replace("%", "")) / 100
|
||||
print("callbackSetUiScaling_new_scaling_float", new_scaling_float)
|
||||
view.showRestartButtonIfRequired()
|
||||
|
||||
def callbackSetFontFamily(value):
|
||||
print("callbackSetFontFamily", value)
|
||||
config.FONT_FAMILY = value
|
||||
view.showRestartButtonIfRequired()
|
||||
|
||||
def callbackSetUiLanguage(value):
|
||||
print("callbackSetUiLanguage", value)
|
||||
value = get_key_by_value(selectable_languages, value)
|
||||
print("callbackSetUiLanguage__after_get_key_by_value", value)
|
||||
config.UI_LANGUAGE = value
|
||||
view.showRestartButtonIfRequired(locale=config.UI_LANGUAGE)
|
||||
|
||||
# Translation Tab
|
||||
def callbackSetDeeplAuthkey(value):
|
||||
print("callbackSetDeeplAuthkey", str(value))
|
||||
if len(value) == 39:
|
||||
result = model.authenticationTranslator(choice_translator="DeepL_API", auth_key=value)
|
||||
if result is True:
|
||||
key = value
|
||||
view.printToTextbox_AuthenticationSuccess()
|
||||
else:
|
||||
key = None
|
||||
view.printToTextbox_AuthenticationError()
|
||||
auth_keys = config.AUTH_KEYS
|
||||
auth_keys["DeepL_API"] = key
|
||||
config.AUTH_KEYS = auth_keys
|
||||
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
|
||||
elif len(value) == 0:
|
||||
auth_keys = config.AUTH_KEYS
|
||||
auth_keys["DeepL_API"] = None
|
||||
config.AUTH_KEYS = auth_keys
|
||||
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
|
||||
|
||||
# Transcription Tab (Mic)
|
||||
def callbackSetMicHost(value):
|
||||
print("callbackSetMicHost", value)
|
||||
config.CHOICE_MIC_HOST = value
|
||||
config.CHOICE_MIC_DEVICE = model.getInputDefaultDevice()
|
||||
|
||||
view.updateSelected_MicDevice(config.CHOICE_MIC_DEVICE)
|
||||
view.updateList_MicDevice(model.getListInputDevice())
|
||||
|
||||
model.stopCheckMicEnergy()
|
||||
view.replaceMicThresholdCheckButton_Passive()
|
||||
|
||||
def callbackSetMicDevice(value):
|
||||
print("callbackSetMicDevice", value)
|
||||
config.CHOICE_MIC_DEVICE = value
|
||||
|
||||
model.stopCheckMicEnergy()
|
||||
view.replaceMicThresholdCheckButton_Passive()
|
||||
|
||||
def callbackSetMicEnergyThreshold(value):
|
||||
print("callbackSetMicEnergyThreshold", value)
|
||||
if value == "": return
|
||||
try:
|
||||
value = int(value)
|
||||
if 0 <= value and value <= config.MAX_MIC_ENERGY_THRESHOLD:
|
||||
view.clearErrorMessage()
|
||||
config.INPUT_MIC_ENERGY_THRESHOLD = value
|
||||
view.setGuiVariable_MicEnergyThreshold(config.INPUT_MIC_ENERGY_THRESHOLD)
|
||||
else:
|
||||
raise ValueError()
|
||||
except:
|
||||
view.showErrorMessage_MicEnergyThreshold()
|
||||
|
||||
def callbackSetMicDynamicEnergyThreshold(value):
|
||||
print("callbackSetMicDynamicEnergyThreshold", value)
|
||||
config.INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD = value
|
||||
if config.INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD is True:
|
||||
view.closeMicEnergyThresholdWidget()
|
||||
else:
|
||||
view.openMicEnergyThresholdWidget()
|
||||
|
||||
def setProgressBarMicEnergy(energy):
|
||||
view.updateSetProgressBar_MicEnergy(energy)
|
||||
|
||||
def callbackCheckMicThreshold(is_turned_on):
|
||||
print("callbackCheckMicThreshold", is_turned_on)
|
||||
if is_turned_on is True:
|
||||
view.replaceMicThresholdCheckButton_Disabled()
|
||||
model.startCheckMicEnergy(setProgressBarMicEnergy, view.initProgressBar_MicEnergy)
|
||||
view.replaceMicThresholdCheckButton_Active()
|
||||
else:
|
||||
view.replaceMicThresholdCheckButton_Disabled()
|
||||
model.stopCheckMicEnergy()
|
||||
view.replaceMicThresholdCheckButton_Passive()
|
||||
|
||||
def callbackSetMicRecordTimeout(value):
|
||||
print("callbackSetMicRecordTimeout", value)
|
||||
if value == "": return
|
||||
try:
|
||||
value = int(value)
|
||||
if 0 <= value and value <= config.INPUT_MIC_PHRASE_TIMEOUT:
|
||||
view.clearErrorMessage()
|
||||
config.INPUT_MIC_RECORD_TIMEOUT = value
|
||||
view.setGuiVariable_MicRecordTimeout(config.INPUT_MIC_RECORD_TIMEOUT)
|
||||
else:
|
||||
raise ValueError()
|
||||
except:
|
||||
view.showErrorMessage_MicRecordTimeout()
|
||||
|
||||
def callbackSetMicPhraseTimeout(value):
|
||||
print("callbackSetMicPhraseTimeout", value)
|
||||
if value == "": return
|
||||
try:
|
||||
value = int(value)
|
||||
if 0 <= value and value >= config.INPUT_MIC_RECORD_TIMEOUT:
|
||||
view.clearErrorMessage()
|
||||
config.INPUT_MIC_PHRASE_TIMEOUT = value
|
||||
view.setGuiVariable_MicPhraseTimeout(config.INPUT_MIC_PHRASE_TIMEOUT)
|
||||
else:
|
||||
raise ValueError()
|
||||
except:
|
||||
view.showErrorMessage_MicPhraseTimeout()
|
||||
|
||||
def callbackSetMicMaxPhrases(value):
|
||||
print("callbackSetMicMaxPhrases", value)
|
||||
if value == "": return
|
||||
try:
|
||||
value = int(value)
|
||||
if 0 <= value:
|
||||
view.clearErrorMessage()
|
||||
config.INPUT_MIC_MAX_PHRASES = value
|
||||
view.setGuiVariable_MicMaxPhrases(config.INPUT_MIC_MAX_PHRASES)
|
||||
else:
|
||||
raise ValueError()
|
||||
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 = []
|
||||
model.resetKeywordProcessor()
|
||||
model.addKeywords()
|
||||
|
||||
def callbackSetSpeakerEnergyThreshold(value):
|
||||
print("callbackSetSpeakerEnergyThreshold", value)
|
||||
if value == "": return
|
||||
try:
|
||||
value = int(value)
|
||||
if 0 <= value and value <= config.MAX_SPEAKER_ENERGY_THRESHOLD:
|
||||
view.clearErrorMessage()
|
||||
config.INPUT_SPEAKER_ENERGY_THRESHOLD = value
|
||||
view.setGuiVariable_SpeakerEnergyThreshold(config.INPUT_SPEAKER_ENERGY_THRESHOLD)
|
||||
else:
|
||||
raise ValueError()
|
||||
except:
|
||||
view.showErrorMessage_SpeakerEnergyThreshold()
|
||||
|
||||
def callbackSetSpeakerDynamicEnergyThreshold(value):
|
||||
print("callbackSetSpeakerDynamicEnergyThreshold", value)
|
||||
config.INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD = value
|
||||
if config.INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD is True:
|
||||
view.closeSpeakerEnergyThresholdWidget()
|
||||
else:
|
||||
view.openSpeakerEnergyThresholdWidget()
|
||||
|
||||
|
||||
def setProgressBarSpeakerEnergy(energy):
|
||||
view.updateSetProgressBar_SpeakerEnergy(energy)
|
||||
|
||||
def callbackCheckSpeakerThreshold(is_turned_on):
|
||||
print("callbackCheckSpeakerThreshold", is_turned_on)
|
||||
if is_turned_on is True:
|
||||
view.replaceSpeakerThresholdCheckButton_Disabled()
|
||||
model.startCheckSpeakerEnergy(
|
||||
setProgressBarSpeakerEnergy,
|
||||
view.initProgressBar_SpeakerEnergy,
|
||||
view.showErrorMessage_CheckSpeakerThreshold_NoDevice
|
||||
)
|
||||
|
||||
view.replaceSpeakerThresholdCheckButton_Active()
|
||||
else:
|
||||
view.replaceSpeakerThresholdCheckButton_Disabled()
|
||||
model.stopCheckSpeakerEnergy()
|
||||
view.replaceSpeakerThresholdCheckButton_Passive()
|
||||
|
||||
def callbackSetSpeakerRecordTimeout(value):
|
||||
print("callbackSetSpeakerRecordTimeout", value)
|
||||
if value == "": return
|
||||
try:
|
||||
value = int(value)
|
||||
if 0 <= value and value <= config.INPUT_SPEAKER_PHRASE_TIMEOUT:
|
||||
view.clearErrorMessage()
|
||||
config.INPUT_SPEAKER_RECORD_TIMEOUT = value
|
||||
view.setGuiVariable_SpeakerRecordTimeout(config.INPUT_SPEAKER_RECORD_TIMEOUT)
|
||||
else:
|
||||
raise ValueError()
|
||||
except:
|
||||
view.showErrorMessage_SpeakerRecordTimeout()
|
||||
|
||||
def callbackSetSpeakerPhraseTimeout(value):
|
||||
print("callbackSetSpeakerPhraseTimeout", value)
|
||||
if value == "": return
|
||||
try:
|
||||
value = int(value)
|
||||
if 0 <= value and value >= config.INPUT_SPEAKER_RECORD_TIMEOUT:
|
||||
view.clearErrorMessage()
|
||||
config.INPUT_SPEAKER_PHRASE_TIMEOUT = value
|
||||
view.setGuiVariable_SpeakerPhraseTimeout(config.INPUT_SPEAKER_PHRASE_TIMEOUT)
|
||||
else:
|
||||
raise ValueError()
|
||||
except:
|
||||
view.showErrorMessage_SpeakerPhraseTimeout()
|
||||
|
||||
def callbackSetSpeakerMaxPhrases(value):
|
||||
print("callbackSetSpeakerMaxPhrases", value)
|
||||
if value == "": return
|
||||
try:
|
||||
value = int(value)
|
||||
if 0 <= value:
|
||||
view.clearErrorMessage()
|
||||
config.INPUT_SPEAKER_MAX_PHRASES = value
|
||||
view.setGuiVariable_SpeakerMaxPhrases(config.INPUT_SPEAKER_MAX_PHRASES)
|
||||
else:
|
||||
raise ValueError()
|
||||
except:
|
||||
view.showErrorMessage_SpeakerMaxPhrases()
|
||||
|
||||
|
||||
# Others Tab
|
||||
def callbackSetEnableAutoClearMessageBox(value):
|
||||
print("callbackSetEnableAutoClearMessageBox", value)
|
||||
config.ENABLE_AUTO_CLEAR_MESSAGE_BOX = value
|
||||
|
||||
def callbackSetEnableNoticeXsoverlay(value):
|
||||
print("callbackSetEnableNoticeXsoverlay", value)
|
||||
config.ENABLE_NOTICE_XSOVERLAY = value
|
||||
|
||||
def callbackSetEnableAutoExportMessageLogs(value):
|
||||
print("callbackSetEnableAutoExportMessageLogs", value)
|
||||
config.ENABLE_LOGGER = value
|
||||
|
||||
if config.ENABLE_LOGGER is True:
|
||||
model.startLogger()
|
||||
else:
|
||||
model.stopLogger()
|
||||
|
||||
def callbackSetMessageFormat(value):
|
||||
print("callbackSetMessageFormat", value)
|
||||
if len(value) > 0:
|
||||
config.MESSAGE_FORMAT = value
|
||||
|
||||
def callbackSetEnableSendMessageToVrc(value):
|
||||
print("callbackSetEnableSendMessageToVrc", value)
|
||||
config.ENABLE_SEND_MESSAGE_TO_VRC = value
|
||||
|
||||
# [deprecated]
|
||||
# def callbackSetStartupOscEnabledCheck(value):
|
||||
# print("callbackSetStartupOscEnabledCheck", value)
|
||||
# config.STARTUP_OSC_ENABLED_CHECK = value
|
||||
|
||||
# Advanced Settings Tab
|
||||
def callbackSetOscIpAddress(value):
|
||||
if value == "": return
|
||||
print("callbackSetOscIpAddress", str(value))
|
||||
config.OSC_IP_ADDRESS = str(value)
|
||||
|
||||
def callbackSetOscPort(value):
|
||||
if value == "": return
|
||||
print("callbackSetOscPort", int(value))
|
||||
config.OSC_PORT = int(value)
|
||||
|
||||
def createMainWindow():
|
||||
# create GUI
|
||||
view.createGUI()
|
||||
|
||||
# init config
|
||||
initSetLanguageAndCountry()
|
||||
|
||||
if model.authenticationTranslator(config.CHOICE_TRANSLATOR, config.AUTH_KEYS[config.CHOICE_TRANSLATOR]) is False:
|
||||
# error update Auth key
|
||||
auth_keys = config.AUTH_KEYS
|
||||
auth_keys[config.CHOICE_TRANSLATOR] = None
|
||||
config.AUTH_KEYS = auth_keys
|
||||
view.printToTextbox_AuthenticationError()
|
||||
config.CHOICE_TRANSLATOR = model.findTranslationEngine(config.SOURCE_LANGUAGE, config.TARGET_LANGUAGE)
|
||||
|
||||
# set word filter
|
||||
model.addKeywords()
|
||||
|
||||
# check OSC started [deprecated]
|
||||
# if config.STARTUP_OSC_ENABLED_CHECK is True and config.ENABLE_SEND_MESSAGE_TO_VRC is True:
|
||||
# model.checkOSCStarted(view.printToTextbox_OSCError)
|
||||
|
||||
# check Software Updated
|
||||
if model.checkSoftwareUpdated() is True:
|
||||
view.showUpdateAvailableButton()
|
||||
|
||||
# init logger
|
||||
if config.ENABLE_LOGGER is True:
|
||||
model.startLogger()
|
||||
|
||||
# set UI and callback
|
||||
view.register(
|
||||
common_registers={
|
||||
"callback_update_software": callbackUpdateSoftware,
|
||||
"callback_restart_software": callbackRestartSoftware,
|
||||
},
|
||||
|
||||
window_action_registers={
|
||||
"callback_open_config_window": callbackOpenConfigWindow,
|
||||
"callback_close_config_window": callbackCloseConfigWindow,
|
||||
},
|
||||
|
||||
main_window_registers={
|
||||
"callback_enable_main_window_sidebar_compact_mode": callbackEnableMainWindowSidebarCompactMode,
|
||||
"callback_disable_main_window_sidebar_compact_mode": callbackDisableMainWindowSidebarCompactMode,
|
||||
|
||||
"callback_toggle_translation": callbackToggleTranslation,
|
||||
"callback_toggle_transcription_send": callbackToggleTranscriptionSend,
|
||||
"callback_toggle_transcription_receive": callbackToggleTranscriptionReceive,
|
||||
"callback_toggle_foreground": callbackToggleForeground,
|
||||
|
||||
"callback_your_language": setYourLanguageAndCountry,
|
||||
"callback_target_language": setTargetLanguageAndCountry,
|
||||
"values": model.getListLanguageAndCountry(),
|
||||
|
||||
"callback_selected_language_preset_tab": callbackSelectedLanguagePresetTab,
|
||||
"message_box_bind_Return": messageBoxPressKeyEnter,
|
||||
"message_box_bind_Any_KeyPress": messageBoxPressKeyAny,
|
||||
"message_box_bind_FocusIn": messageBoxFocusIn,
|
||||
"message_box_bind_FocusOut": messageBoxFocusOut,
|
||||
},
|
||||
|
||||
config_window_registers={
|
||||
# Compact Mode Switch
|
||||
"callback_disable_config_window_compact_mode": callbackEnableConfigWindowCompactMode,
|
||||
"callback_enable_config_window_compact_mode": callbackDisableConfigWindowCompactMode,
|
||||
|
||||
# Appearance Tab
|
||||
"callback_set_transparency": callbackSetTransparency,
|
||||
"callback_set_appearance": callbackSetAppearance,
|
||||
"callback_set_ui_scaling": callbackSetUiScaling,
|
||||
"callback_set_font_family": callbackSetFontFamily,
|
||||
"callback_set_ui_language": callbackSetUiLanguage,
|
||||
|
||||
# Translation Tab
|
||||
"callback_set_deepl_authkey": callbackSetDeeplAuthkey,
|
||||
|
||||
# Transcription Tab (Mic)
|
||||
"callback_set_mic_host": callbackSetMicHost,
|
||||
"list_mic_host": model.getListInputHost(),
|
||||
"callback_set_mic_device": callbackSetMicDevice,
|
||||
"list_mic_device": model.getListInputDevice(),
|
||||
"callback_set_mic_energy_threshold": callbackSetMicEnergyThreshold,
|
||||
"callback_set_mic_dynamic_energy_threshold": callbackSetMicDynamicEnergyThreshold,
|
||||
"callback_check_mic_threshold": callbackCheckMicThreshold,
|
||||
"callback_set_mic_record_timeout": callbackSetMicRecordTimeout,
|
||||
"callback_set_mic_phrase_timeout": callbackSetMicPhraseTimeout,
|
||||
"callback_set_mic_max_phrases": callbackSetMicMaxPhrases,
|
||||
"callback_set_mic_word_filter": callbackSetMicWordFilter,
|
||||
|
||||
# Transcription Tab (Speaker)
|
||||
"callback_set_speaker_energy_threshold": callbackSetSpeakerEnergyThreshold,
|
||||
"callback_set_speaker_dynamic_energy_threshold": callbackSetSpeakerDynamicEnergyThreshold,
|
||||
"callback_check_speaker_threshold": callbackCheckSpeakerThreshold,
|
||||
"callback_set_speaker_record_timeout": callbackSetSpeakerRecordTimeout,
|
||||
"callback_set_speaker_phrase_timeout": callbackSetSpeakerPhraseTimeout,
|
||||
"callback_set_speaker_max_phrases": callbackSetSpeakerMaxPhrases,
|
||||
|
||||
# Others Tab
|
||||
"callback_set_enable_auto_clear_chatbox": callbackSetEnableAutoClearMessageBox,
|
||||
"callback_set_enable_notice_xsoverlay": callbackSetEnableNoticeXsoverlay,
|
||||
"callback_set_enable_auto_export_message_logs": callbackSetEnableAutoExportMessageLogs,
|
||||
"callback_set_message_format": callbackSetMessageFormat,
|
||||
"callback_set_enable_send_message_to_vrc": callbackSetEnableSendMessageToVrc,
|
||||
# "callback_set_startup_osc_enabled_check": callbackSetStartupOscEnabledCheck, # [deprecated]
|
||||
|
||||
# Advanced Settings Tab
|
||||
"callback_set_osc_ip_address": callbackSetOscIpAddress,
|
||||
"callback_set_osc_port": callbackSetOscPort,
|
||||
},
|
||||
)
|
||||
|
||||
def showMainWindow():
|
||||
view.startMainLoop()
|
||||
@@ -1,325 +0,0 @@
|
||||
"""
|
||||
CustomTkinter Scrollable Dropdown Menu
|
||||
Author: Akash Bora
|
||||
License: MIT
|
||||
This is a custom dropdown menu for customtkinter.
|
||||
Homepage: https://github.com/Akascape/CTkScrollableDropdown
|
||||
|
||||
Advanced Scrollable Dropdown class for customtkinter widgets
|
||||
Author: Akash Bora
|
||||
"""
|
||||
import customtkinter
|
||||
import sys
|
||||
import time
|
||||
|
||||
class CTkScrollableDropdown(customtkinter.CTkToplevel):
|
||||
|
||||
def __init__(self, attach, x=None, y=None, button_color=None, height: int = 200, width: int = None,
|
||||
fg_color=None, button_height: int = 20, justify="center", scrollbar_button_color=None,
|
||||
scrollbar=True, scrollbar_button_hover_color=None, frame_border_width=2, values=[],
|
||||
command=None, image_values=[], alpha: float = 0.97, frame_corner_radius=20, double_click=False,
|
||||
resize=True, frame_border_color=None, text_color=None, autocomplete=False, **button_kwargs):
|
||||
|
||||
super().__init__(takefocus=1)
|
||||
self.transient(self.master)
|
||||
self.alpha = alpha
|
||||
self.attach = attach
|
||||
self.corner = frame_corner_radius
|
||||
self.padding = 0
|
||||
self.focus_something = False
|
||||
self.disable = True
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
self.after(100, lambda: self.overrideredirect(True))
|
||||
self.transparent_color = self._apply_appearance_mode(self._fg_color)
|
||||
self.attributes("-transparentcolor", self.transparent_color)
|
||||
elif sys.platform.startswith("darwin"):
|
||||
self.overrideredirect(True)
|
||||
self.transparent_color = 'systemTransparent'
|
||||
self.attributes("-transparent", True)
|
||||
self.focus_something = True
|
||||
else:
|
||||
self.overrideredirect(True)
|
||||
self.transparent_color = '#000001'
|
||||
self.corner = 0
|
||||
self.padding = 18
|
||||
self.withdraw()
|
||||
|
||||
self.hide = True
|
||||
self.attach.bind('<Configure>', lambda e: self._withdraw() if not self.disable else None, add="+")
|
||||
self.attach.winfo_toplevel().bind('<Configure>', lambda e: self._withdraw() if not self.disable else None, add="+")
|
||||
self.attach.winfo_toplevel().bind("<Triple-Button-1>", lambda e: self._withdraw() if not self.disable else None, add="+")
|
||||
self.attach.winfo_toplevel().bind("<Button-3>", lambda e: self._withdraw() if not self.disable else None, add="+")
|
||||
self.attach.winfo_toplevel().bind("<Button-2>", lambda e: self._withdraw() if not self.disable else None, add="+")
|
||||
|
||||
self.attributes('-alpha', 0)
|
||||
self.disable = False
|
||||
self.fg_color = customtkinter.ThemeManager.theme["CTkFrame"]["fg_color"] if fg_color is None else fg_color
|
||||
self.scroll_button_color = customtkinter.ThemeManager.theme["CTkScrollbar"]["button_color"] if scrollbar_button_color is None else scrollbar_button_color
|
||||
self.scroll_hover_color = customtkinter.ThemeManager.theme["CTkScrollbar"]["button_hover_color"] if scrollbar_button_hover_color is None else scrollbar_button_hover_color
|
||||
self.frame_border_color = customtkinter.ThemeManager.theme["CTkFrame"]["border_color"] if frame_border_color is None else frame_border_color
|
||||
self.button_color = customtkinter.ThemeManager.theme["CTkFrame"]["top_fg_color"] if button_color is None else button_color
|
||||
self.text_color = customtkinter.ThemeManager.theme["CTkLabel"]["text_color"] if text_color is None else text_color
|
||||
|
||||
if scrollbar is False:
|
||||
self.scroll_button_color = self.fg_color
|
||||
self.scroll_hover_color = self.fg_color
|
||||
|
||||
self.frame = customtkinter.CTkScrollableFrame(self, bg_color=self.transparent_color, fg_color=self.fg_color,
|
||||
scrollbar_button_hover_color=self.scroll_hover_color,
|
||||
corner_radius=self.corner, border_width=frame_border_width,
|
||||
scrollbar_button_color=self.scroll_button_color,
|
||||
border_color=self.frame_border_color)
|
||||
self.frame._scrollbar.grid_configure(padx=3)
|
||||
self.frame.pack(expand=True, fill="both")
|
||||
|
||||
self.dummy_entry = customtkinter.CTkEntry(self.frame, fg_color="transparent", border_width=0, height=1, width=1)
|
||||
self.no_match = customtkinter.CTkLabel(self.frame, text="No Match")
|
||||
self.height = height
|
||||
self.height_new = height
|
||||
self.width = width
|
||||
self.command = command
|
||||
self.fade = False
|
||||
self.resize = resize
|
||||
self.autocomplete = autocomplete
|
||||
self.var_update = customtkinter.StringVar()
|
||||
self.appear = False
|
||||
|
||||
if justify.lower()=="left":
|
||||
self.justify = "w"
|
||||
elif justify.lower()=="right":
|
||||
self.justify = "e"
|
||||
else:
|
||||
self.justify = "c"
|
||||
|
||||
self.button_height = button_height
|
||||
self.values = values
|
||||
self.button_num = len(self.values)
|
||||
self.image_values = None if len(image_values)!=len(self.values) else image_values
|
||||
|
||||
self.resizable(width=False, height=False)
|
||||
self._init_buttons(**button_kwargs)
|
||||
|
||||
# Add binding for different ctk widgets
|
||||
if double_click or self.attach.winfo_name().startswith("!ctkentry") or self.attach.winfo_name().startswith("!ctkcombobox"):
|
||||
self.attach.bind('<Double-Button-1>', lambda e: self._iconify(), add="+")
|
||||
else:
|
||||
self.attach.bind('<Button-1>', lambda e: self._iconify(), add="+")
|
||||
|
||||
if self.attach.winfo_name().startswith("!ctkcombobox"):
|
||||
self.attach._canvas.tag_bind("right_parts", "<Button-1>", lambda e: self._iconify())
|
||||
self.attach._canvas.tag_bind("dropdown_arrow", "<Button-1>", lambda e: self._iconify())
|
||||
if self.command is None:
|
||||
self.command = self.attach.set
|
||||
|
||||
if self.attach.winfo_name().startswith("!ctkoptionmenu"):
|
||||
self.attach._canvas.bind("<Button-1>", lambda e: self._iconify())
|
||||
self.attach._text_label.bind("<Button-1>", lambda e: self._iconify())
|
||||
if self.command is None:
|
||||
self.command = self.attach.set
|
||||
|
||||
self.update_idletasks()
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
if self.autocomplete:
|
||||
self.bind_autocomplete()
|
||||
|
||||
# self.deiconify()
|
||||
self.withdraw()
|
||||
|
||||
self.attributes("-alpha", self.alpha)
|
||||
|
||||
def _withdraw(self):
|
||||
if self.hide is False: self.withdraw()
|
||||
self.hide = True
|
||||
|
||||
def _update(self, a, b, c):
|
||||
self.live_update(self.attach._entry.get())
|
||||
|
||||
def bind_autocomplete(self, ):
|
||||
def appear(x):
|
||||
self.appear = True
|
||||
|
||||
if self.attach.winfo_name().startswith("!ctkcombobox"):
|
||||
self.attach._entry.configure(textvariable=self.var_update)
|
||||
self.attach._entry.bind("<Key>", appear)
|
||||
self.attach.set(self.values[0])
|
||||
self.var_update.trace_add('write', self._update)
|
||||
|
||||
if self.attach.winfo_name().startswith("!ctkentry"):
|
||||
self.attach.configure(textvariable=self.var_update)
|
||||
self.attach.bind("<Key>", appear)
|
||||
self.var_update.trace_add('write', self._update)
|
||||
|
||||
def fade_out(self):
|
||||
for i in range(100,0,-10):
|
||||
if not self.winfo_exists():
|
||||
break
|
||||
self.attributes("-alpha", i/100)
|
||||
self.update()
|
||||
time.sleep(1/100)
|
||||
|
||||
def fade_in(self):
|
||||
for i in range(0,100,10):
|
||||
if not self.winfo_exists():
|
||||
break
|
||||
self.attributes("-alpha", i/100)
|
||||
self.update()
|
||||
time.sleep(1/100)
|
||||
|
||||
def _init_buttons(self, **button_kwargs):
|
||||
self.i = 0
|
||||
self.widgets = {}
|
||||
for row in self.values:
|
||||
self.widgets[self.i] = customtkinter.CTkButton(self.frame,
|
||||
text=row,
|
||||
height=self.button_height,
|
||||
fg_color=self.button_color,
|
||||
text_color=self.text_color,
|
||||
image=self.image_values[i] if self.image_values is not None else None,
|
||||
anchor=self.justify,
|
||||
command=lambda k=row: self._attach_key_press(k), **button_kwargs)
|
||||
self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0))
|
||||
self.i+=1
|
||||
|
||||
self.hide = False
|
||||
|
||||
def destroy_popup(self):
|
||||
self.destroy()
|
||||
self.disable = True
|
||||
|
||||
def place_dropdown(self):
|
||||
self.x_pos = self.attach.winfo_rootx() if self.x is None else self.x + self.attach.winfo_rootx()
|
||||
self.y_pos = self.attach.winfo_rooty() + self.attach.winfo_reqheight() + 5 if self.y is None else self.y + self.attach.winfo_rooty()
|
||||
self.width_new = self.attach.winfo_width() if self.width is None else self.width
|
||||
|
||||
if self.resize:
|
||||
if self.button_num==1:
|
||||
self.height_new = self.button_height * self.button_num + 45
|
||||
else:
|
||||
self.height_new = self.button_height * self.button_num + 35
|
||||
if self.height_new>self.height:
|
||||
self.height_new = self.height
|
||||
|
||||
self.geometry('{}x{}+{}+{}'.format(self.width_new, self.height_new,
|
||||
self.x_pos, self.y_pos))
|
||||
self.fade_in()
|
||||
self.attributes('-alpha', self.alpha)
|
||||
|
||||
def _iconify(self):
|
||||
if self.disable: return
|
||||
if self.hide:
|
||||
self._deiconify()
|
||||
self.place_dropdown()
|
||||
if self.focus_something:
|
||||
self.dummy_entry.pack()
|
||||
self.dummy_entry.focus_set()
|
||||
self.after(100, self.dummy_entry.pack_forget)
|
||||
self.hide = False
|
||||
self.focus_set()
|
||||
self.focus()
|
||||
else:
|
||||
self.withdraw()
|
||||
self.hide = True
|
||||
|
||||
def _attach_key_press(self, k):
|
||||
self.fade = True
|
||||
if self.command:
|
||||
self.command(k)
|
||||
self.fade = False
|
||||
self.fade_out()
|
||||
self.withdraw()
|
||||
self.hide = True
|
||||
|
||||
def live_update(self, string=None):
|
||||
if not self.appear: return
|
||||
if self.disable: return
|
||||
if self.fade: return
|
||||
if string:
|
||||
self._deiconify()
|
||||
i=1
|
||||
for key in self.widgets.keys():
|
||||
s = self.widgets[key].cget("text")
|
||||
if not s.startswith(string):
|
||||
self.widgets[key].pack_forget()
|
||||
else:
|
||||
self.widgets[key].pack(fill="x", pady=2, padx=(self.padding, 0))
|
||||
i+=1
|
||||
|
||||
if i==1:
|
||||
self.no_match.pack(fill="x", pady=2, padx=(self.padding, 0))
|
||||
else:
|
||||
self.no_match.pack_forget()
|
||||
self.button_num = i
|
||||
self.place_dropdown()
|
||||
|
||||
else:
|
||||
self.no_match.pack_forget()
|
||||
self.button_num = len(self.values)
|
||||
for key in self.widgets.keys():
|
||||
self.widgets[key].destroy()
|
||||
self._init_buttons()
|
||||
self.place_dropdown()
|
||||
|
||||
self.frame._parent_canvas.yview_moveto(0.0)
|
||||
self.appear = False
|
||||
|
||||
def insert(self, value, **kwargs):
|
||||
self.widgets[self.i] = customtkinter.CTkButton(self.frame,
|
||||
text=value,
|
||||
height=self.button_height,
|
||||
fg_color=self.button_color,
|
||||
text_color=self.text_color,
|
||||
anchor=self.justify,
|
||||
command=lambda k=value: self._attach_key_press(k), **kwargs)
|
||||
self.widgets[self.i].pack(fill="x", pady=2, padx=(self.padding, 0))
|
||||
self.i+=1
|
||||
self.values.append(value)
|
||||
|
||||
def _deiconify(self):
|
||||
if len(self.values)>0:
|
||||
self.deiconify()
|
||||
|
||||
def popup(self, x=None, y=None):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.hide = True
|
||||
self._iconify()
|
||||
|
||||
def configure(self, **kwargs):
|
||||
if "height" in kwargs:
|
||||
self.height = kwargs.pop("height")
|
||||
self.height_new = self.height
|
||||
|
||||
if "alpha" in kwargs:
|
||||
self.alpha = kwargs.pop("alpha")
|
||||
|
||||
if "width" in kwargs:
|
||||
self.width = kwargs.pop("width")
|
||||
|
||||
if "fg_color" in kwargs:
|
||||
self.frame.configure(fg_color=kwargs.pop("fg_color"))
|
||||
|
||||
if "values" in kwargs:
|
||||
self.values = kwargs.pop("values")
|
||||
self.image_values = None
|
||||
for key in self.widgets.keys():
|
||||
self.widgets[key].destroy()
|
||||
self._init_buttons()
|
||||
|
||||
if "image_values" in kwargs:
|
||||
self.image_values = kwargs.pop("image_values")
|
||||
self.image_values = None if len(self.image_values)!=len(self.values) else self.image_values
|
||||
if self.image_values is not None:
|
||||
i=0
|
||||
for key in self.widgets.keys():
|
||||
self.widgets[key].configure(image=self.image_values[i])
|
||||
i+=1
|
||||
|
||||
if "button_color" in kwargs:
|
||||
for key in self.widgets.keys():
|
||||
self.widgets[key].configure(fg_color=kwargs.pop("button_color"))
|
||||
|
||||
for key in self.widgets.keys():
|
||||
self.widgets[key].configure(**kwargs)
|
||||
BIN
docs/main_window.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 155 KiB |
BIN
img/arrow_left_disabled.png
Normal file
|
After Width: | Height: | Size: 974 B |
BIN
img/arrow_left_white.png
Normal file
|
After Width: | Height: | Size: 969 B |
BIN
img/configuration_icon_disabled.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
img/configuration_icon_white.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
img/foreground_icon_disabled.png
Normal file
|
After Width: | Height: | Size: 232 B |
BIN
img/foreground_icon_white.png
Normal file
|
After Width: | Height: | Size: 227 B |
BIN
img/headphones_icon_disabled.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
img/headphones_icon_white.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
img/help_icon_disabled.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
img/help_icon_white.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
img/mic_icon_disabled.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
img/mic_icon_white.png
Normal file
|
After Width: | Height: | Size: 952 B |
BIN
img/narrow_arrow_down.png
Normal file
|
After Width: | Height: | Size: 785 B |
BIN
img/refresh_icon.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
img/translation_icon_disabled.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
img/translation_icon_white.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
img/vrct_logo_for_dark_mode.png
Normal file
|
After Width: | Height: | Size: 197 KiB |
BIN
img/vrct_logo_for_light_mode.png
Normal file
|
After Width: | Height: | Size: 219 KiB |
BIN
img/vrct_logo_mark_black.ico
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
img/vrct_logo_mark_black.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
img/vrct_logo_mark_black_icon.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
img/vrct_logo_mark_white.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
img/xsoverlay2.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
@@ -1,6 +1,6 @@
|
||||
selectable_languages = {
|
||||
"en": "English",
|
||||
"ja": "日本語",
|
||||
"ko": "한국어"
|
||||
"ko": "한국어(일부 지원)"
|
||||
# 新しい言語とキーを追加する場合はここに追記してください
|
||||
}
|
||||
187
locales/en.yml
Normal file
@@ -0,0 +1,187 @@
|
||||
main_window:
|
||||
translation: Translation
|
||||
transcription_send: Voice2Chatbox
|
||||
transcription_receive: Speaker2Log
|
||||
foreground: Foreground
|
||||
|
||||
language_settings: Language Settings
|
||||
your_language: Your Language
|
||||
both_direction_desc: Translate Each Other
|
||||
target_language: Target Language
|
||||
|
||||
textbox_tab_all: All
|
||||
textbox_tab_sent: Sent
|
||||
textbox_tab_received: Received
|
||||
textbox_tab_system: System
|
||||
|
||||
textbox_system_message:
|
||||
enabled_translation: Translation feature is turned on.
|
||||
disabled_translation: Translation feature is turned off.
|
||||
enabled_voice2chatbox: Transcription from the microphone has started.
|
||||
disabled_voice2chatbox: Transcription from the microphone has been stopped.
|
||||
enabled_speaker2log: Transcription from the speaker has started.
|
||||
disabled_speaker2log: Transcription from the speaker has been stopped.
|
||||
enabled_foreground: The screen is fixed in the foreground.
|
||||
disabled_foreground: The foreground fixation has been released.
|
||||
|
||||
auth_key_success: Auth key update completed.
|
||||
auth_key_error: Auth Key is incorrect or Usage limit reached.
|
||||
|
||||
no_mic_device_detected_error: No mic device detected.
|
||||
no_speaker_device_detected_error: No speaker device detected.
|
||||
translation_engine_limit_error: It has automatically disabled the translation feature. Access has been temporarily restricted due to an excessive number of requests to the translation engine. Please wait for a while, restart VRCT, and try again.
|
||||
|
||||
detected_by_word_filter: The word %{detected_message} has not been sent due to detection by the word filter.
|
||||
|
||||
selected_your_language: "\"Your Language\" has set to %{your_language}."
|
||||
selected_target_language: "\"Target Language\" has set to %{target_language}."
|
||||
switched_language_preset_tab: Switched to Language Preset Tab No.%{tab_no}."
|
||||
latest_language_setting: "Currently, \"Your Language\" is set to %{your_language}, and \"Target Language\" is set to %{target_language}."
|
||||
|
||||
opened_web_page_booth: Opened Booth page in your web browser.
|
||||
opened_web_page_vrct_documents: "Opened VRCT Documents page in your web browser.\nFor any issues, requests, or inquiries, please feel free to contact us through the links at the bottom of the documents page, the \"Contact Form,\" or via X (formerly Twitter)!"
|
||||
|
||||
update_available: New version is here!
|
||||
|
||||
cover_message: The functionality is temporarily disabled until the settings window is closed.
|
||||
|
||||
confirmation_message:
|
||||
update_software: "Download new version and restart automatically.\nIt'll take a while. Do it now?"
|
||||
deny_update_software: Do it later
|
||||
accept_update_software: Update and Restart
|
||||
updating: Now updating...
|
||||
|
||||
detected_over_ui_size: "Current UI Size: %{current_ui_size}\nVRCT's window size may be larger than your display size.\n* Depending on your display size, you may need to adjust it multiple times."
|
||||
deny_adjust_ui_size: "Keep it at this size"
|
||||
accept_adjust_ui_size: "Set it smaller and restart"
|
||||
|
||||
|
||||
translation_engine_limit_error: "It has automatically disabled the translation feature.\nAccess has been temporarily restricted\ndue to an excessive number of requests to the translation engine.\nPlease wait for a while, restart VRCT, and try again."
|
||||
accept_translation_engine_limit_error: Accept and close
|
||||
|
||||
|
||||
selectable_language_window:
|
||||
title_your_language: Select Your Language
|
||||
title_target_language: Select Target Language
|
||||
go_back_button: Go Back
|
||||
|
||||
|
||||
config_window:
|
||||
config_title: Settings
|
||||
compact_mode: Compact Mode
|
||||
version: version %{version}
|
||||
restart_message: Apply changes with a restart.
|
||||
common_error_message:
|
||||
invalid_value: Invalid value.
|
||||
|
||||
side_menu_labels:
|
||||
appearance: Appearance
|
||||
translation: Translation
|
||||
transcription: Transcription
|
||||
transcription_mic: Mic
|
||||
transcription_speaker: Speaker
|
||||
others: Others
|
||||
advanced_settings: Advanced Settings
|
||||
|
||||
|
||||
transparency:
|
||||
label: Transparency
|
||||
desc: Change the main window's transparency.
|
||||
|
||||
appearance_theme:
|
||||
label: Theme [Under development]
|
||||
desc: Change the color theme. Currently, only the Dark theme is supported. The Light theme is under development.
|
||||
|
||||
ui_size:
|
||||
label: UI Size
|
||||
|
||||
font_family:
|
||||
label: Font Family
|
||||
|
||||
ui_language:
|
||||
label: UI Language
|
||||
|
||||
deepl_auth_key:
|
||||
label: DeepL Auth Key
|
||||
|
||||
mic_host:
|
||||
label: Mic Host/Driver
|
||||
|
||||
mic_device:
|
||||
label: Mic Device
|
||||
|
||||
mic_dynamic_energy_threshold:
|
||||
label_for_automatic: "Mic Energy Threshold (Current Setting: Automatic)"
|
||||
desc_for_automatic: "Automatically determine microphone input sensitivity."
|
||||
label_for_manual: "Mic Energy Threshold (Current Setting: Manual)"
|
||||
desc_for_manual: "Manually determine the microphone input sensitivity using the slider. Press the microphone icon to input your voice and adjust the sensitivity while monitoring the volume."
|
||||
error_message: You can set it with a value between 0 to %{max}.
|
||||
|
||||
mic_record_timeout:
|
||||
label: Mic Record Timeout
|
||||
desc: Detects silence and, when the specified number of seconds has passed, considers the mic input to have ended. (Second(s))
|
||||
error_message: It cannot be greater than '%{mic_phrase_timeout_label}' with a value of 0 or more.
|
||||
|
||||
mic_phrase_timeout:
|
||||
label: Mic Phrase Timeout
|
||||
desc: Transcription processing is performed at intervals of the specified number of seconds.
|
||||
error_message: It cannot be set lower than '%{mic_record_timeout_label}' with a value of 0 or more.
|
||||
|
||||
mic_max_phrase:
|
||||
label: Mic Max Words
|
||||
desc: It is the lower limit for the number of transcribed words, and only when this number is exceeded will the transcription results be displayed logs and send to VRChat.
|
||||
error_message: You can set a number equal to or greater than 0.
|
||||
|
||||
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"
|
||||
|
||||
|
||||
speaker_dynamic_energy_threshold:
|
||||
label_for_automatic: "Speaker Energy Threshold (Current Setting: Automatic)"
|
||||
desc_for_automatic: "Automatically determine speaker input sensitivity."
|
||||
label_for_manual: "Speaker Energy Threshold (Current Setting: Manual)"
|
||||
desc_for_manual: "Manually determine the speaker input sensitivity using the slider. Press the headphones icon to listen to the audio and adjust the sensitivity while monitoring the volume."
|
||||
error_message: You can set it with a value between 0 to %{max}.
|
||||
no_device_error_message: No speaker device detected.
|
||||
|
||||
speaker_record_timeout:
|
||||
label: Speaker Record Timeout
|
||||
desc: Detects silence and, when the specified number of seconds has passed, considers the speaker input to have ended. (Second(s))
|
||||
error_message: It cannot be greater than '%{speaker_phrase_timeout_label}' with a value of 0 or more.
|
||||
|
||||
speaker_phrase_timeout:
|
||||
label: Speaker Phrase Timeout
|
||||
desc: Transcription processing is performed at intervals of the specified number of seconds.
|
||||
error_message: It cannot be set lower than '%{speaker_record_timeout_label}' with a value of 0 or more.
|
||||
|
||||
speaker_max_phrase:
|
||||
label: Speaker Max Words
|
||||
desc: It is the lower limit for the number of transcribed words, and only when this number is exceeded will the transcription results be displayed logs.
|
||||
error_message: You can set a number equal to or greater than 0.
|
||||
|
||||
|
||||
auto_clear_the_message_box:
|
||||
label: Auto Clear The Message Box
|
||||
|
||||
notice_xsoverlay:
|
||||
label: Notification XSOverlay (VR Only)
|
||||
desc: Notify received messages by using XSOverlay's notification feature.
|
||||
|
||||
auto_export_message_logs:
|
||||
label: Auto Export Message Logs
|
||||
desc: Automatically export the conversation messages as a text file.
|
||||
|
||||
message_format:
|
||||
label: Message Format
|
||||
desc: "You can change the decoration of the message you want to send.\n[message] will be replaced with the message, and [translation] will be replaced with the translated message.\nIt will be used in Notification XSOverlay too."
|
||||
|
||||
send_message_to_vrc:
|
||||
label: Send Message To VRChat
|
||||
desc: There is a way to use it without sending messages to VRChat, but it is not supported. Enable this feature when you intend to send a message to VRChat.
|
||||
|
||||
osc_ip_address:
|
||||
label: OSC IP Address
|
||||
|
||||
osc_port:
|
||||
label: OSC Port
|
||||
186
locales/ja.yml
Normal file
@@ -0,0 +1,186 @@
|
||||
main_window:
|
||||
translation: 翻訳
|
||||
transcription_send: 音声認識(マイク)
|
||||
transcription_receive: 音声認識(スピーカー)
|
||||
foreground: 最前面表示
|
||||
|
||||
language_settings: 言語設定
|
||||
your_language: あなたの言語
|
||||
both_direction_desc: 双方向に翻訳
|
||||
target_language: 相手の言語
|
||||
|
||||
textbox_tab_all: 全て
|
||||
textbox_tab_sent: 送信
|
||||
textbox_tab_received: 受信
|
||||
textbox_tab_system: システム
|
||||
|
||||
textbox_system_message:
|
||||
enabled_translation: 翻訳機能をONにしました。
|
||||
disabled_translation: 翻訳機能をOFFしました。
|
||||
enabled_voice2chatbox: マイクからの音声入力、文字起こしを開始します。
|
||||
disabled_voice2chatbox: マイクからの音声入力、文字起こしを終了しました。
|
||||
enabled_speaker2log: スピーカーからの音声聞き取り、文字起こしを開始します。
|
||||
disabled_speaker2log: スピーカーからの音声聞き取り、文字起こしを終了しました。
|
||||
enabled_foreground: 画面を常に最前面へ固定します。
|
||||
disabled_foreground: 最前面への固定を解除しました。
|
||||
|
||||
auth_key_success: 認証キーの更新が完了しました。
|
||||
auth_key_error: 認証キーが間違っているか、API使用制限が上限に達しています.
|
||||
|
||||
no_mic_device_detected_error: マイクデバイスが検出されませんでした。
|
||||
no_speaker_device_detected_error: スピーカーデバイスが検出されませんでした。
|
||||
translation_engine_limit_error: 翻訳機能を自動的に停止しました。翻訳エンジンへのリクエストが多すぎるため、一時的にアクセスが制限されています。しばらく待ってから、VRCTの再起動をしてもう一度試してみてください。
|
||||
|
||||
detected_by_word_filter: ワードフィルターに登録されている単語 %{detected_message} が検出されたため送信しませんでした。
|
||||
|
||||
selected_your_language: 「あなたの言語」 を %{your_language} に設定しました。
|
||||
selected_target_language: 「相手の言語」 を %{target_language} に設定しました。
|
||||
switched_language_preset_tab: 言語プリセット番号 %{tab_no} に切り替わりました。
|
||||
latest_language_setting: 現在「あなたの言語」は %{your_language}、「相手の言語」は %{target_language} に設定されています。
|
||||
|
||||
opened_web_page_booth: お使いのブラウザで、Boothのページを開きました。
|
||||
opened_web_page_vrct_documents: "お使いのブラウザで、VRCTのドキュメントを開きました。使用方法などはそちらに記載されています。\n不具合、ご要望、その他お問い合わせはドキュメント最下部にあるLinks、「お問合せフォーム」もしくはX(元Twitter)にて気軽にご連絡ください!"
|
||||
|
||||
update_available: 新しいバージョンが出ました!
|
||||
|
||||
cover_message: 設定画面が閉じられるまで、一時的に機能を停止しています。
|
||||
|
||||
confirmation_message:
|
||||
update_software: "新しいバージョンをダウンロードして再起動します。\n少し時間がかかるかもしれません。今すぐ行いますか?"
|
||||
deny_update_software: 後でする
|
||||
accept_update_software: アップデートして再起動
|
||||
updating: アップデート中...
|
||||
|
||||
detected_over_ui_size: "現在のUI サイズ: %{current_ui_size}\nVRCTのウィンドウサイズが、お使いのディスプレイサイズより大きい可能性があります。\n※ディスプレイサイズによっては、何度か再設定が必要な場合があります。"
|
||||
deny_adjust_ui_size: このサイズのままで良い
|
||||
accept_adjust_ui_size: 小さく設定して再起動
|
||||
|
||||
|
||||
translation_engine_limit_error: "翻訳機能を自動的に停止しました。\n翻訳エンジンへのリクエストが多すぎるため\n一時的にアクセスが制限されています。\nしばらく待ってから、VRCTの再起動をしてもう一度試してみてください。"
|
||||
accept_translation_engine_limit_error: 了承して閉じる
|
||||
|
||||
|
||||
selectable_language_window:
|
||||
title_your_language: あなたの言語
|
||||
title_target_language: 相手の言語
|
||||
go_back_button: 戻る
|
||||
|
||||
|
||||
config_window:
|
||||
config_title: 設定
|
||||
compact_mode: コンパクトモード
|
||||
version: バージョン %{version}
|
||||
restart_message: 再起動して変更を適用する。
|
||||
common_error_message:
|
||||
invalid_value: 無効な値です。
|
||||
|
||||
side_menu_labels:
|
||||
appearance: デザイン
|
||||
translation: 翻訳
|
||||
transcription: 音声認識
|
||||
transcription_mic: マイク
|
||||
transcription_speaker: スピーカー
|
||||
others: その他
|
||||
advanced_settings: 高度な設定
|
||||
|
||||
|
||||
transparency:
|
||||
label: 透明度
|
||||
desc: メイン画面の透明度を変更できます。
|
||||
|
||||
appearance_theme:
|
||||
label: 外観テーマ [開発中]
|
||||
desc: カラーテーマを変更できます。現在はDarkテーマのみ対応。Lightテーマは制作中です。
|
||||
|
||||
ui_size:
|
||||
label: UIサイズ
|
||||
|
||||
font_family:
|
||||
label: 使用フォント
|
||||
|
||||
ui_language:
|
||||
label: UIの言語 / UI Language
|
||||
|
||||
deepl_auth_key:
|
||||
label: DeepL 認証キー
|
||||
|
||||
mic_host:
|
||||
label: マイク(ホスト/ドライバー)
|
||||
|
||||
mic_device:
|
||||
label: マイク (デバイス)
|
||||
|
||||
mic_dynamic_energy_threshold:
|
||||
label_for_automatic: "マイク入力感度の調整 (現在の設定: 自動)"
|
||||
desc_for_automatic: マイクの入力感度を自動的に調節する。
|
||||
label_for_manual: "マイク入力感度の調整 (現在の設定: 手動)"
|
||||
desc_for_manual: スライダーを調整して入力感度を手動で決められます。マイクのアイコンを押すと、実際に声を入力し、音量を確認しながら調節できます。
|
||||
error_message: 0 から %{max} までの数値で設定できます。
|
||||
|
||||
mic_record_timeout:
|
||||
label: 入力が終了したとみなす無音時間
|
||||
desc: 無音を検出し、設定された秒数経過すると、音声入力が終了したとみなします。
|
||||
error_message: 0 以上で 「%{mic_phrase_timeout_label}」より大きくすることはできません。
|
||||
|
||||
mic_phrase_timeout:
|
||||
label: 一度に文字起こしする時間の長さ
|
||||
desc: 設定された秒数ごとに文字起こし処理が行われます。
|
||||
error_message: 0 以上で 「%{mic_record_timeout_label}」より小さくすることはできません。
|
||||
|
||||
mic_max_phrase:
|
||||
label: 送信するまでに保持する単語数
|
||||
desc: 文字起こしされた単語数の下限値で、この数値を超えた場合のみ結果をVRChatへ送信し、ログに表示します。
|
||||
error_message: 0以上の数値を設定できます。
|
||||
|
||||
mic_word_filter:
|
||||
label: ワードフィルター
|
||||
desc: "設定された単語を検出すると、その文章は送信されません。\n設定の例: AAA,BBB,CCC"
|
||||
|
||||
|
||||
speaker_dynamic_energy_threshold:
|
||||
label_for_automatic: "スピーカー入力感度の調整 (現在の設定: 自動)"
|
||||
desc_for_automatic: スピーカーの入力感度を自動的に調節する。
|
||||
label_for_manual: "スピーカー入力感度の調整 (現在の設定: 手動)"
|
||||
desc_for_manual: スライダーを調整して入力感度を手動で決められます。ヘッドフォンのアイコンを押すと、実際に音声を聞き取り、音量を確認しながら調節できます。
|
||||
error_message: 0 から %{max} までの数値で設定できます。
|
||||
no_device_error_message: スピーカーデバイスが検出されませんでした。
|
||||
|
||||
speaker_record_timeout:
|
||||
label: 入力が終了したとみなす無音時間
|
||||
desc: 無音を検出し、設定された秒数経過すると、音声入力が終了したとみなします。
|
||||
error_message: 0 以上で 「%{speaker_phrase_timeout_label}」より大きくすることはできません。
|
||||
|
||||
speaker_phrase_timeout:
|
||||
label: 一度に文字起こしする時間の長さ
|
||||
desc: 設定された秒数ごとに文字起こし処理が行われます。
|
||||
error_message: 0 以上で 「%{speaker_record_timeout_label}」より小さくすることはできません。
|
||||
|
||||
speaker_max_phrase:
|
||||
label: ログとして表示するまでに保持する単語数
|
||||
desc: 文字起こしされた単語数の下限値で、この数値を超えた場合のみ結果をログに表示します。
|
||||
error_message: 0以上の数値を設定できます。
|
||||
|
||||
auto_clear_the_message_box:
|
||||
label: 送信後はチャットボックスを空にする
|
||||
|
||||
notice_xsoverlay:
|
||||
label: XSOverlayでの通知受け取り機能を有効 (VR限定)
|
||||
desc: 文字起こし(受信)されたメッセージをXSOverlayの機能を使って通知として受け取れます。
|
||||
|
||||
auto_export_message_logs:
|
||||
label: 会話ログを自動的に保存する
|
||||
desc: テキストファイルとしてログがlogsフォルダ内に保存されます。
|
||||
|
||||
message_format:
|
||||
label: 送信するメッセージのフォーマット
|
||||
desc: "VRChatで相手に実際に見えるフォーマットを変更できます。\n[message]がメッセージに置換され、\n[translation]が翻訳されたメッセージに置換されます。\n※XSOverlayでの通知受け取り機能でも使われます。"
|
||||
|
||||
send_message_to_vrc:
|
||||
label: VRChatにメッセージを送信する
|
||||
desc: "サポート対象外ですが、VRChatにメッセージを送信せずに使う方法があります。送信したい場合、この機能を有効にする事を忘れないでください。"
|
||||
|
||||
osc_ip_address:
|
||||
label: OSC IP Address
|
||||
|
||||
osc_port:
|
||||
label: OSC Port
|
||||
187
locales/ko.yml
Normal file
@@ -0,0 +1,187 @@
|
||||
main_window:
|
||||
translation: 번역
|
||||
transcription_send: 마이크 -> 챗박스
|
||||
transcription_receive: 스피커 -> 로그
|
||||
foreground: 항상 위로
|
||||
|
||||
# language_settings: Language Settings
|
||||
# your_language: Your Language
|
||||
# both_direction_desc: Translate Each Other
|
||||
# target_language: Target Language
|
||||
|
||||
textbox_tab_all: 전체
|
||||
textbox_tab_sent: 전송
|
||||
textbox_tab_received: 수신
|
||||
textbox_tab_system: 시스템
|
||||
|
||||
# textbox_system_message:
|
||||
# enabled_translation: Translation feature is turned on.
|
||||
# disabled_translation: Translation feature is turned off.
|
||||
# enabled_voice2chatbox: Transcription from the microphone has started.
|
||||
# disabled_voice2chatbox: Transcription from the microphone has been stopped.
|
||||
# enabled_speaker2log: Transcription from the speaker has started.
|
||||
# disabled_speaker2log: Transcription from the speaker has been stopped.
|
||||
# enabled_foreground: The screen is fixed in the foreground.
|
||||
# disabled_foreground: The foreground fixation has been released.
|
||||
|
||||
# auth_key_success: Auth key update completed.
|
||||
# auth_key_error: Auth Key is incorrect or Usage limit reached.
|
||||
|
||||
# no_mic_device_detected_error: No mic device detected.
|
||||
# no_speaker_device_detected_error: No speaker device detected.
|
||||
# translation_engine_limit_error: It has automatically disabled the translation feature. Access has been temporarily restricted due to an excessive number of requests to the translation engine. Please wait for a while, restart VRCT, and try again.
|
||||
|
||||
# detected_by_word_filter: The word %{detected_message} has not been sent due to detection by the word filter.
|
||||
|
||||
# selected_your_language: "\"Your Language\" has set to %{your_language}."
|
||||
# selected_target_language: "\"Target Language\" has set to %{target_language}."
|
||||
# switched_language_preset_tab: Switched to Language Preset Tab No.%{tab_no}."
|
||||
# latest_language_setting: "Currently, \"Your Language\" is set to %{your_language}, and \"Target Language\" is set to %{target_language}."
|
||||
|
||||
# opened_web_page_booth: Opened Booth page in your web browser.
|
||||
# opened_web_page_vrct_documents: "Opened VRCT Documents page in your web browser.\nFor any issues, requests, or inquiries, please feel free to contact us through the links at the bottom of the documents page, the \"Contact Form,\" or via X (formerly Twitter)!"
|
||||
|
||||
# update_available: New version is here!
|
||||
|
||||
# cover_message: The functionality is temporarily disabled until the settings window is closed.
|
||||
|
||||
# confirmation_message:
|
||||
# update_software: "Download new version and restart automatically.\nIt'll take a while. Do it now?"
|
||||
# deny_update_software: Do it later
|
||||
# accept_update_software: Update and Restart
|
||||
# updating: Now updating...
|
||||
|
||||
# detected_over_ui_size: "Current UI Size: %{current_ui_size}\nVRCT's window size may be larger than your display size.\n* Depending on your display size, you may need to adjust it multiple times."
|
||||
# deny_adjust_ui_size: "Keep it at this size"
|
||||
# accept_adjust_ui_size: "Set it smaller and restart"
|
||||
|
||||
|
||||
# translation_engine_limit_error: "It has automatically disabled the translation feature.\nAccess has been temporarily restricted\ndue to an excessive number of requests to the translation engine.\nPlease wait for a while, restart VRCT, and try again."
|
||||
# accept_translation_engine_limit_error: Accept and close
|
||||
|
||||
|
||||
# selectable_language_window:
|
||||
# title_your_language: Select Your Language
|
||||
# title_target_language: Select Target Language
|
||||
# go_back_button: Go Back
|
||||
|
||||
|
||||
config_window:
|
||||
# config_title: Settings
|
||||
# compact_mode: Compact Mode
|
||||
# version: version %{version}
|
||||
# restart_message: Apply changes with a restart.
|
||||
# common_error_message:
|
||||
# invalid_value: Invalid value.
|
||||
|
||||
side_menu_labels:
|
||||
# appearance: Appearance
|
||||
translation: 번역
|
||||
transcription: 음성인식
|
||||
transcription_mic: 마이크
|
||||
transcription_speaker: 스피커
|
||||
others: 기타
|
||||
# advanced_settings: Advanced Settings
|
||||
|
||||
|
||||
transparency:
|
||||
label: 투명도
|
||||
# desc: Change the main window's transparency.
|
||||
|
||||
appearance_theme:
|
||||
label: 테마 [Under development]
|
||||
# desc: Change the color theme. Currently, only the Dark theme is supported. The Light theme is under development.
|
||||
|
||||
ui_size:
|
||||
label: UI 크기
|
||||
|
||||
font_family:
|
||||
label: 폰트
|
||||
|
||||
ui_language:
|
||||
label: UI 언어 / UI Language
|
||||
|
||||
deepl_auth_key:
|
||||
label: DeepL 인증키
|
||||
|
||||
mic_host:
|
||||
label: 마이크 호스트/Driver
|
||||
|
||||
mic_device:
|
||||
label: 마이크 장치
|
||||
|
||||
mic_dynamic_energy_threshold:
|
||||
label_for_automatic: "음성 입력 최소 볼륨 (Current Setting: Automatic)"
|
||||
# desc_for_automatic: "Automatically determine microphone input sensitivity."
|
||||
label_for_manual: "음성 입력 최소 볼륨 (Current Setting: Manual)"
|
||||
# desc_for_manual: "Manually determine the microphone input sensitivity using the slider. Press the microphone icon to input your voice and adjust the sensitivity while monitoring the volume."
|
||||
# error_message: You can set it with a value between 0 to %{max}.
|
||||
|
||||
mic_record_timeout:
|
||||
label: 최대 무음 시간
|
||||
# desc: Detects silence and, when the specified number of seconds has passed, considers the mic input to have ended. (Second(s))
|
||||
# error_message: It cannot be greater than '%{mic_phrase_timeout_label}' with a value of 0 or more.
|
||||
|
||||
mic_phrase_timeout:
|
||||
label: 최대 인식 시간
|
||||
# desc: Transcription processing is performed at intervals of the specified number of seconds.
|
||||
# error_message: It cannot be set lower than '%{mic_record_timeout_label}' with a value of 0 or more.
|
||||
|
||||
mic_max_phrase:
|
||||
label: 최대 입력 절(phrases) 수
|
||||
# desc: It is the lower limit for the number of transcribed words, and only when this number is exceeded will the transcription results be displayed logs and send to VRChat.
|
||||
# error_message: You can set a number equal to or greater than 0.
|
||||
|
||||
mic_word_filter:
|
||||
label: 단어 필터
|
||||
# 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"
|
||||
|
||||
|
||||
speaker_dynamic_energy_threshold:
|
||||
label_for_automatic: "음성 입력 최소 볼륨 (Current Setting: Automatic)"
|
||||
# desc_for_automatic: "Automatically determine speaker input sensitivity."
|
||||
label_for_manual: "음성 입력 최소 볼륨 (Current Setting: Manual)"
|
||||
# desc_for_manual: "Manually determine the speaker input sensitivity using the slider. Press the headphones icon to listen to the audio and adjust the sensitivity while monitoring the volume."
|
||||
# error_message: You can set it with a value between 0 to %{max}.
|
||||
# no_device_error_message: No speaker device detected.
|
||||
|
||||
speaker_record_timeout:
|
||||
label: 최대 무음 시간
|
||||
# desc: Detects silence and, when the specified number of seconds has passed, considers the speaker input to have ended. (Second(s))
|
||||
# error_message: It cannot be greater than '%{speaker_phrase_timeout_label}' with a value of 0 or more.
|
||||
|
||||
speaker_phrase_timeout:
|
||||
label: 최대 인식 시간
|
||||
# desc: Transcription processing is performed at intervals of the specified number of seconds.
|
||||
# error_message: It cannot be set lower than '%{speaker_record_timeout_label}' with a value of 0 or more.
|
||||
|
||||
speaker_max_phrase:
|
||||
label: 최대 입력 절(phrases) 수
|
||||
# desc: It is the lower limit for the number of transcribed words, and only when this number is exceeded will the transcription results be displayed logs.
|
||||
# error_message: You can set a number equal to or greater than 0.
|
||||
|
||||
|
||||
auto_clear_the_message_box:
|
||||
label: 챗박스 자동 삭제
|
||||
|
||||
# notice_xsoverlay:
|
||||
# label: Notification XSOverlay (VR Only)
|
||||
# desc: Notify received messages by using XSOverlay's notification feature.
|
||||
|
||||
# auto_export_message_logs:
|
||||
# label: Auto Export Message Logs
|
||||
# desc: Automatically export the conversation messages as a text file.
|
||||
|
||||
message_format:
|
||||
label: 전송 형식
|
||||
# desc: "You can change the decoration of the message you want to send.\n[message] will be replaced with the message, and [translation] will be replaced with the translated message.\nIt will be used in Notification XSOverlay too."
|
||||
|
||||
# send_message_to_vrc:
|
||||
# label: Send Message To VRChat
|
||||
# desc: There is a way to use it without sending messages to VRChat, but it is not supported. Enable this feature when you intend to send a message to VRChat.
|
||||
|
||||
osc_ip_address:
|
||||
label: OSC IP 주소
|
||||
|
||||
osc_port:
|
||||
label: OSC 포트
|
||||
18
main.py
Normal file
@@ -0,0 +1,18 @@
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
import ctypes
|
||||
ctypes.windll.shcore.SetProcessDpiAwareness(0)
|
||||
|
||||
from vrct_gui.splash_window import SplashWindow
|
||||
splash = SplashWindow()
|
||||
splash.showSplash()
|
||||
|
||||
import controller
|
||||
controller.createMainWindow()
|
||||
splash.destroySplash()
|
||||
controller.showMainWindow()
|
||||
|
||||
except Exception as e:
|
||||
import traceback
|
||||
with open('error.log', 'a') as f:
|
||||
traceback.print_exc(file=f)
|
||||
398
model.py
@@ -1,22 +1,34 @@
|
||||
import sys
|
||||
from zipfile import ZipFile
|
||||
from subprocess import Popen
|
||||
from os import makedirs as os_makedirs
|
||||
from os import path as os_path, rename as os_rename
|
||||
from shutil import rmtree
|
||||
from datetime import datetime
|
||||
from logging import getLogger, FileHandler, Formatter, INFO
|
||||
from time import sleep
|
||||
from queue import Queue
|
||||
from threading import Thread, Event
|
||||
from requests import get as requests_get
|
||||
import webbrowser
|
||||
|
||||
from flashtext import KeywordProcessor
|
||||
from models.translation.translation_translator import Translator
|
||||
from models.transcription.transcription_utils import getInputDevices, getOutputDevices, getDefaultInputDevice, getDefaultOutputDevice
|
||||
from models.transcription.transcription_utils import getInputDevices, getDefaultOutputDevice
|
||||
from models.osc.osc_tools import sendTyping, sendMessage, sendTestAction, receiveOscParameters
|
||||
from models.transcription.transcription_recorder import SelectedMicRecorder, SelectedSpeakerRecorder
|
||||
from models.transcription.transcription_recorder import SelectedMicEnergyRecorder, SelectedSpeakeEnergyRecorder
|
||||
from models.transcription.transcription_transcriber import AudioTranscriber
|
||||
from models.xsoverlay.notification import xsoverlayForVRCT
|
||||
from models.translation.translation_languages import translatorEngine, translation_lang
|
||||
from models.transcription.transcription_languages import transcription_lang
|
||||
from config import config
|
||||
|
||||
class threadFnc(Thread):
|
||||
def __init__(self, fnc, daemon=True, *args, **kwargs):
|
||||
def __init__(self, fnc, end_fnc=None, daemon=True, *args, **kwargs):
|
||||
super(threadFnc, self).__init__(daemon=daemon, *args, **kwargs)
|
||||
self.fnc = fnc
|
||||
self.end_fnc = end_fnc
|
||||
self._stop = Event()
|
||||
def stop(self):
|
||||
self._stop.set()
|
||||
@@ -25,10 +37,21 @@ class threadFnc(Thread):
|
||||
def run(self):
|
||||
while True:
|
||||
if self.stopped():
|
||||
if callable(self.end_fnc):
|
||||
self.end_fnc()
|
||||
return
|
||||
self.fnc(*self._args, **self._kwargs)
|
||||
|
||||
class Model:
|
||||
# Languages available for both transcription and translation
|
||||
SUPPORTED_LANGUAGES = [
|
||||
'Afrikaans', 'Arabic', 'Basque', 'Bulgarian', 'Catalan', 'Chinese', 'Croatian',
|
||||
'Czech', 'Danish', 'Dutch', 'English', 'Filipino', 'Finnish', 'French', 'German',
|
||||
'Greek', 'Hebrew', 'Hindi', 'Hungarian', 'Indonesian', 'Italian', 'Japanese',
|
||||
'Korean', 'Lithuanian', 'Malay', 'Norwegian', 'Polish', 'Portuguese', 'Romanian',
|
||||
'Russian', 'Serbian', 'Slovak', 'Slovenian', 'Spanish', 'Swedish', 'Thai', 'Turkish',
|
||||
'Ukrainian', 'Vietnamese'
|
||||
]
|
||||
_instance = None
|
||||
|
||||
def __new__(cls):
|
||||
@@ -38,9 +61,14 @@ class Model:
|
||||
return cls._instance
|
||||
|
||||
def init(self):
|
||||
self.logger = None
|
||||
self.mic_print_transcript = None
|
||||
self.mic_audio_recorder = None
|
||||
self.mic_energy_recorder = None
|
||||
self.mic_energy_plot_progressbar = None
|
||||
self.speaker_energy_get_progressbar = None
|
||||
self.speaker_print_transcript = None
|
||||
self.speaker_audio_recorder = None
|
||||
self.speaker_energy_recorder = None
|
||||
self.speaker_energy_plot_progressbar = None
|
||||
self.translator = Translator()
|
||||
self.keyword_processor = KeywordProcessor()
|
||||
@@ -50,7 +78,7 @@ class Model:
|
||||
self.translator = Translator()
|
||||
|
||||
def resetKeywordProcessor(self):
|
||||
del self.translator
|
||||
del self.keyword_processor
|
||||
self.keyword_processor = KeywordProcessor()
|
||||
|
||||
def authenticationTranslator(self, choice_translator=None, auth_key=None):
|
||||
@@ -60,37 +88,117 @@ class Model:
|
||||
auth_key = config.AUTH_KEYS[choice_translator]
|
||||
|
||||
result = self.translator.authentication(choice_translator, auth_key)
|
||||
if result:
|
||||
auth_keys = config.AUTH_KEYS
|
||||
auth_keys[choice_translator] = auth_key
|
||||
config.AUTH_KEYS = auth_keys
|
||||
return result
|
||||
|
||||
def getTranslatorStatus(self):
|
||||
return self.translator.translator_status[config.CHOICE_TRANSLATOR]
|
||||
def startLogger(self):
|
||||
os_makedirs(os_path.join(os_path.dirname(sys.argv[0]), "logs"), exist_ok=True)
|
||||
logger = getLogger()
|
||||
logger.setLevel(INFO)
|
||||
file_name = os_path.join(os_path.dirname(sys.argv[0]), "logs", f"{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.log")
|
||||
file_handler = FileHandler(file_name, encoding="utf-8", delay=True)
|
||||
formatter = Formatter("[%(asctime)s] %(message)s")
|
||||
file_handler.setFormatter(formatter)
|
||||
logger.addHandler(file_handler)
|
||||
self.logger = logger
|
||||
self.logger.disabled = False
|
||||
|
||||
def getListTranslatorName(self):
|
||||
return list(self.translator.translator_status.keys())
|
||||
def stopLogger(self):
|
||||
self.logger.disabled = True
|
||||
self.logger = None
|
||||
|
||||
@staticmethod
|
||||
def getListLanguageAndCountry():
|
||||
langs = []
|
||||
for lang in model.SUPPORTED_LANGUAGES:
|
||||
for country in transcription_lang[lang]:
|
||||
langs.append(f"{lang}\n({country})")
|
||||
return langs
|
||||
|
||||
@staticmethod
|
||||
def getLanguageAndCountry(select):
|
||||
parts = select.split("\n")
|
||||
language = parts[0]
|
||||
country = parts[1][1:-1]
|
||||
return language, country
|
||||
|
||||
def findTranslationEngine(self, source_lang, target_lang):
|
||||
compatible_engines = []
|
||||
for engine in translatorEngine:
|
||||
source_languages = translation_lang.get(engine, {}).get("source", {})
|
||||
target_languages = translation_lang.get(engine, {}).get("target", {})
|
||||
if source_lang in source_languages and target_lang in target_languages:
|
||||
compatible_engines.append(engine)
|
||||
engine_name = compatible_engines[0]
|
||||
|
||||
if engine_name == "DeepL" and config.AUTH_KEYS["DeepL_API"] != None:
|
||||
if self.authenticationTranslator(engine_name, config.AUTH_KEYS["DeepL_API"]) is True:
|
||||
engine_name = "DeepL_API"
|
||||
elif engine_name == "DeepL_API" and config.AUTH_KEYS["DeepL_API"] == None:
|
||||
engine_name = "DeepL"
|
||||
|
||||
return engine_name
|
||||
|
||||
def getInputTranslate(self, message):
|
||||
translator_name=config.CHOICE_TRANSLATOR
|
||||
source_language=config.SOURCE_LANGUAGE
|
||||
target_language=config.TARGET_LANGUAGE
|
||||
target_country = config.TARGET_COUNTRY
|
||||
|
||||
if translator_name == "DeepL_API":
|
||||
if target_language == "English":
|
||||
if target_country in ["United States", "Canada", "Philippines"]:
|
||||
target_language = "English American"
|
||||
else:
|
||||
target_language = "English British"
|
||||
elif target_language == "Portuguese":
|
||||
if target_country in ["Portugal"]:
|
||||
target_language = "Portuguese European"
|
||||
else:
|
||||
target_language = "Portuguese Brazilian"
|
||||
elif translator_name == "DeepL":
|
||||
if target_language in ["English American", "English British"]:
|
||||
target_language = "English"
|
||||
elif target_language in ["Portuguese European", "Portuguese Brazilian"]:
|
||||
target_language = "Portuguese"
|
||||
|
||||
translation = self.translator.translate(
|
||||
translator_name=config.CHOICE_TRANSLATOR,
|
||||
source_language=config.INPUT_SOURCE_LANG,
|
||||
target_language=config.INPUT_TARGET_LANG,
|
||||
translator_name=translator_name,
|
||||
source_language=source_language,
|
||||
target_language=target_language,
|
||||
message=message
|
||||
)
|
||||
message = config.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", translation)
|
||||
return message
|
||||
return translation
|
||||
|
||||
def getOutputTranslate(self, message):
|
||||
translator_name=config.CHOICE_TRANSLATOR
|
||||
source_language=config.TARGET_LANGUAGE
|
||||
target_language=config.SOURCE_LANGUAGE
|
||||
target_country = config.SOURCE_COUNTRY
|
||||
|
||||
if translator_name == "DeepL_API":
|
||||
if target_language == "English":
|
||||
if target_country in ["United States", "Canada", "Philippines"]:
|
||||
target_language = "English American"
|
||||
else:
|
||||
target_language = "English British"
|
||||
elif target_language == "Portuguese":
|
||||
if target_country in ["Portugal"]:
|
||||
target_language = "Portuguese European"
|
||||
else:
|
||||
target_language = "Portuguese Brazilian"
|
||||
elif translator_name == "DeepL":
|
||||
if target_language in ["English American", "English British"]:
|
||||
target_language = "English"
|
||||
elif target_language in ["Portuguese European", "Portuguese Brazilian"]:
|
||||
target_language = "Portuguese"
|
||||
|
||||
translation = self.translator.translate(
|
||||
translator_name=config.CHOICE_TRANSLATOR,
|
||||
source_language=config.OUTPUT_SOURCE_LANG,
|
||||
target_language=config.OUTPUT_TARGET_LANG,
|
||||
translator_name=translator_name,
|
||||
source_language=source_language,
|
||||
target_language=target_language,
|
||||
message=message
|
||||
)
|
||||
message = config.MESSAGE_FORMAT.replace("[message]", message).replace("[translation]", translation)
|
||||
return message
|
||||
return translation
|
||||
|
||||
def addKeywords(self):
|
||||
for f in config.INPUT_MIC_WORD_FILTER:
|
||||
@@ -111,27 +219,85 @@ class Model:
|
||||
def oscSendMessage(message):
|
||||
sendMessage(message, config.OSC_IP_ADDRESS, config.OSC_PORT)
|
||||
|
||||
@staticmethod
|
||||
def checkOSCStarted():
|
||||
def checkOSCStarted(self, fnc):
|
||||
self.is_valid_osc = False
|
||||
def checkOscReceive(address, osc_arguments):
|
||||
if config.ENABLE_OSC is False:
|
||||
config.ENABLE_OSC = True
|
||||
if self.is_valid_osc is False:
|
||||
self.is_valid_osc = True
|
||||
|
||||
self.listening_server = receiveOscParameters(checkOscReceive)
|
||||
def oscListener():
|
||||
self.listening_server.serve_forever()
|
||||
|
||||
def sendTestActionLoop():
|
||||
for _ in range(10):
|
||||
sendTestAction()
|
||||
if self.is_valid_osc is True:
|
||||
break
|
||||
sleep(0.1)
|
||||
self.listening_server.shutdown()
|
||||
|
||||
# start receive osc
|
||||
th_receive_osc_parameters = Thread(target=receiveOscParameters, args=(checkOscReceive,))
|
||||
th_receive_osc_parameters = Thread(target=oscListener)
|
||||
th_receive_osc_parameters.daemon = True
|
||||
th_receive_osc_parameters.start()
|
||||
|
||||
# check osc started
|
||||
sendTestAction()
|
||||
th_send_osc_test_action = Thread(target=sendTestActionLoop)
|
||||
th_send_osc_test_action.daemon = True
|
||||
th_send_osc_test_action.start()
|
||||
|
||||
th_receive_osc_parameters.join()
|
||||
th_send_osc_test_action.join()
|
||||
|
||||
if self.is_valid_osc is False:
|
||||
fnc()
|
||||
|
||||
@staticmethod
|
||||
def checkSoftwareUpdated():
|
||||
# check update
|
||||
update_flag = False
|
||||
response = requests_get(config.GITHUB_URL)
|
||||
tag_name = response.json()["tag_name"]
|
||||
if tag_name != config.VERSION:
|
||||
config.UPDATE_FLAG = True
|
||||
new_version = response.json()["name"]
|
||||
if new_version != config.VERSION:
|
||||
update_flag = True
|
||||
print("software version", "now:", config.VERSION, "new:", new_version)
|
||||
return update_flag
|
||||
|
||||
@staticmethod
|
||||
def updateSoftware(restart:bool=True):
|
||||
filename = 'download.zip'
|
||||
program_name = 'VRCT.exe'
|
||||
temporary_name = '_VRCT.exe'
|
||||
tmp_directory_name = 'tmp'
|
||||
batch_name = 'update.bat'
|
||||
current_directory = os_path.dirname(sys.argv[0])
|
||||
program_directory = os_path.dirname(__file__)
|
||||
|
||||
try:
|
||||
res = requests_get(config.GITHUB_URL)
|
||||
url = res.json()['assets'][0]['browser_download_url']
|
||||
res = requests_get(url, stream=True)
|
||||
os_makedirs(os_path.join(current_directory, tmp_directory_name), exist_ok=True)
|
||||
with open(os_path.join(current_directory, tmp_directory_name, filename), 'wb') as file:
|
||||
for chunk in res.iter_content(chunk_size=1024):
|
||||
file.write(chunk)
|
||||
with ZipFile(os_path.join(current_directory, tmp_directory_name, filename)) as zf:
|
||||
zf.extract(program_name, os_path.join(current_directory, tmp_directory_name))
|
||||
os_rename(os_path.join(current_directory, tmp_directory_name, program_name), os_path.join(current_directory, temporary_name))
|
||||
rmtree(os_path.join(current_directory, tmp_directory_name))
|
||||
command = [os_path.join(program_directory, "batch", batch_name), program_name, temporary_name, str(restart)]
|
||||
Popen(command)
|
||||
except:
|
||||
webbrowser.open(config.BOOTH_URL, new=2, autoraise=True)
|
||||
|
||||
@staticmethod
|
||||
def reStartSoftware():
|
||||
program_name = 'VRCT.exe'
|
||||
batch_name = 'restart.bat'
|
||||
program_directory = os_path.dirname(__file__)
|
||||
command = [os_path.join(program_directory, "batch", batch_name), program_name]
|
||||
Popen(command)
|
||||
|
||||
@staticmethod
|
||||
def getListInputHost():
|
||||
@@ -146,35 +312,44 @@ class Model:
|
||||
return [device["name"] for device in getInputDevices()[config.CHOICE_MIC_HOST]][0]
|
||||
|
||||
@staticmethod
|
||||
def getListOutputDevice():
|
||||
return [device["name"] for device in getOutputDevices()]
|
||||
def getOutputDefaultDevice():
|
||||
return getDefaultOutputDevice()["name"]
|
||||
|
||||
@staticmethod
|
||||
def checkSpeakerStatus(choice=config.CHOICE_SPEAKER_DEVICE):
|
||||
speaker_device = [device for device in getOutputDevices() if device["name"] == choice][0]
|
||||
if getDefaultOutputDevice()["index"] == speaker_device["index"]:
|
||||
return True
|
||||
return False
|
||||
def startMicTranscript(self, fnc, error_fnc=None):
|
||||
if config.CHOICE_MIC_HOST == "NoHost" or config.CHOICE_MIC_DEVICE == "NoDevice":
|
||||
try:
|
||||
error_fnc()
|
||||
except:
|
||||
pass
|
||||
return
|
||||
|
||||
def startMicTranscript(self, fnc):
|
||||
mic_audio_queue = Queue()
|
||||
device = [device for device in getInputDevices()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0]
|
||||
record_timeout = config.INPUT_MIC_RECORD_TIMEOUT
|
||||
phase_timeout = config.INPUT_MIC_PHRASE_TIMEOUT
|
||||
if record_timeout > phase_timeout:
|
||||
record_timeout = phase_timeout
|
||||
|
||||
self.mic_audio_recorder = SelectedMicRecorder(
|
||||
[device for device in getInputDevices()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0],
|
||||
config.INPUT_MIC_ENERGY_THRESHOLD,
|
||||
config.INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD,
|
||||
config.INPUT_MIC_RECORD_TIMEOUT,
|
||||
device=device,
|
||||
energy_threshold=config.INPUT_MIC_ENERGY_THRESHOLD,
|
||||
dynamic_energy_threshold=config.INPUT_MIC_DYNAMIC_ENERGY_THRESHOLD,
|
||||
record_timeout=record_timeout,
|
||||
)
|
||||
self.mic_audio_recorder.recordIntoQueue(mic_audio_queue)
|
||||
mic_transcriber = AudioTranscriber(
|
||||
speaker=False,
|
||||
source=self.mic_audio_recorder.source,
|
||||
phrase_timeout=config.INPUT_MIC_PHRASE_TIMEOUT,
|
||||
phrase_timeout=phase_timeout,
|
||||
max_phrases=config.INPUT_MIC_MAX_PHRASES,
|
||||
)
|
||||
def sendMicTranscript():
|
||||
mic_transcriber.transcribeAudioQueue(mic_audio_queue, config.INPUT_MIC_VOICE_LANGUAGE)
|
||||
mic_transcriber.transcribeAudioQueue(mic_audio_queue, config.SOURCE_LANGUAGE, config.SOURCE_COUNTRY)
|
||||
message = mic_transcriber.getTranscript()
|
||||
fnc(message)
|
||||
try:
|
||||
fnc(message)
|
||||
except:
|
||||
pass
|
||||
|
||||
self.mic_print_transcript = threadFnc(sendMicTranscript)
|
||||
self.mic_print_transcript.daemon = True
|
||||
@@ -183,89 +358,124 @@ class Model:
|
||||
def stopMicTranscript(self):
|
||||
if isinstance(self.mic_print_transcript, threadFnc):
|
||||
self.mic_print_transcript.stop()
|
||||
if self.mic_audio_recorder.stop != None:
|
||||
self.mic_print_transcript = None
|
||||
if isinstance(self.mic_audio_recorder, SelectedMicRecorder):
|
||||
self.mic_audio_recorder.stop()
|
||||
self.mic_audio_recorder.stop = None
|
||||
self.mic_audio_recorder = None
|
||||
|
||||
def startCheckMicEnergy(self, fnc, end_fnc, error_fnc=None):
|
||||
if config.CHOICE_MIC_HOST == "NoHost" or config.CHOICE_MIC_DEVICE == "NoDevice":
|
||||
try:
|
||||
error_fnc()
|
||||
except:
|
||||
pass
|
||||
return
|
||||
|
||||
def startCheckMicEnergy(self, fnc):
|
||||
def sendMicEnergy():
|
||||
if mic_energy_queue.empty() is False:
|
||||
energy = mic_energy_queue.get()
|
||||
fnc(energy)
|
||||
try:
|
||||
fnc(energy)
|
||||
except:
|
||||
pass
|
||||
sleep(0.01)
|
||||
|
||||
mic_energy_queue = Queue()
|
||||
mic_device = [device for device in getInputDevices()[config.CHOICE_MIC_HOST] if device["name"] == config.CHOICE_MIC_DEVICE][0]
|
||||
self.mic_energy_recorder = SelectedMicEnergyRecorder(mic_device)
|
||||
self.mic_energy_recorder.recordIntoQueue(mic_energy_queue)
|
||||
self.mic_energy_plot_progressbar = threadFnc(sendMicEnergy)
|
||||
self.mic_energy_plot_progressbar = threadFnc(sendMicEnergy, end_fnc=end_fnc)
|
||||
self.mic_energy_plot_progressbar.daemon = True
|
||||
self.mic_energy_plot_progressbar.start()
|
||||
|
||||
def stopCheckMicEnergy(self):
|
||||
if self.mic_energy_recorder != None:
|
||||
self.mic_energy_recorder.stop()
|
||||
if self.mic_energy_plot_progressbar != None:
|
||||
if isinstance(self.mic_energy_plot_progressbar, threadFnc):
|
||||
self.mic_energy_plot_progressbar.stop()
|
||||
self.mic_energy_plot_progressbar = None
|
||||
if isinstance(self.mic_energy_recorder, SelectedMicEnergyRecorder):
|
||||
self.mic_energy_recorder.stop()
|
||||
self.mic_energy_recorder = None
|
||||
|
||||
def startSpeakerTranscript(self, fnc):
|
||||
spk_audio_queue = Queue()
|
||||
spk_device = [device for device in getOutputDevices() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0]
|
||||
self.spk_audio_recorder = SelectedSpeakerRecorder(
|
||||
spk_device,
|
||||
config.INPUT_SPEAKER_ENERGY_THRESHOLD,
|
||||
config.INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD,
|
||||
config.INPUT_SPEAKER_RECORD_TIMEOUT,
|
||||
def startSpeakerTranscript(self, fnc, error_fnc=None):
|
||||
speaker_device = getDefaultOutputDevice()
|
||||
if speaker_device["name"] == "NoDevice":
|
||||
try:
|
||||
error_fnc()
|
||||
except:
|
||||
pass
|
||||
return
|
||||
|
||||
speaker_audio_queue = Queue()
|
||||
record_timeout = config.INPUT_SPEAKER_RECORD_TIMEOUT
|
||||
phase_timeout = config.INPUT_SPEAKER_PHRASE_TIMEOUT
|
||||
if record_timeout > phase_timeout:
|
||||
record_timeout = phase_timeout
|
||||
|
||||
self.speaker_audio_recorder = SelectedSpeakerRecorder(
|
||||
device=speaker_device,
|
||||
energy_threshold=config.INPUT_SPEAKER_ENERGY_THRESHOLD,
|
||||
dynamic_energy_threshold=config.INPUT_SPEAKER_DYNAMIC_ENERGY_THRESHOLD,
|
||||
record_timeout=record_timeout,
|
||||
)
|
||||
self.spk_audio_recorder.recordIntoQueue(spk_audio_queue)
|
||||
spk_transcriber = AudioTranscriber(
|
||||
self.speaker_audio_recorder.recordIntoQueue(speaker_audio_queue)
|
||||
speaker_transcriber = AudioTranscriber(
|
||||
speaker=True,
|
||||
source=self.spk_audio_recorder.source,
|
||||
phrase_timeout=config.INPUT_SPEAKER_PHRASE_TIMEOUT,
|
||||
source=self.speaker_audio_recorder.source,
|
||||
phrase_timeout=phase_timeout,
|
||||
max_phrases=config.INPUT_SPEAKER_MAX_PHRASES,
|
||||
)
|
||||
def sendSpkTranscript():
|
||||
spk_transcriber.transcribeAudioQueue(spk_audio_queue, config.INPUT_SPEAKER_VOICE_LANGUAGE)
|
||||
message = spk_transcriber.getTranscript()
|
||||
fnc(message)
|
||||
def sendSpeakerTranscript():
|
||||
speaker_transcriber.transcribeAudioQueue(speaker_audio_queue, config.TARGET_LANGUAGE, config.TARGET_COUNTRY)
|
||||
message = speaker_transcriber.getTranscript()
|
||||
try:
|
||||
fnc(message)
|
||||
except:
|
||||
pass
|
||||
|
||||
self.spk_print_transcript = threadFnc(sendSpkTranscript)
|
||||
self.spk_print_transcript.daemon = True
|
||||
self.spk_print_transcript.start()
|
||||
self.speaker_print_transcript = threadFnc(sendSpeakerTranscript)
|
||||
self.speaker_print_transcript.daemon = True
|
||||
self.speaker_print_transcript.start()
|
||||
|
||||
def stopSpeakerTranscript(self):
|
||||
if isinstance(self.spk_print_transcript, threadFnc):
|
||||
self.spk_print_transcript.stop()
|
||||
if self.spk_audio_recorder.stop != None:
|
||||
self.spk_audio_recorder.stop()
|
||||
self.spk_audio_recorder.stop = None
|
||||
if isinstance(self.speaker_print_transcript, threadFnc):
|
||||
self.speaker_print_transcript.stop()
|
||||
self.speaker_print_transcript = None
|
||||
if isinstance(self.speaker_audio_recorder, SelectedSpeakerRecorder):
|
||||
self.speaker_audio_recorder.stop()
|
||||
self.speaker_audio_recorder = None
|
||||
|
||||
def startCheckSpeakerEnergy(self, fnc, end_fnc, error_fnc=None):
|
||||
speaker_device = getDefaultOutputDevice()
|
||||
if speaker_device["name"] == "NoDevice":
|
||||
try:
|
||||
error_fnc()
|
||||
except:
|
||||
pass
|
||||
return
|
||||
|
||||
def startCheckSpeakerEnergy(self, fnc):
|
||||
def sendSpeakerEnergy():
|
||||
if speaker_energy_queue.empty() is False:
|
||||
energy = speaker_energy_queue.get()
|
||||
fnc(energy)
|
||||
try:
|
||||
fnc(energy)
|
||||
except:
|
||||
pass
|
||||
sleep(0.01)
|
||||
|
||||
def getSpeakerEnergy():
|
||||
with self.speaker_energy_recorder.source as source:
|
||||
energy = self.speaker_energy_recorder.recorder.listen_energy(source)
|
||||
speaker_energy_queue.put(energy)
|
||||
|
||||
speaker_device = [device for device in getOutputDevices() if device["name"] == config.CHOICE_SPEAKER_DEVICE][0]
|
||||
speaker_energy_queue = Queue()
|
||||
self.speaker_energy_recorder = SelectedSpeakeEnergyRecorder(speaker_device)
|
||||
self.speaker_energy_get_progressbar = threadFnc(getSpeakerEnergy)
|
||||
self.speaker_energy_get_progressbar.daemon = True
|
||||
self.speaker_energy_get_progressbar.start()
|
||||
self.speaker_energy_plot_progressbar = threadFnc(sendSpeakerEnergy)
|
||||
self.speaker_energy_recorder.recordIntoQueue(speaker_energy_queue)
|
||||
self.speaker_energy_plot_progressbar = threadFnc(sendSpeakerEnergy, end_fnc=end_fnc)
|
||||
self.speaker_energy_plot_progressbar.daemon = True
|
||||
self.speaker_energy_plot_progressbar.start()
|
||||
|
||||
def stopCheckSpeakerEnergy(self):
|
||||
if self.speaker_energy_get_progressbar != None:
|
||||
self.speaker_energy_get_progressbar.stop()
|
||||
if self.speaker_energy_plot_progressbar != None:
|
||||
if isinstance(self.speaker_energy_plot_progressbar, threadFnc):
|
||||
self.speaker_energy_plot_progressbar.stop()
|
||||
self.speaker_energy_plot_progressbar = None
|
||||
if isinstance(self.speaker_energy_recorder, SelectedSpeakeEnergyRecorder):
|
||||
self.speaker_energy_recorder.stop()
|
||||
self.speaker_energy_recorder = None
|
||||
|
||||
def notificationXSOverlay(self, message):
|
||||
xsoverlayForVRCT(content=f"{message}")
|
||||
|
||||
@@ -30,8 +30,28 @@ def sendTestAction(ip_address="127.0.0.1", port=9000):
|
||||
sleep(0.01)
|
||||
client.send_message("/input/Vertical", False)
|
||||
|
||||
# send Input Voice
|
||||
def sendInputVoice(flag=False, ip_address="127.0.0.1", port=9000):
|
||||
input_voice = osc_message_builder.OscMessageBuilder(address="/input/Voice")
|
||||
input_voice.add_arg(flag)
|
||||
b_input_voice = input_voice.build()
|
||||
client = udp_client.SimpleUDPClient(ip_address, port)
|
||||
client.send(b_input_voice)
|
||||
|
||||
def sendChangeVoice(ip_address="127.0.0.1", port=9000):
|
||||
sendInputVoice(flag=0, ip_address=ip_address, port=port)
|
||||
sleep(0.05)
|
||||
sendInputVoice(flag=1, ip_address=ip_address, port=port)
|
||||
sleep(0.05)
|
||||
sendInputVoice(flag=0, ip_address=ip_address, port=port)
|
||||
sleep(0.05)
|
||||
|
||||
def receiveOscParameters(target, filter="/*", ip_address="127.0.0.1", port=9001):
|
||||
_dispatcher = dispatcher.Dispatcher()
|
||||
_dispatcher.map(filter, target)
|
||||
server = osc_server.ThreadingOSCUDPServer((ip_address, port), _dispatcher)
|
||||
server.serve_forever()
|
||||
return server
|
||||
|
||||
if __name__ == "__main__":
|
||||
sendChangeVoice()
|
||||
sendChangeVoice()
|
||||
@@ -1,91 +1,177 @@
|
||||
transcription_lang = {
|
||||
"Japanese (Japan)":"ja-JP",
|
||||
"English (United States)":"en-US",
|
||||
"English (United Kingdom)":"en-GB",
|
||||
"Afrikaans (South Africa)":"af-ZA",
|
||||
"Arabic (Algeria)":"ar-DZ",
|
||||
"Arabic (Bahrain)":"ar-BH",
|
||||
"Arabic (Egypt)":"ar-EG",
|
||||
"Arabic (Israel)":"ar-IL",
|
||||
"Arabic (Iraq)":"ar-IQ",
|
||||
"Arabic (Jordan)":"ar-JO",
|
||||
"Arabic (Kuwait)":"ar-KW",
|
||||
"Arabic (Lebanon)":"ar-LB",
|
||||
"Arabic (Morocco)":"ar-MA",
|
||||
"Arabic (Oman)":"ar-OM",
|
||||
"Arabic (State of Palestine)":"ar-PS",
|
||||
"Arabic (Qatar)":"ar-QA",
|
||||
"Arabic (Saudi Arabia)":"ar-SA",
|
||||
"Arabic (Tunisia)":"ar-TN",
|
||||
"Arabic (United Arab Emirates)":"ar-AE",
|
||||
"Basque (Spain)":"eu-ES",
|
||||
"Bulgarian (Bulgaria)":"bg-BG",
|
||||
"Catalan (Spain)":"ca-ES",
|
||||
"Chinese, Mandarin (Simplified, China)":"cmn-Hans-CN",
|
||||
"Chinese, Mandarin (Simplified, Hong Kong)":"cmn-Hans-HK",
|
||||
"Chinese, Mandarin (Traditional, Taiwan)":"cmn-Hant-TW",
|
||||
"Chinese, Cantonese (Traditional Hong Kong)":"yue-Hant-HK",
|
||||
"Croatian (Croatia)":"hr-HR",
|
||||
"Czech (Czech Republic)":"cs-CZ",
|
||||
"Danish (Denmark)":"da-DK",
|
||||
"English (Australia)":"en-AU",
|
||||
"English (Canada)":"en-CA",
|
||||
"English (India)":"en-IN",
|
||||
"English (Ireland)":"en-IE",
|
||||
"English (New Zealand)":"en-NZ",
|
||||
"English (Philippines)":"en-PH",
|
||||
"English (South Africa)":"en-ZA",
|
||||
"Persian (Iran)":"fa-IR",
|
||||
"French (France)":"fr-FR",
|
||||
"Filipino (Philippines)":"fil-PH",
|
||||
"Galician (Spain)":"gl-ES",
|
||||
"German (Germany)":"de-DE",
|
||||
"Greek (Greece)":"el-GR",
|
||||
"Finnish (Finland)":"fi-FI",
|
||||
"Hebrew (Israel)":"he-IL",
|
||||
"Hindi (India)":"hi-IN",
|
||||
"Hungarian (Hungary)":"hu-HU",
|
||||
"Indonesian (Indonesia)":"id-ID",
|
||||
"Icelandic (Iceland)":"is-IS",
|
||||
"Italian (Italy)":"it-IT",
|
||||
"Italian (Switzerland)":"it-CH",
|
||||
"Korean (South Korea)":"ko-KR",
|
||||
"Lithuanian (Lithuania)":"lt-LT",
|
||||
"Malay (Malaysia)":"ms-MY",
|
||||
"Dutch (Netherlands)":"nl-NL",
|
||||
"Norwegian Bokmål (Norway)":"nb-NO",
|
||||
"Polish (Poland)":"pl-PL",
|
||||
"Portuguese (Brazil)":"pt-BR",
|
||||
"Portuguese (Portugal)":"pt-PT",
|
||||
"Romanian (Romania)":"ro-RO",
|
||||
"Russian (Russia)":"ru-RU",
|
||||
"Serbian (Serbia)":"sr-RS",
|
||||
"Slovak (Slovakia)":"sk-SK",
|
||||
"Slovenian (Slovenia)":"sl-SI",
|
||||
"Spanish (Argentina)":"es-AR",
|
||||
"Spanish (Bolivia)":"es-BO",
|
||||
"Spanish (Chile)":"es-CL",
|
||||
"Spanish (Colombia)":"es-CO",
|
||||
"Spanish (Costa Rica)":"es-CR",
|
||||
"Spanish (Dominican Republic)":"es-DO",
|
||||
"Spanish (Ecuador)":"es-EC",
|
||||
"Spanish (El Salvador)":"es-SV",
|
||||
"Spanish (Guatemala)":"es-GT",
|
||||
"Spanish (Honduras)":"es-HN",
|
||||
"Spanish (Mexico)":"es-MX",
|
||||
"Spanish (Nicaragua)":"es-NI",
|
||||
"Spanish (Panama)":"es-PA",
|
||||
"Spanish (Paraguay)":"es-PY",
|
||||
"Spanish (Peru)":"es-PE",
|
||||
"Spanish (Puerto Rico)":"es-PR",
|
||||
"Spanish (Spain)":"es-ES",
|
||||
"Spanish (Uruguay)":"es-UY",
|
||||
"Spanish (United States)":"es-US",
|
||||
"Spanish (Venezuela)":"es-VE",
|
||||
"Swedish (Sweden)":"sv-SE",
|
||||
"Thai (Thailand)":"th-TH",
|
||||
"Turkish (Turkey)":"tr-TR",
|
||||
"Ukrainian (Ukraine)":"uk-UA",
|
||||
"Vietnamese (Vietnam)":"vi-VN",
|
||||
"Zulu (South Africa)":"zu-ZA"
|
||||
"Afrikaans":{
|
||||
"South Africa":"af-ZA",
|
||||
},
|
||||
"Arabic":{
|
||||
"Algeria":"ar-DZ",
|
||||
"Bahrain":"ar-BH",
|
||||
"Egypt":"ar-EG",
|
||||
"Israel":"ar-IL",
|
||||
"Iraq":"ar-IQ",
|
||||
"Jordan":"ar-JO",
|
||||
"Kuwait":"ar-KW",
|
||||
"Lebanon":"ar-LB",
|
||||
"Morocco":"ar-MA",
|
||||
"Oman":"ar-OM",
|
||||
"State of Palestine":"ar-PS",
|
||||
"Qatar":"ar-QA",
|
||||
"Saudi Arabia":"ar-SA",
|
||||
"Tunisia":"ar-TN",
|
||||
"United Arab Emirates":"ar-AE",
|
||||
},
|
||||
"Basque":{
|
||||
"Spain":"eu-ES",
|
||||
},
|
||||
"Bulgarian":{
|
||||
"Bulgaria":"bg-BG",
|
||||
},
|
||||
"Catalan":{
|
||||
"Spain":"ca-ES",
|
||||
},
|
||||
"Chinese":{
|
||||
"Mandarin (Simplified, China)":"cmn-Hans-CN",
|
||||
"Mandarin (Simplified, Hong Kong)":"cmn-Hans-HK",
|
||||
"Mandarin (Traditional, Taiwan)":"cmn-Hant-TW",
|
||||
"Cantonese (Traditional Hong Kong)":"yue-Hant-HK",
|
||||
},
|
||||
"Croatian":{
|
||||
"Croatia":"hr-HR",
|
||||
},
|
||||
"Czech":{
|
||||
"Czech Republic":"cs-CZ",
|
||||
},
|
||||
"Danish":{
|
||||
"Denmark":"da-DK",
|
||||
},
|
||||
"Dutch":{
|
||||
"Netherlands":"nl-NL",
|
||||
},
|
||||
"English": {
|
||||
"United States":"en-US",
|
||||
"United Kingdom":"en-GB",
|
||||
"Australia":"en-AU",
|
||||
"Canada":"en-CA",
|
||||
"India":"en-IN",
|
||||
"Ireland":"en-IE",
|
||||
"New Zealand":"en-NZ",
|
||||
"Philippines":"en-PH",
|
||||
"South Africa":"en-ZA",
|
||||
},
|
||||
"Filipino":{
|
||||
"Philippines":"fil-PH",
|
||||
},
|
||||
"Finnish":{
|
||||
"Finland":"fi-FI",
|
||||
},
|
||||
"French":{
|
||||
"France":"fr-FR",
|
||||
},
|
||||
"Galician":{
|
||||
"Spain":"gl-ES",
|
||||
},
|
||||
"German":{
|
||||
"Germany":"de-DE",
|
||||
},
|
||||
"Greek":{
|
||||
"Greece":"el-GR",
|
||||
},
|
||||
"Hebrew":{
|
||||
"Israel":"he-IL",
|
||||
},
|
||||
"Hindi": {
|
||||
"India":"hi-IN",
|
||||
},
|
||||
"Hungarian":{
|
||||
"Hungary":"hu-HU",
|
||||
},
|
||||
"Indonesian":{
|
||||
"Indonesia":"id-ID",
|
||||
},
|
||||
"Icelandic":{
|
||||
"Iceland":"is-IS",
|
||||
},
|
||||
"Italian":{
|
||||
"Italy":"it-IT",
|
||||
"Switzerland":"it-CH",
|
||||
},
|
||||
"Japanese":{
|
||||
"Japan":"ja-JP",
|
||||
},
|
||||
"Korean":{
|
||||
"South Korea":"ko-KR",
|
||||
},
|
||||
"Lithuanian":{
|
||||
"Lithuania":"lt-LT",
|
||||
},
|
||||
"Malay":{
|
||||
"Malaysia":"ms-MY",
|
||||
},
|
||||
"Norwegian":{
|
||||
"Norway":"nb-NO",
|
||||
},
|
||||
"Persian":{
|
||||
"Iran":"fa-IR",
|
||||
},
|
||||
"Polish":{
|
||||
"Poland":"pl-PL",
|
||||
},
|
||||
"Portuguese":{
|
||||
"Brazil":"pt-BR",
|
||||
"Portugal":"pt-PT",
|
||||
},
|
||||
"Romanian":{
|
||||
"Romania":"ro-RO",
|
||||
},
|
||||
"Russian":{
|
||||
"Russia":"ru-RU",
|
||||
},
|
||||
"Serbian":{
|
||||
"Serbia":"sr-RS",
|
||||
},
|
||||
"Slovak":{
|
||||
"Slovakia":"sk-SK",
|
||||
},
|
||||
"Slovenian":{
|
||||
"Slovenia":"sl-SI",
|
||||
},
|
||||
"Spanish":{
|
||||
"Argentina":"es-AR",
|
||||
"Bolivia":"es-BO",
|
||||
"Chile":"es-CL",
|
||||
"Colombia":"es-CO",
|
||||
"Costa Rica":"es-CR",
|
||||
"Dominican Republic":"es-DO",
|
||||
"Ecuador":"es-EC",
|
||||
"El Salvador":"es-SV",
|
||||
"Guatemala":"es-GT",
|
||||
"Honduras":"es-HN",
|
||||
"Mexico":"es-MX",
|
||||
"Nicaragua":"es-NI",
|
||||
"Panama":"es-PA",
|
||||
"Paraguay":"es-PY",
|
||||
"Peru":"es-PE",
|
||||
"Puerto Rico":"es-PR",
|
||||
"Spain":"es-ES",
|
||||
"Uruguay":"es-UY",
|
||||
"United States":"es-US",
|
||||
"Venezuela":"es-VE",
|
||||
},
|
||||
"Swedish":{
|
||||
"Sweden":"sv-SE",
|
||||
},
|
||||
"Thai":{
|
||||
"Thailand":"th-TH",
|
||||
},
|
||||
"Turkish":{
|
||||
"Turkey":"tr-TR",
|
||||
},
|
||||
"Ukrainian":{
|
||||
"Ukraine":"uk-UA",
|
||||
},
|
||||
"Vietnamese":{
|
||||
"Vietnam":"vi-VN",
|
||||
},
|
||||
"Zulu":{
|
||||
"South Africa":"zu-ZA"
|
||||
},
|
||||
}
|
||||
@@ -84,7 +84,6 @@ class SelectedSpeakeEnergyRecorder(BaseEnergyRecorder):
|
||||
source = Microphone(speaker=True,
|
||||
device_index= device["index"],
|
||||
sample_rate=int(device["defaultSampleRate"]),
|
||||
chunk_size=get_sample_size(paInt16),
|
||||
channels=device["maxInputChannels"]
|
||||
)
|
||||
super().__init__(source=source)
|
||||
|
||||
@@ -27,7 +27,7 @@ class AudioTranscriber:
|
||||
"process_data_func": self.processSpeakerData if speaker else self.processSpeakerData
|
||||
}
|
||||
|
||||
def transcribeAudioQueue(self, audio_queue, language):
|
||||
def transcribeAudioQueue(self, audio_queue, language, country):
|
||||
# while True:
|
||||
audio, time_spoken = audio_queue.get()
|
||||
self.updateLastSampleAndPhraseStatus(audio, time_spoken)
|
||||
@@ -37,7 +37,7 @@ class AudioTranscriber:
|
||||
# fd, path = tempfile.mkstemp(suffix=".wav")
|
||||
# os.close(fd)
|
||||
audio_data = self.audio_sources["process_data_func"]()
|
||||
text = self.audio_recognizer.recognize_google(audio_data, language=transcription_lang[language])
|
||||
text = self.audio_recognizer.recognize_google(audio_data, language=transcription_lang[language][country])
|
||||
except Exception as e:
|
||||
pass
|
||||
finally:
|
||||
|
||||
@@ -12,15 +12,8 @@ def getInputDevices():
|
||||
devices[host["name"]].append(device)
|
||||
else:
|
||||
devices[host["name"]] = [device]
|
||||
return devices
|
||||
|
||||
def getOutputDevices():
|
||||
devices =[]
|
||||
with PyAudio() as p:
|
||||
wasapi_info = p.get_host_api_info_by_type(paWASAPI)
|
||||
for device in p.get_loopback_device_info_generator():
|
||||
if device["hostApi"] == wasapi_info["index"] and device["isLoopbackDevice"] is True:
|
||||
devices.append(device)
|
||||
if len(devices) == 0:
|
||||
devices = {"NoHost": [{"name": "NoDevice"}]}
|
||||
return devices
|
||||
|
||||
def getDefaultInputDevice():
|
||||
@@ -33,7 +26,8 @@ def getDefaultInputDevice():
|
||||
for device_index in range(0, p. get_host_api_info_by_index(host_index)['deviceCount']):
|
||||
device = p.get_device_info_by_host_api_device_index(host_index, device_index)
|
||||
if device["index"] == defaultInputDevice:
|
||||
return {"host":host, "device": device}
|
||||
return {"host": host, "device": device}
|
||||
return {"host": {"name": "NoHost"}, "device": {"name": "NoDevice"}}
|
||||
|
||||
def getDefaultOutputDevice():
|
||||
with PyAudio() as p:
|
||||
@@ -49,4 +43,5 @@ def getDefaultOutputDevice():
|
||||
for loopback in p.get_loopback_device_info_generator():
|
||||
if default_speakers["name"] in loopback["name"]:
|
||||
default_device = loopback
|
||||
return default_device
|
||||
return default_device
|
||||
return {"name":"NoDevice"}
|
||||
@@ -1,6 +1,6 @@
|
||||
translatorEngine = ["DeepL(web)", "DeepL(auth)", "Google(web)", "Bing(web)"]
|
||||
translatorEngine = ["DeepL", "DeepL_API", "Google", "Bing"]
|
||||
translation_lang = {}
|
||||
dict_deepl_web_languages = {
|
||||
dict_deepl_languages = {
|
||||
"Japanese":"JA",
|
||||
"English":"EN",
|
||||
"Korean":"KO",
|
||||
@@ -31,12 +31,12 @@ dict_deepl_web_languages = {
|
||||
"Turkish":"TR",
|
||||
"Norwegian":"NB",
|
||||
}
|
||||
translation_lang["DeepL(web)"] = {
|
||||
"source":dict_deepl_web_languages,
|
||||
"target":dict_deepl_web_languages,
|
||||
translation_lang["DeepL"] = {
|
||||
"source":dict_deepl_languages,
|
||||
"target":dict_deepl_languages,
|
||||
}
|
||||
|
||||
dict_deepl_auth_source_languages = {
|
||||
dict_deepl_api_source_languages = {
|
||||
"Japanese":"ja",
|
||||
"English":"en",
|
||||
"Bulgarian":"bg",
|
||||
@@ -67,7 +67,7 @@ dict_deepl_auth_source_languages = {
|
||||
"Ukrainian":"uk",
|
||||
"Chinese":"zh"
|
||||
}
|
||||
dict_deepl_auth_target_languages = {
|
||||
dict_deepl_api_target_languages = {
|
||||
"Japanese":"ja",
|
||||
"English American":"en-US",
|
||||
"English British":"en-GB",
|
||||
@@ -101,12 +101,12 @@ dict_deepl_auth_target_languages = {
|
||||
"Ukrainian":"uk",
|
||||
"Chinese":"zh"
|
||||
}
|
||||
translation_lang["DeepL(auth)"] = {
|
||||
"source": dict_deepl_auth_source_languages,
|
||||
"target": dict_deepl_auth_target_languages,
|
||||
translation_lang["DeepL_API"] = {
|
||||
"source": dict_deepl_api_source_languages,
|
||||
"target": dict_deepl_api_target_languages,
|
||||
}
|
||||
|
||||
dict_google_web_languages = {
|
||||
dict_google_languages = {
|
||||
"Japanese":"ja",
|
||||
"English":"en",
|
||||
"Chinese":"zh",
|
||||
@@ -170,12 +170,12 @@ dict_google_web_languages = {
|
||||
"Basque":"eu",
|
||||
"Irish":"ga"
|
||||
}
|
||||
translation_lang["Google(web)"] = {
|
||||
"source":dict_google_web_languages,
|
||||
"target":dict_google_web_languages,
|
||||
translation_lang["Google"] = {
|
||||
"source":dict_google_languages,
|
||||
"target":dict_google_languages,
|
||||
}
|
||||
|
||||
dict_bing_web_languages = {
|
||||
dict_bing_languages = {
|
||||
"Japanese":"ja",
|
||||
"English":"en",
|
||||
"Chinese":"zh",
|
||||
@@ -237,7 +237,7 @@ dict_bing_web_languages = {
|
||||
"Punjabi":"pa",
|
||||
"Irish":"ga"
|
||||
}
|
||||
translation_lang["Bing(web)"] = {
|
||||
"source":dict_bing_web_languages,
|
||||
"target":dict_bing_web_languages,
|
||||
translation_lang["Bing"] = {
|
||||
"source":dict_bing_languages,
|
||||
"target":dict_bing_languages,
|
||||
}
|
||||
@@ -6,63 +6,55 @@ from .translation_languages import translatorEngine, translation_lang
|
||||
# Translator
|
||||
class Translator():
|
||||
def __init__(self):
|
||||
pass
|
||||
self.translator_status = {}
|
||||
for translator in translatorEngine:
|
||||
self.translator_status[translator] = False
|
||||
self.deepl_client = None
|
||||
|
||||
def authentication(self, translator_name, authkey=None):
|
||||
result = False
|
||||
try:
|
||||
if translator_name == "DeepL(web)":
|
||||
self.translator_status["DeepL(web)"] = True
|
||||
result = True
|
||||
elif translator_name == "DeepL(auth)":
|
||||
self.deepl_client = deepl_Translator(authkey)
|
||||
self.deepl_client.translate_text(" ", target_lang="EN-US")
|
||||
self.translator_status["DeepL(auth)"] = True
|
||||
result = True
|
||||
elif translator_name == "Google(web)":
|
||||
self.translator_status["Google(web)"] = True
|
||||
result = True
|
||||
elif translator_name == "Bing(web)":
|
||||
self.translator_status["Bing(web)"] = True
|
||||
result = True
|
||||
except:
|
||||
pass
|
||||
result = True
|
||||
match translator_name:
|
||||
case "DeepL_API":
|
||||
try:
|
||||
self.deepl_client = deepl_Translator(authkey)
|
||||
self.deepl_client.translate_text(" ", target_lang="EN-US")
|
||||
except:
|
||||
result = False
|
||||
return result
|
||||
|
||||
def translate(self, translator_name, source_language, target_language, message):
|
||||
result = ""
|
||||
try:
|
||||
result = ""
|
||||
source_language=translation_lang[translator_name]["source"][source_language]
|
||||
target_language=translation_lang[translator_name]["target"][target_language]
|
||||
if translator_name == "DeepL(web)":
|
||||
result = deepl_web_Translator(
|
||||
source_language=source_language,
|
||||
target_language=target_language,
|
||||
text=message
|
||||
)
|
||||
elif translator_name == "DeepL(auth)":
|
||||
result = self.deepl_client.translate_text(
|
||||
message,
|
||||
source_lang=source_language,
|
||||
target_lang=target_language,
|
||||
).text
|
||||
elif translator_name == "Google(web)":
|
||||
result = other_web_Translator(
|
||||
query_text=message,
|
||||
translator="google",
|
||||
from_language=source_language,
|
||||
to_language=target_language,
|
||||
)
|
||||
elif translator_name == "Bing(web)":
|
||||
result = other_web_Translator(
|
||||
query_text=message,
|
||||
translator="bing",
|
||||
from_language=source_language,
|
||||
to_language=target_language,
|
||||
)
|
||||
except:
|
||||
pass
|
||||
match translator_name:
|
||||
case "DeepL":
|
||||
result = deepl_web_Translator(
|
||||
source_language=source_language,
|
||||
target_language=target_language,
|
||||
text=message
|
||||
)
|
||||
case "DeepL_API":
|
||||
result = self.deepl_client.translate_text(
|
||||
message,
|
||||
source_lang=source_language,
|
||||
target_lang=target_language,
|
||||
).text
|
||||
case "Google":
|
||||
result = other_web_Translator(
|
||||
query_text=message,
|
||||
translator="google",
|
||||
from_language=source_language,
|
||||
to_language=target_language,
|
||||
)
|
||||
case "Bing":
|
||||
result = other_web_Translator(
|
||||
query_text=message,
|
||||
translator="bing",
|
||||
from_language=source_language,
|
||||
to_language=target_language,
|
||||
)
|
||||
except Exception as e:
|
||||
import traceback
|
||||
with open('error.log', 'a') as f:
|
||||
traceback.print_exc(file=f)
|
||||
result = False
|
||||
return result
|
||||
@@ -18,6 +18,7 @@
|
||||
import socket
|
||||
import json
|
||||
import base64
|
||||
from os import path as os_path
|
||||
|
||||
def XSOverlay(
|
||||
endpoint:tuple=("127.0.0.1", 42069), messageType:int=1, index:int=0, timeout:float=2,
|
||||
@@ -63,7 +64,7 @@ def xsoverlayForVRCT(content:str="") -> int:
|
||||
title="VRCT",
|
||||
content=content,
|
||||
useBase64Icon=True,
|
||||
icon="./img/xsoverlay.png",
|
||||
icon=os_path.join(os_path.dirname(__file__), "img", "xsoverlay2.png"),
|
||||
sourceApp="VRCT"
|
||||
)
|
||||
return response
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
pillow
|
||||
PyAudioWPatch
|
||||
python-osc
|
||||
customtkinter
|
||||
deepl
|
||||
flashtext
|
||||
pyyaml
|
||||
pillow == 10.0.0
|
||||
PyAudioWPatch == 0.2.12.6
|
||||
python-osc == 1.8.3
|
||||
customtkinter == 5.2.0
|
||||
deepl == 1.15.0
|
||||
flashtext == 2.7
|
||||
pyyaml == 6.0.1
|
||||
python-i18n == 0.3.9
|
||||
111
utils.py
@@ -1,39 +1,9 @@
|
||||
from os import path as os_path
|
||||
import yaml
|
||||
from datetime import datetime
|
||||
from PIL.Image import open as Image_open
|
||||
|
||||
def print_textbox(textbox, message, tags=None):
|
||||
now = datetime.now()
|
||||
now = now.strftime('%H:%M:%S')
|
||||
|
||||
textbox.tag_config("ERROR", foreground="#FF0000")
|
||||
textbox.tag_config("INFO", foreground="#1BFF00")
|
||||
textbox.tag_config("SEND", foreground="#0378e2")
|
||||
textbox.tag_config("RECEIVE", foreground="#ffa500")
|
||||
|
||||
textbox.configure(state='normal')
|
||||
textbox.insert("end", f"[{now}][")
|
||||
textbox.insert("end", f"{tags}", tags)
|
||||
textbox.insert("end", f"]{message}\n")
|
||||
textbox.configure(state='disabled')
|
||||
textbox.see("end")
|
||||
|
||||
def get_localized_text(language):
|
||||
file_path = os_path.join(os_path.dirname(__file__), "locales.yml")
|
||||
|
||||
with open(file_path, encoding="utf-8") as file:
|
||||
languages_yaml_data = yaml.safe_load(file)
|
||||
default_language = "en"
|
||||
if language in languages_yaml_data:
|
||||
localized_text = languages_yaml_data[language]
|
||||
if default_language in languages_yaml_data:
|
||||
default_text = languages_yaml_data[default_language]
|
||||
merged_text = {**default_text, **localized_text}
|
||||
return merged_text
|
||||
else:
|
||||
return localized_text
|
||||
else:
|
||||
return None
|
||||
def getImageFile(file_name):
|
||||
img = Image_open(os_path.join(os_path.dirname(__file__), "img", file_name))
|
||||
return img
|
||||
|
||||
def get_key_by_value(dictionary, value):
|
||||
for key, val in dictionary.items():
|
||||
@@ -41,66 +11,19 @@ def get_key_by_value(dictionary, value):
|
||||
return key
|
||||
return None
|
||||
|
||||
def widget_config_window_label_setter(self, language_yaml_data):
|
||||
widget_names = [
|
||||
# tab UI
|
||||
"label_transparency",
|
||||
"label_appearance_theme",
|
||||
"label_ui_scaling",
|
||||
"label_font_family",
|
||||
"label_ui_language",
|
||||
def callFunctionIfCallable(function, *args):
|
||||
if callable(function) is True: function(*args)
|
||||
|
||||
# tab Translation
|
||||
"label_translation_translator",
|
||||
"label_translation_input_language",
|
||||
"label_translation_output_language",
|
||||
def isEven(number):
|
||||
return number % 2 == 0
|
||||
|
||||
# tab Transcription
|
||||
"label_input_mic_host",
|
||||
"label_input_mic_device",
|
||||
"label_input_mic_voice_language",
|
||||
"label_input_mic_energy_threshold",
|
||||
"checkbox_input_mic_threshold_check",
|
||||
"label_input_mic_dynamic_energy_threshold",
|
||||
"label_input_mic_record_timeout",
|
||||
"label_input_mic_phrase_timeout",
|
||||
"label_input_mic_max_phrases",
|
||||
"label_input_mic_word_filter",
|
||||
def makeEven(number, minus:bool=False):
|
||||
if minus is True:
|
||||
return number if isEven(number) else number - 1
|
||||
return number if isEven(number) else number + 1
|
||||
|
||||
"label_input_speaker_device",
|
||||
"label_input_speaker_voice_language",
|
||||
"label_input_speaker_energy_threshold",
|
||||
"checkbox_input_speaker_threshold_check",
|
||||
"label_input_speaker_dynamic_energy_threshold",
|
||||
"label_input_speaker_record_timeout",
|
||||
"label_input_speaker_phrase_timeout",
|
||||
"label_input_speaker_max_phrases",
|
||||
|
||||
# tab Parameter
|
||||
"label_ip_address",
|
||||
"label_port",
|
||||
"label_authkey",
|
||||
"label_message_format",
|
||||
|
||||
# tab Others
|
||||
"label_checkbox_auto_clear_chatbox",
|
||||
"label_checkbox_notice_xsoverlay",
|
||||
]
|
||||
for name in widget_names:
|
||||
widget = getattr(self, name)
|
||||
text_value = language_yaml_data.get(name)
|
||||
if widget is not None and text_value is not None:
|
||||
widget.configure(text=text_value + ":")
|
||||
|
||||
def widget_main_window_label_setter(self, language_yaml_data):
|
||||
widget_names = [
|
||||
"checkbox_translation",
|
||||
"checkbox_transcription_send",
|
||||
"checkbox_transcription_receive",
|
||||
"checkbox_foreground",
|
||||
]
|
||||
for name in widget_names:
|
||||
widget = getattr(self, name)
|
||||
text_value = language_yaml_data.get(name)
|
||||
if widget is not None and text_value is not None:
|
||||
widget.configure(text=text_value)
|
||||
def generatePercentageStringsList(start=40, end=200, step=10):
|
||||
strings = []
|
||||
for percent in range(start, end + 1, step):
|
||||
strings.append(f"{percent}%")
|
||||
return strings
|
||||
240
vrct_gui/_CreateConfirmationModal.py
Normal file
@@ -0,0 +1,240 @@
|
||||
from customtkinter import CTkToplevel, CTkFrame, CTkLabel, CTkFont
|
||||
|
||||
from .ui_utils import fadeInAnimation, setGeometryToCenterOfTheWidget, bindButtonFunctionAndColor
|
||||
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
class _CreateConfirmationModal(CTkToplevel):
|
||||
def __init__(self, attach_window, settings, view_variable, modal_type=None):
|
||||
super().__init__()
|
||||
self.withdraw()
|
||||
|
||||
self.attach_window = attach_window
|
||||
self.settings = settings
|
||||
self._view_variable = view_variable
|
||||
|
||||
|
||||
self.title("")
|
||||
self.overrideredirect(True)
|
||||
self.wm_attributes("-toolwindow", True)
|
||||
|
||||
self.BIND_FOCUS_OUT_FUNC_ID=None
|
||||
|
||||
|
||||
|
||||
self.configure(fg_color=self.settings.ctm.FAKE_BORDER_COLOR)
|
||||
self.protocol("WM_DELETE_WINDOW", lambda: callFunctionIfCallable(self._view_variable.CALLBACK_HIDE_CONFIRMATION_MODAL))
|
||||
|
||||
|
||||
|
||||
self.grid_rowconfigure(0,weight=1)
|
||||
self.grid_columnconfigure(0,weight=1)
|
||||
self.modal_container = CTkFrame(self, corner_radius=0, fg_color=self.settings.ctm.BG_COLOR)
|
||||
self.modal_container.grid(row=0, column=0, padx=self.settings.uism.FAKE_BORDER_SIZE, pady=self.settings.uism.FAKE_BORDER_SIZE)
|
||||
|
||||
|
||||
self.modal_contents_wrapper = CTkFrame(self.modal_container, corner_radius=0, fg_color=self.settings.ctm.BG_COLOR)
|
||||
self.modal_contents_wrapper.grid(row=0, column=0, padx=self.settings.uism.CONTENTS_WRAPPER, pady=self.settings.uism.CONTENTS_WRAPPER)
|
||||
|
||||
|
||||
|
||||
self.modal_contents_wrapper.grid_rowconfigure(1, minsize=self.settings.uism.MARGIN_BETWEEN_MESSAGE_AND_BUTTONS)
|
||||
|
||||
self.modal_message_label_wrapper = CTkFrame(self.modal_contents_wrapper, corner_radius=0, fg_color=self.settings.ctm.BG_COLOR)
|
||||
self.modal_message_label_wrapper.grid(row=0, column=0)
|
||||
|
||||
self.modal_message_label_wrapper.grid_rowconfigure((0,2),weight=1)
|
||||
self.modal_message_label_wrapper.grid_columnconfigure((0,2),weight=1)
|
||||
|
||||
self.modal_message_label = CTkLabel(
|
||||
self.modal_message_label_wrapper,
|
||||
textvariable=self._view_variable.VAR_MESSAGE_CONFIRMATION_MODAL,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.MESSAGE_FONT_SIZE, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=self.settings.ctm.MESSAGE_TEXT_COLOR,
|
||||
)
|
||||
self.modal_message_label.grid(row=1, column=1)
|
||||
|
||||
|
||||
|
||||
self.modal_buttons_container = CTkFrame(self.modal_contents_wrapper, corner_radius=0, fg_color=self.settings.ctm.BG_COLOR)
|
||||
self.modal_buttons_container.grid(row=2, column=0, sticky="nsew")
|
||||
|
||||
self.modal_buttons_container.grid_rowconfigure((0,2),weight=1)
|
||||
self.modal_buttons_container.grid_columnconfigure(0,weight=1)
|
||||
|
||||
self.modal_buttons_wrapper = CTkFrame(self.modal_buttons_container, corner_radius=0, fg_color=self.settings.ctm.BG_COLOR)
|
||||
self.modal_buttons_wrapper.grid(row=1, column=0, sticky="ew")
|
||||
|
||||
|
||||
if modal_type == "information":
|
||||
# self.modal_buttons_wrapper.grid_columnconfigure(1, weight=1, minsize=self.settings.uism.BUTTONS_BETWEEN_PADDING)
|
||||
self.modal_buttons_wrapper.grid_columnconfigure((0,2), weight=1)
|
||||
|
||||
|
||||
self.accept_button = CTkFrame(self.modal_buttons_wrapper, corner_radius=self.settings.uism.BUTTONS_CORNER_RADIUS, fg_color=self.settings.ctm.ACCEPT_BUTTON_BG_COLOR, cursor="hand2")
|
||||
self.accept_button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
|
||||
self.accept_button.grid_columnconfigure(0, weight=1)
|
||||
self.accept_button_label_wrapper = CTkFrame(self.accept_button, corner_radius=0, fg_color=self.settings.ctm.ACCEPT_BUTTON_BG_COLOR)
|
||||
self.accept_button_label_wrapper.grid(row=0, column=0, padx=self.settings.uism.BUTTONS_IPADX, pady=self.settings.uism.BUTTONS_IPADY, sticky="ew")
|
||||
|
||||
self.accept_button_label_wrapper.grid_columnconfigure((0,2), weight=1)
|
||||
self.accept_button_label = CTkLabel(
|
||||
self.accept_button_label_wrapper,
|
||||
textvariable=self._view_variable.VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.CONFIRMATION_BUTTONS_TEXT_FONT_SIZE, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=self.settings.ctm.CONFIRMATION_BUTTONS_TEXT_COLOR,
|
||||
)
|
||||
self.accept_button_label.grid(row=0, column=1)
|
||||
|
||||
|
||||
|
||||
bindButtonFunctionAndColor(
|
||||
target_widgets=[
|
||||
self.accept_button,
|
||||
self.accept_button_label_wrapper,
|
||||
self.accept_button_label,
|
||||
],
|
||||
enter_color=settings.ctm.ACCEPT_BUTTON_HOVERED_BG_COLOR,
|
||||
leave_color=settings.ctm.ACCEPT_BUTTON_BG_COLOR,
|
||||
clicked_color=settings.ctm.ACCEPT_BUTTON_CLICKED_BG_COLOR,
|
||||
buttonReleasedFunction=lambda _e: callFunctionIfCallable(self._view_variable.CALLBACK_ACCEPTED_CONFIRMATION_MODAL),
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
else:
|
||||
self.modal_buttons_wrapper.grid_columnconfigure(1, weight=1, minsize=self.settings.uism.BUTTONS_BETWEEN_PADDING)
|
||||
self.modal_buttons_wrapper.grid_columnconfigure((0,2), weight=0, uniform="button_wrapper")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
self.deny_button = CTkFrame(self.modal_buttons_wrapper, corner_radius=self.settings.uism.BUTTONS_CORNER_RADIUS, fg_color=self.settings.ctm.DENY_BUTTON_BG_COLOR, cursor="hand2")
|
||||
self.deny_button.grid(row=0, column=0, sticky="ew")
|
||||
|
||||
|
||||
self.deny_button.grid_columnconfigure(0, weight=1)
|
||||
self.deny_button_label_wrapper = CTkFrame(self.deny_button, corner_radius=0, fg_color=self.settings.ctm.DENY_BUTTON_BG_COLOR)
|
||||
self.deny_button_label_wrapper.grid(row=0, column=0, padx=self.settings.uism.BUTTONS_IPADX, pady=self.settings.uism.BUTTONS_IPADY, sticky="ew")
|
||||
|
||||
self.deny_button_label_wrapper.grid_columnconfigure((0,2), weight=1)
|
||||
|
||||
|
||||
self.deny_button_label_wrapper.grid_columnconfigure(0, weight=1)
|
||||
self.deny_button_label = CTkLabel(
|
||||
self.deny_button_label_wrapper,
|
||||
textvariable=self._view_variable.VAR_LABEL_CONFIRMATION_MODAL_DENY_BUTTON,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.CONFIRMATION_BUTTONS_TEXT_FONT_SIZE, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=self.settings.ctm.CONFIRMATION_BUTTONS_TEXT_COLOR,
|
||||
)
|
||||
self.deny_button_label.grid(row=0, column=1)
|
||||
|
||||
|
||||
|
||||
bindButtonFunctionAndColor(
|
||||
target_widgets=[
|
||||
self.deny_button,
|
||||
self.deny_button_label_wrapper,
|
||||
self.deny_button_label,
|
||||
],
|
||||
enter_color=settings.ctm.DENY_BUTTON_HOVERED_BG_COLOR,
|
||||
leave_color=settings.ctm.DENY_BUTTON_BG_COLOR,
|
||||
clicked_color=settings.ctm.DENY_BUTTON_CLICKED_BG_COLOR,
|
||||
buttonReleasedFunction=lambda _e: callFunctionIfCallable(self._view_variable.CALLBACK_DENIED_CONFIRMATION_MODAL),
|
||||
)
|
||||
|
||||
|
||||
|
||||
self.accept_button = CTkFrame(self.modal_buttons_wrapper, corner_radius=self.settings.uism.BUTTONS_CORNER_RADIUS, fg_color=self.settings.ctm.ACCEPT_BUTTON_BG_COLOR, cursor="hand2")
|
||||
self.accept_button.grid(row=0, column=2, sticky="ew")
|
||||
|
||||
|
||||
self.accept_button.grid_columnconfigure(0, weight=1)
|
||||
self.accept_button_label_wrapper = CTkFrame(self.accept_button, corner_radius=0, fg_color=self.settings.ctm.ACCEPT_BUTTON_BG_COLOR)
|
||||
self.accept_button_label_wrapper.grid(row=0, column=0, padx=self.settings.uism.BUTTONS_IPADX, pady=self.settings.uism.BUTTONS_IPADY, sticky="ew")
|
||||
|
||||
self.accept_button_label_wrapper.grid_columnconfigure((0,2), weight=1)
|
||||
self.accept_button_label = CTkLabel(
|
||||
self.accept_button_label_wrapper,
|
||||
textvariable=self._view_variable.VAR_LABEL_CONFIRMATION_MODAL_ACCEPT_BUTTON,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.CONFIRMATION_BUTTONS_TEXT_FONT_SIZE, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=self.settings.ctm.CONFIRMATION_BUTTONS_TEXT_COLOR,
|
||||
)
|
||||
self.accept_button_label.grid(row=0, column=1)
|
||||
|
||||
|
||||
|
||||
bindButtonFunctionAndColor(
|
||||
target_widgets=[
|
||||
self.accept_button,
|
||||
self.accept_button_label_wrapper,
|
||||
self.accept_button_label,
|
||||
],
|
||||
enter_color=settings.ctm.ACCEPT_BUTTON_HOVERED_BG_COLOR,
|
||||
leave_color=settings.ctm.ACCEPT_BUTTON_BG_COLOR,
|
||||
clicked_color=settings.ctm.ACCEPT_BUTTON_CLICKED_BG_COLOR,
|
||||
buttonReleasedFunction=lambda _e: callFunctionIfCallable(self._view_variable.CALLBACK_ACCEPTED_CONFIRMATION_MODAL),
|
||||
)
|
||||
|
||||
|
||||
|
||||
def hide_buttons(self):
|
||||
self.modal_buttons_wrapper.grid_remove()
|
||||
|
||||
|
||||
def show(self, hide_title_bar:bool=True, close_when_focusout:bool=True):
|
||||
self.modal_buttons_wrapper.grid()
|
||||
|
||||
if hide_title_bar is False:
|
||||
self.overrideredirect(False)
|
||||
else:
|
||||
self.overrideredirect(True)
|
||||
|
||||
self.close_when_focusout = close_when_focusout
|
||||
if self.close_when_focusout is True:
|
||||
self.BIND_FOCUS_OUT_FUNC_ID = self.bind("<FocusOut>", self.focusOutFunction, "+")
|
||||
else:
|
||||
self._grab_set()
|
||||
|
||||
|
||||
self.attributes("-alpha", 0)
|
||||
self.deiconify()
|
||||
setGeometryToCenterOfTheWidget(
|
||||
attach_widget=self.attach_window,
|
||||
target_widget=self
|
||||
)
|
||||
fadeInAnimation(self, steps=5, interval=0.005, max_alpha=1)
|
||||
self.focus_set()
|
||||
|
||||
|
||||
def hide(self):
|
||||
if self.BIND_FOCUS_OUT_FUNC_ID is not None:
|
||||
self.unbind("<FocusOut>", self.BIND_FOCUS_OUT_FUNC_ID)
|
||||
|
||||
self.withdraw()
|
||||
self.grab_release()
|
||||
|
||||
def focusOutFunction(self, e):
|
||||
if str(e.widget) != ".!_createconfirmationmodal": return
|
||||
callFunctionIfCallable(self._view_variable.CALLBACK_HIDE_CONFIRMATION_MODAL)
|
||||
|
||||
def _grab_set(self):
|
||||
self.grab_set()
|
||||
355
vrct_gui/_CreateDropdownMenuWindow.py
Normal file
@@ -0,0 +1,355 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
from customtkinter import CTkToplevel, CTkFrame, CTkLabel, CTkFont, CTkScrollableFrame
|
||||
from time import sleep
|
||||
|
||||
from .ui_utils import bindButtonReleaseFunction, bindEnterAndLeaveColor, bindButtonPressColor, getLatestHeight, applyUiScalingAndFixTheBugScrollBar, getLatestWidth, getLongestText
|
||||
from functools import partial
|
||||
|
||||
from utils import isEven, makeEven
|
||||
|
||||
class _CreateDropdownMenuWindow(CTkToplevel):
|
||||
def __init__(
|
||||
self,
|
||||
settings,
|
||||
view_variable,
|
||||
|
||||
window_additional_y_pos,
|
||||
window_border_width,
|
||||
scrollbar_ipadx,
|
||||
scrollbar_width,
|
||||
value_ipadx,
|
||||
value_ipady,
|
||||
value_pady,
|
||||
value_font_size,
|
||||
dropdown_menu_default_min_width,
|
||||
|
||||
window_bg_color,
|
||||
window_border_color,
|
||||
values_bg_color,
|
||||
values_hovered_bg_color,
|
||||
values_clicked_bg_color,
|
||||
values_text_color,
|
||||
):
|
||||
|
||||
super().__init__()
|
||||
self.withdraw()
|
||||
self.hide = True
|
||||
|
||||
self.window_additional_y_pos=window_additional_y_pos
|
||||
self.window_border_width=window_border_width
|
||||
self.scrollbar_ipadx=scrollbar_ipadx
|
||||
self.scrollbar_width=scrollbar_width
|
||||
self.value_ipadx=value_ipadx
|
||||
self.value_ipady=value_ipady
|
||||
self.value_pady=value_pady
|
||||
self.value_font_size=value_font_size
|
||||
self.dropdown_menu_default_min_width=dropdown_menu_default_min_width
|
||||
|
||||
self.window_bg_color=window_bg_color
|
||||
self.window_border_color=window_border_color
|
||||
self.values_bg_color=values_bg_color
|
||||
self.values_hovered_bg_color=values_hovered_bg_color
|
||||
self.values_clicked_bg_color=values_clicked_bg_color
|
||||
self.values_text_color=values_text_color
|
||||
|
||||
|
||||
self.settings = settings
|
||||
self.attach_widget = None
|
||||
self._view_variable = view_variable
|
||||
self.wrapper_widget = None
|
||||
|
||||
self.dropdown_menu_widgets = {}
|
||||
self.active_dropdown_menu_widget = None
|
||||
|
||||
|
||||
|
||||
self.attach_widget_width = None
|
||||
self.attach_widget_height = None
|
||||
self.attach_widget_x_pos = None
|
||||
self.attach_widget_y_pos = None
|
||||
self.x_pos = None
|
||||
self.y_pos = None
|
||||
|
||||
self.init_height = 200
|
||||
self.new_height = self.init_height
|
||||
self.init_width = 200
|
||||
self.new_width = self.init_width
|
||||
|
||||
self.init_max_display_length = 8
|
||||
self.max_display_length = self.init_max_display_length
|
||||
|
||||
self.title("")
|
||||
self.overrideredirect(True)
|
||||
|
||||
self.wm_attributes("-alpha", 0)
|
||||
self.wm_attributes("-toolwindow", True)
|
||||
|
||||
self.configure(fg_color=self.window_bg_color)
|
||||
self.resizable(width=False, height=False)
|
||||
|
||||
|
||||
|
||||
def updateDropdownMenuValues(self, dropdown_menu_widget_id, dropdown_menu_values):
|
||||
self.dropdown_menu_widgets[dropdown_menu_widget_id].widget.destroy()
|
||||
self.createDropdownMenuBox(
|
||||
dropdown_menu_widget_id=dropdown_menu_widget_id,
|
||||
dropdown_menu_values=dropdown_menu_values,
|
||||
command=self.dropdown_menu_widgets[dropdown_menu_widget_id].command,
|
||||
wrapper_widget=self.dropdown_menu_widgets[dropdown_menu_widget_id].wrapper_widget,
|
||||
attach_widget=self.dropdown_menu_widgets[dropdown_menu_widget_id].attach_widget,
|
||||
|
||||
dropdown_menu_min_width=self.dropdown_menu_widgets[dropdown_menu_widget_id].dropdown_menu_settings.dropdown_menu_min_width,
|
||||
dropdown_menu_height=self.dropdown_menu_widgets[dropdown_menu_widget_id].dropdown_menu_settings.dropdown_menu_height,
|
||||
max_display_length=self.dropdown_menu_widgets[dropdown_menu_widget_id].dropdown_menu_settings.max_display_length,
|
||||
)
|
||||
|
||||
|
||||
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):
|
||||
|
||||
self.attach_widget = attach_widget
|
||||
self.wrapper_widget = wrapper_widget
|
||||
|
||||
|
||||
self.new_width = dropdown_menu_min_width if dropdown_menu_min_width is not None else self.dropdown_menu_default_min_width
|
||||
self.new_height = dropdown_menu_height if dropdown_menu_height is not None else self.init_height
|
||||
self.max_display_length = max_display_length if max_display_length is not None else self.init_max_display_length
|
||||
|
||||
|
||||
self.dropdown_menu_container = CTkFrame(self, corner_radius=0, fg_color=self.window_border_color, width=0, height=0)
|
||||
self.dropdown_menu_container.grid(row=0, column=0, sticky="nsew")
|
||||
|
||||
|
||||
BORDER_WIDTH=self.window_border_width
|
||||
self.scroll_frame_container = CTkScrollableFrame(
|
||||
self.dropdown_menu_container,
|
||||
corner_radius=0,
|
||||
fg_color=self.window_bg_color,
|
||||
width=0,
|
||||
height=0,
|
||||
border_width=0,
|
||||
)
|
||||
self.scroll_frame_container.grid(row=0, column=0, padx=BORDER_WIDTH, pady=BORDER_WIDTH, sticky="nsew")
|
||||
self.scroll_frame_container.grid_columnconfigure(0, weight=1)
|
||||
|
||||
|
||||
|
||||
self._createDropdownMenuValues(dropdown_menu_widget_id, dropdown_menu_values, command)
|
||||
|
||||
applyUiScalingAndFixTheBugScrollBar(
|
||||
scrollbar_widget=self.scroll_frame_container,
|
||||
padx=self.scrollbar_ipadx,
|
||||
width=self.scrollbar_width,
|
||||
)
|
||||
|
||||
geometry_width = int(self.new_width + self.scroll_frame_container._scrollbar.winfo_width() + (BORDER_WIDTH*2) + (self.scrollbar_ipadx[0] + self.scrollbar_ipadx[1]))
|
||||
geometry_height = int(self.new_height + (BORDER_WIDTH*2))
|
||||
|
||||
self.dropdown_menu_widgets[dropdown_menu_widget_id] = SimpleNamespace()
|
||||
|
||||
self.dropdown_menu_widgets[dropdown_menu_widget_id] = SimpleNamespace(
|
||||
widget=self.dropdown_menu_container,
|
||||
command=command,
|
||||
wrapper_widget=wrapper_widget,
|
||||
attach_widget=attach_widget,
|
||||
dropdown_menu_settings=SimpleNamespace(
|
||||
dropdown_menu_min_width=dropdown_menu_min_width,
|
||||
dropdown_menu_height=dropdown_menu_height,
|
||||
max_display_length=max_display_length,
|
||||
),
|
||||
_settings=SimpleNamespace(
|
||||
geometry_width=geometry_width,
|
||||
geometry_height=geometry_height,
|
||||
),
|
||||
)
|
||||
|
||||
self.dropdown_menu_container.grid_remove()
|
||||
|
||||
|
||||
def _createDropdownMenuValues(self, dropdown_menu_widget_id, dropdown_menu_values, command):
|
||||
|
||||
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)
|
||||
|
||||
# for get to the height__________________
|
||||
__dropdown_menu_value_wrapper = CTkFrame(self.dropdown_menu_values_wrapper, corner_radius=0, fg_color=self.values_bg_color, width=0, height=0)
|
||||
__dropdown_menu_value_wrapper.grid(row=0, column=0, pady=self.value_pady, sticky="nsew")
|
||||
setattr(self, f"{dropdown_menu_widget_id}__{0}", __dropdown_menu_value_wrapper)
|
||||
|
||||
|
||||
__dropdown_menu_value_wrapper.grid_rowconfigure((0,2), weight=1)
|
||||
# __dropdown_menu_value_wrapper.grid_columnconfigure(0, weight=1)
|
||||
__label_widget = CTkLabel(
|
||||
__dropdown_menu_value_wrapper,
|
||||
text=longest_text,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.value_font_size, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=self.values_text_color,
|
||||
)
|
||||
# setattr(self, f"l", __label_widget)
|
||||
|
||||
__label_widget.grid(row=1, column=0, padx=self.value_ipadx, pady=self.value_ipady, sticky="w")
|
||||
|
||||
label_height = getLatestHeight(__dropdown_menu_value_wrapper)
|
||||
label_width = getLatestWidth(__label_widget)
|
||||
label_width += self.scroll_frame_container._scrollbar.winfo_width() + (self.window_border_width*2) + (self.scrollbar_ipadx[0] + self.scrollbar_ipadx[1])
|
||||
if label_width > self.new_width:
|
||||
additional_width = int(label_width - self.new_width)
|
||||
self.new_width += additional_width
|
||||
|
||||
# for fixing 1px bug
|
||||
if isEven(label_height) is False:
|
||||
self.value_ipady = (self.value_ipady[0], self.value_ipady[1] - 1)
|
||||
|
||||
__dropdown_menu_value_wrapper.destroy()
|
||||
# ______________________________________
|
||||
|
||||
dropdown_menu_values_length = len(dropdown_menu_values)
|
||||
if dropdown_menu_values_length < self.max_display_length:
|
||||
self.new_height = int(dropdown_menu_values_length * label_height)
|
||||
else:
|
||||
self.new_height = int(self.max_display_length * label_height)
|
||||
|
||||
|
||||
# for fixing 1px bug
|
||||
self.new_height = makeEven(self.new_height)
|
||||
self.new_width = makeEven(self.new_width)
|
||||
self.scroll_frame_container.configure(width=self.new_width, height=self.new_height)
|
||||
|
||||
|
||||
|
||||
row=0
|
||||
for dropdown_menu_value in dropdown_menu_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)
|
||||
|
||||
|
||||
|
||||
dropdown_menu_value_wrapper.grid_rowconfigure((0,2), weight=1)
|
||||
label_widget = CTkLabel(
|
||||
dropdown_menu_value_wrapper,
|
||||
text=dropdown_menu_value,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.value_font_size, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=self.values_text_color,
|
||||
)
|
||||
|
||||
label_widget.grid(row=1, column=0, padx=self.value_ipadx, pady=self.value_ipady, sticky="w")
|
||||
|
||||
|
||||
bindEnterAndLeaveColor([dropdown_menu_value_wrapper, label_widget], self.values_hovered_bg_color, self.values_bg_color)
|
||||
bindButtonPressColor([dropdown_menu_value_wrapper, label_widget], self.values_clicked_bg_color, self.values_bg_color)
|
||||
|
||||
|
||||
|
||||
def optimizedCommand(value, _e):
|
||||
command(value)
|
||||
self._withdraw()
|
||||
|
||||
callback = partial(optimizedCommand, dropdown_menu_value)
|
||||
bindButtonReleaseFunction([dropdown_menu_value_wrapper, label_widget], callback)
|
||||
|
||||
row+=1
|
||||
|
||||
|
||||
|
||||
def show(self, dropdown_menu_widget_id):
|
||||
if self.hide is False: return
|
||||
self.wm_attributes("-alpha", 0)
|
||||
|
||||
|
||||
|
||||
if self.active_dropdown_menu_widget is not None:
|
||||
self.active_dropdown_menu_widget.grid_remove()
|
||||
|
||||
target_data = self.dropdown_menu_widgets[dropdown_menu_widget_id]
|
||||
self.attach_widget = target_data.attach_widget
|
||||
|
||||
target_data.widget.grid()
|
||||
self.active_dropdown_menu_widget = target_data.widget
|
||||
|
||||
self.geometry("{}x{}".format(target_data._settings.geometry_width, target_data._settings.geometry_height))
|
||||
|
||||
|
||||
self.deiconify()
|
||||
self._adjustToTargetWidgetGeometry()
|
||||
self.BIND_CONFIGURE_FUNC_ID = self.attach_widget.winfo_toplevel().bind("<Configure>", self._adjustToTargetWidgetGeometry, "+")
|
||||
self.BIND_UNMAP_FUNC_ID = self.attach_widget.bind("<Unmap>", self._withdraw, "+")
|
||||
|
||||
self.BIND_BUTTON_1_FUNC_ID = self.attach_widget.winfo_toplevel().bind("<Button-1>", self._withdraw, "+")
|
||||
|
||||
|
||||
self.hide = False
|
||||
|
||||
|
||||
|
||||
for i in range(0,91,10):
|
||||
if not self.winfo_exists():
|
||||
break
|
||||
self.attributes("-alpha", i/100)
|
||||
self.update()
|
||||
sleep(1/100)
|
||||
self.wm_attributes("-alpha", 1)
|
||||
self.update()
|
||||
|
||||
|
||||
|
||||
def _withdraw(self, e=None):
|
||||
self.withdraw()
|
||||
self.attach_widget.winfo_toplevel().unbind("<Configure>", self.BIND_CONFIGURE_FUNC_ID)
|
||||
self.attach_widget.unbind("<Unmap>", self.BIND_UNMAP_FUNC_ID)
|
||||
self.attach_widget.winfo_toplevel().unbind("<Button-1>", self.BIND_BUTTON_1_FUNC_ID)
|
||||
self.hide = True
|
||||
|
||||
|
||||
def _adjustToTargetWidgetGeometry(self, e=None):
|
||||
if not self.attach_widget.winfo_exists():
|
||||
return
|
||||
self.attach_widget.update_idletasks()
|
||||
|
||||
|
||||
|
||||
self.update()
|
||||
if self.attach_widget_x_pos == self.attach_widget.winfo_rootx() and self.attach_widget_y_pos == self.attach_widget.winfo_rooty():
|
||||
self.lift()
|
||||
return
|
||||
|
||||
self.wrapper_widget_y_pos = self.wrapper_widget.winfo_rooty()
|
||||
self.wrapper_widget_bottom_y_pos = self.wrapper_widget_y_pos + self.wrapper_widget.winfo_height()
|
||||
|
||||
self.attach_widget_width = self.attach_widget.winfo_width()
|
||||
self.attach_widget_height = self.attach_widget.winfo_height()
|
||||
self.attach_widget_x_pos = self.attach_widget.winfo_rootx()
|
||||
self.attach_widget_y_pos = self.attach_widget.winfo_rooty()
|
||||
|
||||
|
||||
self.y_pos = int(self.attach_widget_y_pos + self.attach_widget_height + self.window_additional_y_pos)
|
||||
|
||||
if self.wrapper_widget_y_pos > self.y_pos or self.y_pos > self.wrapper_widget_bottom_y_pos:
|
||||
self.hideTemporarily()
|
||||
else:
|
||||
if self.winfo_exists():
|
||||
self.deiconify()
|
||||
|
||||
|
||||
if self.winfo_width() >= self.attach_widget_width:
|
||||
self.x_pos = int(self.attach_widget_x_pos - (self.winfo_width() - self.attach_widget_width))
|
||||
else:
|
||||
self.x_pos = self.attach_widget_x_pos
|
||||
|
||||
self.geometry("+{}+{}".format(self.x_pos, self.y_pos))
|
||||
|
||||
self.lift()
|
||||
|
||||
def hideTemporarily(self):
|
||||
self.withdraw()
|
||||
|
||||
|
||||
177
vrct_gui/_CreateErrorWindow.py
Normal file
@@ -0,0 +1,177 @@
|
||||
from customtkinter import CTkToplevel, CTkFrame, CTkLabel, CTkFont
|
||||
from time import sleep
|
||||
|
||||
from .ui_utils import getLatestWidth, getLatestHeight
|
||||
from utils import isEven
|
||||
|
||||
|
||||
class _CreateErrorWindow(CTkToplevel):
|
||||
def __init__(
|
||||
self,
|
||||
settings,
|
||||
view_variable,
|
||||
wrapper_widget,
|
||||
|
||||
message_ipadx,
|
||||
message_ipady,
|
||||
message_font_size,
|
||||
|
||||
message_bg_color,
|
||||
message_text_color,
|
||||
):
|
||||
|
||||
super().__init__()
|
||||
self.withdraw()
|
||||
self.hide = True
|
||||
|
||||
self.settings = settings
|
||||
self.attach_widget = None
|
||||
self._view_variable = view_variable
|
||||
self.wrapper_widget = wrapper_widget
|
||||
|
||||
|
||||
self.message_ipadx = message_ipadx
|
||||
self.message_ipady = message_ipady
|
||||
self.message_font_size = message_font_size
|
||||
|
||||
self.message_bg_color = message_bg_color
|
||||
self.message_text_color = message_text_color
|
||||
|
||||
|
||||
self.attach_widget_width = None
|
||||
self.attach_widget_height = None
|
||||
self.attach_widget_x_pos = None
|
||||
self.attach_widget_y_pos = None
|
||||
self.x_pos = None
|
||||
self.y_pos = None
|
||||
|
||||
self.title("")
|
||||
self.overrideredirect(True)
|
||||
|
||||
self.wm_attributes("-alpha", 0)
|
||||
self.wm_attributes("-toolwindow", True)
|
||||
|
||||
self.configure(fg_color=self.message_bg_color)
|
||||
|
||||
|
||||
|
||||
|
||||
self.grid_rowconfigure(0,weight=1)
|
||||
self.grid_columnconfigure(0,weight=1)
|
||||
|
||||
self.error_message_container = CTkFrame(self, corner_radius=0, fg_color=self.message_bg_color, width=0, height=0)
|
||||
self.error_message_container.grid(row=0, column=0, sticky="nsew")
|
||||
|
||||
|
||||
self.error_message_container_label_wrapper = CTkLabel(
|
||||
self.error_message_container,
|
||||
# text=message,
|
||||
textvariable=self._view_variable.VAR_ERROR_MESSAGE,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.message_font_size, weight="normal"),
|
||||
anchor="w",
|
||||
justify="left",
|
||||
text_color=self.message_text_color,
|
||||
)
|
||||
self.error_message_container_label_wrapper.grid(row=0, column=0, padx=self.message_ipadx, pady=self.message_ipady, sticky="nsew")
|
||||
|
||||
|
||||
|
||||
|
||||
def show(self, target_widget):
|
||||
if self.hide is False: return
|
||||
|
||||
self.attach_widget = target_widget
|
||||
|
||||
self.deiconify()
|
||||
self._adjustToTargetWidgetGeometry()
|
||||
self.BIND_CONFIGURE_FUNC_ID = self.attach_widget.winfo_toplevel().bind("<Configure>", self._adjustToTargetWidgetGeometry, "+")
|
||||
self.BIND_UNMAP_FUNC_ID = self.attach_widget.bind("<Unmap>", self._withdraw, "+")
|
||||
|
||||
self.hide = False
|
||||
|
||||
label_width = getLatestWidth(self.error_message_container_label_wrapper)
|
||||
label_height = getLatestHeight(self.error_message_container_label_wrapper)
|
||||
|
||||
# for fixing 1px bug
|
||||
if isEven(label_width) is False:
|
||||
self.error_message_container_label_wrapper.grid(padx=(self.message_ipadx[0], self.message_ipadx[1]-1))
|
||||
else:
|
||||
self.error_message_container_label_wrapper.grid(padx=self.message_ipadx)
|
||||
|
||||
# for fixing 1px bug
|
||||
if isEven(label_height) is False:
|
||||
self.error_message_container_label_wrapper.grid(pady=(self.message_ipady[0], self.message_ipady[1]-1))
|
||||
else:
|
||||
self.error_message_container_label_wrapper.grid(pady=self.message_ipady)
|
||||
|
||||
|
||||
for i in range(0,101,20):
|
||||
if not self.winfo_exists():
|
||||
break
|
||||
self.attributes("-alpha", i/100)
|
||||
self.update()
|
||||
sleep(1/100)
|
||||
|
||||
sleep(0.1)
|
||||
|
||||
for i in range(0,91,10):
|
||||
if not self.winfo_exists():
|
||||
break
|
||||
self.attributes("-alpha", i/100)
|
||||
self.update()
|
||||
sleep(1/80)
|
||||
|
||||
|
||||
def _withdraw(self, e=None):
|
||||
self.withdraw()
|
||||
self.attach_widget.winfo_toplevel().unbind("<Configure>", self.BIND_CONFIGURE_FUNC_ID)
|
||||
self.attach_widget.unbind("<Unmap>", self.BIND_UNMAP_FUNC_ID)
|
||||
self.hide = True
|
||||
|
||||
|
||||
|
||||
def _adjustToTargetWidgetGeometry(self, e=None):
|
||||
if not self.attach_widget.winfo_exists():
|
||||
return
|
||||
self.attach_widget.update_idletasks()
|
||||
|
||||
|
||||
|
||||
self.update()
|
||||
if self.attach_widget_x_pos == self.attach_widget.winfo_rootx() and self.attach_widget_y_pos == self.attach_widget.winfo_rooty():
|
||||
self.lift()
|
||||
return
|
||||
|
||||
self.wrapper_widget_y_pos = self.wrapper_widget.winfo_rooty()
|
||||
self.wrapper_widget_bottom_y_pos = self.wrapper_widget_y_pos + self.wrapper_widget.winfo_height()
|
||||
|
||||
self.attach_widget_width = self.attach_widget.winfo_width()
|
||||
self.attach_widget_height = self.attach_widget.winfo_height()
|
||||
self.attach_widget_x_pos = self.attach_widget.winfo_rootx()
|
||||
self.attach_widget_y_pos = self.attach_widget.winfo_rooty()
|
||||
|
||||
|
||||
self.y_pos = int(self.attach_widget_y_pos + self.attach_widget_height + 4)
|
||||
|
||||
if self.wrapper_widget_y_pos > self.y_pos or self.y_pos > self.wrapper_widget_bottom_y_pos:
|
||||
self.hideTemporarily()
|
||||
else:
|
||||
if self.winfo_exists():
|
||||
self.deiconify()
|
||||
|
||||
|
||||
if self.winfo_width() >= self.attach_widget_width:
|
||||
self.x_pos = int(self.attach_widget_x_pos - (self.winfo_width() - self.attach_widget_width))
|
||||
else:
|
||||
self.x_pos = self.attach_widget_x_pos
|
||||
|
||||
self.geometry("+{}+{}".format(self.x_pos, self.y_pos))
|
||||
|
||||
self.lift()
|
||||
|
||||
def hideTemporarily(self):
|
||||
self.withdraw()
|
||||
|
||||
|
||||
182
vrct_gui/_CreateSelectableLanguagesWindow.py
Normal file
@@ -0,0 +1,182 @@
|
||||
from functools import partial
|
||||
|
||||
from .ui_utils import bindButtonReleaseFunction, bindEnterAndLeaveColor, bindButtonPressColor, applyUiScalingAndFixTheBugScrollBar
|
||||
from utils import callFunctionIfCallable, makeEven
|
||||
|
||||
from customtkinter import CTkToplevel, CTkFrame, CTkLabel, CTkFont, CTkScrollableFrame
|
||||
|
||||
class _CreateSelectableLanguagesWindow(CTkToplevel):
|
||||
def __init__(self, vrct_gui, settings, view_variable):
|
||||
super().__init__()
|
||||
self.withdraw()
|
||||
|
||||
self.attach = vrct_gui.main_bg_container
|
||||
self.vrct_gui = vrct_gui
|
||||
self.settings = settings
|
||||
self._view_variable = view_variable
|
||||
|
||||
self.is_created = False
|
||||
self.selectable_language_window_type = None
|
||||
|
||||
|
||||
self.title("_CreateSelectableLanguagesWindow")
|
||||
self.overrideredirect(True)
|
||||
self.configure(fg_color=self.settings.ctm.TOP_BG_COLOR)
|
||||
self.protocol("WM_DELETE_WINDOW", vrct_gui._closeSelectableLanguagesWindow)
|
||||
self.bind("<FocusOut>", self.focusOutFunction)
|
||||
|
||||
|
||||
|
||||
|
||||
def createContainer(self, selectable_language_window_type):
|
||||
self.selectable_language_window_type = selectable_language_window_type
|
||||
|
||||
self.attach.update_idletasks()
|
||||
self.x_pos = self.attach.winfo_rootx()
|
||||
self.y_pos = self.attach.winfo_rooty()
|
||||
self.width_new = makeEven(self.attach.winfo_width())
|
||||
self.height_new = makeEven(self.attach.winfo_height())
|
||||
|
||||
|
||||
self.geometry("{}x{}+{}+{}".format(self.width_new, self.height_new, self.x_pos, self.y_pos))
|
||||
|
||||
|
||||
|
||||
if self.is_created is True:
|
||||
pass
|
||||
else:
|
||||
self._createContainer()
|
||||
|
||||
|
||||
def callbackSelectableLanguages(self, value, _e):
|
||||
if self.selectable_language_window_type == "your_language":
|
||||
callback = self._view_variable.CALLBACK_SELECTED_YOUR_LANGUAGE
|
||||
target_variable = self._view_variable.VAR_YOUR_LANGUAGE
|
||||
elif self.selectable_language_window_type == "target_language":
|
||||
callback = self._view_variable.CALLBACK_SELECTED_TARGET_LANGUAGE
|
||||
target_variable = self._view_variable.VAR_TARGET_LANGUAGE
|
||||
|
||||
target_variable.set(value)
|
||||
callFunctionIfCallable(callback, value)
|
||||
self.vrct_gui._closeSelectableLanguagesWindow()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def _createContainer(self):
|
||||
self.grid_rowconfigure(0, minsize=self.settings.uism.TOP_BAR_MIN_HEIGHT)
|
||||
self.grid_rowconfigure(1, weight=1)
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
self.top_container = CTkFrame(self, corner_radius=0, fg_color=self.settings.ctm.TOP_BG_COLOR, width=0, height=0)
|
||||
self.top_container.grid(row=0, column=0, sticky="nsew")
|
||||
|
||||
|
||||
self.top_container.grid_rowconfigure((0,2), weight=1)
|
||||
self.top_container.grid_columnconfigure(1, weight=1)
|
||||
self.go_back_button_container = CTkFrame(self.top_container, corner_radius=0, fg_color=self.settings.ctm.GO_BACK_BUTTON_BG_COLOR, width=0, height=0, cursor="hand2")
|
||||
self.go_back_button_container.grid(row=1, column=0)
|
||||
|
||||
self.go_back_button_label = CTkLabel(
|
||||
self.go_back_button_container,
|
||||
textvariable=self._view_variable.VAR_GO_BACK_LABEL_SELECTABLE_LANGUAGE,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.GO_BACK_BUTTON_LABEL_FONT_SIZE, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=self.settings.ctm.BASIC_TEXT_COLOR,
|
||||
)
|
||||
self.go_back_button_label.grid(row=0, column=0, padx=self.settings.uism.GO_BACK_BUTTON_IPADX, pady=self.settings.uism.GO_BACK_BUTTON_IPADY)
|
||||
|
||||
|
||||
bindEnterAndLeaveColor([self.go_back_button_container, self.go_back_button_label], self.settings.ctm.GO_BACK_BUTTON_BG_HOVERED_COLOR, self.settings.ctm.GO_BACK_BUTTON_BG_COLOR)
|
||||
bindButtonPressColor([self.go_back_button_container, self.go_back_button_label], self.settings.ctm.GO_BACK_BUTTON_BG_CLICKED_COLOR, self.settings.ctm.GO_BACK_BUTTON_BG_COLOR)
|
||||
|
||||
|
||||
bindButtonReleaseFunction([self.go_back_button_container, self.go_back_button_label], lambda _e: self.vrct_gui._closeSelectableLanguagesWindow())
|
||||
|
||||
|
||||
|
||||
self.title_container = CTkFrame(self.top_container, corner_radius=0, fg_color=self.settings.ctm.TOP_BG_COLOR, width=0, height=0)
|
||||
self.title_container.grid(row=1, column=1, sticky="nsew")
|
||||
|
||||
self.title_container.grid_columnconfigure((0,2), weight=1)
|
||||
self.title_container.grid_rowconfigure((0,2), weight=1)
|
||||
self.title_label = CTkLabel(
|
||||
self.title_container,
|
||||
textvariable=self._view_variable.VAR_TITLE_LABEL_SELECTABLE_LANGUAGE,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.TITLE_FONT_SIZE, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=self.settings.ctm.TITLE_TEXT_COLOR,
|
||||
)
|
||||
self.title_label.grid(row=1, column=1)
|
||||
|
||||
|
||||
|
||||
|
||||
self.scroll_frame_container = CTkScrollableFrame(self, corner_radius=0, fg_color=self.settings.ctm.MAIN_BG_COLOR, width=self.width_new, height=self.height_new)
|
||||
self.scroll_frame_container.grid(row=1, column=0, sticky="nsew")
|
||||
|
||||
applyUiScalingAndFixTheBugScrollBar(
|
||||
scrollbar_widget=self.scroll_frame_container,
|
||||
padx=self.settings.uism.SCROLLBAR_IPADX,
|
||||
width=self.settings.uism.SCROLLBAR_WIDTH,
|
||||
)
|
||||
|
||||
|
||||
self.container = CTkFrame(self.scroll_frame_container, corner_radius=0, fg_color=self.settings.ctm.MAIN_BG_COLOR, width=0, height=0)
|
||||
self.container.grid(row=0, column=0, sticky="nsew")
|
||||
|
||||
|
||||
|
||||
max_row = int(len(self._view_variable.LIST_SELECTABLE_LANGUAGES)/3) + 1
|
||||
max_row+=1
|
||||
row=0
|
||||
column=0
|
||||
for selectable_language_name in self._view_variable.LIST_SELECTABLE_LANGUAGES:
|
||||
|
||||
self.wrapper = CTkFrame(self.container, corner_radius=0, fg_color=self.settings.ctm.LANGUAGE_BUTTON_BG_COLOR, width=0, height=0, cursor="hand2")
|
||||
self.wrapper.grid(row=row, column=column, sticky="nsew")
|
||||
setattr(self, f"{row}_{column}", self.wrapper)
|
||||
|
||||
|
||||
|
||||
self.wrapper.grid_rowconfigure((0,2), weight=1)
|
||||
selectable_language_name_for_text = selectable_language_name.replace("\n", " ")
|
||||
label_widget = CTkLabel(
|
||||
self.wrapper,
|
||||
text=selectable_language_name_for_text,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.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.VALUES_TEXT_IPADX, pady=self.settings.uism.VALUES_TEXT_IPADY)
|
||||
|
||||
|
||||
|
||||
bindEnterAndLeaveColor([self.wrapper, label_widget], self.settings.ctm.LANGUAGE_BUTTON_BG_HOVERED_COLOR, self.settings.ctm.LANGUAGE_BUTTON_BG_COLOR)
|
||||
bindButtonPressColor([self.wrapper, label_widget], self.settings.ctm.LANGUAGE_BUTTON_BG_CLICKED_COLOR, self.settings.ctm.LANGUAGE_BUTTON_BG_COLOR)
|
||||
|
||||
|
||||
|
||||
callback = partial(self.callbackSelectableLanguages, selectable_language_name)
|
||||
bindButtonReleaseFunction([self.wrapper, label_widget], callback)
|
||||
|
||||
if row == max_row:
|
||||
row=0
|
||||
column+=1
|
||||
else:
|
||||
row+=1
|
||||
|
||||
|
||||
self.is_created = True
|
||||
|
||||
|
||||
def focusOutFunction(self, e):
|
||||
if str(e.widget) != ".!_createselectablelanguageswindow": return
|
||||
self.vrct_gui._closeSelectableLanguagesWindow()
|
||||
80
vrct_gui/_CreateWindowCover.py
Normal file
@@ -0,0 +1,80 @@
|
||||
from customtkinter import CTkToplevel, CTkFrame, CTkLabel, CTkFont
|
||||
|
||||
from .ui_utils import fadeInAnimation
|
||||
from utils import makeEven
|
||||
|
||||
class _CreateWindowCover(CTkToplevel):
|
||||
def __init__(self, attach_window, settings, view_variable):
|
||||
super().__init__()
|
||||
self.withdraw()
|
||||
|
||||
self.BIND_CONFIGURE_ADJUSTED_GEOMETRY_FUNC_ID=None
|
||||
self.BIND_FOCUS_IN_FUNC_ID=None
|
||||
|
||||
self.attach_window = attach_window
|
||||
self.settings = settings
|
||||
self._view_variable = view_variable
|
||||
|
||||
self.title("")
|
||||
self.overrideredirect(True)
|
||||
self.wm_attributes("-toolwindow", True)
|
||||
self.configure(fg_color="black")
|
||||
self.protocol("WM_DELETE_WINDOW", lambda: self.withdraw())
|
||||
|
||||
|
||||
self.grid_rowconfigure(0,weight=1)
|
||||
self.grid_columnconfigure(0,weight=1)
|
||||
self.cover_container = CTkFrame(self, corner_radius=0, fg_color="black", width=0, height=0)
|
||||
self.cover_container.grid(row=0, column=0, sticky="nsew")
|
||||
|
||||
|
||||
self.cover_container_label_wrapper = CTkLabel(
|
||||
self.cover_container,
|
||||
textvariable=self._view_variable.VAR_LABEL_MAIN_WINDOW_COVER_MESSAGE,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.TEXT_FONT_SIZE, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=self.settings.ctm.TEXT_COLOR,
|
||||
)
|
||||
self.cover_container_label_wrapper.place(relx=0.5, rely=0.5, anchor="center")
|
||||
|
||||
|
||||
def show(self, bind_focusin=None):
|
||||
self.BIND_CONFIGURE_ADJUSTED_GEOMETRY_FUNC_ID = self.attach_window.bind("<Configure>", self._adjustToMainWindowGeometry, "+")
|
||||
if bind_focusin is not None:
|
||||
self.BIND_FOCUS_IN_FUNC_ID = self.bind("<FocusIn>", lambda _e: bind_focusin(), "+")
|
||||
else:
|
||||
self.BIND_FOCUS_IN_FUNC_ID = None
|
||||
|
||||
|
||||
self.attributes("-alpha", 0)
|
||||
self.deiconify()
|
||||
self.attach_window.update_idletasks()
|
||||
self.x_pos = self.attach_window.winfo_rootx()
|
||||
self.y_pos = self.attach_window.winfo_rooty()
|
||||
self.width_new = self.attach_window.winfo_width()
|
||||
self.height_new = self.attach_window.winfo_height()
|
||||
self.geometry("{}x{}+{}+{}".format(self.width_new, self.height_new, self.x_pos, self.y_pos))
|
||||
fadeInAnimation(self, steps=5, interval=0.005, max_alpha=0.5)
|
||||
|
||||
|
||||
|
||||
def hide(self):
|
||||
self.attach_window.unbind("<Configure>", self.BIND_CONFIGURE_ADJUSTED_GEOMETRY_FUNC_ID)
|
||||
if self.BIND_FOCUS_IN_FUNC_ID is not None:
|
||||
self.unbind("<FocusIn>", self.BIND_FOCUS_IN_FUNC_ID)
|
||||
|
||||
self.withdraw()
|
||||
|
||||
|
||||
|
||||
def _adjustToMainWindowGeometry(self, e=None):
|
||||
self.attach_window.update_idletasks()
|
||||
x_pos = self.attach_window.winfo_rootx()
|
||||
y_pos = self.attach_window.winfo_rooty()
|
||||
width_new = makeEven(self.attach_window.winfo_width())
|
||||
height_new = makeEven(self.attach_window.winfo_height())
|
||||
self.geometry("{}x{}+{}+{}".format(width_new, height_new, x_pos, y_pos))
|
||||
|
||||
self.lift()
|
||||
1
vrct_gui/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .vrct_gui import vrct_gui
|
||||
40
vrct_gui/_changeConfigWindowWidgetsStatus.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from customtkinter import CTkImage
|
||||
|
||||
def _changeConfigWindowWidgetsStatus(config_window, settings, view_variable, status, target_names):
|
||||
# if target_names == "All":
|
||||
# target_names = []
|
||||
|
||||
|
||||
def disableOptionmenuWidget(target_widget):
|
||||
target_widget.label_widget.configure(text_color=settings.ctm.LABELS_TEXT_DISABLED_COLOR)
|
||||
if target_widget.desc_widget is not None:
|
||||
target_widget.desc_widget.configure(text_color=settings.ctm.LABELS_TEXT_DISABLED_COLOR)
|
||||
target_widget.optionmenu_label_widget.configure(text_color=settings.ctm.LABELS_TEXT_DISABLED_COLOR)
|
||||
target_widget.optionmenu_img_widget.configure(image=CTkImage(settings.image_file.ARROW_LEFT_DISABLED.rotate(90), size=settings.uism.SB__OPTIONMENU_IMG_SIZE))
|
||||
target_widget.optionmenu_box.unbindFunction()
|
||||
target_widget.optionmenu_box.configure(cursor="")
|
||||
|
||||
|
||||
for target_name in target_names:
|
||||
match target_name:
|
||||
case "sb__optionmenu_mic_host":
|
||||
if status == "disabled":
|
||||
target_widget = config_window.sb__widgets["sb__optionmenu_mic_host"]
|
||||
disableOptionmenuWidget(target_widget)
|
||||
|
||||
case "sb__optionmenu_mic_device":
|
||||
if status == "disabled":
|
||||
target_widget = config_window.sb__widgets["sb__optionmenu_mic_device"]
|
||||
disableOptionmenuWidget(target_widget)
|
||||
|
||||
case "sb__optionmenu_appearance_theme":
|
||||
if status == "disabled":
|
||||
target_widget = config_window.sb__widgets["sb__optionmenu_appearance_theme"]
|
||||
disableOptionmenuWidget(target_widget)
|
||||
|
||||
case _:
|
||||
raise ValueError(f"No matching case for target_name: {target_name}")
|
||||
|
||||
|
||||
|
||||
config_window.update()
|
||||
158
vrct_gui/_changeMainWindowWidgetsStatus.py
Normal file
@@ -0,0 +1,158 @@
|
||||
from customtkinter import CTkImage
|
||||
hold_state_list=[]
|
||||
def _changeMainWindowWidgetsStatus(vrct_gui, settings, view_variable, status, target_names:list, to_hold_state:bool=False):
|
||||
global hold_state_list
|
||||
if target_names == "All":
|
||||
target_names = ["translation_switch", "transcription_send_switch", "transcription_receive_switch", "foreground_switch", "quick_language_settings", "config_button", "minimize_sidebar_button", "entry_message_box"]
|
||||
|
||||
|
||||
for item in hold_state_list:
|
||||
if item in target_names:
|
||||
target_names.remove(item)
|
||||
|
||||
|
||||
def update_switch_status(
|
||||
widget_frame,
|
||||
widget_label,
|
||||
widget_switch_box,
|
||||
widget_selected_mark,
|
||||
widget_compact_mode_icon,
|
||||
icon_name,
|
||||
disabled_icon_name,
|
||||
):
|
||||
|
||||
if status == "disabled":
|
||||
widget_frame.configure(cursor="")
|
||||
widget_label.configure(text_color=settings.ctm.SF__TEXT_DISABLED_COLOR)
|
||||
widget_switch_box.configure(state="disabled", progress_color=settings.ctm.SF__SWITCH_BOX_DISABLE_BG_COLOR)
|
||||
widget_selected_mark.configure(fg_color=settings.ctm.SF__SELECTED_MARK_DISABLE_BG_COLOR)
|
||||
icon_file = disabled_icon_name
|
||||
elif status == "normal":
|
||||
widget_frame.configure(cursor="hand2")
|
||||
widget_label.configure(text_color=settings.ctm.LABELS_TEXT_COLOR)
|
||||
widget_switch_box.configure(state="normal", progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_BG_COLOR)
|
||||
widget_selected_mark.configure(fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_BG_COLOR)
|
||||
icon_file = icon_name
|
||||
|
||||
image = CTkImage(icon_file, size=settings.uism.SF__COMPACT_MODE_IMAGE_SIZE)
|
||||
widget_compact_mode_icon.configure(image=image)
|
||||
|
||||
|
||||
|
||||
|
||||
for target_name in target_names:
|
||||
match target_name:
|
||||
case "translation_switch":
|
||||
update_switch_status(
|
||||
widget_frame=vrct_gui.translation_frame,
|
||||
widget_label=vrct_gui.label_translation,
|
||||
widget_switch_box=vrct_gui.translation_switch_box,
|
||||
widget_selected_mark=vrct_gui.translation_selected_mark,
|
||||
widget_compact_mode_icon=vrct_gui.translation_compact_mode_icon,
|
||||
icon_name=settings.image_file.TRANSLATION_ICON,
|
||||
disabled_icon_name=settings.image_file.TRANSLATION_ICON_DISABLED
|
||||
)
|
||||
case "transcription_send_switch":
|
||||
update_switch_status(
|
||||
widget_frame=vrct_gui.transcription_send_frame,
|
||||
widget_label=vrct_gui.label_transcription_send,
|
||||
widget_switch_box=vrct_gui.transcription_send_switch_box,
|
||||
widget_selected_mark=vrct_gui.transcription_send_selected_mark,
|
||||
widget_compact_mode_icon=vrct_gui.transcription_send_compact_mode_icon,
|
||||
icon_name=settings.image_file.MIC_ICON,
|
||||
disabled_icon_name=settings.image_file.MIC_ICON_DISABLED
|
||||
)
|
||||
case "transcription_receive_switch":
|
||||
update_switch_status(
|
||||
widget_frame=vrct_gui.transcription_receive_frame,
|
||||
widget_label=vrct_gui.label_transcription_receive,
|
||||
widget_switch_box=vrct_gui.transcription_receive_switch_box,
|
||||
widget_selected_mark=vrct_gui.transcription_receive_selected_mark,
|
||||
widget_compact_mode_icon=vrct_gui.transcription_receive_compact_mode_icon,
|
||||
icon_name=settings.image_file.HEADPHONES_ICON,
|
||||
disabled_icon_name=settings.image_file.HEADPHONES_ICON_DISABLED
|
||||
)
|
||||
case "foreground_switch":
|
||||
update_switch_status(
|
||||
widget_frame=vrct_gui.foreground_frame,
|
||||
widget_label=vrct_gui.label_foreground,
|
||||
widget_switch_box=vrct_gui.foreground_switch_box,
|
||||
widget_selected_mark=vrct_gui.foreground_selected_mark,
|
||||
widget_compact_mode_icon=vrct_gui.foreground_compact_mode_icon,
|
||||
icon_name=settings.image_file.FOREGROUND_ICON,
|
||||
disabled_icon_name=settings.image_file.FOREGROUND_ICON_DISABLED
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
case "quick_language_settings":
|
||||
if status == "disabled":
|
||||
vrct_gui.sls__container_title.configure(text_color=settings.ctm.SF__TEXT_DISABLED_COLOR)
|
||||
vrct_gui.sls__title_text_your_language.configure(text_color=settings.ctm.SF__TEXT_DISABLED_COLOR)
|
||||
vrct_gui.sls__title_text_target_language.configure(text_color=settings.ctm.SF__TEXT_DISABLED_COLOR)
|
||||
if view_variable.IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE is False:
|
||||
vrct_gui.current_active_preset_tab.children["!ctklabel"].configure(text_color=settings.ctm.SLS__PRESETS_TAB_ACTIVE_TEXT_COLOR_PASSIVE)
|
||||
|
||||
|
||||
elif status == "normal":
|
||||
vrct_gui.sls__container_title.configure(text_color=settings.ctm.LABELS_TEXT_COLOR)
|
||||
vrct_gui.sls__title_text_your_language.configure(text_color=settings.ctm.LABELS_TEXT_COLOR)
|
||||
vrct_gui.sls__title_text_target_language.configure(text_color=settings.ctm.LABELS_TEXT_COLOR)
|
||||
if view_variable.IS_MAIN_WINDOW_SIDEBAR_COMPACT_MODE is False:
|
||||
vrct_gui.current_active_preset_tab.children["!ctklabel"].configure(text_color=settings.ctm.SLS__PRESETS_TAB_ACTIVE_TEXT_COLOR)
|
||||
vrct_gui.current_active_preset_tab.children["!ctklabel"].configure(text_color=settings.ctm.SLS__PRESETS_TAB_ACTIVE_TEXT_COLOR)
|
||||
|
||||
|
||||
|
||||
case "config_button":
|
||||
if status == "disabled":
|
||||
vrct_gui.sidebar_config_button_wrapper.configure(cursor="")
|
||||
vrct_gui.sidebar_config_button.configure(
|
||||
image=CTkImage(settings.image_file.CONFIGURATION_ICON_DISABLED, size=settings.uism.SF__COMPACT_MODE_IMAGE_SIZE),
|
||||
)
|
||||
elif status == "normal":
|
||||
vrct_gui.sidebar_config_button_wrapper.configure(cursor="hand2")
|
||||
vrct_gui.sidebar_config_button.configure(
|
||||
image=CTkImage(settings.image_file.CONFIGURATION_ICON, size=settings.uism.SF__COMPACT_MODE_IMAGE_SIZE),
|
||||
)
|
||||
|
||||
|
||||
case "minimize_sidebar_button":
|
||||
MINIMIZE_SIDEBAR_IMAGE_SIZE = vrct_gui.minimize_sidebar_button__for_opening.cget("image").cget("size")
|
||||
if status == "disabled":
|
||||
vrct_gui.minimize_sidebar_button_container__for_opening.configure(cursor="")
|
||||
vrct_gui.minimize_sidebar_button_container__for_closing.configure(cursor="")
|
||||
|
||||
image_file__for_opening = CTkImage((settings.image_file.ARROW_LEFT_DISABLED).rotate(180), size=MINIMIZE_SIDEBAR_IMAGE_SIZE)
|
||||
image_file__for_closing = CTkImage((settings.image_file.ARROW_LEFT_DISABLED), size=MINIMIZE_SIDEBAR_IMAGE_SIZE)
|
||||
|
||||
elif status == "normal":
|
||||
vrct_gui.minimize_sidebar_button_container__for_opening.configure(cursor="hand2")
|
||||
vrct_gui.minimize_sidebar_button_container__for_closing.configure(cursor="hand2")
|
||||
|
||||
image_file__for_opening = CTkImage((settings.image_file.ARROW_LEFT).rotate(180), size=MINIMIZE_SIDEBAR_IMAGE_SIZE)
|
||||
image_file__for_closing = CTkImage((settings.image_file.ARROW_LEFT), size=MINIMIZE_SIDEBAR_IMAGE_SIZE)
|
||||
vrct_gui.minimize_sidebar_button__for_opening.configure(image=image_file__for_opening)
|
||||
vrct_gui.minimize_sidebar_button__for_closing.configure(image=image_file__for_closing)
|
||||
|
||||
|
||||
case "entry_message_box":
|
||||
if status == "disabled":
|
||||
vrct_gui.entry_message_box.configure(state="disabled", placeholder_text_color=settings.ctm.TEXTBOX_ENTRY_PLACEHOLDER_DISABLED_COLOR, text_color=settings.ctm.TEXTBOX_ENTRY_TEXT_DISABLED_COLOR)
|
||||
elif status == "normal":
|
||||
vrct_gui.entry_message_box.configure(state="normal", placeholder_text_color=settings.ctm.TEXTBOX_ENTRY_PLACEHOLDER_COLOR, text_color=settings.ctm.TEXTBOX_ENTRY_TEXT_COLOR)
|
||||
|
||||
|
||||
case _:
|
||||
raise ValueError(f"No matching case for target_name: {target_name}")
|
||||
|
||||
|
||||
if to_hold_state is True:
|
||||
for item in target_names:
|
||||
if item not in hold_state_list:
|
||||
hold_state_list.append(item)
|
||||
|
||||
vrct_gui.update()
|
||||
98
vrct_gui/_printToTextbox.py
Normal file
@@ -0,0 +1,98 @@
|
||||
from datetime import datetime
|
||||
from customtkinter import CTkFont
|
||||
|
||||
def _printToTextbox(vrct_gui,
|
||||
settings,
|
||||
target_type,
|
||||
original_message=None,
|
||||
translated_message=None,
|
||||
tags=None,
|
||||
disable_print_to_textbox_all:bool=False,
|
||||
):
|
||||
|
||||
now_raw_data = datetime.now()
|
||||
# now = now_raw_data.strftime("%H:%M:%S")
|
||||
now_hm = now_raw_data.strftime("%H:%M")
|
||||
# set target textbox widget
|
||||
|
||||
is_only_one_message = True if original_message is None or translated_message is None or translated_message == "" else False
|
||||
|
||||
match (target_type):
|
||||
case "SYSTEM":
|
||||
target_textbox = vrct_gui.textbox_system
|
||||
case "SENT":
|
||||
target_textbox = vrct_gui.textbox_sent
|
||||
case "RECEIVED":
|
||||
target_textbox = vrct_gui.textbox_received
|
||||
case (_):
|
||||
raise ValueError(f"No matching case for target_type: {target_type}")
|
||||
|
||||
|
||||
def printEachTextbox(target_textbox):
|
||||
target_textbox.tag_config("JUSTIFY_CENTER", justify="center")
|
||||
target_textbox.tag_config("JUSTIFY_RIGHT", justify="right")
|
||||
target_textbox.tag_config("JUSTIFY_LEFT", justify="left")
|
||||
|
||||
# common tag settings
|
||||
# target_textbox._textbox.tag_configure("START", spacing1=16)
|
||||
target_textbox._textbox.tag_configure("LABEL", font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TEXTBOX_FONT_SIZE__LABEL, weight="normal"))
|
||||
target_textbox._textbox.tag_configure("TIMESTAMP", font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TEXTBOX_FONT_SIZE__TIMESTAMP, weight="normal"), foreground=settings.ctm.TEXTBOX_TIMESTAMP_TEXT_COLOR)
|
||||
target_textbox._textbox.tag_configure("SECONDARY_TEXT_FONT", font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TEXTBOX_FONT_SIZE__SECONDARY_TEXT_FONT, weight="normal"))
|
||||
target_textbox._textbox.tag_configure("MAIN_TEXT_FONT", font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TEXTBOX_FONT_SIZE__MAIN_TEXT_FONT, weight="normal"))
|
||||
|
||||
# System Tag Settings
|
||||
target_textbox.tag_config("FIRST_INSERT_SPACING", spacing1=settings.uism.TEXTBOX_FIRST_INSERT_SPACING)
|
||||
target_textbox.tag_config("SYSTEM_TAG", foreground=settings.ctm.TEXTBOX_SYSTEM_TAG_TEXT_COLOR)
|
||||
target_textbox.tag_config("SYSTEM_TEXT", foreground=settings.ctm.TEXTBOX_TEXT_SUB_COLOR)
|
||||
target_textbox._textbox.tag_configure("SYSTEM_TEXT_FONT", font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TEXTBOX_FONT_SIZE__SYSTEM_TEXT_FONT, weight="normal"))
|
||||
|
||||
# Sent Tag Settings
|
||||
target_textbox.tag_config("SENT_TAG", foreground=settings.ctm.TEXTBOX_SENT_TAG_TEXT_COLOR)
|
||||
target_textbox.tag_config("SENT_TEXT", foreground=settings.ctm.TEXTBOX_TEXT_COLOR)
|
||||
target_textbox.tag_config("SENT_SUB_TEXT", foreground=settings.ctm.TEXTBOX_TEXT_SUB_COLOR)
|
||||
|
||||
# Received Tag Settings
|
||||
target_textbox.tag_config("RECEIVED_TAG", foreground=settings.ctm.TEXTBOX_RECEIVED_TAG_TEXT_COLOR)
|
||||
target_textbox.tag_config("RECEIVED_TEXT", foreground=settings.ctm.TEXTBOX_TEXT_COLOR)
|
||||
target_textbox.tag_config("RECEIVED_SUB_TEXT", foreground=settings.ctm.TEXTBOX_TEXT_SUB_COLOR)
|
||||
|
||||
FAKE_MARGIN = " "
|
||||
# insert
|
||||
target_textbox.configure(state="normal")
|
||||
target_textbox.insert("end", "\n")
|
||||
match (target_type):
|
||||
case "SYSTEM":
|
||||
target_textbox.insert("end", "System", ("SYSTEM_TAG", "FIRST_INSERT_SPACING", "JUSTIFY_CENTER", "LABEL"))
|
||||
target_textbox.insert("end", FAKE_MARGIN+original_message+FAKE_MARGIN, ("SYSTEM_TEXT", "SYSTEM_TEXT_FONT", "JUSTIFY_CENTER"))
|
||||
target_textbox.insert("end", now_hm, ("TIMESTAMP", "JUSTIFY_CENTER"))
|
||||
|
||||
case "SENT":
|
||||
target_textbox.insert("end", now_hm, ("TIMESTAMP", "FIRST_INSERT_SPACING", "JUSTIFY_RIGHT"))
|
||||
target_textbox.insert("end", FAKE_MARGIN+"Sent", ("SENT_TAG", "LABEL"))
|
||||
target_textbox.insert("end", "\n")
|
||||
if is_only_one_message is False:
|
||||
target_textbox.insert("end", original_message, ("SENT_SUB_TEXT", "SECONDARY_TEXT_FONT", "JUSTIFY_RIGHT"))
|
||||
target_textbox.insert("end", "\n")
|
||||
target_textbox.insert("end", translated_message, ("SENT_TEXT", "MAIN_TEXT_FONT", "JUSTIFY_RIGHT"))
|
||||
else:
|
||||
target_textbox.insert("end", original_message, ("SENT_TEXT", "MAIN_TEXT_FONT", "JUSTIFY_RIGHT"))
|
||||
|
||||
case "RECEIVED":
|
||||
target_textbox.insert("end", "Received", ("RECEIVED_TAG", "FIRST_INSERT_SPACING", "JUSTIFY_LEFT", "LABEL"))
|
||||
target_textbox.insert("end", FAKE_MARGIN+now_hm, ("TIMESTAMP"))
|
||||
if is_only_one_message is False:
|
||||
target_textbox.insert("end", "\n")
|
||||
target_textbox.insert("end", original_message, ("RECEIVED_SUB_TEXT", "SECONDARY_TEXT_FONT"))
|
||||
target_textbox.insert("end", "\n")
|
||||
target_textbox.insert("end", translated_message, ("RECEIVED_TEXT", "MAIN_TEXT_FONT", "JUSTIFY_LEFT"))
|
||||
else:
|
||||
target_textbox.insert("end", "\n")
|
||||
target_textbox.insert("end", original_message, ("RECEIVED_TEXT", "MAIN_TEXT_FONT", "JUSTIFY_LEFT"))
|
||||
|
||||
target_textbox.configure(state="disabled")
|
||||
target_textbox.see("end")
|
||||
|
||||
printEachTextbox(target_textbox)
|
||||
|
||||
# To automatically print the same log to the textbox_all widget as well.
|
||||
if disable_print_to_textbox_all is not True: printEachTextbox(vrct_gui.textbox_all)
|
||||
66
vrct_gui/config_window/ConfigWindow.py
Normal file
@@ -0,0 +1,66 @@
|
||||
from .widgets import createConfigWindowTitle, createSideMenuAndSettingsBoxContainers, createSettingBoxTopBar
|
||||
|
||||
|
||||
from customtkinter import CTkToplevel, CTkFrame, CTkLabel, CTkFont
|
||||
|
||||
from ..ui_utils import getImagePath, getLatestWidth
|
||||
from utils import isEven
|
||||
|
||||
class ConfigWindow(CTkToplevel):
|
||||
def __init__(self, vrct_gui, settings, view_variable):
|
||||
super().__init__()
|
||||
self.withdraw()
|
||||
|
||||
self.settings = settings
|
||||
self._view_variable = view_variable
|
||||
|
||||
# configure window
|
||||
self.after(200, lambda: self.iconbitmap(getImagePath("vrct_logo_mark_black.ico")))
|
||||
self.geometry(f"{self.settings.uism.DEFAULT_WIDTH}x{self.settings.uism.DEFAULT_HEIGHT}")
|
||||
|
||||
|
||||
self.configure(fg_color=self.settings.ctm.MAIN_BG_COLOR)
|
||||
self.protocol("WM_DELETE_WINDOW", self._view_variable.CALLBACK_CLICKED_CLOSE_CONFIG_WINDOW_BUTTON)
|
||||
|
||||
|
||||
self.title(self._view_variable.VAR_CONFIG_WINDOW_TITLE.get())
|
||||
# When the configuration window's compact mode is turned on, it will call `grid_remove()` on each widget appended to this array. In the opposite case, `grid()` will be called.
|
||||
self.additional_widgets = []
|
||||
|
||||
self.sb__widgets = {}
|
||||
|
||||
createConfigWindowTitle(config_window=self, settings=self.settings, view_variable=self._view_variable)
|
||||
|
||||
createSettingBoxTopBar(config_window=self, settings=self.settings, view_variable=self._view_variable)
|
||||
|
||||
createSideMenuAndSettingsBoxContainers(config_window=self, settings=self.settings, view_variable=self._view_variable)
|
||||
|
||||
# for fixing 1px bug
|
||||
l_width = getLatestWidth(self.side_menu_bg_container)
|
||||
if isEven(l_width) is False:
|
||||
self.side_menu_bg_container.grid_columnconfigure(0, weight=0, minsize=l_width+1)
|
||||
|
||||
# for fixing 1px bug
|
||||
self.side_menu_bg_container.grid_rowconfigure(2, weight=1)
|
||||
sls__box_optionmenu_wrapper_fix_1px_bug = CTkFrame(self.side_menu_bg_container, corner_radius=0, width=0, height=0)
|
||||
sls__box_optionmenu_wrapper_fix_1px_bug.grid(row=3, column=0, sticky="sew")
|
||||
|
||||
# for fixing 1px bug
|
||||
l_width = getLatestWidth(self.side_menu_bg_container)
|
||||
|
||||
|
||||
|
||||
# VRCT Now Version Label(Tmp)
|
||||
version_label = CTkLabel(
|
||||
self.side_menu_bg_container,
|
||||
textvariable=self._view_variable.VAR_VERSION,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.NOW_VERSION_FONT_SIZE, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=self.settings.ctm.NOW_VERSION_TEXT_COLOR,
|
||||
)
|
||||
version_label.place(relx=0.05, rely=0.99, anchor="sw")
|
||||
|
||||
|
||||
self.bind_all("<Button-1>", lambda event: event.widget.focus_set(), "+")
|
||||
1
vrct_gui/config_window/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .ConfigWindow import ConfigWindow
|
||||
4
vrct_gui/config_window/widgets/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from .createConfigWindowTitle import createConfigWindowTitle
|
||||
from .createSettingBoxTopBar import createSettingBoxTopBar
|
||||
|
||||
from .createSideMenuAndSettingsBoxContainers import createSideMenuAndSettingsBoxContainers
|
||||
36
vrct_gui/config_window/widgets/createConfigWindowTitle.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from customtkinter import CTkFont, CTkFrame, CTkLabel, CTkImage
|
||||
|
||||
def createConfigWindowTitle(config_window, settings, view_variable):
|
||||
|
||||
config_window.grid_columnconfigure(0, weight=0, minsize=settings.uism.TOP_BAR_SIDE_AREA_MIN_WIDTH)
|
||||
config_window.grid_rowconfigure(0, weight=0, minsize=settings.uism.TOP_BAR__MIN_HEIGHT)
|
||||
config_window.side_menu_config_window_title_logo_frame = CTkFrame(config_window, corner_radius=0, fg_color=settings.ctm.TOP_BAR_BG_COLOR, width=0, height=0)
|
||||
config_window.side_menu_config_window_title_logo_frame.grid(row=0, column=0, sticky="nsew")
|
||||
|
||||
config_window.side_menu_config_window_title_logo_frame.grid_rowconfigure(0,weight=1)
|
||||
config_window.side_menu_config_window_title_logo_frame.grid_columnconfigure(0,weight=1)
|
||||
config_window.side_menu_config_window_title_logo_wrapper = CTkFrame(config_window.side_menu_config_window_title_logo_frame, corner_radius=0, fg_color=settings.ctm.TOP_BAR_BG_COLOR, width=0, height=0)
|
||||
config_window.side_menu_config_window_title_logo_wrapper.grid(row=0, column=0, padx=settings.uism.TOP_BAR_SIDE__TITLE_PADX, pady=settings.uism.TOP_BAR__IPADY, sticky="nsew")
|
||||
|
||||
|
||||
|
||||
|
||||
config_window.side_menu_config_window_title_logo_wrapper.grid_rowconfigure(0,weight=1)
|
||||
config_window.side_menu_config_window_title = CTkLabel(
|
||||
config_window.side_menu_config_window_title_logo_frame,
|
||||
textvariable=view_variable.VAR_CONFIG_WINDOW_TITLE,
|
||||
height=0,
|
||||
anchor="w",
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TOP_BAR_SIDE__CONFIG_TITLE_FONT_SIZE, weight="bold"),
|
||||
text_color=settings.ctm.LABELS_TEXT_COLOR,
|
||||
)
|
||||
config_window.side_menu_config_window_title.place(relx=0.255, rely=0.5, anchor="w")
|
||||
|
||||
config_window.side_menu_config_window_title_logo = CTkLabel(
|
||||
config_window.side_menu_config_window_title_logo_frame,
|
||||
text=None,
|
||||
height=0,
|
||||
anchor="w",
|
||||
image=CTkImage(settings.image_file.VRCT_LOGO_MARK, size=settings.uism.TOP_BAR_SIDE__CONFIG_LOGO_MARK_SIZE),
|
||||
)
|
||||
config_window.side_menu_config_window_title_logo.place(relx=0.08, rely=0.58, anchor="w")
|
||||
@@ -0,0 +1 @@
|
||||
from .createSettingBoxTopBar import createSettingBoxTopBar
|
||||
@@ -0,0 +1,37 @@
|
||||
from customtkinter import CTkFont, CTkFrame, CTkLabel
|
||||
from utils import callFunctionIfCallable
|
||||
from ....ui_utils import bindButtonFunctionAndColor
|
||||
|
||||
def _createRestartButton(parent_widget, config_window, settings, view_variable, column_num):
|
||||
|
||||
parent_widget.grid_columnconfigure(0, weight=1)
|
||||
config_window.restart_button_container = CTkFrame(parent_widget, corner_radius=settings.uism.RESTART_BUTTON_CORNER_RADIUS, fg_color=settings.ctm.RESTART_BUTTON_BG_COLOR, width=0, height=0, cursor="hand2")
|
||||
config_window.restart_button_container.grid(row=0, column=column_num, padx=settings.uism.RESTART_BUTTON_PADX, sticky="ew")
|
||||
|
||||
|
||||
config_window.restart_button_container.grid_rowconfigure(0, weight=1)
|
||||
config_window.restart_button_label = CTkLabel(
|
||||
config_window.restart_button_container,
|
||||
height=0,
|
||||
textvariable=view_variable.VAR_CONFIG_WINDOW_RESTART_BUTTON_LABEL,
|
||||
anchor="w",
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.RESTART_BUTTON_LABEL_FONT_SIZE, weight="normal"),
|
||||
text_color=settings.ctm.LABELS_TEXT_COLOR
|
||||
)
|
||||
config_window.restart_button_label.grid(row=0, column=0, padx=settings.uism.RESTART_BUTTON_IPADX, pady=settings.uism.RESTART_BUTTON_IPADY)
|
||||
|
||||
|
||||
|
||||
bindButtonFunctionAndColor(
|
||||
target_widgets=[
|
||||
config_window.restart_button_container,
|
||||
config_window.restart_button_label,
|
||||
],
|
||||
enter_color=settings.ctm.RESTART_BUTTON_HOVERED_BG_COLOR,
|
||||
leave_color=settings.ctm.RESTART_BUTTON_BG_COLOR,
|
||||
clicked_color=settings.ctm.RESTART_BUTTON_CLICKED_BG_COLOR,
|
||||
buttonReleasedFunction=lambda _e: callFunctionIfCallable(view_variable.CALLBACK_RESTART_SOFTWARE),
|
||||
)
|
||||
|
||||
|
||||
config_window.restart_button_container.grid_remove()
|
||||
@@ -0,0 +1,66 @@
|
||||
from customtkinter import CTkFont, CTkFrame, CTkLabel, CTkSwitch
|
||||
|
||||
def _createSettingBoxCompactModeButton(parent_widget, config_window, settings, view_variable, column_num):
|
||||
|
||||
def switchConfigWindowCompactMode():
|
||||
if config_window.setting_box_compact_mode_switch_box.get() is True:
|
||||
if callable(view_variable.CALLBACK_ENABLE_CONFIG_WINDOW_COMPACT_MODE) is True:
|
||||
view_variable.CALLBACK_ENABLE_CONFIG_WINDOW_COMPACT_MODE()
|
||||
else:
|
||||
if callable(view_variable.CALLBACK_DISABLE_CONFIG_WINDOW_COMPACT_MODE) is True:
|
||||
view_variable.CALLBACK_DISABLE_CONFIG_WINDOW_COMPACT_MODE()
|
||||
|
||||
|
||||
|
||||
config_window.setting_box_compact_mode_button_container = CTkFrame(parent_widget, corner_radius=0, fg_color=settings.ctm.TOP_BAR_BG_COLOR, width=0, height=0)
|
||||
config_window.setting_box_compact_mode_button_container.grid(row=0, column=column_num, padx=settings.uism.COMPACT_MODE_PADX, sticky="nse")
|
||||
|
||||
|
||||
|
||||
config_window.setting_box_compact_mode_button_container.grid_rowconfigure((0,2), weight=1)
|
||||
config_window.setting_box_compact_mode_button_container = CTkFrame(config_window.setting_box_compact_mode_button_container, corner_radius=0, fg_color=settings.ctm.TOP_BAR_BG_COLOR, width=0, height=0)
|
||||
config_window.setting_box_compact_mode_button_container.grid(row=1, column=0, sticky="nsew")
|
||||
|
||||
|
||||
config_window.setting_box_compact_mode_button_container.grid_rowconfigure(0, weight=1)
|
||||
config_window.setting_box_compact_mode_label = CTkLabel(
|
||||
config_window.setting_box_compact_mode_button_container,
|
||||
height=0,
|
||||
# text="Compact Mode",
|
||||
textvariable=view_variable.VAR_CONFIG_WINDOW_COMPACT_MODE_LABEL,
|
||||
anchor="w",
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.COMPACT_MODE_LABEL_FONT_SIZE, weight="normal"),
|
||||
text_color=settings.ctm.LABELS_TEXT_COLOR
|
||||
)
|
||||
config_window.setting_box_compact_mode_label.grid(row=0, column=0, padx=settings.uism.COMPACT_MODE_LABEL_PADX)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
config_window.setting_box_compact_mode_switch_frame = CTkFrame(config_window.setting_box_compact_mode_button_container, corner_radius=0, width=0, height=0, fg_color=settings.ctm.TOP_BAR_BG_COLOR)
|
||||
config_window.setting_box_compact_mode_switch_frame.grid(row=0, column=1, padx=0, sticky="e")
|
||||
|
||||
config_window.setting_box_compact_mode_switch_box = CTkSwitch(
|
||||
config_window.setting_box_compact_mode_switch_frame,
|
||||
text=None,
|
||||
height=0,
|
||||
width=0,
|
||||
# corner_radius=0,
|
||||
border_width=0,
|
||||
switch_width=settings.uism.COMPACT_MODE_SWITCH_WIDTH,
|
||||
switch_height=settings.uism.COMPACT_MODE_SWITCH_HEIGHT,
|
||||
onvalue=True,
|
||||
offvalue=False,
|
||||
command=switchConfigWindowCompactMode,
|
||||
fg_color=settings.ctm.COMPACT_MODE_SWITCH_BOX_BG_COLOR,
|
||||
# bg_color="red",
|
||||
progress_color=settings.ctm.COMPACT_MODE_SWITCH_BOX_ACTIVE_BG_COLOR,
|
||||
button_color=settings.ctm.COMPACT_MODE_SWITCH_BOX_BUTTON_COLOR,
|
||||
button_hover_color=settings.ctm.COMPACT_MODE_SWITCH_BOX_BUTTON_HOVERED_COLOR,
|
||||
)
|
||||
|
||||
config_window.setting_box_compact_mode_switch_box.grid(row=0, column=0)
|
||||
@@ -0,0 +1,24 @@
|
||||
from customtkinter import CTkFont, CTkFrame, CTkLabel
|
||||
|
||||
def _createSettingBoxTitle(parent_widget, config_window, settings, view_variable, column_num):
|
||||
|
||||
parent_widget.grid_columnconfigure(0, weight=1)
|
||||
config_window.main_current_active_config_title_container = CTkFrame(parent_widget, corner_radius=0, fg_color=settings.ctm.TOP_BAR_BG_COLOR, width=0, height=0)
|
||||
config_window.main_current_active_config_title_container.grid(row=0, column=column_num, sticky="nsew")
|
||||
|
||||
|
||||
config_window.main_current_active_config_title_container.grid_rowconfigure(0, weight=1)
|
||||
config_window.main_current_active_config_title = CTkLabel(
|
||||
config_window.main_current_active_config_title_container,
|
||||
height=0,
|
||||
textvariable=view_variable.VAR_CURRENT_ACTIVE_CONFIG_TITLE,
|
||||
anchor="w",
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TOP_BAR_MAIN__TITLE_FONT_SIZE, weight="bold"),
|
||||
text_color=settings.ctm.LABELS_TEXT_COLOR
|
||||
)
|
||||
config_window.main_current_active_config_title.grid(row=0, column=0, padx=0, pady=settings.uism.TOP_BAR__IPADY)
|
||||
|
||||
|
||||
# for fixing 1px bug
|
||||
sls__box_optionmenu_wrapper_fix_1px_bug = CTkFrame(config_window.main_current_active_config_title, corner_radius=0, width=0, height=0)
|
||||
sls__box_optionmenu_wrapper_fix_1px_bug.grid(row=0, column=column_num, sticky="ns")
|
||||
@@ -0,0 +1,40 @@
|
||||
from customtkinter import CTkFrame
|
||||
|
||||
from ._createSettingBoxTitle import _createSettingBoxTitle
|
||||
from ._createRestartButton import _createRestartButton
|
||||
from ._createSettingBoxCompactModeButton import _createSettingBoxCompactModeButton
|
||||
|
||||
from ....ui_utils import getLatestHeight
|
||||
from utils import isEven
|
||||
|
||||
def createSettingBoxTopBar(config_window, settings, view_variable):
|
||||
|
||||
config_window.grid_columnconfigure(1, weight=1)
|
||||
config_window.setting_box_top_bar = CTkFrame(config_window, corner_radius=0, fg_color=settings.ctm.TOP_BAR_BG_COLOR, width=0, height=0)
|
||||
config_window.setting_box_top_bar.grid(row=0, column=1, sticky="nsew")
|
||||
|
||||
|
||||
config_window.setting_box_top_bar.grid_rowconfigure(0, weight=1)
|
||||
|
||||
column_num=0
|
||||
_createSettingBoxTitle(parent_widget=config_window.setting_box_top_bar, config_window=config_window, settings=settings, view_variable=view_variable, column_num=column_num)
|
||||
column_num+=1
|
||||
|
||||
config_window.setting_box_top_bar.grid_columnconfigure(column_num, weight=1)
|
||||
column_num+=1
|
||||
|
||||
# Restart Button(Tmp)
|
||||
_createRestartButton(parent_widget=config_window.setting_box_top_bar, config_window=config_window, settings=settings, view_variable=view_variable, column_num=column_num)
|
||||
column_num+=1
|
||||
|
||||
_createSettingBoxCompactModeButton(parent_widget=config_window.setting_box_top_bar, config_window=config_window, settings=settings, view_variable=view_variable, column_num=column_num)
|
||||
column_num+=1
|
||||
|
||||
|
||||
l_height = getLatestHeight(config_window.side_menu_config_window_title_logo_frame)
|
||||
if isEven(l_height) is False:
|
||||
config_window.grid_rowconfigure(0, weight=0, minsize=l_height+1)
|
||||
|
||||
# for fixing 1px bug
|
||||
setting_box_top_bar_fix_1px_bug = CTkFrame(config_window.setting_box_top_bar, corner_radius=0, width=0, height=0)
|
||||
setting_box_top_bar_fix_1px_bug.grid(row=0, column=column_num, sticky="nse")
|
||||
@@ -0,0 +1 @@
|
||||
from .createSideMenuAndSettingsBoxContainers import createSideMenuAndSettingsBoxContainers
|
||||
@@ -0,0 +1,107 @@
|
||||
from customtkinter import CTkFont, CTkFrame, CTkLabel
|
||||
|
||||
from ....ui_utils import bindEnterAndLeaveColor, bindButtonPressColor, bindButtonReleaseFunction, switchActiveTabAndPassiveTab, switchTabsColor
|
||||
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
|
||||
def _addConfigSideMenuItem(config_window, settings, view_variable, side_menu_settings, side_menu_row, all_side_menu_tab_attr_name):
|
||||
|
||||
|
||||
def switchActiveAndPassiveSettingBoxContainerTabsColor(target_active_widget):
|
||||
|
||||
setting_box_container_tabs = []
|
||||
for tab_attr_name in all_side_menu_tab_attr_name:
|
||||
tab_attr = getattr(config_window, tab_attr_name)
|
||||
setting_box_container_tabs.append(tab_attr)
|
||||
|
||||
switchTabsColor(
|
||||
target_widget=target_active_widget,
|
||||
tab_buttons=setting_box_container_tabs,
|
||||
active_bg_color=settings.ctm.SIDE_MENU_LABELS_BG_COLOR,
|
||||
active_text_color=settings.ctm.SIDE_MENU_LABELS_SELECTED_TEXT_COLOR,
|
||||
passive_bg_color=settings.ctm.SIDE_MENU_LABELS_BG_COLOR,
|
||||
passive_text_color=settings.ctm.LABELS_TEXT_COLOR
|
||||
)
|
||||
|
||||
for setting_box_container_tab in setting_box_container_tabs:
|
||||
setting_box_container_tab.children["!ctkframe"].place(relx=-1)
|
||||
|
||||
target_active_widget.children["!ctkframe"].place(relx=0)
|
||||
|
||||
|
||||
|
||||
|
||||
def switchSettingBoxContainerTabFunction(target_active_widget):
|
||||
switchActiveAndPassiveSettingBoxContainerTabsColor(target_active_widget)
|
||||
switchActiveTabAndPassiveTab(target_active_widget, config_window.current_active_side_menu_tab, config_window.current_active_side_menu_tab.passive_function, settings.ctm.SIDE_MENU_LABELS_HOVERED_BG_COLOR, settings.ctm.SIDE_MENU_LABELS_CLICKED_BG_COLOR, settings.ctm.SIDE_MENU_LABELS_BG_COLOR)
|
||||
config_window.current_active_side_menu_tab = target_active_widget
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def switchSettingBoxContainer(target_setting_box_container_attr_name):
|
||||
config_window.current_active_setting_box_container.grid_remove()
|
||||
config_window.current_active_setting_box_container = getattr(config_window, target_setting_box_container_attr_name)
|
||||
config_window.current_active_setting_box_container.grid()
|
||||
|
||||
# Move to the top position when the setting box is switched.
|
||||
config_window.main_setting_box_scrollable_container._parent_canvas.yview_moveto("0")
|
||||
|
||||
|
||||
def switchToTargetSettingBoxContainer(textvariable, target_active_tab_widget_attr_name, target_setting_box_container_attr_name):
|
||||
view_variable.VAR_CURRENT_ACTIVE_CONFIG_TITLE.set(textvariable.get())
|
||||
target_active_tab_widget = getattr(config_window, target_active_tab_widget_attr_name)
|
||||
switchSettingBoxContainerTabFunction(target_active_tab_widget)
|
||||
switchSettingBoxContainer(target_setting_box_container_attr_name)
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SELECTED_SETTING_BOX_TAB, target_active_tab_widget_attr_name)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
side_menu_tab_attr_name = side_menu_settings["side_menu_tab_attr_name"]
|
||||
label_attr_name = side_menu_settings["label_attr_name"]
|
||||
selected_mark_attr_name = side_menu_settings["selected_mark_attr_name"]
|
||||
textvariable = side_menu_settings["textvariable"]
|
||||
setting_box_container_attr_name = side_menu_settings["setting_box_container_settings"]["setting_box_container_attr_name"]
|
||||
command = lambda _e: switchToTargetSettingBoxContainer(
|
||||
textvariable=textvariable,
|
||||
target_active_tab_widget_attr_name=side_menu_tab_attr_name,
|
||||
target_setting_box_container_attr_name=setting_box_container_attr_name,
|
||||
)
|
||||
|
||||
|
||||
# Side menu
|
||||
frame_widget = CTkFrame(config_window.side_menu_container, corner_radius=0, fg_color=settings.ctm.SIDE_MENU_LABELS_BG_COLOR, cursor="hand2", width=0, height=0)
|
||||
setattr(config_window, side_menu_tab_attr_name, frame_widget)
|
||||
|
||||
frame_widget.grid(row=side_menu_row, column=0, pady=(0,1), sticky="ew")
|
||||
frame_widget.grid_columnconfigure(0, weight=1)
|
||||
|
||||
label_widget = CTkLabel(
|
||||
frame_widget,
|
||||
textvariable=textvariable,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SIDE_MENU_LABELS_FONT_SIZE, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=settings.ctm.LABELS_TEXT_COLOR,
|
||||
)
|
||||
setattr(config_window, label_attr_name, label_widget)
|
||||
|
||||
selected_mark_widget = CTkFrame(frame_widget, corner_radius=0, fg_color=settings.ctm.SIDE_MENU_SELECTED_MARK_ACTIVE_BG_COLOR, width=3, height=0)
|
||||
setattr(config_window, selected_mark_attr_name, selected_mark_widget)
|
||||
|
||||
|
||||
# Arrange
|
||||
selected_mark_widget.place(relx=-1, rely=0.5, relheight=1, anchor="w")
|
||||
label_widget.grid(row=0, column=0, padx=settings.uism.SIDE_MENU_LABELS_IPADX, pady=settings.uism.SIDE_MENU_LABELS_IPADY, sticky="ew")
|
||||
|
||||
bindEnterAndLeaveColor([frame_widget, label_widget], settings.ctm.SIDE_MENU_LABELS_HOVERED_BG_COLOR, settings.ctm.SIDE_MENU_LABELS_BG_COLOR)
|
||||
bindButtonPressColor([frame_widget, label_widget], settings.ctm.SIDE_MENU_LABELS_CLICKED_BG_COLOR, settings.ctm.SIDE_MENU_LABELS_BG_COLOR)
|
||||
|
||||
frame_widget.passive_function = command
|
||||
bindButtonReleaseFunction([frame_widget, label_widget], command)
|
||||
@@ -0,0 +1,63 @@
|
||||
from customtkinter import CTkFont, CTkFrame, CTkLabel
|
||||
|
||||
|
||||
def _createSettingBoxContainer(config_window, settings, view_variable, setting_box_container_settings):
|
||||
|
||||
|
||||
def createSectionTitle(container_widget, var_section_title):
|
||||
|
||||
setting_box_wrapper_section_title = CTkLabel(
|
||||
container_widget,
|
||||
textvariable=var_section_title,
|
||||
anchor="w",
|
||||
height=0,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SB__SECTION_TITLE_FONT_SIZE, weight="normal"),
|
||||
text_color=settings.ctm.LABELS_TEXT_COLOR
|
||||
)
|
||||
setting_box_wrapper_section_title.place(relx=0, rely=0)
|
||||
|
||||
return container_widget
|
||||
|
||||
|
||||
# Setting box container
|
||||
setting_box_container_widget = CTkFrame(config_window.main_setting_box_bg_wrapper, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0)
|
||||
setattr(config_window, setting_box_container_settings["setting_box_container_attr_name"], setting_box_container_widget)
|
||||
setting_box_container_widget.grid(row=0, pady=settings.uism.SB__BOTTOM_MARGIN)
|
||||
setting_box_container_widget.grid_remove()
|
||||
|
||||
|
||||
|
||||
setting_box_row=0
|
||||
for setting_box_setting in setting_box_container_settings["setting_boxes"]:
|
||||
# Top-Padding that can be container the section title
|
||||
setting_box_top_padding = CTkFrame(setting_box_container_widget, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=settings.uism.SB__TOP_PADY)
|
||||
setting_box_top_padding.grid(row=setting_box_row, column=0, sticky="ew", padx=0, pady=0)
|
||||
setting_box_top_padding.grid_columnconfigure(0, weight=1)
|
||||
setting_box_row+=1
|
||||
|
||||
if setting_box_setting["var_section_title"] is not None:
|
||||
setting_box_wrapper_section_title = CTkLabel(
|
||||
setting_box_top_padding,
|
||||
textvariable=setting_box_setting["var_section_title"],
|
||||
anchor="w",
|
||||
height=0,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SB__SECTION_TITLE_FONT_SIZE, weight="normal"),
|
||||
text_color=settings.ctm.LABELS_TEXT_COLOR
|
||||
)
|
||||
setting_box_wrapper_section_title.place(relx=0, rely=0.4, anchor="nw")
|
||||
|
||||
|
||||
setting_box_wrapper = CTkFrame(setting_box_container_widget, fg_color=settings.ctm.SB__WRAPPER_BG_COLOR, corner_radius=0, width=0, height=0)
|
||||
setting_box_wrapper.grid(row=setting_box_row, column=0, sticky="ew")
|
||||
setting_box_wrapper.grid_columnconfigure(0, weight=1)
|
||||
setting_box_row+=1
|
||||
|
||||
|
||||
if setting_box_setting["setting_box"] is not None:
|
||||
setting_box_setting["setting_box"](
|
||||
setting_box_wrapper=setting_box_wrapper,
|
||||
config_window=config_window,
|
||||
settings=settings,
|
||||
view_variable=view_variable,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
from customtkinter import CTkFrame, CTkScrollableFrame
|
||||
|
||||
from ....ui_utils import setDefaultActiveTab, applyUiScalingAndFixTheBugScrollBar
|
||||
|
||||
from ._addConfigSideMenuItem import _addConfigSideMenuItem
|
||||
from ._createSettingBoxContainer import _createSettingBoxContainer
|
||||
|
||||
|
||||
from .setting_box_containers.setting_box_appearance import createSettingBox_Appearance
|
||||
from .setting_box_containers.setting_box_transcription import createSettingBox_Mic, createSettingBox_Speaker
|
||||
from .setting_box_containers.setting_box_others import createSettingBox_Others
|
||||
from .setting_box_containers.setting_box_advanced_settings import createSettingBox_AdvancedSettings
|
||||
from .setting_box_containers.setting_box_translation import createSettingBox_Translation
|
||||
|
||||
|
||||
def createSideMenuAndSettingsBoxContainers(config_window, settings, view_variable):
|
||||
|
||||
# Main container
|
||||
config_window.main_bg_container = CTkFrame(config_window, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0)
|
||||
config_window.main_bg_container.grid(row=1, column=1, sticky="nsew")
|
||||
|
||||
config_window.main_bg_container.grid_columnconfigure(0, weight=1)
|
||||
config_window.main_bg_container.grid_rowconfigure(0, weight=0)
|
||||
|
||||
|
||||
|
||||
|
||||
# Side menu Base
|
||||
config_window.grid_rowconfigure(1, weight=1)
|
||||
config_window.side_menu_bg_container = CTkFrame(config_window, corner_radius=0, fg_color=settings.ctm.SIDE_MENU_BG_COLOR, width=0, height=0)
|
||||
config_window.side_menu_bg_container.grid(row=1, column=0, sticky="nsew")
|
||||
config_window.side_menu_bg_container.grid_columnconfigure(0, weight=1)
|
||||
|
||||
config_window.side_menu_container = CTkFrame(config_window.side_menu_bg_container, corner_radius=0, fg_color=settings.ctm.SIDE_MENU_LABELS_BG_FOR_FAKE_BORDER_COLOR, width=0, height=0)
|
||||
config_window.side_menu_container.grid(row=0, column=0, padx=settings.uism.TOP_BAR_SIDE__TITLE_PADX, pady=(settings.uism.SIDE_MENU_TOP_PADY, 0), sticky="nsew")
|
||||
|
||||
|
||||
|
||||
# Setting box container
|
||||
config_window.main_bg_container.grid_rowconfigure(1, weight=1)
|
||||
config_window.main_setting_box_scrollable_container = CTkScrollableFrame(config_window.main_bg_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR)
|
||||
config_window.main_setting_box_scrollable_container.grid(row=1, column=0, sticky="nsew")
|
||||
|
||||
applyUiScalingAndFixTheBugScrollBar(
|
||||
scrollbar_widget=config_window.main_setting_box_scrollable_container,
|
||||
padx=settings.uism.SCROLLBAR_IPADX,
|
||||
width=settings.uism.SCROLLBAR_WIDTH,
|
||||
)
|
||||
|
||||
|
||||
config_window.main_setting_box_bg_wrapper = CTkFrame(config_window.main_setting_box_scrollable_container, corner_radius=0, width=0, height=0, fg_color=settings.ctm.MAIN_BG_COLOR)
|
||||
config_window.main_setting_box_bg_wrapper.grid(row=0, column=0, pady=settings.uism.SB__BOTTOM_MARGIN, sticky="n")
|
||||
|
||||
|
||||
|
||||
side_menu_and_setting_box_containers_settings = [
|
||||
{
|
||||
"side_menu_tab_attr_name": "side_menu_tab_appearance",
|
||||
"label_attr_name": "label_appearance",
|
||||
"selected_mark_attr_name": "selected_mark_appearance",
|
||||
"textvariable": view_variable.VAR_SIDE_MENU_LABEL_APPEARANCE,
|
||||
"setting_box_container_settings": {
|
||||
"setting_box_container_attr_name": "setting_box_container_appearance",
|
||||
"setting_boxes": [
|
||||
{ "var_section_title": None, "setting_box": createSettingBox_Appearance },
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"side_menu_tab_attr_name": "side_menu_tab_translation",
|
||||
"label_attr_name": "label_translation",
|
||||
"selected_mark_attr_name": "selected_mark_translation",
|
||||
"textvariable": view_variable.VAR_SIDE_MENU_LABEL_TRANSLATION,
|
||||
"setting_box_container_settings": {
|
||||
"setting_box_container_attr_name": "setting_box_container_translation",
|
||||
"setting_boxes": [
|
||||
{ "var_section_title": None, "setting_box": createSettingBox_Translation },
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"side_menu_tab_attr_name": "side_menu_tab_transcription",
|
||||
"label_attr_name": "label_transcription",
|
||||
"selected_mark_attr_name": "selected_mark_transcription",
|
||||
"textvariable": view_variable.VAR_SIDE_MENU_LABEL_TRANSCRIPTION,
|
||||
"setting_box_container_settings": {
|
||||
"setting_box_container_attr_name": "setting_box_container_transcription",
|
||||
"setting_boxes": [
|
||||
{
|
||||
"var_section_title": view_variable.VAR_SECOND_TITLE_TRANSCRIPTION_MIC,
|
||||
"setting_box": createSettingBox_Mic
|
||||
},
|
||||
{
|
||||
"var_section_title": view_variable.VAR_SECOND_TITLE_TRANSCRIPTION_SPEAKER,
|
||||
"setting_box": createSettingBox_Speaker
|
||||
},
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"side_menu_tab_attr_name": "side_menu_tab_others",
|
||||
"label_attr_name": "label_others",
|
||||
"selected_mark_attr_name": "selected_mark_others",
|
||||
"textvariable": view_variable.VAR_SIDE_MENU_LABEL_OTHERS,
|
||||
"setting_box_container_settings": {
|
||||
"setting_box_container_attr_name": "setting_box_container_others",
|
||||
"setting_boxes": [
|
||||
{ "var_section_title": None, "setting_box": createSettingBox_Others },
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
"side_menu_tab_attr_name": "side_menu_tab_advanced",
|
||||
"label_attr_name": "label_advanced",
|
||||
"selected_mark_attr_name": "selected_mark_advanced",
|
||||
"textvariable": view_variable.VAR_SIDE_MENU_LABEL_ADVANCED_SETTINGS,
|
||||
"setting_box_container_settings": {
|
||||
"setting_box_container_attr_name": "setting_box_container_advanced",
|
||||
"setting_boxes": [
|
||||
{ "var_section_title": None, "setting_box": createSettingBox_AdvancedSettings },
|
||||
]
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
all_side_menu_tab_attr_name = [item["side_menu_tab_attr_name"] for item in side_menu_and_setting_box_containers_settings]
|
||||
|
||||
side_menu_row=0
|
||||
for sm_and_sbc_setting in side_menu_and_setting_box_containers_settings:
|
||||
_addConfigSideMenuItem(
|
||||
config_window=config_window,
|
||||
settings=settings,
|
||||
view_variable=view_variable,
|
||||
# view_variable=view_variable,
|
||||
side_menu_settings=sm_and_sbc_setting,
|
||||
side_menu_row=side_menu_row,
|
||||
all_side_menu_tab_attr_name=all_side_menu_tab_attr_name,
|
||||
)
|
||||
side_menu_row+=1
|
||||
|
||||
|
||||
_createSettingBoxContainer(
|
||||
config_window=config_window,
|
||||
settings=settings,
|
||||
view_variable=view_variable,
|
||||
setting_box_container_settings=sm_and_sbc_setting["setting_box_container_settings"],
|
||||
|
||||
)
|
||||
|
||||
|
||||
if sm_and_sbc_setting["side_menu_tab_attr_name"] == view_variable.ACTIVE_SETTING_BOX_TAB_ATTR_NAME:
|
||||
# Set default active side menu tab
|
||||
view_variable.VAR_CURRENT_ACTIVE_CONFIG_TITLE.set(sm_and_sbc_setting["textvariable"].get())
|
||||
config_window.current_active_side_menu_tab = getattr(config_window, sm_and_sbc_setting["side_menu_tab_attr_name"])
|
||||
setDefaultActiveTab(
|
||||
active_tab_widget=config_window.current_active_side_menu_tab,
|
||||
active_bg_color=settings.ctm.SIDE_MENU_LABELS_BG_COLOR,
|
||||
active_text_color=settings.ctm.SIDE_MENU_LABELS_SELECTED_TEXT_COLOR
|
||||
)
|
||||
config_window.current_active_side_menu_tab.children["!ctkframe"].place(relx=0)
|
||||
|
||||
# Set default active setting box container
|
||||
config_window.current_active_setting_box_container = getattr(config_window, sm_and_sbc_setting["setting_box_container_settings"]["setting_box_container_attr_name"])
|
||||
config_window.current_active_setting_box_container.grid()
|
||||
@@ -0,0 +1,570 @@
|
||||
from functools import partial
|
||||
from types import SimpleNamespace
|
||||
from typing import Union
|
||||
|
||||
from customtkinter import CTkOptionMenu, CTkFont, CTkFrame, CTkLabel, CTkRadioButton, CTkEntry, CTkSlider, CTkSwitch, CTkCheckBox, CTkProgressBar
|
||||
|
||||
from vrct_gui.ui_utils import createButtonWithImage, getLatestWidth, createOptionMenuBox
|
||||
from vrct_gui import vrct_gui
|
||||
|
||||
SETTING_BOX_COLUMN = 1
|
||||
|
||||
class _SettingBoxGenerator():
|
||||
def __init__(self, parent_widget, config_window, settings, view_variable):
|
||||
self.view_variable = view_variable
|
||||
self.config_window = config_window
|
||||
self.parent_widget = parent_widget
|
||||
self.settings = settings
|
||||
|
||||
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):
|
||||
self.config_window.sb__widgets[sb__attr_name] = SimpleNamespace()
|
||||
|
||||
setting_box_frame = CTkFrame(self.parent_widget, corner_radius=0, fg_color=self.settings.ctm.SB__BG_COLOR, width=0, height=0)
|
||||
|
||||
# "pady=(0,1)" is for bottom padding. It can be removed(override) when you do like "self.attr_name.grid(row=row, pady=0)"
|
||||
setting_box_frame.grid(column=0, padx=0, pady=self.settings.uism.SB__FAKE_BOTTOM_BORDER_SIZE, sticky="ew")
|
||||
setting_box_frame.grid_columnconfigure(0, weight=1)
|
||||
|
||||
|
||||
setting_box_frame_wrapper = CTkFrame(setting_box_frame, corner_radius=0, fg_color=self.settings.ctm.SB__BG_COLOR, width=0, height=0)
|
||||
setting_box_frame_wrapper.grid(row=0, column=0, padx=self.settings.uism.SB__IPADX, pady=self.settings.uism.SB__IPADY, sticky="ew")
|
||||
setting_box_frame_wrapper.grid_columnconfigure(0, weight=0, minsize=int(self.settings.uism.MAIN_AREA_MIN_WIDTH / 2))
|
||||
setting_box_frame_wrapper.grid_columnconfigure(2, weight=1, minsize=int(self.settings.uism.MAIN_AREA_MIN_WIDTH / 2))
|
||||
|
||||
setting_box_frame_wrapper_fix_border = CTkFrame(setting_box_frame, corner_radius=0, width=0, height=0)
|
||||
setting_box_frame_wrapper_fix_border.grid(row=1, column=0, sticky="ew")
|
||||
|
||||
setting_box_frame_wrapper_fix_border2 = CTkFrame(setting_box_frame, corner_radius=0, width=0, height=0)
|
||||
setting_box_frame_wrapper_fix_border2.grid(row=0, column=1, sticky="ns")
|
||||
|
||||
if for_var_label_text is not None:
|
||||
self._setSettingBoxLabels(sb__attr_name, setting_box_frame_wrapper, for_var_label_text, for_var_desc_text)
|
||||
|
||||
# setting_box_item_frame = CTkFrame(setting_box_frame_wrapper, corner_radius=0, width=0, height=0, fg_color="red")
|
||||
setting_box_item_frame = CTkFrame(setting_box_frame_wrapper, corner_radius=0, width=0, height=0, fg_color=self.settings.ctm.SB__BG_COLOR)
|
||||
if for_var_label_text is not None:
|
||||
setting_box_item_frame.grid(row=0, column=2, padx=0, sticky="nsew")
|
||||
else:
|
||||
setting_box_item_frame.grid(row=0, columnspan=3, padx=0, sticky="nsew")
|
||||
setting_box_item_frame.grid_rowconfigure((0,2), weight=1)
|
||||
setting_box_item_frame.grid_columnconfigure(0, weight=1)
|
||||
|
||||
return (setting_box_frame, setting_box_item_frame)
|
||||
|
||||
def _setSettingBoxLabels(self, sb__attr_name, setting_box_frame_wrapper, for_var_label_text, for_var_desc_text=None):
|
||||
|
||||
setting_box_labels_frame = CTkFrame(setting_box_frame_wrapper, corner_radius=0, fg_color=self.settings.ctm.SB__BG_COLOR, width=0, height=0)
|
||||
setting_box_labels_frame.grid(row=0, column=0, padx=0, pady=0, sticky="nsew")
|
||||
|
||||
setting_box_labels_frame.grid_rowconfigure((0,3), weight=1)
|
||||
setting_box_label = CTkLabel(
|
||||
setting_box_labels_frame,
|
||||
textvariable=for_var_label_text,
|
||||
anchor="w",
|
||||
height=0,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__LABEL_FONT_SIZE, weight="normal"),
|
||||
text_color=self.settings.ctm.LABELS_TEXT_COLOR
|
||||
)
|
||||
setting_box_label.grid(row=1, column=0, padx=0, pady=0, sticky="ew")
|
||||
self.config_window.sb__widgets[sb__attr_name].label_widget = setting_box_label
|
||||
|
||||
|
||||
if for_var_desc_text is not None:
|
||||
setting_box_desc = CTkLabel(
|
||||
setting_box_labels_frame,
|
||||
textvariable=for_var_desc_text,
|
||||
anchor="w",
|
||||
justify="left",
|
||||
height=0,
|
||||
wraplength=int(self.settings.uism.MAIN_AREA_MIN_WIDTH / 2),
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__DESC_FONT_SIZE, weight="normal"),
|
||||
text_color=self.settings.ctm.LABELS_DESC_TEXT_COLOR
|
||||
)
|
||||
setting_box_desc.grid(row=2, column=0, padx=0, pady=(self.settings.uism.SB__DESC_TOP_PADY,0), sticky="ew")
|
||||
self.config_window.additional_widgets.append(setting_box_desc)
|
||||
self.config_window.sb__widgets[sb__attr_name].desc_widget=setting_box_desc
|
||||
else:
|
||||
self.config_window.sb__widgets[sb__attr_name].desc_widget=None
|
||||
|
||||
|
||||
|
||||
|
||||
def createSettingBoxDropdownMenu(
|
||||
self,
|
||||
for_var_label_text, for_var_desc_text,
|
||||
optionmenu_attr_name,
|
||||
command,
|
||||
dropdown_menu_min_width=None,
|
||||
dropdown_menu_values=None,
|
||||
variable=None,
|
||||
):
|
||||
|
||||
(setting_box_frame, setting_box_item_frame) = self._createSettingBoxFrame(optionmenu_attr_name, for_var_label_text, for_var_desc_text)
|
||||
|
||||
def adjustedCommand(value):
|
||||
variable.set(value)
|
||||
command(value)
|
||||
|
||||
|
||||
(option_menu_widget, optionmenu_label_widget, optionmenu_img_widget) = createOptionMenuBox(
|
||||
parent_widget=setting_box_item_frame,
|
||||
optionmenu_bg_color=self.settings.ctm.SB__OPTIONMENU_BG_COLOR,
|
||||
optionmenu_hovered_bg_color=self.settings.ctm.SB__OPTIONMENU_HOVERED_BG_COLOR,
|
||||
optionmenu_clicked_bg_color=self.settings.ctm.SB__OPTIONMENU_CLICKED_BG_COLOR,
|
||||
optionmenu_ipadx=self.settings.uism.SB__OPTIONMENU_IPADX,
|
||||
optionmenu_ipady=self.settings.uism.SB__OPTIONMENU_IPADY,
|
||||
optionmenu_padx_between_img=self.settings.uism.SB__OPTIONMENU_IPADX_BETWEEN_IMG,
|
||||
optionmenu_min_height=self.settings.uism.SB__OPTIONMENU_MIN_HEIGHT,
|
||||
optionmenu_min_width=self.settings.uism.SB__OPTIONMENU_MIN_WIDTH,
|
||||
variable=variable,
|
||||
font_family=self.settings.FONT_FAMILY,
|
||||
font_size=self.settings.uism.SB__OPTION_MENU_FONT_SIZE,
|
||||
text_color=self.settings.ctm.LABELS_TEXT_COLOR,
|
||||
image_file=self.settings.image_file.ARROW_LEFT.rotate(90),
|
||||
image_size=self.settings.uism.SB__OPTIONMENU_IMG_SIZE,
|
||||
optionmenu_clicked_command=lambda _e: self.dropdown_menu_window.show(
|
||||
dropdown_menu_widget_id=optionmenu_attr_name,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
self.config_window.sb__widgets[optionmenu_attr_name].optionmenu_box = option_menu_widget
|
||||
self.config_window.sb__widgets[optionmenu_attr_name].optionmenu_label_widget = optionmenu_label_widget
|
||||
self.config_window.sb__widgets[optionmenu_attr_name].optionmenu_img_widget = optionmenu_img_widget
|
||||
|
||||
|
||||
option_menu_widget.grid(row=1, column=SETTING_BOX_COLUMN, sticky="e")
|
||||
setattr(self.config_window, optionmenu_attr_name, option_menu_widget)
|
||||
|
||||
self.dropdown_menu_window.createDropdownMenuBox(
|
||||
dropdown_menu_widget_id=optionmenu_attr_name,
|
||||
dropdown_menu_values=dropdown_menu_values,
|
||||
command=adjustedCommand,
|
||||
wrapper_widget=self.config_window.main_bg_container,
|
||||
attach_widget=option_menu_widget,
|
||||
dropdown_menu_min_width=dropdown_menu_min_width,
|
||||
)
|
||||
|
||||
return setting_box_frame
|
||||
|
||||
|
||||
|
||||
|
||||
def createSettingBoxSwitch(self,
|
||||
for_var_label_text, for_var_desc_text,
|
||||
switch_attr_name,
|
||||
variable,
|
||||
command,
|
||||
):
|
||||
|
||||
(setting_box_frame, setting_box_item_frame) = self._createSettingBoxFrame(switch_attr_name, for_var_label_text, for_var_desc_text)
|
||||
|
||||
switch_widget = CTkSwitch(
|
||||
setting_box_item_frame,
|
||||
text=None,
|
||||
height=0,
|
||||
width=0,
|
||||
corner_radius=int(self.settings.uism.SB__SWITCH_BOX_HEIGHT/2),
|
||||
border_width=0,
|
||||
switch_height=self.settings.uism.SB__SWITCH_BOX_HEIGHT,
|
||||
switch_width=self.settings.uism.SB__SWITCH_BOX_WIDTH,
|
||||
onvalue=True,
|
||||
offvalue=False,
|
||||
variable=variable,
|
||||
command=command,
|
||||
fg_color=self.settings.ctm.SB__SWITCH_BOX_BG_COLOR,
|
||||
# bg_color="red",
|
||||
progress_color=self.settings.ctm.SB__SWITCH_BOX_ACTIVE_BG_COLOR,
|
||||
button_color=self.settings.ctm.SB__SWITCH_BOX_BUTTON_COLOR,
|
||||
button_hover_color=self.settings.ctm.SB__SWITCH_BOX_BUTTON_HOVERED_COLOR,
|
||||
)
|
||||
setattr(self.config_window, switch_attr_name, switch_widget)
|
||||
|
||||
switch_widget.grid(row=1, column=SETTING_BOX_COLUMN, sticky="e")
|
||||
|
||||
return setting_box_frame
|
||||
|
||||
|
||||
|
||||
def createSettingBoxCheckbox(self,
|
||||
for_var_label_text, for_var_desc_text,
|
||||
checkbox_attr_name,
|
||||
command,
|
||||
variable,
|
||||
):
|
||||
|
||||
(setting_box_frame, setting_box_item_frame) = self._createSettingBoxFrame(checkbox_attr_name, for_var_label_text, for_var_desc_text)
|
||||
|
||||
checkbox_widget = CTkCheckBox(
|
||||
setting_box_item_frame,
|
||||
text=None,
|
||||
width=0,
|
||||
checkbox_width=self.settings.uism.SB__CHECKBOX_SIZE,
|
||||
checkbox_height=self.settings.uism.SB__CHECKBOX_SIZE,
|
||||
onvalue=True,
|
||||
offvalue=False,
|
||||
variable=variable,
|
||||
command=command,
|
||||
corner_radius=self.settings.uism.SB__CHECKBOX_CORNER_RADIUS,
|
||||
border_width=self.settings.uism.SB__CHECKBOX_BORDER_WIDTH,
|
||||
border_color=self.settings.ctm.SB__CHECKBOX_BORDER_COLOR,
|
||||
hover_color=self.settings.ctm.SB__CHECKBOX_HOVER_COLOR,
|
||||
checkmark_color=self.settings.ctm.SB__CHECKBOX_CHECKMARK_COLOR,
|
||||
fg_color=self.settings.ctm.SB__CHECKBOX_CHECKED_COLOR,
|
||||
# fg_color=self.settings.ctm.SB__SWITCH_BOX_BG_COLOR,
|
||||
# bg_color="red",
|
||||
# progress_color=self.settings.ctm.SB__SWITCH_BOX_ACTIVE_BG_COLOR,
|
||||
)
|
||||
setattr(self.config_window, checkbox_attr_name, checkbox_widget)
|
||||
|
||||
checkbox_widget.grid(row=1, column=SETTING_BOX_COLUMN, sticky="e")
|
||||
|
||||
return setting_box_frame
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def createSettingBoxSlider(
|
||||
self,
|
||||
for_var_label_text, for_var_desc_text,
|
||||
slider_attr_name,
|
||||
slider_range,
|
||||
command,
|
||||
variable,
|
||||
slider_number_of_steps: Union[int,
|
||||
None] = None,
|
||||
slider_bind__ButtonPress=None,
|
||||
slider_bind__ButtonRelease=None
|
||||
):
|
||||
|
||||
(setting_box_frame, setting_box_item_frame) = self._createSettingBoxFrame(slider_attr_name, for_var_label_text, for_var_desc_text)
|
||||
|
||||
|
||||
slider_widget = CTkSlider(
|
||||
setting_box_item_frame,
|
||||
width=self.settings.uism.SB__SLIDER_WIDTH,
|
||||
height=self.settings.uism.SB__SLIDER_HEIGHT,
|
||||
from_=slider_range[0],
|
||||
to=slider_range[1],
|
||||
number_of_steps=slider_number_of_steps,
|
||||
fg_color=self.settings.ctm.SB__SLIDER_BG_COLOR,
|
||||
progress_color=self.settings.ctm.SB__SLIDER_PROGRESS_BG_COLOR,
|
||||
button_color=self.settings.ctm.SB__SLIDER_BUTTON_COLOR,
|
||||
button_hover_color=self.settings.ctm.SB__SLIDER_BUTTON_HOVERED_COLOR,
|
||||
command=command,
|
||||
variable=variable,
|
||||
)
|
||||
setattr(self.config_window, slider_attr_name, slider_widget)
|
||||
|
||||
slider_widget.grid(row=1, column=SETTING_BOX_COLUMN, sticky="e")
|
||||
|
||||
if slider_bind__ButtonPress is not None:
|
||||
def adjusted_slider_bind__ButtonPress(_e):
|
||||
command(_e)
|
||||
slider_bind__ButtonPress()
|
||||
slider_widget.configure(command=adjusted_slider_bind__ButtonPress)
|
||||
|
||||
if slider_bind__ButtonRelease is not None:
|
||||
def adjusted_slider_bind__ButtonRelease(_e):
|
||||
slider_bind__ButtonRelease()
|
||||
slider_widget.bind("<ButtonRelease>", adjusted_slider_bind__ButtonRelease, "+")
|
||||
|
||||
return setting_box_frame
|
||||
|
||||
|
||||
|
||||
|
||||
def createSettingBoxProgressbarXSlider(
|
||||
self,
|
||||
command, progressbar_x_slider_attr_name,
|
||||
entry_attr_name, entry_bind__FocusOut,
|
||||
slider_attr_name, slider_range,
|
||||
progressbar_attr_name,
|
||||
passive_button_attr_name, passive_button_command,
|
||||
active_button_attr_name, active_button_command,
|
||||
disabled_button_attr_name, disabled_button_image_file,
|
||||
button_image_file,
|
||||
|
||||
entry_variable,
|
||||
slider_variable,
|
||||
|
||||
slider_number_of_steps: Union[int, None] = None,
|
||||
):
|
||||
|
||||
(setting_box_frame, setting_box_item_frame) = self._createSettingBoxFrame(progressbar_x_slider_attr_name)
|
||||
|
||||
def adjusted_command__for_entry_bind__Any_KeyRelease(e):
|
||||
command(e.widget.get())
|
||||
def adjusted_command__for_slider(value):
|
||||
command(value)
|
||||
|
||||
setting_box_item_frame.grid_columnconfigure((0,2), weight=0)
|
||||
setting_box_item_frame.grid_columnconfigure(1, weight=1)
|
||||
entry_widget = CTkEntry(
|
||||
setting_box_item_frame,
|
||||
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=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__ENTRY_WIDTH,
|
||||
height=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__ENTRY_HEIGHT,
|
||||
textvariable=entry_variable,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__ENTRY_FONT_SIZE, weight="normal"),
|
||||
)
|
||||
|
||||
entry_widget.bind("<Any-KeyRelease>", adjusted_command__for_entry_bind__Any_KeyRelease)
|
||||
if entry_bind__FocusOut is not None:
|
||||
entry_widget.bind("<FocusOut>", entry_bind__FocusOut, "+")
|
||||
|
||||
entry_widget.grid(row=1, column=2, padx=0, pady=0, sticky="e")
|
||||
setattr(self.config_window, entry_attr_name, entry_widget)
|
||||
|
||||
|
||||
|
||||
# at least 2px is needed otherwise the slider button is gonna broken.
|
||||
SLIDER_BORDER_WIDTH = max(2,self.settings.uism.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_LENGTH)
|
||||
SLIDER_BUTTON_LENGTH = int(SLIDER_BORDER_WIDTH/2)
|
||||
slider_widget = CTkSlider(
|
||||
setting_box_item_frame,
|
||||
from_=slider_range[0],
|
||||
to=slider_range[1],
|
||||
number_of_steps=slider_number_of_steps,
|
||||
command=adjusted_command__for_slider,
|
||||
variable=slider_variable,
|
||||
height=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__SLIDER_HEIGHT,
|
||||
border_width=0,
|
||||
button_length=SLIDER_BORDER_WIDTH,
|
||||
button_corner_radius=SLIDER_BUTTON_LENGTH,
|
||||
corner_radius=0,
|
||||
button_color=self.settings.ctm.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_COLOR,
|
||||
button_hover_color=self.settings.ctm.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_HOVERED_COLOR,
|
||||
fg_color=self.settings.ctm.SB__BG_COLOR,
|
||||
progress_color=self.settings.ctm.SB__BG_COLOR,
|
||||
border_color=self.settings.ctm.SB__BG_COLOR,
|
||||
)
|
||||
slider_widget.grid(row=1, column=1, padx=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__BAR_PADX, sticky="ew")
|
||||
setattr(self.config_window, slider_attr_name, slider_widget)
|
||||
|
||||
|
||||
|
||||
|
||||
progressbar_widget = CTkProgressBar(
|
||||
setting_box_item_frame,
|
||||
height=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__PROGRESSBAR_HEIGHT,
|
||||
corner_radius=0,
|
||||
fg_color=self.settings.ctm.SB__PROGRESSBAR_X_SLIDER__PROGRESSBAR_BG_COLOR,
|
||||
progress_color=self.settings.ctm.SB__PROGRESSBAR_X_SLIDER__PROGRESSBAR_PROGRESS_BG_COLOR,
|
||||
)
|
||||
setattr(self.config_window, progressbar_attr_name, progressbar_widget)
|
||||
progressbar_widget.grid(row=1, column=1, padx=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__BAR_PADX, sticky="ew")
|
||||
progressbar_widget.set(0)
|
||||
|
||||
|
||||
|
||||
|
||||
passive_button_wrapper = self._createPassiveButtonForProgressbarXSlider(setting_box_item_frame, passive_button_command, button_image_file)
|
||||
setattr(self.config_window, passive_button_attr_name, passive_button_wrapper)
|
||||
|
||||
disabled_button_wrapper = self._createDisabledButtonForProgressbarXSlider(setting_box_item_frame, disabled_button_image_file)
|
||||
setattr(self.config_window, disabled_button_attr_name, disabled_button_wrapper)
|
||||
|
||||
active_button_wrapper = self._createActiveButtonForProgressbarXSlider(setting_box_item_frame, active_button_command, button_image_file)
|
||||
setattr(self.config_window, active_button_attr_name, active_button_wrapper)
|
||||
|
||||
passive_button_wrapper.grid(row=1, column=0, padx=0, sticky="w")
|
||||
passive_button_wrapper.configure(corner_radius=int(getLatestWidth(passive_button_wrapper)/2))
|
||||
|
||||
disabled_button_wrapper.grid(row=1, column=0, padx=0, sticky="w")
|
||||
disabled_button_wrapper.configure(corner_radius=int(getLatestWidth(passive_button_wrapper)/2))
|
||||
|
||||
active_button_wrapper.grid(row=1, column=0, padx=0, sticky="w")
|
||||
active_button_wrapper.configure(corner_radius=int(getLatestWidth(passive_button_wrapper)/2))
|
||||
|
||||
passive_button_wrapper.grid_remove()
|
||||
disabled_button_wrapper.grid_remove()
|
||||
active_button_wrapper.grid_remove()
|
||||
|
||||
passive_button_wrapper.grid()
|
||||
return setting_box_frame
|
||||
|
||||
|
||||
|
||||
|
||||
def createSettingBoxEntry(self,
|
||||
for_var_label_text, for_var_desc_text,
|
||||
entry_attr_name,
|
||||
entry_width,
|
||||
entry_textvariable,
|
||||
entry_bind__Any_KeyRelease,
|
||||
entry_bind__FocusOut=None,
|
||||
):
|
||||
|
||||
(setting_box_frame, setting_box_item_frame) = self._createSettingBoxFrame(entry_attr_name, for_var_label_text, for_var_desc_text)
|
||||
|
||||
def adjusted_command__for_entry_bind__Any_KeyRelease(e):
|
||||
entry_bind__Any_KeyRelease(e.widget.get())
|
||||
|
||||
entry_widget = CTkEntry(
|
||||
setting_box_item_frame,
|
||||
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,
|
||||
height=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__ENTRY_HEIGHT,
|
||||
textvariable=entry_textvariable,
|
||||
font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__ENTRY_FONT_SIZE, weight="normal"),
|
||||
)
|
||||
entry_widget.bind("<Any-KeyRelease>", adjusted_command__for_entry_bind__Any_KeyRelease)
|
||||
setattr(self.config_window, entry_attr_name, entry_widget)
|
||||
|
||||
|
||||
entry_widget.grid(row=1, column=SETTING_BOX_COLUMN, sticky="e")
|
||||
|
||||
if entry_bind__FocusOut is not None:
|
||||
entry_widget.bind("<FocusOut>", entry_bind__FocusOut, "+")
|
||||
|
||||
return setting_box_frame
|
||||
|
||||
|
||||
|
||||
# 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)
|
||||
# self.setting_box_dropdown_menu_x_dropdown_menu.grid(row=0, column=1, padx=(0, self.settings.uism.SB__RIGHT_PADX), rowspan=2, sticky="e")
|
||||
|
||||
|
||||
|
||||
# # Labels
|
||||
# self.optionmenu_label_left = CTkLabel(
|
||||
# self.setting_box_dropdown_menu_x_dropdown_menu,
|
||||
# text=kwargs["left_dropdown_menu_label"],
|
||||
# font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__OPTION_MENU_FONT_SIZE, weight="normal"),
|
||||
# )
|
||||
# self.optionmenu_label_left.grid(row=0, column=0)
|
||||
|
||||
# self.the_space_between_optionmenu = CTkLabel(
|
||||
# self.setting_box_dropdown_menu_x_dropdown_menu,
|
||||
# text=None,
|
||||
# )
|
||||
# self.the_space_between_optionmenu.grid(row=0, column=1)
|
||||
|
||||
|
||||
# self.optionmenu_label_right = CTkLabel(
|
||||
# self.setting_box_dropdown_menu_x_dropdown_menu,
|
||||
# text=kwargs["right_dropdown_menu_label"],
|
||||
# font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__OPTION_MENU_FONT_SIZE, weight="normal"),
|
||||
# )
|
||||
# self.optionmenu_label_right.grid(row=0, column=2)
|
||||
|
||||
|
||||
|
||||
# # Option menus
|
||||
# self.createOption_DropdownMenu(
|
||||
# setattr_obj,
|
||||
# self.setting_box_dropdown_menu_x_dropdown_menu,
|
||||
# kwargs["left_optionmenu_attr_name"],
|
||||
# kwargs["left_dropdown_menu_attr_name"],
|
||||
# dropdown_menu_values=kwargs["left_dropdown_menu_values"],
|
||||
# width=150,
|
||||
# command=kwargs["left_dropdown_menu_command"],
|
||||
# variable=kwargs["left_dropdown_menu_variable"],
|
||||
# )
|
||||
# getattr(setattr_obj, kwargs["left_optionmenu_attr_name"]).grid(row=1, column=0)
|
||||
|
||||
|
||||
|
||||
# self.the_label_between_optionmenu = CTkLabel(
|
||||
# self.setting_box_dropdown_menu_x_dropdown_menu,
|
||||
# text="-->",
|
||||
# # anchor="w",
|
||||
# font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__OPTION_MENU_FONT_SIZE, weight="normal"),
|
||||
# text_color=self.settings.ctm.LABELS_TEXT_COLOR
|
||||
# )
|
||||
# self.the_label_between_optionmenu.grid(row=1, column=1, padx=self.settings.uism.SB__RIGHT_PADX/2)
|
||||
|
||||
|
||||
# self.createOption_DropdownMenu(
|
||||
# setattr_obj,
|
||||
# self.setting_box_dropdown_menu_x_dropdown_menu,
|
||||
# kwargs["right_optionmenu_attr_name"],
|
||||
# kwargs["right_dropdown_menu_attr_name"],
|
||||
# dropdown_menu_values=kwargs["right_dropdown_menu_values"],
|
||||
# width=150,
|
||||
# command=kwargs["right_dropdown_menu_command"],
|
||||
# variable=kwargs["right_dropdown_menu_variable"],
|
||||
# )
|
||||
# getattr(setattr_obj, kwargs["right_optionmenu_attr_name"]).grid(row=1, column=2)
|
||||
|
||||
|
||||
|
||||
|
||||
# if setting_box_type == "radio_buttons":
|
||||
# self.setting_box_radio_buttons_frame = CTkFrame(self.setting_box, corner_radius=0, width=0, height=0)
|
||||
# self.setting_box_radio_buttons_frame.grid(row=0, column=1, padx=(0, self.settings.uism.SB__RIGHT_PADX), rowspan=2, sticky="e")
|
||||
|
||||
# RADIO_BUTTON_RIGHT_PAD = 14
|
||||
# self.setting_box_radio_button_1 = CTkRadioButton(
|
||||
# self.setting_box_radio_buttons_frame,
|
||||
# text="lorem ipsum",
|
||||
# font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__RADIO_BUTTON_FONT_SIZE, weight="normal")
|
||||
# )
|
||||
# self.setting_box_radio_button_1.grid(row=0, column=0, padx=(0,RADIO_BUTTON_RIGHT_PAD), sticky="e")
|
||||
|
||||
# self.setting_box_radio_button_2 = CTkRadioButton(
|
||||
# self.setting_box_radio_buttons_frame,
|
||||
# text="lorem ipsum",
|
||||
# font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__RADIO_BUTTON_FONT_SIZE, weight="normal")
|
||||
# )
|
||||
# self.setting_box_radio_button_2.grid(row=0, column=1, padx=(0,RADIO_BUTTON_RIGHT_PAD), sticky="e")
|
||||
|
||||
# self.setting_box_radio_button_3 = CTkRadioButton(
|
||||
# self.setting_box_radio_buttons_frame,
|
||||
# text="lorem ipsum",
|
||||
# font=CTkFont(family=self.settings.FONT_FAMILY, size=self.settings.uism.SB__RADIO_BUTTON_FONT_SIZE, weight="normal")
|
||||
# )
|
||||
# self.setting_box_radio_button_3.grid(row=0, column=2, padx=(0,RADIO_BUTTON_RIGHT_PAD), sticky="e")
|
||||
|
||||
|
||||
|
||||
def _createPassiveButtonForProgressbarXSlider(self, setting_box_progressbar_x_slider_frame, button_command, button_image_file):
|
||||
button_wrapper = createButtonWithImage(
|
||||
parent_widget=setting_box_progressbar_x_slider_frame,
|
||||
button_fg_color=self.settings.ctm.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_COLOR,
|
||||
button_enter_color=self.settings.ctm.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_HOVERED_COLOR,
|
||||
button_clicked_color=self.settings.ctm.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_CLICKED_COLOR,
|
||||
button_image_file=button_image_file,
|
||||
button_image_size=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__BUTTON_ICON_SIZE,
|
||||
button_ipadxy=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__BUTTON_IPADXY,
|
||||
button_command=button_command,
|
||||
)
|
||||
return button_wrapper
|
||||
|
||||
|
||||
|
||||
def _createActiveButtonForProgressbarXSlider(self, setting_box_progressbar_x_slider_frame, button_command, button_image_file):
|
||||
button_wrapper = createButtonWithImage(
|
||||
parent_widget=setting_box_progressbar_x_slider_frame,
|
||||
button_fg_color=self.settings.ctm.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_COLOR,
|
||||
button_enter_color=self.settings.ctm.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_HOVERED_COLOR,
|
||||
button_clicked_color=self.settings.ctm.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_CLICKED_COLOR,
|
||||
button_image_file=button_image_file,
|
||||
button_image_size=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__BUTTON_ICON_SIZE,
|
||||
button_ipadxy=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__BUTTON_IPADXY,
|
||||
button_command=button_command,
|
||||
)
|
||||
return button_wrapper
|
||||
|
||||
|
||||
|
||||
def _createDisabledButtonForProgressbarXSlider(self, setting_box_progressbar_x_slider_frame, button_image_file):
|
||||
button_wrapper = createButtonWithImage(
|
||||
parent_widget=setting_box_progressbar_x_slider_frame,
|
||||
button_fg_color=self.settings.ctm.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_DISABLED_COLOR,
|
||||
button_image_file=button_image_file,
|
||||
button_image_size=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__BUTTON_ICON_SIZE,
|
||||
button_ipadxy=self.settings.uism.SB__PROGRESSBAR_X_SLIDER__BUTTON_IPADXY,
|
||||
no_bind=True,
|
||||
)
|
||||
return button_wrapper
|
||||
@@ -0,0 +1 @@
|
||||
from .createSettingBox_AdvancedSettings import createSettingBox_AdvancedSettings
|
||||
@@ -0,0 +1,38 @@
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
from .._SettingBoxGenerator import _SettingBoxGenerator
|
||||
|
||||
def createSettingBox_AdvancedSettings(setting_box_wrapper, config_window, settings, view_variable):
|
||||
sbg = _SettingBoxGenerator(setting_box_wrapper, config_window, settings, view_variable)
|
||||
createSettingBoxEntry = sbg.createSettingBoxEntry
|
||||
|
||||
|
||||
def entry_ip_address_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_OSC_IP_ADDRESS, value)
|
||||
|
||||
def entry_port_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_OSC_PORT, value)
|
||||
|
||||
row=0
|
||||
config_window.sb__ip_address = createSettingBoxEntry(
|
||||
for_var_label_text=view_variable.VAR_LABEL_OSC_IP_ADDRESS,
|
||||
for_var_desc_text=view_variable.VAR_DESC_OSC_IP_ADDRESS,
|
||||
entry_attr_name="sb__entry_ip_address",
|
||||
entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_150,
|
||||
entry_bind__Any_KeyRelease=lambda value: entry_ip_address_callback(value),
|
||||
entry_textvariable=view_variable.VAR_OSC_IP_ADDRESS,
|
||||
)
|
||||
config_window.sb__ip_address.grid(row=row)
|
||||
row+=1
|
||||
|
||||
|
||||
config_window.sb__port = createSettingBoxEntry(
|
||||
for_var_label_text=view_variable.VAR_LABEL_OSC_PORT,
|
||||
for_var_desc_text=view_variable.VAR_DESC_OSC_PORT,
|
||||
entry_attr_name="sb__entry_port",
|
||||
entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_150,
|
||||
entry_bind__Any_KeyRelease=lambda value: entry_port_callback(value),
|
||||
entry_textvariable=view_variable.VAR_OSC_PORT,
|
||||
)
|
||||
config_window.sb__port.grid(row=row, pady=0)
|
||||
row+=1
|
||||
@@ -0,0 +1 @@
|
||||
from .createSettingBox_Appearance import createSettingBox_Appearance
|
||||
@@ -0,0 +1,89 @@
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
from .._SettingBoxGenerator import _SettingBoxGenerator
|
||||
|
||||
def createSettingBox_Appearance(setting_box_wrapper, config_window, settings, view_variable):
|
||||
sbg = _SettingBoxGenerator(setting_box_wrapper, config_window, settings, view_variable)
|
||||
createSettingBoxDropdownMenu = sbg.createSettingBoxDropdownMenu
|
||||
createSettingBoxSlider = sbg.createSettingBoxSlider
|
||||
|
||||
# 関数名は変えるかもしれない。
|
||||
# テーマ変更、フォント変更時、 Widget再生成か再起動かは検討中
|
||||
def slider_transparency_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_TRANSPARENCY, value)
|
||||
|
||||
def optionmenu_appearance_theme_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_APPEARANCE, value)
|
||||
|
||||
def optionmenu_ui_scaling_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_UI_SCALING, value)
|
||||
|
||||
def optionmenu_font_family_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_FONT_FAMILY, value)
|
||||
|
||||
def optionmenu_ui_language_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_UI_LANGUAGE, value)
|
||||
|
||||
|
||||
row=0
|
||||
config_window.sb__transparency = createSettingBoxSlider(
|
||||
for_var_label_text=view_variable.VAR_LABEL_TRANSPARENCY,
|
||||
for_var_desc_text=view_variable.VAR_DESC_TRANSPARENCY,
|
||||
slider_attr_name="sb__slider_transparency",
|
||||
slider_range=view_variable.SLIDER_RANGE_TRANSPARENCY,
|
||||
command=lambda value: slider_transparency_callback(value),
|
||||
variable=view_variable.VAR_TRANSPARENCY,
|
||||
slider_bind__ButtonPress=view_variable.CALLBACK_BUTTON_PRESS_TRANSPARENCY,
|
||||
slider_bind__ButtonRelease=view_variable.CALLBACK_BUTTON_RELEASE_TRANSPARENCY,
|
||||
)
|
||||
config_window.sb__transparency.grid(row=row)
|
||||
row+=1
|
||||
|
||||
|
||||
config_window.sb__appearance_theme = createSettingBoxDropdownMenu(
|
||||
for_var_label_text=view_variable.VAR_LABEL_APPEARANCE_THEME,
|
||||
for_var_desc_text=view_variable.VAR_DESC_APPEARANCE_THEME,
|
||||
optionmenu_attr_name="sb__optionmenu_appearance_theme",
|
||||
dropdown_menu_values=view_variable.LIST_APPEARANCE_THEME,
|
||||
command=lambda value: optionmenu_appearance_theme_callback(value),
|
||||
variable=view_variable.VAR_APPEARANCE_THEME,
|
||||
)
|
||||
config_window.sb__appearance_theme.grid(row=row)
|
||||
row+=1
|
||||
|
||||
|
||||
|
||||
config_window.sb__ui_scaling = createSettingBoxDropdownMenu(
|
||||
for_var_label_text=view_variable.VAR_LABEL_UI_SCALING,
|
||||
for_var_desc_text=view_variable.VAR_DESC_UI_SCALING,
|
||||
optionmenu_attr_name="sb__optionmenu_ui_scaling",
|
||||
dropdown_menu_values=view_variable.LIST_UI_SCALING,
|
||||
command=lambda value: optionmenu_ui_scaling_callback(value),
|
||||
variable=view_variable.VAR_UI_SCALING,
|
||||
)
|
||||
config_window.sb__ui_scaling.grid(row=row)
|
||||
row+=1
|
||||
|
||||
|
||||
config_window.sb__font_family = createSettingBoxDropdownMenu(
|
||||
for_var_label_text=view_variable.VAR_LABEL_FONT_FAMILY,
|
||||
for_var_desc_text=view_variable.VAR_DESC_FONT_FAMILY,
|
||||
optionmenu_attr_name="sb__optionmenu_font_family",
|
||||
dropdown_menu_values=view_variable.LIST_FONT_FAMILY,
|
||||
command=lambda value: optionmenu_font_family_callback(value),
|
||||
variable=view_variable.VAR_FONT_FAMILY,
|
||||
)
|
||||
config_window.sb__font_family.grid(row=row)
|
||||
row+=1
|
||||
|
||||
|
||||
config_window.sb__ui_language = createSettingBoxDropdownMenu(
|
||||
for_var_label_text=view_variable.VAR_LABEL_UI_LANGUAGE,
|
||||
for_var_desc_text=view_variable.VAR_DESC_UI_LANGUAGE,
|
||||
optionmenu_attr_name="sb__optionmenu_ui_language",
|
||||
dropdown_menu_values=view_variable.LIST_UI_LANGUAGE,
|
||||
command=lambda value: optionmenu_ui_language_callback(value),
|
||||
variable=view_variable.VAR_UI_LANGUAGE,
|
||||
)
|
||||
config_window.sb__ui_language.grid(row=row, pady=0)
|
||||
row+=1
|
||||
@@ -0,0 +1 @@
|
||||
from .createSettingBox_Others import createSettingBox_Others
|
||||
@@ -0,0 +1,98 @@
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
from .._SettingBoxGenerator import _SettingBoxGenerator
|
||||
|
||||
def createSettingBox_Others(setting_box_wrapper, config_window, settings, view_variable):
|
||||
sbg = _SettingBoxGenerator(setting_box_wrapper, config_window, settings, view_variable)
|
||||
createSettingBoxCheckbox = sbg.createSettingBoxCheckbox
|
||||
createSettingBoxEntry = sbg.createSettingBoxEntry
|
||||
|
||||
|
||||
# 元 checkbox_auto_clear_chatbox_callback
|
||||
def checkbox_auto_clear_message_box_callback(checkbox_box_widget):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_ENABLE_AUTO_CLEAR_MESSAGE_BOX, checkbox_box_widget.get())
|
||||
|
||||
def checkbox_notice_xsoverlay_callback(checkbox_box_widget):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_ENABLE_NOTICE_XSOVERLAY, checkbox_box_widget.get())
|
||||
|
||||
def checkbox_auto_export_message_logs_callback(checkbox_box_widget):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_ENABLE_AUTO_EXPORT_MESSAGE_LOGS, checkbox_box_widget.get())
|
||||
|
||||
def checkbox_enable_send_message_to_vrc_callback(checkbox_box_widget):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_ENABLE_SEND_MESSAGE_TO_VRC, checkbox_box_widget.get())
|
||||
|
||||
# [deprecated]
|
||||
# def checkbox_startup_osc_enabled_check_callback(checkbox_box_widget):
|
||||
# callFunctionIfCallable(view_variable.CALLBACK_SET_STARTUP_OSC_ENABLED_CHECK, checkbox_box_widget.get())
|
||||
|
||||
def entry_message_format_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_MESSAGE_FORMAT, value)
|
||||
|
||||
|
||||
row=0
|
||||
config_window.sb__auto_clear_message_box = createSettingBoxCheckbox(
|
||||
for_var_label_text=view_variable.VAR_LABEL_ENABLE_AUTO_CLEAR_MESSAGE_BOX,
|
||||
for_var_desc_text=view_variable.VAR_DESC_ENABLE_AUTO_CLEAR_MESSAGE_BOX,
|
||||
checkbox_attr_name="sb__checkbox_auto_clear_message_box",
|
||||
command=lambda: checkbox_auto_clear_message_box_callback(config_window.sb__checkbox_auto_clear_message_box),
|
||||
variable=view_variable.VAR_ENABLE_AUTO_CLEAR_MESSAGE_BOX,
|
||||
)
|
||||
config_window.sb__auto_clear_message_box.grid(row=row)
|
||||
row+=1
|
||||
|
||||
|
||||
config_window.sb__notice_xsoverlay = createSettingBoxCheckbox(
|
||||
for_var_label_text=view_variable.VAR_LABEL_ENABLE_NOTICE_XSOVERLAY,
|
||||
for_var_desc_text=view_variable.VAR_DESC_ENABLE_NOTICE_XSOVERLAY,
|
||||
checkbox_attr_name="sb__checkbox_notice_xsoverlay",
|
||||
command=lambda: checkbox_notice_xsoverlay_callback(config_window.sb__checkbox_notice_xsoverlay),
|
||||
variable=view_variable.VAR_ENABLE_NOTICE_XSOVERLAY,
|
||||
)
|
||||
config_window.sb__notice_xsoverlay.grid(row=row)
|
||||
row+=1
|
||||
|
||||
|
||||
config_window.sb__auto_export_message_logs = createSettingBoxCheckbox(
|
||||
for_var_label_text=view_variable.VAR_LABEL_ENABLE_AUTO_EXPORT_MESSAGE_LOGS,
|
||||
for_var_desc_text=view_variable.VAR_DESC_ENABLE_AUTO_EXPORT_MESSAGE_LOGS,
|
||||
checkbox_attr_name="sb__checkbox_auto_export_message_logs",
|
||||
command=lambda: checkbox_auto_export_message_logs_callback(config_window.sb__checkbox_auto_export_message_logs),
|
||||
variable=view_variable.VAR_ENABLE_AUTO_EXPORT_MESSAGE_LOGS,
|
||||
)
|
||||
config_window.sb__auto_export_message_logs.grid(row=row)
|
||||
row+=1
|
||||
|
||||
|
||||
config_window.sb__message_format = createSettingBoxEntry(
|
||||
for_var_label_text=view_variable.VAR_LABEL_MESSAGE_FORMAT,
|
||||
for_var_desc_text=view_variable.VAR_DESC_MESSAGE_FORMAT,
|
||||
entry_attr_name="sb__entry_message_format",
|
||||
entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_250,
|
||||
entry_bind__Any_KeyRelease=lambda value: entry_message_format_callback(value),
|
||||
entry_textvariable=view_variable.VAR_MESSAGE_FORMAT,
|
||||
)
|
||||
config_window.sb__message_format.grid(row=row)
|
||||
row+=1
|
||||
|
||||
|
||||
config_window.sb__enable_send_message_to_vrc = createSettingBoxCheckbox(
|
||||
for_var_label_text=view_variable.VAR_LABEL_ENABLE_SEND_MESSAGE_TO_VRC,
|
||||
for_var_desc_text=view_variable.VAR_DESC_ENABLE_SEND_MESSAGE_TO_VRC,
|
||||
checkbox_attr_name="sb__checkbox_enable_send_message_to_vrc",
|
||||
command=lambda: checkbox_enable_send_message_to_vrc_callback(config_window.sb__checkbox_enable_send_message_to_vrc),
|
||||
variable=view_variable.VAR_ENABLE_SEND_MESSAGE_TO_VRC,
|
||||
)
|
||||
config_window.sb__enable_send_message_to_vrc.grid(row=row, pady=0)
|
||||
row+=1
|
||||
|
||||
# [deprecated]
|
||||
# config_window.sb__startup_osc_enabled_check = createSettingBoxCheckbox(
|
||||
# for_var_label_text=view_variable.VAR_LABEL_STARTUP_OSC_ENABLED_CHECK,
|
||||
# for_var_desc_text=view_variable.VAR_DESC_STARTUP_OSC_ENABLED_CHECK,
|
||||
# checkbox_attr_name="sb__checkbox_startup_osc_enabled_check",
|
||||
# command=lambda: checkbox_startup_osc_enabled_check_callback(config_window.sb__checkbox_startup_osc_enabled_check),
|
||||
# variable=view_variable.VAR_STARTUP_OSC_ENABLED_CHECK,
|
||||
# )
|
||||
# config_window.sb__startup_osc_enabled_check.grid(row=row, pady=0)
|
||||
# row+=1
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
from .createSettingBox_Mic import createSettingBox_Mic
|
||||
from .createSettingBox_Speaker import createSettingBox_Speaker
|
||||
@@ -0,0 +1,152 @@
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
from .._SettingBoxGenerator import _SettingBoxGenerator
|
||||
|
||||
def createSettingBox_Mic(setting_box_wrapper, config_window, settings, view_variable):
|
||||
sbg = _SettingBoxGenerator(setting_box_wrapper, config_window, settings, view_variable)
|
||||
createSettingBoxDropdownMenu = sbg.createSettingBoxDropdownMenu
|
||||
createSettingBoxSwitch = sbg.createSettingBoxSwitch
|
||||
createSettingBoxProgressbarXSlider = sbg.createSettingBoxProgressbarXSlider
|
||||
createSettingBoxEntry = sbg.createSettingBoxEntry
|
||||
|
||||
|
||||
def checkbox_input_mic_threshold_check_callback(is_turned_on):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_CHECK_MIC_THRESHOLD, is_turned_on)
|
||||
|
||||
|
||||
def optionmenu_mic_host_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_MIC_HOST, value)
|
||||
|
||||
def optionmenu_input_mic_device_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_MIC_DEVICE, value)
|
||||
|
||||
def slider_input_mic_energy_threshold_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_MIC_ENERGY_THRESHOLD, value)
|
||||
|
||||
def checkbox_input_mic_dynamic_energy_threshold_callback(checkbox_box_widget):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_MIC_DYNAMIC_ENERGY_THRESHOLD, checkbox_box_widget.get())
|
||||
|
||||
|
||||
def entry_input_mic_record_timeout_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_MIC_RECORD_TIMEOUT, value)
|
||||
|
||||
def entry_input_mic_phrase_timeout_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_MIC_PHRASE_TIMEOUT, value)
|
||||
|
||||
def entry_input_mic_max_phrases_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_MIC_MAX_PHRASES, value)
|
||||
|
||||
def entry_input_mic_word_filters_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_MIC_WORD_FILTER, value)
|
||||
|
||||
|
||||
row=0
|
||||
# Mic Host と Mic Device は一つの項目として引っ付ける予定
|
||||
config_window.sb__mic_host = createSettingBoxDropdownMenu(
|
||||
for_var_label_text=view_variable.VAR_LABEL_MIC_HOST,
|
||||
for_var_desc_text=view_variable.VAR_DESC_MIC_HOST,
|
||||
optionmenu_attr_name="sb__optionmenu_mic_host",
|
||||
dropdown_menu_values=view_variable.LIST_MIC_HOST,
|
||||
command=lambda value: optionmenu_mic_host_callback(value),
|
||||
variable=view_variable.VAR_MIC_HOST,
|
||||
)
|
||||
config_window.sb__mic_host.grid(row=row)
|
||||
row+=1
|
||||
|
||||
config_window.sb__mic_device = createSettingBoxDropdownMenu(
|
||||
for_var_label_text=view_variable.VAR_LABEL_MIC_DEVICE,
|
||||
for_var_desc_text=view_variable.VAR_DESC_MIC_DEVICE,
|
||||
optionmenu_attr_name="sb__optionmenu_mic_device",
|
||||
dropdown_menu_values=view_variable.LIST_MIC_DEVICE,
|
||||
command=lambda value: optionmenu_input_mic_device_callback(value),
|
||||
variable=view_variable.VAR_MIC_DEVICE,
|
||||
)
|
||||
config_window.sb__mic_device.grid(row=row)
|
||||
row+=1
|
||||
|
||||
config_window.sb__mic_dynamic_energy_threshold = createSettingBoxSwitch(
|
||||
for_var_label_text=view_variable.VAR_LABEL_MIC_DYNAMIC_ENERGY_THRESHOLD,
|
||||
for_var_desc_text=view_variable.VAR_DESC_MIC_DYNAMIC_ENERGY_THRESHOLD,
|
||||
switch_attr_name="sb__checkbox_mic_dynamic_energy_threshold",
|
||||
command=lambda: checkbox_input_mic_dynamic_energy_threshold_callback(config_window.sb__checkbox_mic_dynamic_energy_threshold),
|
||||
variable=view_variable.VAR_MIC_DYNAMIC_ENERGY_THRESHOLD
|
||||
)
|
||||
config_window.sb__mic_dynamic_energy_threshold.grid(row=row, pady=0)
|
||||
row+=1
|
||||
|
||||
config_window.sb__mic_energy_threshold = createSettingBoxProgressbarXSlider(
|
||||
command=slider_input_mic_energy_threshold_callback,
|
||||
progressbar_x_slider_attr_name="sb__mic_energy_threshold",
|
||||
|
||||
entry_attr_name="sb__progressbar_x_slider__entry_mic_energy_threshold",
|
||||
entry_variable=view_variable.VAR_MIC_ENERGY_THRESHOLD__ENTRY,
|
||||
entry_bind__FocusOut=view_variable.CALLBACK_FOCUS_OUT_MIC_ENERGY_THRESHOLD,
|
||||
|
||||
|
||||
slider_attr_name="progressbar_x_slider__slider_mic_energy_threshold",
|
||||
slider_range=view_variable.SLIDER_RANGE_MIC_ENERGY_THRESHOLD,
|
||||
slider_variable=view_variable.VAR_MIC_ENERGY_THRESHOLD__SLIDER,
|
||||
|
||||
progressbar_attr_name="sb__progressbar_x_slider__progressbar_mic_energy_threshold",
|
||||
|
||||
passive_button_attr_name="sb__progressbar_x_slider__passive_button_mic_energy_threshold",
|
||||
passive_button_command=lambda _e: checkbox_input_mic_threshold_check_callback(True),
|
||||
active_button_attr_name="sb__progressbar_x_slider__active_button_mic_energy_threshold",
|
||||
active_button_command=lambda _e: checkbox_input_mic_threshold_check_callback(False),
|
||||
button_image_file=settings.image_file.MIC_ICON,
|
||||
disabled_button_attr_name="sb__progressbar_x_slider__disabled_button_mic_energy_threshold",
|
||||
disabled_button_image_file=settings.image_file.MIC_ICON_DISABLED,
|
||||
)
|
||||
config_window.sb__mic_energy_threshold.grid(row=row)
|
||||
row+=1
|
||||
|
||||
|
||||
# 以下3つも一つの項目にまとめるかもしれない
|
||||
config_window.sb__mic_record_timeout = createSettingBoxEntry(
|
||||
for_var_label_text=view_variable.VAR_LABEL_MIC_RECORD_TIMEOUT,
|
||||
for_var_desc_text=view_variable.VAR_DESC_MIC_RECORD_TIMEOUT,
|
||||
entry_attr_name="sb__entry_mic_record_timeout",
|
||||
entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_100,
|
||||
entry_bind__Any_KeyRelease=lambda value: entry_input_mic_record_timeout_callback(value),
|
||||
entry_textvariable=view_variable.VAR_MIC_RECORD_TIMEOUT,
|
||||
entry_bind__FocusOut=view_variable.CALLBACK_FOCUS_OUT_MIC_RECORD_TIMEOUT,
|
||||
)
|
||||
config_window.sb__mic_record_timeout.grid(row=row)
|
||||
row+=1
|
||||
|
||||
config_window.sb__mic_phrase_timeout = createSettingBoxEntry(
|
||||
for_var_label_text=view_variable.VAR_LABEL_MIC_PHRASE_TIMEOUT,
|
||||
for_var_desc_text=view_variable.VAR_DESC_MIC_PHRASE_TIMEOUT,
|
||||
entry_attr_name="sb__entry_mic_phrase_timeout",
|
||||
entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_100,
|
||||
entry_bind__Any_KeyRelease=lambda value: entry_input_mic_phrase_timeout_callback(value),
|
||||
entry_textvariable=view_variable.VAR_MIC_PHRASE_TIMEOUT,
|
||||
entry_bind__FocusOut=view_variable.CALLBACK_FOCUS_OUT_MIC_PHRASE_TIMEOUT,
|
||||
)
|
||||
config_window.sb__mic_phrase_timeout.grid(row=row)
|
||||
row+=1
|
||||
|
||||
config_window.sb__mic_max_phrases = createSettingBoxEntry(
|
||||
for_var_label_text=view_variable.VAR_LABEL_MIC_MAX_PHRASES,
|
||||
for_var_desc_text=view_variable.VAR_DESC_MIC_MAX_PHRASES,
|
||||
entry_attr_name="sb__entry_mic_max_phrases",
|
||||
entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_100,
|
||||
entry_bind__Any_KeyRelease=lambda value: entry_input_mic_max_phrases_callback(value),
|
||||
entry_textvariable=view_variable.VAR_MIC_MAX_PHRASES,
|
||||
entry_bind__FocusOut=view_variable.CALLBACK_FOCUS_OUT_MIC_MAX_PHRASES,
|
||||
)
|
||||
config_window.sb__mic_max_phrases.grid(row=row)
|
||||
row+=1
|
||||
# # __________
|
||||
|
||||
|
||||
config_window.sb__mic_word_filter = createSettingBoxEntry(
|
||||
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,
|
||||
)
|
||||
config_window.sb__mic_word_filter.grid(row=row, pady=0)
|
||||
row+=1
|
||||
@@ -0,0 +1,108 @@
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
from .._SettingBoxGenerator import _SettingBoxGenerator
|
||||
|
||||
def createSettingBox_Speaker(setting_box_wrapper, config_window, settings, view_variable):
|
||||
sbg = _SettingBoxGenerator(setting_box_wrapper, config_window, settings, view_variable)
|
||||
createSettingBoxSwitch = sbg.createSettingBoxSwitch
|
||||
createSettingBoxProgressbarXSlider = sbg.createSettingBoxProgressbarXSlider
|
||||
createSettingBoxEntry = sbg.createSettingBoxEntry
|
||||
|
||||
|
||||
def checkbox_input_speaker_threshold_check_callback(is_turned_on):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_CHECK_SPEAKER_THRESHOLD, is_turned_on)
|
||||
|
||||
|
||||
def slider_input_speaker_energy_threshold_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_SPEAKER_ENERGY_THRESHOLD, value)
|
||||
|
||||
def checkbox_input_speaker_dynamic_energy_threshold_callback(checkbox_box_widget):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_SPEAKER_DYNAMIC_ENERGY_THRESHOLD, checkbox_box_widget.get())
|
||||
|
||||
|
||||
def entry_input_speaker_record_timeout_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_SPEAKER_RECORD_TIMEOUT, value)
|
||||
|
||||
def entry_input_speaker_phrase_timeout_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_SPEAKER_PHRASE_TIMEOUT, value)
|
||||
|
||||
def entry_input_speaker_max_phrases_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_SPEAKER_MAX_PHRASES, value)
|
||||
|
||||
|
||||
|
||||
row=0
|
||||
config_window.sb__speaker_dynamic_energy_threshold = createSettingBoxSwitch(
|
||||
for_var_label_text=view_variable.VAR_LABEL_SPEAKER_DYNAMIC_ENERGY_THRESHOLD,
|
||||
for_var_desc_text=view_variable.VAR_DESC_SPEAKER_DYNAMIC_ENERGY_THRESHOLD,
|
||||
switch_attr_name="sb__checkbox_speaker_dynamic_energy_threshold",
|
||||
command=lambda: checkbox_input_speaker_dynamic_energy_threshold_callback(config_window.sb__checkbox_speaker_dynamic_energy_threshold),
|
||||
variable=view_variable.VAR_SPEAKER_DYNAMIC_ENERGY_THRESHOLD,
|
||||
)
|
||||
config_window.sb__speaker_dynamic_energy_threshold.grid(row=row, pady=0)
|
||||
row+=1
|
||||
|
||||
config_window.sb__speaker_energy_threshold = createSettingBoxProgressbarXSlider(
|
||||
command=slider_input_speaker_energy_threshold_callback,
|
||||
progressbar_x_slider_attr_name="sb__speaker_energy_threshold",
|
||||
|
||||
entry_variable=view_variable.VAR_SPEAKER_ENERGY_THRESHOLD__ENTRY,
|
||||
entry_attr_name="sb__progressbar_x_slider__entry_speaker_energy_threshold",
|
||||
entry_bind__FocusOut=view_variable.CALLBACK_FOCUS_OUT_SPEAKER_ENERGY_THRESHOLD,
|
||||
|
||||
|
||||
slider_attr_name="progressbar_x_slider__slider_speaker_energy_threshold",
|
||||
slider_range=view_variable.SLIDER_RANGE_SPEAKER_ENERGY_THRESHOLD,
|
||||
slider_variable=view_variable.VAR_SPEAKER_ENERGY_THRESHOLD__SLIDER,
|
||||
|
||||
progressbar_attr_name="sb__progressbar_x_slider__progressbar_speaker_energy_threshold",
|
||||
|
||||
passive_button_attr_name="sb__progressbar_x_slider__passive_button_speaker_energy_threshold",
|
||||
passive_button_command=lambda _e: checkbox_input_speaker_threshold_check_callback(True),
|
||||
active_button_attr_name="sb__progressbar_x_slider__active_button_speaker_energy_threshold",
|
||||
active_button_command=lambda _e: checkbox_input_speaker_threshold_check_callback(False),
|
||||
button_image_file=settings.image_file.HEADPHONES_ICON,
|
||||
disabled_button_attr_name="sb__progressbar_x_slider__disabled_button_speaker_energy_threshold",
|
||||
disabled_button_image_file=settings.image_file.HEADPHONES_ICON_DISABLED,
|
||||
)
|
||||
config_window.sb__speaker_energy_threshold.grid(row=row)
|
||||
row+=1
|
||||
|
||||
|
||||
# 以下3つも一つの項目にまとめるかもしれない
|
||||
config_window.sb__speaker_record_timeout = createSettingBoxEntry(
|
||||
for_var_label_text=view_variable.VAR_LABEL_SPEAKER_RECORD_TIMEOUT,
|
||||
for_var_desc_text=view_variable.VAR_DESC_SPEAKER_RECORD_TIMEOUT,
|
||||
entry_attr_name="sb__entry_speaker_record_timeout",
|
||||
entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_100,
|
||||
entry_bind__Any_KeyRelease=lambda value: entry_input_speaker_record_timeout_callback(value),
|
||||
entry_textvariable=view_variable.VAR_SPEAKER_RECORD_TIMEOUT,
|
||||
entry_bind__FocusOut=view_variable.CALLBACK_FOCUS_OUT_SPEAKER_RECORD_TIMEOUT,
|
||||
)
|
||||
config_window.sb__speaker_record_timeout.grid(row=row)
|
||||
row+=1
|
||||
|
||||
config_window.sb__speaker_phrase_timeout = createSettingBoxEntry(
|
||||
for_var_label_text=view_variable.VAR_LABEL_SPEAKER_PHRASE_TIMEOUT,
|
||||
for_var_desc_text=view_variable.VAR_DESC_SPEAKER_PHRASE_TIMEOUT,
|
||||
entry_attr_name="sb__entry_speaker_phrase_timeout",
|
||||
entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_100,
|
||||
entry_bind__Any_KeyRelease=lambda value: entry_input_speaker_phrase_timeout_callback(value),
|
||||
entry_textvariable=view_variable.VAR_SPEAKER_PHRASE_TIMEOUT,
|
||||
entry_bind__FocusOut=view_variable.CALLBACK_FOCUS_OUT_SPEAKER_PHRASE_TIMEOUT,
|
||||
)
|
||||
config_window.sb__speaker_phrase_timeout.grid(row=row)
|
||||
row+=1
|
||||
|
||||
config_window.sb__speaker_max_phrases = createSettingBoxEntry(
|
||||
for_var_label_text=view_variable.VAR_LABEL_SPEAKER_MAX_PHRASES,
|
||||
for_var_desc_text=view_variable.VAR_DESC_SPEAKER_MAX_PHRASES,
|
||||
entry_attr_name="sb__entry_speaker_max_phrases",
|
||||
entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_100,
|
||||
entry_bind__Any_KeyRelease=lambda value: entry_input_speaker_max_phrases_callback(value),
|
||||
entry_textvariable=view_variable.VAR_SPEAKER_MAX_PHRASES,
|
||||
entry_bind__FocusOut=view_variable.CALLBACK_FOCUS_OUT_SPEAKER_MAX_PHRASES,
|
||||
)
|
||||
config_window.sb__speaker_max_phrases.grid(row=row, pady=0)
|
||||
row+=1
|
||||
# __________
|
||||
@@ -0,0 +1 @@
|
||||
from .createSettingBox_Translation import createSettingBox_Translation
|
||||
@@ -0,0 +1,24 @@
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
from .._SettingBoxGenerator import _SettingBoxGenerator
|
||||
|
||||
def createSettingBox_Translation(setting_box_wrapper, config_window, settings, view_variable):
|
||||
sbg = _SettingBoxGenerator(setting_box_wrapper, config_window, settings, view_variable)
|
||||
createSettingBoxEntry = sbg.createSettingBoxEntry
|
||||
|
||||
|
||||
def deepl_authkey_callback(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SET_DEEPL_AUTHKEY, value)
|
||||
|
||||
|
||||
row=0
|
||||
config_window.sb__deepl_authkey = createSettingBoxEntry(
|
||||
for_var_label_text=view_variable.VAR_LABEL_DEEPL_AUTH_KEY,
|
||||
for_var_desc_text=view_variable.VAR_DESC_DEEPL_AUTH_KEY,
|
||||
entry_attr_name="sb__entry_deepl_authkey",
|
||||
entry_width=settings.uism.RESPONSIVE_UI_SIZE_INT_300,
|
||||
entry_bind__Any_KeyRelease=lambda value: deepl_authkey_callback(value),
|
||||
entry_textvariable=view_variable.VAR_DEEPL_AUTH_KEY,
|
||||
)
|
||||
config_window.sb__deepl_authkey.grid(row=row, pady=0)
|
||||
row+=1
|
||||
1
vrct_gui/main_window/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .createMainWindowWidgets import createMainWindowWidgets
|
||||
125
vrct_gui/main_window/createMainWindowWidgets.py
Normal file
@@ -0,0 +1,125 @@
|
||||
from .widgets import createSidebar, createMinimizeSidebarButton, createTextbox, createEntryMessageBox
|
||||
|
||||
from customtkinter import CTkFrame, CTkLabel, CTkFont, CTkImage
|
||||
|
||||
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.iconbitmap(getImagePath("vrct_logo_mark_black.ico"))
|
||||
vrct_gui.title("VRCT")
|
||||
# vrct_gui.minsize(200, 200)
|
||||
|
||||
|
||||
# Main Container
|
||||
vrct_gui.grid_columnconfigure(0, weight=1)
|
||||
vrct_gui.grid_rowconfigure(0, weight=1)
|
||||
# vrct_gui.grid_columnconfigure(0, weight=1, minsize=settings.uism.MAIN_AREA_MIN_WIDTH)
|
||||
|
||||
vrct_gui.configure(fg_color=settings.ctm.MAIN_BG_COLOR)
|
||||
|
||||
vrct_gui.toplevel_wrapper = CTkFrame(vrct_gui, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0)
|
||||
vrct_gui.toplevel_wrapper.grid(row=0, column=0, sticky="nsew")
|
||||
vrct_gui.toplevel_wrapper.grid_columnconfigure(1, weight=1)
|
||||
|
||||
|
||||
# Main Container
|
||||
vrct_gui.main_bg_container = CTkFrame(vrct_gui.toplevel_wrapper, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0)
|
||||
vrct_gui.main_bg_container.grid(row=0, column=1, sticky="nsew")
|
||||
|
||||
|
||||
# top bar
|
||||
vrct_gui.main_bg_container.grid_columnconfigure(0, weight=1)
|
||||
vrct_gui.main_topbar_container = CTkFrame(vrct_gui.main_bg_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0)
|
||||
vrct_gui.main_topbar_container.grid(row=0, column=0, sticky="ew")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
vrct_gui.main_topbar_container.grid_columnconfigure(1,weight=1)
|
||||
vrct_gui.main_topbar_center_container = CTkFrame(vrct_gui.main_topbar_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0)
|
||||
vrct_gui.main_topbar_center_container.grid(row=0, column=1, sticky="nsew")
|
||||
|
||||
|
||||
|
||||
# Main Top Bar Container - Right Side
|
||||
# start from 3
|
||||
main_topbar_column=3
|
||||
# Update Available Button
|
||||
vrct_gui.update_available_container = CTkFrame(
|
||||
vrct_gui.main_topbar_container,
|
||||
corner_radius=settings.uism.UPDATE_AVAILABLE_BUTTON_CORNER_RADIUS,
|
||||
fg_color=settings.ctm.MAIN_BG_COLOR,
|
||||
cursor="hand2",
|
||||
)
|
||||
vrct_gui.update_available_container.grid(row=0, column=main_topbar_column, padx=settings.uism.UPDATE_AVAILABLE_BUTTON_PADX, pady=settings.uism.TOP_BAR_BUTTON_PADY, sticky="nse")
|
||||
vrct_gui.update_available_container.grid_remove()
|
||||
main_topbar_column+=1
|
||||
|
||||
|
||||
vrct_gui.update_available_container.grid_rowconfigure((0,2), weight=1)
|
||||
|
||||
vrct_gui.update_available_icon = CTkLabel(
|
||||
vrct_gui.update_available_container,
|
||||
text=None,
|
||||
corner_radius=0,
|
||||
height=0,
|
||||
image=CTkImage(settings.image_file.REFRESH_ICON.rotate(25), size=settings.uism.UPDATE_AVAILABLE_BUTTON_SIZE)
|
||||
)
|
||||
vrct_gui.update_available_icon.grid(row=1, column=0, padx=(settings.uism.UPDATE_AVAILABLE_BUTTON_IPADX, settings.uism.UPDATE_AVAILABLE_PADX_BETWEEN_LABEL_AND_ICON), pady=0)
|
||||
|
||||
|
||||
vrct_gui.update_available_label = CTkLabel(
|
||||
vrct_gui.update_available_container,
|
||||
textvariable=view_variable.VAR_UPDATE_AVAILABLE,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.UPDATE_AVAILABLE_BUTTON_FONT_SIZE, weight="normal"),
|
||||
anchor="e",
|
||||
text_color=settings.ctm.UPDATE_AVAILABLE_BUTTON_TEXT_COLOR,
|
||||
)
|
||||
# This "right padx +1" is for fixing a bug that sticks out from the frame. I don't know why that happens...
|
||||
vrct_gui.update_available_label.grid(row=1, column=1, padx=(0,settings.uism.UPDATE_AVAILABLE_BUTTON_IPADX+1), pady=0)
|
||||
|
||||
|
||||
bindButtonFunctionAndColor(
|
||||
target_widgets=[
|
||||
vrct_gui.update_available_container,
|
||||
vrct_gui.update_available_label,
|
||||
vrct_gui.update_available_icon,
|
||||
],
|
||||
enter_color=settings.ctm.UPDATE_AVAILABLE_BUTTON_HOVERED_BG_COLOR,
|
||||
leave_color=settings.ctm.UPDATE_AVAILABLE_BUTTON_BG_COLOR,
|
||||
clicked_color=settings.ctm.UPDATE_AVAILABLE_BUTTON_CLICKED_BG_COLOR,
|
||||
buttonReleasedFunction=lambda e: callFunctionIfCallable(view_variable.CALLBACK_CLICKED_UPDATE_AVAILABLE),
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Help and Info button
|
||||
vrct_gui.help_and_info_button_container = createButtonWithImage(
|
||||
parent_widget=vrct_gui.main_topbar_container,
|
||||
button_fg_color=settings.ctm.HELP_AND_INFO_BUTTON_BG_COLOR,
|
||||
button_enter_color=settings.ctm.HELP_AND_INFO_BUTTON_HOVERED_BG_COLOR,
|
||||
button_clicked_color=settings.ctm.HELP_AND_INFO_BUTTON_CLICKED_BG_COLOR,
|
||||
button_image_file=settings.image_file.HELP_ICON,
|
||||
button_image_size=settings.uism.HELP_AND_INFO_BUTTON_SIZE,
|
||||
button_ipadxy=settings.uism.HELP_AND_INFO_BUTTON_IPADXY,
|
||||
button_command=lambda e: callFunctionIfCallable(view_variable.CALLBACK_CLICKED_HELP_AND_INFO),
|
||||
corner_radius=settings.uism.HELP_AND_INFO_BUTTON_CORNER_RADIUS,
|
||||
)
|
||||
vrct_gui.help_and_info_button_container.grid(row=0, column=main_topbar_column, padx=settings.uism.HELP_AND_INFO_BUTTON_PADX, pady=settings.uism.TOP_BAR_BUTTON_PADY, sticky="e")
|
||||
main_topbar_column+=1
|
||||
createSidebar(settings, vrct_gui, view_variable)
|
||||
|
||||
createMinimizeSidebarButton(settings, vrct_gui, view_variable)
|
||||
|
||||
createTextbox(settings, vrct_gui, view_variable)
|
||||
|
||||
createEntryMessageBox(settings, vrct_gui)
|
||||
4
vrct_gui/main_window/widgets/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from .create_sidebar import createSidebar
|
||||
from .create_minimize_sidebar_button import createMinimizeSidebarButton
|
||||
from .create_textbox import createTextbox
|
||||
from .create_entry_message_box import createEntryMessageBox
|
||||
2
vrct_gui/main_window/widgets/_create_sidebar/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .createSidebarFeatures import createSidebarFeatures
|
||||
from .createSidebarLanguagesSettings import createSidebarLanguagesSettings
|
||||
@@ -0,0 +1,287 @@
|
||||
from functools import partial
|
||||
|
||||
from customtkinter import CTkFont, CTkFrame, CTkLabel, CTkSwitch, CTkImage
|
||||
|
||||
from ....ui_utils import openImageKeepAspectRatio, retag, getLatestHeight, bindEnterAndLeaveFunction, bindButtonReleaseFunction, bindButtonPressAndReleaseFunction
|
||||
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
def createSidebarFeatures(settings, main_window, view_variable):
|
||||
|
||||
def toggleSidebarFeatureSelectedMarkIfTurnedOn(is_turned_on, mark_widget):
|
||||
mark_widget.place(relx=0.85) if is_turned_on else mark_widget.place(relx=-1)
|
||||
|
||||
|
||||
def toggleTranslationFeature():
|
||||
is_turned_on = main_window.translation_switch_box.get()
|
||||
callFunctionIfCallable(view_variable.CALLBACK_TOGGLE_TRANSLATION, is_turned_on)
|
||||
main_window.translation_frame.markToggleManually(is_turned_on=is_turned_on)
|
||||
|
||||
def toggleTranscriptionSendFeature():
|
||||
is_turned_on = main_window.transcription_send_switch_box.get()
|
||||
callFunctionIfCallable(view_variable.CALLBACK_TOGGLE_TRANSCRIPTION_SEND, is_turned_on)
|
||||
main_window.transcription_send_frame.markToggleManually(is_turned_on=is_turned_on)
|
||||
|
||||
def toggleTranscriptionReceiveFeature():
|
||||
is_turned_on = main_window.transcription_receive_switch_box.get()
|
||||
callFunctionIfCallable(view_variable.CALLBACK_TOGGLE_TRANSCRIPTION_RECEIVE, is_turned_on)
|
||||
main_window.transcription_receive_frame.markToggleManually(is_turned_on=is_turned_on)
|
||||
|
||||
def toggleForegroundFeature():
|
||||
is_turned_on = main_window.foreground_switch_box.get()
|
||||
callFunctionIfCallable(view_variable.CALLBACK_TOGGLE_FOREGROUND, is_turned_on)
|
||||
main_window.foreground_frame.markToggleManually(is_turned_on=is_turned_on)
|
||||
|
||||
|
||||
|
||||
|
||||
def changeSidebarFeaturesColorByEvents(ww, event_name):
|
||||
target_frame_widget = getattr(main_window, ww)
|
||||
target_compact_mode_frame_widget = getattr(main_window, "compact_mode_"+ww)
|
||||
if event_name == "enter":
|
||||
target_frame_widget.configure(fg_color=settings.ctm.SF__HOVERED_BG_COLOR)
|
||||
target_frame_widget.children["!ctkswitch"].configure(fg_color=settings.ctm.SF__SWITCH_BOX_HOVERED_BG_COLOR, progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_HOVERED_BG_COLOR)
|
||||
target_compact_mode_frame_widget.configure(fg_color=settings.ctm.SF__HOVERED_BG_COLOR)
|
||||
target_compact_mode_frame_widget.children["!ctkframe"].configure(fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_HOVERED_BG_COLOR)
|
||||
|
||||
elif event_name == "leave":
|
||||
target_frame_widget.configure(fg_color=settings.ctm.SF__BG_COLOR)
|
||||
target_frame_widget.children["!ctkswitch"].configure(fg_color=settings.ctm.SF__SWITCH_BOX_BG_COLOR, progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_BG_COLOR)
|
||||
target_compact_mode_frame_widget.configure(fg_color=settings.ctm.SF__BG_COLOR)
|
||||
target_compact_mode_frame_widget.children["!ctkframe"].configure(fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_BG_COLOR)
|
||||
|
||||
elif event_name == "button_press":
|
||||
target_frame_widget.configure(fg_color=settings.ctm.SF__CLICKED_BG_COLOR)
|
||||
target_frame_widget.children["!ctkswitch"].configure(fg_color=settings.ctm.SF__SWITCH_BOX_CLICKED_BG_COLOR, progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_CLICKED_BG_COLOR)
|
||||
target_compact_mode_frame_widget.configure(fg_color=settings.ctm.SF__CLICKED_BG_COLOR)
|
||||
target_compact_mode_frame_widget.children["!ctkframe"].configure(fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_CLICKED_BG_COLOR)
|
||||
|
||||
elif event_name == "button_release":
|
||||
target_frame_widget.configure(fg_color=settings.ctm.SF__BG_COLOR)
|
||||
target_frame_widget.children["!ctkswitch"].configure(fg_color=settings.ctm.SF__SWITCH_BOX_BG_COLOR, progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_BG_COLOR)
|
||||
target_compact_mode_frame_widget.configure(fg_color=settings.ctm.SF__BG_COLOR)
|
||||
target_compact_mode_frame_widget.children["!ctkframe"].configure(fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_BG_COLOR)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(img, width, height) = openImageKeepAspectRatio(settings.image_file.VRCT_LOGO, settings.uism.SF__LOGO_MAX_SIZE)
|
||||
main_window.sidebar_logo = CTkLabel(
|
||||
main_window.sidebar_bg_container,
|
||||
fg_color=settings.ctm.SIDEBAR_BG_COLOR,
|
||||
text=None,
|
||||
height=0,
|
||||
image=CTkImage(img, size=(width,height))
|
||||
)
|
||||
main_window.sidebar_logo.grid(row=0, column=0, pady=settings.uism.SF__LOGO_PADY)
|
||||
|
||||
# "height-a_s" represents the adjustment in size, and the "pady+a_s/2" indicates a padding increase of 4 pixels to compensate for the reduction.
|
||||
a_s = settings.uism.SF__LOGO_HEIGHT_FOR_ADJUSTMENT
|
||||
(img, width, height) = openImageKeepAspectRatio(settings.image_file.VRCT_LOGO_MARK, height-a_s)
|
||||
main_window.sidebar_compact_mode_logo = CTkLabel(
|
||||
main_window.sidebar_compact_mode_bg_container,
|
||||
fg_color=settings.ctm.SIDEBAR_BG_COLOR,
|
||||
text=None,
|
||||
height=0,
|
||||
image=CTkImage(img, size=(width,height))
|
||||
)
|
||||
main_window.sidebar_compact_mode_logo.grid(row=0, column=0, pady=(
|
||||
int(settings.uism.SF__LOGO_PADY[0]+a_s/2),
|
||||
int(settings.uism.SF__LOGO_PADY[1]+a_s/2)
|
||||
))
|
||||
|
||||
# Sidebar Features
|
||||
main_window.sidebar_features_container = CTkFrame(main_window.sidebar_bg_container, corner_radius=0, fg_color="transparent", width=0, height=0)
|
||||
main_window.sidebar_features_container.grid(row=1, column=0, pady=0, sticky="ew")
|
||||
main_window.sidebar_features_container.grid_columnconfigure(0, weight=1)
|
||||
|
||||
|
||||
|
||||
# Sidebar Features Compact Mode
|
||||
main_window.sidebar_compact_mode_features_container = CTkFrame(main_window.sidebar_compact_mode_bg_container, corner_radius=0, fg_color="transparent", width=0, height=0)
|
||||
main_window.sidebar_compact_mode_features_container.grid(row=1, column=0, pady=0, sticky="ew")
|
||||
main_window.sidebar_compact_mode_features_container.grid_columnconfigure(0, weight=1)
|
||||
|
||||
|
||||
|
||||
sidebar_features_settings = [
|
||||
{
|
||||
"frame_attr_name": "translation_frame",
|
||||
"command": toggleTranslationFeature,
|
||||
"switch_box_attr_name": "translation_switch_box",
|
||||
"toggle_switch_box_command": lambda e: main_window.translation_switch_box.toggle(),
|
||||
"label_attr_name": "label_translation",
|
||||
"compact_mode_icon_attr_name": "translation_compact_mode_icon",
|
||||
"compact_mode_frame_attr_name": "compact_mode_translation_frame",
|
||||
"selected_mark_attr_name": "translation_selected_mark",
|
||||
"var_label_text": view_variable.VAR_LABEL_TRANSLATION,
|
||||
"icon_file": settings.image_file.TRANSLATION_ICON,
|
||||
},
|
||||
{
|
||||
"frame_attr_name": "transcription_send_frame",
|
||||
"command": toggleTranscriptionSendFeature,
|
||||
"switch_box_attr_name": "transcription_send_switch_box",
|
||||
"toggle_switch_box_command": lambda e: main_window.transcription_send_switch_box.toggle(),
|
||||
"label_attr_name": "label_transcription_send",
|
||||
"compact_mode_icon_attr_name": "transcription_send_compact_mode_icon",
|
||||
"compact_mode_frame_attr_name": "compact_mode_transcription_send_frame",
|
||||
"selected_mark_attr_name": "transcription_send_selected_mark",
|
||||
"var_label_text": view_variable.VAR_LABEL_TRANSCRIPTION_SEND,
|
||||
"icon_file": settings.image_file.MIC_ICON,
|
||||
},
|
||||
{
|
||||
"frame_attr_name": "transcription_receive_frame",
|
||||
"command": toggleTranscriptionReceiveFeature,
|
||||
"switch_box_attr_name": "transcription_receive_switch_box",
|
||||
"toggle_switch_box_command": lambda e: main_window.transcription_receive_switch_box.toggle(),
|
||||
"label_attr_name": "label_transcription_receive",
|
||||
"compact_mode_icon_attr_name": "transcription_receive_compact_mode_icon",
|
||||
"compact_mode_frame_attr_name": "compact_mode_transcription_receive_frame",
|
||||
"selected_mark_attr_name": "transcription_receive_selected_mark",
|
||||
"var_label_text": view_variable.VAR_LABEL_TRANSCRIPTION_RECEIVE,
|
||||
"icon_file": settings.image_file.HEADPHONES_ICON,
|
||||
},
|
||||
{
|
||||
"frame_attr_name": "foreground_frame",
|
||||
"command": toggleForegroundFeature,
|
||||
"switch_box_attr_name": "foreground_switch_box",
|
||||
"toggle_switch_box_command": lambda e: main_window.foreground_switch_box.toggle(),
|
||||
"label_attr_name": "label_foreground",
|
||||
"compact_mode_icon_attr_name": "foreground_compact_mode_icon",
|
||||
"compact_mode_frame_attr_name": "compact_mode_foreground_frame",
|
||||
"selected_mark_attr_name": "foreground_selected_mark",
|
||||
"var_label_text": view_variable.VAR_LABEL_FOREGROUND,
|
||||
"icon_file": settings.image_file.FOREGROUND_ICON,
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
||||
row=0
|
||||
for sfs in sidebar_features_settings:
|
||||
frame_attr_name = sfs["frame_attr_name"]
|
||||
command = sfs["command"]
|
||||
switch_box_attr_name = sfs["switch_box_attr_name"]
|
||||
toggle_switch_box_command = sfs["toggle_switch_box_command"]
|
||||
label_attr_name = sfs["label_attr_name"]
|
||||
compact_mode_icon_attr_name = sfs["compact_mode_icon_attr_name"]
|
||||
compact_mode_frame_attr_name = sfs["compact_mode_frame_attr_name"]
|
||||
selected_mark_attr_name = sfs["selected_mark_attr_name"]
|
||||
var_label_text = sfs["var_label_text"]
|
||||
icon_file = sfs["icon_file"]
|
||||
|
||||
frame_widget = CTkFrame(main_window.sidebar_features_container, corner_radius=0, fg_color=settings.ctm.SF__BG_COLOR, cursor="hand2", width=0, height=0)
|
||||
setattr(main_window, frame_attr_name, frame_widget)
|
||||
|
||||
frame_widget.grid(row=row, column=0, pady=(0,1), sticky="ew")
|
||||
frame_widget.grid_columnconfigure(0, weight=1)
|
||||
|
||||
compact_mode_frame_widget = CTkFrame(main_window.sidebar_compact_mode_features_container, corner_radius=0, fg_color=settings.ctm.SF__BG_COLOR, cursor="hand2", width=0, height=0)
|
||||
setattr(main_window, compact_mode_frame_attr_name, compact_mode_frame_widget)
|
||||
|
||||
compact_mode_frame_widget.grid(row=row, column=0, pady=(0,1), sticky="ew")
|
||||
compact_mode_frame_widget.grid_columnconfigure(0, weight=1)
|
||||
|
||||
|
||||
label_widget = CTkLabel(
|
||||
frame_widget,
|
||||
textvariable=var_label_text,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SF__LABEL_FONT_SIZE, weight="normal"),
|
||||
anchor="w",
|
||||
text_color=settings.ctm.LABELS_TEXT_COLOR,
|
||||
)
|
||||
setattr(main_window, label_attr_name, label_widget)
|
||||
|
||||
|
||||
switch_box_widget = CTkSwitch(
|
||||
frame_widget,
|
||||
text=None,
|
||||
height=0,
|
||||
width=0,
|
||||
corner_radius=int(settings.uism.SF__SWITCH_BOX_HEIGHT/2),
|
||||
border_width=0,
|
||||
switch_height=settings.uism.SF__SWITCH_BOX_HEIGHT,
|
||||
switch_width=settings.uism.SF__SWITCH_BOX_WIDTH,
|
||||
onvalue=True,
|
||||
offvalue=False,
|
||||
command=command,
|
||||
fg_color=settings.ctm.SF__SWITCH_BOX_BG_COLOR,
|
||||
bg_color=settings.ctm.SF__BG_COLOR,
|
||||
progress_color=settings.ctm.SF__SWITCH_BOX_ACTIVE_BG_COLOR,
|
||||
button_color=settings.ctm.SF__SWITCH_BOX_BUTTON_COLOR,
|
||||
# button_hover_color=settings.ctm.SF__SWITCH_BOX_BUTTON_HOVERED_COLOR,
|
||||
)
|
||||
setattr(main_window, switch_box_attr_name, switch_box_widget)
|
||||
|
||||
|
||||
|
||||
# for compact mode
|
||||
compact_mode_icon_widget = CTkLabel(
|
||||
compact_mode_frame_widget,
|
||||
text=None,
|
||||
height=0,
|
||||
corner_radius=0,
|
||||
image=CTkImage(icon_file, size=settings.uism.SF__COMPACT_MODE_IMAGE_SIZE),
|
||||
)
|
||||
setattr(main_window, compact_mode_icon_attr_name, compact_mode_icon_widget)
|
||||
|
||||
selected_mark_widget = CTkFrame(
|
||||
compact_mode_frame_widget,
|
||||
corner_radius=0,
|
||||
fg_color=settings.ctm.SF__SELECTED_MARK_ACTIVE_BG_COLOR,
|
||||
width=settings.uism.SF__SELECTED_MARK_WIDTH,
|
||||
height=0
|
||||
)
|
||||
setattr(main_window, selected_mark_attr_name, selected_mark_widget)
|
||||
|
||||
|
||||
# Arrange
|
||||
compact_mode_icon_widget.grid(row=row, column=0, padx=settings.uism.SF__COMPACT_MODE_ICON_PADX, pady=settings.uism.SF__COMPACT_MODE_ICON_PADY)
|
||||
selected_mark_widget.place(relx=-1, rely=0.5, relheight=0.75, anchor="center")
|
||||
|
||||
label_widget.grid(row=row, column=0, pady=settings.uism.SF__LABELS_IPADY, padx=(settings.uism.SF__LABEL_LEFT_PAD,0), sticky="ew")
|
||||
switch_box_widget.grid(row=row, column=1, padx=settings.uism.SF__SWITCH_BOX_PADX, sticky="e")
|
||||
|
||||
|
||||
# Unbind the event "<Button-1>" originally set up by the widget to manually control it.
|
||||
switch_box_widget._canvas.unbind("<Button-1>")
|
||||
switch_box_widget._text_label.unbind("<Button-1>")
|
||||
|
||||
bindButtonReleaseFunction([compact_mode_icon_widget, frame_widget, compact_mode_frame_widget, label_widget, selected_mark_widget, switch_box_widget._canvas, switch_box_widget._bg_canvas], toggle_switch_box_command)
|
||||
|
||||
retag("vrct_"+frame_attr_name, compact_mode_icon_widget, frame_widget, compact_mode_frame_widget, label_widget, selected_mark_widget, switch_box_widget)
|
||||
|
||||
def commonEventFunction(e, event_type):
|
||||
for ww in e.widget.master.bindtags():
|
||||
if ww.startswith("vrct_"):
|
||||
ww = ww.replace("vrct_", "")
|
||||
changeSidebarFeaturesColorByEvents(ww, event_type)
|
||||
break
|
||||
|
||||
def enterFunction(e):
|
||||
commonEventFunction(e, "enter")
|
||||
|
||||
def leaveFunction(e):
|
||||
commonEventFunction(e, "leave")
|
||||
|
||||
def buttonPressFunction(e):
|
||||
commonEventFunction(e, "button_press")
|
||||
|
||||
def buttonReleasedFunction(e):
|
||||
commonEventFunction(e, "button_release")
|
||||
|
||||
bindEnterAndLeaveFunction([compact_mode_icon_widget, frame_widget, compact_mode_frame_widget, label_widget, selected_mark_widget, switch_box_widget._canvas, switch_box_widget._bg_canvas], enterFunction, leaveFunction)
|
||||
|
||||
bindButtonPressAndReleaseFunction([compact_mode_icon_widget, frame_widget, compact_mode_frame_widget, label_widget, selected_mark_widget, switch_box_widget._canvas, switch_box_widget._bg_canvas], buttonPressFunction, buttonReleasedFunction)
|
||||
|
||||
callback = partial(toggleSidebarFeatureSelectedMarkIfTurnedOn, mark_widget=selected_mark_widget)
|
||||
frame_widget.markToggleManually = callback
|
||||
|
||||
row+=1
|
||||
@@ -0,0 +1,271 @@
|
||||
from customtkinter import CTkFont, CTkFrame, CTkLabel, CTkImage
|
||||
|
||||
from ....ui_utils import bindEnterAndLeaveColor, bindButtonPressColor, bindButtonReleaseFunction, switchActiveTabAndPassiveTab, switchTabsColor, createOptionMenuBox
|
||||
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
|
||||
def createSidebarLanguagesSettings(settings, main_window, view_variable):
|
||||
|
||||
|
||||
def switchActiveAndPassivePresetsTabsColor(target_active_widget):
|
||||
quick_setting_tabs = [
|
||||
getattr(main_window, "sls__presets_button_1"),
|
||||
getattr(main_window, "sls__presets_button_2"),
|
||||
getattr(main_window, "sls__presets_button_3")
|
||||
]
|
||||
|
||||
switchTabsColor(
|
||||
target_widget=target_active_widget,
|
||||
tab_buttons=quick_setting_tabs,
|
||||
active_bg_color=settings.ctm.SLS__PRESETS_TAB_BG_ACTIVE_COLOR,
|
||||
active_text_color=settings.ctm.SLS__PRESETS_TAB_ACTIVE_TEXT_COLOR,
|
||||
passive_bg_color=settings.ctm.SLS__PRESETS_TAB_BG_PASSIVE_COLOR,
|
||||
passive_text_color=settings.ctm.SLS__PRESETS_TAB_ACTIVE_TEXT_COLOR_PASSIVE
|
||||
)
|
||||
|
||||
def switchPresetTabFunction(target_active_widget):
|
||||
switchActiveAndPassivePresetsTabsColor(target_active_widget)
|
||||
switchActiveTabAndPassiveTab(target_active_widget, main_window.current_active_preset_tab, main_window.current_active_preset_tab.passive_function, settings.ctm.SLS__PRESETS_TAB_BG_HOVERED_COLOR, settings.ctm.SLS__PRESETS_TAB_BG_CLICKED_COLOR, settings.ctm.SLS__PRESETS_TAB_BG_PASSIVE_COLOR)
|
||||
main_window.current_active_preset_tab = target_active_widget
|
||||
|
||||
|
||||
|
||||
def switchToPreset1(e):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SELECTED_LANGUAGE_PRESET_TAB, "1")
|
||||
target_active_widget = getattr(main_window, "sls__presets_button_1")
|
||||
switchPresetTabFunction(target_active_widget)
|
||||
|
||||
def switchToPreset2(e):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SELECTED_LANGUAGE_PRESET_TAB, "2")
|
||||
target_active_widget = getattr(main_window, "sls__presets_button_2")
|
||||
switchPresetTabFunction(target_active_widget)
|
||||
|
||||
def switchToPreset3(e):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_SELECTED_LANGUAGE_PRESET_TAB, "3")
|
||||
target_active_widget = getattr(main_window, "sls__presets_button_3")
|
||||
switchPresetTabFunction(target_active_widget)
|
||||
|
||||
|
||||
|
||||
def createLanguageSettingBox(parent_widget, var_title_text, title_text_attr_name, arrow_img_attr_name, open_selectable_language_window_command, variable):
|
||||
sls__box = CTkFrame(parent_widget, corner_radius=0, fg_color=settings.ctm.SLS__BOX_BG_COLOR, width=0, height=0)
|
||||
|
||||
sls__box.grid_columnconfigure(1, weight=1)
|
||||
|
||||
sls__box_wrapper = CTkFrame(sls__box, corner_radius=0, fg_color=settings.ctm.SLS__BOX_BG_COLOR, width=0, height=0)
|
||||
sls__box_wrapper.grid(row=2, column=1, padx=settings.uism.SLS__BOX_IPADX, pady=settings.uism.SLS__BOX_IPADY, sticky="ew")
|
||||
|
||||
sls__box_wrapper.grid_columnconfigure(0, weight=1)
|
||||
|
||||
|
||||
sls__box_label_wrapper = CTkFrame(sls__box_wrapper, corner_radius=0, fg_color=settings.ctm.SLS__BOX_BG_COLOR, width=0, height=0)
|
||||
sls__box_label_wrapper.grid(row=0, column=0)
|
||||
|
||||
sls__box_label_wrapper.grid_columnconfigure((0,2), weight=1)
|
||||
sls__label = CTkLabel(
|
||||
sls__box_label_wrapper,
|
||||
textvariable=var_title_text,
|
||||
height=0,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SLS__BOX_SECTION_TITLE_FONT_SIZE, weight="normal"),
|
||||
text_color=settings.ctm.SLS__BOX_SECTION_TITLE_TEXT_COLOR
|
||||
)
|
||||
sls__label.grid(row=0, column=1, pady=(0,settings.uism.SLS__BOX_SECTION_TITLE_BOTTOM_PADY))
|
||||
setattr(main_window, title_text_attr_name, sls__label)
|
||||
|
||||
|
||||
|
||||
|
||||
sls__box_optionmenu_wrapper = CTkFrame(sls__box_wrapper, corner_radius=0, fg_color=settings.ctm.SLS__BOX_BG_COLOR, width=0, height=0)
|
||||
sls__box_optionmenu_wrapper.grid(row=1, column=0, sticky="ew")
|
||||
|
||||
sls__box_optionmenu_wrapper.grid_columnconfigure(0, weight=1)
|
||||
(sls__selected_language_box, optionmenu_label_widget, optionmenu_img_widget) = createOptionMenuBox(
|
||||
parent_widget=sls__box_optionmenu_wrapper,
|
||||
optionmenu_bg_color=settings.ctm.SLS__OPTIONMENU_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,0),
|
||||
optionmenu_ipady=settings.uism.SLS__BOX_OPTION_MENU_IPADY,
|
||||
variable=variable,
|
||||
font_family=settings.FONT_FAMILY,
|
||||
font_size=settings.uism.SLS__BOX_OPTION_MENU_FONT_SIZE,
|
||||
text_color=settings.ctm.LABELS_TEXT_COLOR,
|
||||
image_file=settings.image_file.ARROW_LEFT.rotate(180),
|
||||
image_size=settings.uism.SLS__BOX_OPTION_MENU_ARROW_IMAGE_SIZE,
|
||||
optionmenu_clicked_command=open_selectable_language_window_command,
|
||||
|
||||
optionmenu_position="center",
|
||||
setattr_widget=main_window,
|
||||
image_widget_attr_name=arrow_img_attr_name,
|
||||
)
|
||||
sls__selected_language_box.grid(row=0, column=0, sticky="ew")
|
||||
|
||||
sls__box_optionmenu_wrapper_fix_1px_bug = CTkFrame(optionmenu_label_widget, corner_radius=0, width=0, height=0)
|
||||
sls__box_optionmenu_wrapper_fix_1px_bug.grid(row=0, column=1, sticky="ns")
|
||||
|
||||
return sls__box
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Sidebar Languages Settings, SLS
|
||||
main_window.sls__container = CTkFrame(main_window.sidebar_bg_container, corner_radius=0, fg_color=settings.ctm.SIDEBAR_BG_COLOR, width=0, height=0)
|
||||
|
||||
main_window.sls__container.grid(row=2, column=0, sticky="new")
|
||||
|
||||
main_window.sls__container.grid_columnconfigure(0, weight=1)
|
||||
|
||||
|
||||
main_window.sls__container_title = CTkLabel(main_window.sls__container,
|
||||
textvariable=view_variable.VAR_LABEL_LANGUAGE_SETTINGS,
|
||||
height=0,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SLS__TITLE_FONT_SIZE, weight="normal"),
|
||||
text_color=settings.ctm.SLS__TITLE_TEXT_COLOR
|
||||
)
|
||||
main_window.sls__container_title.grid(row=0, column=0, pady=settings.uism.SLS__TITLE_PADY, sticky="nsew")
|
||||
|
||||
|
||||
|
||||
# Presets buttons
|
||||
main_window.sidebar_bg_container.grid_rowconfigure(2, weight=1)
|
||||
main_window.sls__presets_buttons_container = CTkFrame(main_window.sls__container, corner_radius=0, fg_color=settings.ctm.SIDEBAR_BG_COLOR, width=0, height=settings.uism.SLS__PRESET_TAB_NUMBER_HEIGHT)
|
||||
main_window.sls__presets_buttons_container.grid(row=1, column=0, sticky="nsew")
|
||||
|
||||
main_window.sls__presets_buttons_box = CTkFrame(main_window.sls__presets_buttons_container, corner_radius=0, fg_color=settings.ctm.SIDEBAR_BG_COLOR, width=0, height=0)
|
||||
main_window.sls__presets_buttons_box.place(relwidth=1, relx=0, rely=1.15, anchor="sw")
|
||||
|
||||
main_window.sls__presets_buttons_box.grid_columnconfigure((0,1,2), weight=1)
|
||||
|
||||
|
||||
preset_tabs_settings = [
|
||||
{
|
||||
"preset_tab_attr_name": "sls__presets_button_1",
|
||||
"command": switchToPreset1,
|
||||
"text": "1",
|
||||
},
|
||||
{
|
||||
"preset_tab_attr_name": "sls__presets_button_2",
|
||||
"command": switchToPreset2,
|
||||
"text": "2",
|
||||
},
|
||||
{
|
||||
"preset_tab_attr_name": "sls__presets_button_3",
|
||||
"command": switchToPreset3,
|
||||
"text": "3",
|
||||
},
|
||||
]
|
||||
|
||||
column=0
|
||||
for preset_tab_settings in preset_tabs_settings:
|
||||
preset_tab_attr_name = preset_tab_settings["preset_tab_attr_name"]
|
||||
command = preset_tab_settings["command"]
|
||||
text = preset_tab_settings["text"]
|
||||
|
||||
setattr(
|
||||
main_window,
|
||||
preset_tab_attr_name,
|
||||
CTkFrame(
|
||||
main_window.sls__presets_buttons_box,
|
||||
corner_radius=settings.uism.SLS__PRESET_TAB_NUMBER_CORNER_RADIUS,
|
||||
fg_color=settings.ctm.SLS__PRESETS_TAB_BG_PASSIVE_COLOR,
|
||||
width=0,
|
||||
height=settings.uism.SLS__PRESET_TAB_NUMBER_ADJUSTED_HEIGHT,
|
||||
cursor="hand2",
|
||||
)
|
||||
)
|
||||
parent_widget = getattr(main_window, preset_tab_attr_name)
|
||||
parent_widget.grid(row=0, column=column, sticky="ew")
|
||||
|
||||
label_widget = CTkLabel(
|
||||
parent_widget,
|
||||
text=text,
|
||||
height=0,
|
||||
fg_color=settings.ctm.SLS__PRESETS_TAB_BG_PASSIVE_COLOR,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SLS__PRESET_TAB_NUMBER_FONT_SIZE, weight="bold"),
|
||||
anchor="center",
|
||||
text_color=settings.ctm.SLS__PRESETS_TAB_ACTIVE_TEXT_COLOR_PASSIVE
|
||||
)
|
||||
label_widget.place(relx=0.5, rely=0.44, anchor="center")
|
||||
|
||||
|
||||
|
||||
bindEnterAndLeaveColor([parent_widget, label_widget], settings.ctm.SLS__PRESETS_TAB_BG_HOVERED_COLOR, settings.ctm.SLS__PRESETS_TAB_BG_PASSIVE_COLOR)
|
||||
bindButtonPressColor([parent_widget, label_widget], settings.ctm.SLS__PRESETS_TAB_BG_CLICKED_COLOR, settings.ctm.SLS__PRESETS_TAB_BG_PASSIVE_COLOR)
|
||||
|
||||
parent_widget.passive_function = command
|
||||
bindButtonReleaseFunction([parent_widget, label_widget], command)
|
||||
|
||||
column+=1
|
||||
|
||||
|
||||
def callbackOpenSelectableYourLanguageWindow(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_OPEN_SELECTABLE_YOUR_LANGUAGE_WINDOW, value)
|
||||
|
||||
|
||||
def callbackOpenSelectableTargetLanguageWindow(value):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_OPEN_SELECTABLE_TARGET_LANGUAGE_WINDOW, value)
|
||||
|
||||
# Language Settings BOX
|
||||
main_window.sls__box_frame = CTkFrame(main_window.sls__container, corner_radius=0, fg_color=settings.ctm.SLS__BG_COLOR, width=0, height=0)
|
||||
main_window.sls__box_frame.grid(row=2, column=0, sticky="ew")
|
||||
main_window.sls__box_frame.grid_columnconfigure(0, weight=1)
|
||||
|
||||
# Your language
|
||||
main_window.sls__box_your_language = createLanguageSettingBox(
|
||||
parent_widget=main_window.sls__box_frame,
|
||||
var_title_text=view_variable.VAR_LABEL_YOUR_LANGUAGE,
|
||||
title_text_attr_name="sls__title_text_your_language",
|
||||
arrow_img_attr_name="sls__arrow_img_your_language",
|
||||
open_selectable_language_window_command=callbackOpenSelectableYourLanguageWindow,
|
||||
variable=view_variable.VAR_YOUR_LANGUAGE
|
||||
)
|
||||
main_window.sls__box_your_language.grid(row=2, column=0, pady=(settings.uism.SLS__BOX_TOP_PADY,0),sticky="ew")
|
||||
|
||||
|
||||
# Both direction arrow icon
|
||||
main_window.sls__arrow_direction_box = CTkFrame(main_window.sls__box_frame, corner_radius=0, fg_color=settings.ctm.SLS__BG_COLOR, width=0, height=0)
|
||||
main_window.sls__arrow_direction_box.grid(row=3, column=0, pady=settings.uism.SLS__BOX_ARROWS_PADY,sticky="ew")
|
||||
|
||||
main_window.sls__arrow_direction_box.grid_columnconfigure((0,4), weight=1)
|
||||
|
||||
main_window.sls__both_direction_up = CTkLabel(
|
||||
main_window.sls__arrow_direction_box,
|
||||
text=None,
|
||||
height=0,
|
||||
image=CTkImage((settings.image_file.NARROW_ARROW_DOWN).rotate(180),size=settings.uism.SLS__BOX_ARROWS_IMAGE_SIZE)
|
||||
|
||||
)
|
||||
main_window.sls__both_direction_up.grid(row=0, column=1, pady=0)
|
||||
|
||||
main_window.sls__both_direction_desc = CTkLabel(
|
||||
main_window.sls__arrow_direction_box,
|
||||
textvariable=view_variable.VAR_LABEL_BOTH_DIRECTION_DESC,
|
||||
height=0,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.SLS__BOX_ARROWS_DESC_FONT_SIZE, weight="normal"),
|
||||
text_color=settings.ctm.SLS__BOX_ARROWS_TEXT_COLOR,
|
||||
)
|
||||
main_window.sls__both_direction_desc.grid(row=0, column=2, padx=settings.uism.SLS__BOX_ARROWS_DESC_PADX)
|
||||
|
||||
main_window.sls__both_direction_label_down = CTkLabel(
|
||||
main_window.sls__arrow_direction_box,
|
||||
text=None,
|
||||
height=0,
|
||||
image=CTkImage((settings.image_file.NARROW_ARROW_DOWN).rotate(0),size=settings.uism.SLS__BOX_ARROWS_IMAGE_SIZE)
|
||||
|
||||
)
|
||||
main_window.sls__both_direction_label_down.grid(row=0, column=3)
|
||||
|
||||
|
||||
|
||||
# Target language
|
||||
main_window.sls__box_target_language = createLanguageSettingBox(
|
||||
parent_widget=main_window.sls__box_frame,
|
||||
var_title_text=view_variable.VAR_LABEL_TARGET_LANGUAGE,
|
||||
title_text_attr_name="sls__title_text_target_language",
|
||||
arrow_img_attr_name="sls__arrow_img_target_language",
|
||||
open_selectable_language_window_command=callbackOpenSelectableTargetLanguageWindow,
|
||||
variable=view_variable.VAR_TARGET_LANGUAGE
|
||||
)
|
||||
main_window.sls__box_target_language.grid(row=4, column=0, sticky="ew")
|
||||
34
vrct_gui/main_window/widgets/create_entry_message_box.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from customtkinter import CTkFont, CTkFrame, CTkEntry
|
||||
|
||||
def createEntryMessageBox(settings, main_window):
|
||||
main_window.main_entry_message_container = CTkFrame(main_window.main_bg_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0)
|
||||
main_window.main_entry_message_container.grid(row=2, column=0, sticky="ew")
|
||||
|
||||
|
||||
main_window.main_entry_message_container.grid_columnconfigure(0, weight=1)
|
||||
main_window.entry_message_box = CTkEntry(
|
||||
main_window.main_entry_message_container,
|
||||
border_color=settings.ctm.TEXTBOX_ENTRY_BORDER_COLOR,
|
||||
fg_color=settings.ctm.TEXTBOX_ENTRY_BG_COLOR,
|
||||
text_color=settings.ctm.TEXTBOX_ENTRY_TEXT_COLOR,
|
||||
placeholder_text="Enter your message...",
|
||||
placeholder_text_color=settings.ctm.TEXTBOX_ENTRY_PLACEHOLDER_COLOR,
|
||||
height=settings.uism.TEXTBOX_ENTRY_HEIGHT,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TEXTBOX_ENTRY_FONT_SIZE, weight="normal"),
|
||||
)
|
||||
main_window.entry_message_box.grid(row=0, column=0, padx=settings.uism.TEXTBOX_ENTRY_PADX, pady=settings.uism.TEXTBOX_ENTRY_PADY, sticky="nsew")
|
||||
main_window.entry_message_box._entry.grid(padx=settings.uism.TEXTBOX_ENTRY_IPADX, pady=settings.uism.TEXTBOX_ENTRY_IPADY)
|
||||
|
||||
|
||||
def messageBoxAnyKeyPress(e):
|
||||
BREAK_KEYSYM_LIST = [
|
||||
"Delete", "Select", "Up", "Down", "Next", "End", "Print",
|
||||
"Prior","Insert","Home", "Left", "Clear", "Right", "Linefeed"
|
||||
]
|
||||
if e.keysym != "??":
|
||||
if len(e.char) != 0 and e.keysym in BREAK_KEYSYM_LIST:
|
||||
main_window.entry_message_box.insert("end", e.char)
|
||||
return "break"
|
||||
|
||||
main_window.entry_message_box.bind("<Any-KeyPress>", messageBoxAnyKeyPress)
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
|
||||
from customtkinter import CTkFrame, CTkLabel, CTkImage
|
||||
|
||||
from ...ui_utils import bindEnterAndLeaveColor, bindButtonPressColor, bindButtonReleaseFunction
|
||||
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
def createMinimizeSidebarButton(settings, main_window, view_variable):
|
||||
|
||||
def enableCompactMode(e):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_ENABLE_MAIN_WINDOW_SIDEBAR_COMPACT_MODE)
|
||||
|
||||
def disableCompactMode(e):
|
||||
callFunctionIfCallable(view_variable.CALLBACK_DISABLE_MAIN_WINDOW_SIDEBAR_COMPACT_MODE)
|
||||
|
||||
|
||||
|
||||
main_window.minimize_sidebar_button_container__for_closing = CTkFrame(main_window.main_topbar_container, corner_radius=0, fg_color=settings.ctm.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR, cursor="hand2", width=0, height=0)
|
||||
main_window.minimize_sidebar_button_container__for_opening = CTkFrame(main_window.main_topbar_container, corner_radius=0, fg_color=settings.ctm.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR, cursor="hand2", width=0, height=0)
|
||||
|
||||
|
||||
|
||||
|
||||
# For Closing [<]
|
||||
main_window.minimize_sidebar_button__for_closing = CTkLabel(
|
||||
main_window.minimize_sidebar_button_container__for_closing,
|
||||
text=None,
|
||||
corner_radius=0,
|
||||
height=0,
|
||||
image=CTkImage((settings.image_file.ARROW_LEFT),size=(settings.uism.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_X,settings.uism.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_Y))
|
||||
)
|
||||
|
||||
main_window.minimize_sidebar_button_container__for_closing.grid_rowconfigure((0,2), weight=1)
|
||||
main_window.minimize_sidebar_button__for_closing.grid(row=1, column=0, padx=0, pady=0)
|
||||
|
||||
|
||||
bindEnterAndLeaveColor([main_window.minimize_sidebar_button__for_closing, main_window.minimize_sidebar_button_container__for_closing], settings.ctm.MINIMIZE_SIDEBAR_BUTTON_HOVERED_BG_COLOR, settings.ctm.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR)
|
||||
bindButtonPressColor([main_window.minimize_sidebar_button__for_closing, main_window.minimize_sidebar_button_container__for_closing], settings.ctm.MINIMIZE_SIDEBAR_BUTTON_CLICKED_BG_COLOR, settings.ctm.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR)
|
||||
bindButtonReleaseFunction([main_window.minimize_sidebar_button_container__for_closing, main_window.minimize_sidebar_button__for_closing], enableCompactMode)
|
||||
|
||||
|
||||
|
||||
|
||||
# For Opening [>]
|
||||
main_window.minimize_sidebar_button__for_opening = CTkLabel(
|
||||
main_window.minimize_sidebar_button_container__for_opening,
|
||||
text=None,
|
||||
corner_radius=0,
|
||||
height=0,
|
||||
image=CTkImage((settings.image_file.ARROW_LEFT).rotate(180),size=(settings.uism.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_X,settings.uism.MINIMIZE_SIDEBAR_BUTTON_ICON_SIZE_Y))
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
main_window.minimize_sidebar_button_container__for_opening.grid_rowconfigure((0,2), weight=1)
|
||||
main_window.minimize_sidebar_button__for_opening.grid(row=1, column=0, padx=0, pady=0)
|
||||
|
||||
|
||||
bindEnterAndLeaveColor([main_window.minimize_sidebar_button__for_opening, main_window.minimize_sidebar_button_container__for_opening], settings.ctm.MINIMIZE_SIDEBAR_BUTTON_HOVERED_BG_COLOR, settings.ctm.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR)
|
||||
bindButtonPressColor([main_window.minimize_sidebar_button__for_opening, main_window.minimize_sidebar_button_container__for_opening], settings.ctm.MINIMIZE_SIDEBAR_BUTTON_CLICKED_BG_COLOR, settings.ctm.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR)
|
||||
bindButtonReleaseFunction([main_window.minimize_sidebar_button_container__for_opening, main_window.minimize_sidebar_button__for_opening], disableCompactMode)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
main_window.minimize_sidebar_button_container__for_opening.grid(row=0, column=0, sticky="nsw")
|
||||
main_window.minimize_sidebar_button_container__for_closing.grid(row=0, column=0, sticky="nsw")
|
||||
main_window.minimize_sidebar_button_container__for_opening.grid_remove()
|
||||
64
vrct_gui/main_window/widgets/create_sidebar.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from customtkinter import CTkFrame, CTkLabel, CTkImage
|
||||
|
||||
from ...ui_utils import bindButtonFunctionAndColor
|
||||
from utils import callFunctionIfCallable
|
||||
|
||||
from ._create_sidebar import createSidebarFeatures, createSidebarLanguagesSettings
|
||||
|
||||
def createSidebar(settings, main_window, view_variable):
|
||||
# Side Bar Container
|
||||
main_window.toplevel_wrapper.grid_rowconfigure(0, weight=1)
|
||||
|
||||
main_window.sidebar_bg_container_wrapper = CTkFrame(main_window.toplevel_wrapper, corner_radius=0, fg_color=settings.ctm.SIDEBAR_BG_COLOR, width=0, height=0)
|
||||
main_window.sidebar_bg_container_wrapper.grid(row=0, column=0, sticky="nsew")
|
||||
|
||||
|
||||
main_window.sidebar_bg_container = CTkFrame(main_window.sidebar_bg_container_wrapper, corner_radius=0, fg_color=settings.ctm.SIDEBAR_BG_COLOR, width=0, height=0)
|
||||
main_window.sidebar_compact_mode_bg_container = CTkFrame(main_window.sidebar_bg_container_wrapper, corner_radius=0, fg_color=settings.ctm.SIDEBAR_BG_COLOR, width=0, height=0)
|
||||
|
||||
|
||||
main_window.sidebar_bg_container.grid_columnconfigure(0, weight=1, minsize=settings.uism.SIDEBAR_MIN_WIDTH)
|
||||
main_window.sidebar_compact_mode_bg_container.grid_columnconfigure(0, weight=1)
|
||||
|
||||
|
||||
createSidebarFeatures(settings, main_window, view_variable)
|
||||
createSidebarLanguagesSettings(settings, main_window, view_variable)
|
||||
|
||||
|
||||
main_window.sidebar_bg_container.grid(row=0, column=0, sticky="nsew")
|
||||
main_window.sidebar_compact_mode_bg_container.grid(row=0, column=0, sticky="nsew")
|
||||
main_window.sidebar_compact_mode_bg_container.grid_remove()
|
||||
|
||||
|
||||
# Config Button
|
||||
main_window.sidebar_bg_container_wrapper.grid_rowconfigure(3, weight=1)
|
||||
|
||||
main_window.sidebar_config_button_container = CTkFrame(main_window.sidebar_bg_container_wrapper, corner_radius=0, fg_color=settings.ctm.CONFIG_BUTTON_BG_COLOR, width=0, height=0)
|
||||
main_window.sidebar_config_button_container.grid(row=4, column=0, sticky="sew")
|
||||
|
||||
|
||||
main_window.sidebar_config_button_container.grid_columnconfigure(0, weight=1)
|
||||
main_window.sidebar_config_button_wrapper = CTkFrame(main_window.sidebar_config_button_container, corner_radius=settings.uism.SIDEBAR_CONFIG_BUTTON_CORNER_RADIUS, fg_color=settings.ctm.CONFIG_BUTTON_BG_COLOR, height=0, width=0, cursor="hand2")
|
||||
main_window.sidebar_config_button_wrapper.grid(row=0, column=0, padx=settings.uism.SIDEBAR_CONFIG_BUTTON_PADX, pady=settings.uism.SIDEBAR_CONFIG_BUTTON_PADY, sticky="ew")
|
||||
|
||||
|
||||
|
||||
|
||||
main_window.sidebar_config_button_wrapper.grid_columnconfigure(0, weight=1)
|
||||
|
||||
main_window.sidebar_config_button = CTkLabel(
|
||||
main_window.sidebar_config_button_wrapper,
|
||||
text=None,
|
||||
height=0,
|
||||
image=CTkImage(settings.image_file.CONFIGURATION_ICON, size=settings.uism.SIDEBAR_CONFIG_BUTTON_IMAGE_SIZE)
|
||||
)
|
||||
main_window.sidebar_config_button.grid(row=0, column=0, padx=0, pady=settings.uism.SIDEBAR_CONFIG_BUTTON_IPADY)
|
||||
|
||||
|
||||
bindButtonFunctionAndColor(
|
||||
target_widgets=[main_window.sidebar_config_button_wrapper, main_window.sidebar_config_button],
|
||||
enter_color=settings.ctm.CONFIG_BUTTON_HOVERED_BG_COLOR,
|
||||
leave_color=settings.ctm.CONFIG_BUTTON_BG_COLOR,
|
||||
clicked_color=settings.ctm.CONFIG_BUTTON_CLICKED_BG_COLOR,
|
||||
buttonReleasedFunction=lambda _e: callFunctionIfCallable(view_variable.CALLBACK_CLICKED_OPEN_CONFIG_WINDOW_BUTTON),
|
||||
)
|
||||
162
vrct_gui/main_window/widgets/create_textbox.py
Normal file
@@ -0,0 +1,162 @@
|
||||
from customtkinter import CTkFont, CTkFrame, CTkLabel, CTkTextbox
|
||||
|
||||
from ...ui_utils import bindEnterAndLeaveColor, bindButtonPressColor, bindButtonReleaseFunction, setDefaultActiveTab, switchActiveTabAndPassiveTab, switchTabsColor
|
||||
|
||||
|
||||
def createTextbox(settings, main_window, view_variable):
|
||||
|
||||
def switchTextbox(target_textbox_attr_name):
|
||||
main_window.current_active_textbox.grid_remove()
|
||||
main_window.current_active_textbox = getattr(main_window, target_textbox_attr_name)
|
||||
main_window.current_active_textbox.grid()
|
||||
|
||||
def switchToTextboxAll(e):
|
||||
target_active_widget = getattr(main_window, "textbox_tab_all")
|
||||
switchTextboxTabFunction(target_active_widget)
|
||||
switchTextbox("textbox_all")
|
||||
|
||||
def switchToTextboxSent(e):
|
||||
target_active_widget = getattr(main_window, "textbox_tab_sent")
|
||||
switchTextboxTabFunction(target_active_widget)
|
||||
switchTextbox("textbox_sent")
|
||||
|
||||
def switchToTextboxReceived(e):
|
||||
target_active_widget = getattr(main_window, "textbox_tab_received")
|
||||
switchTextboxTabFunction(target_active_widget)
|
||||
switchTextbox("textbox_received")
|
||||
|
||||
def switchToTextboxSystem(e):
|
||||
target_active_widget = getattr(main_window, "textbox_tab_system")
|
||||
switchTextboxTabFunction(target_active_widget)
|
||||
switchTextbox("textbox_system")
|
||||
|
||||
|
||||
def switchTextboxTabFunction(target_active_widget):
|
||||
switchActiveAndPassiveTextboxTabsColor(target_active_widget)
|
||||
switchActiveTabAndPassiveTab(target_active_widget, main_window.current_active_textbox_tab, main_window.current_active_textbox_tab.passive_function, settings.ctm.TEXTBOX_TAB_BG_HOVERED_COLOR, settings.ctm.TEXTBOX_TAB_BG_CLICKED_COLOR, settings.ctm.TEXTBOX_TAB_BG_PASSIVE_COLOR)
|
||||
main_window.current_active_textbox_tab = target_active_widget
|
||||
|
||||
def switchActiveAndPassiveTextboxTabsColor(target_active_widget):
|
||||
textbox_tabs = [
|
||||
getattr(main_window, "textbox_tab_all"),
|
||||
getattr(main_window, "textbox_tab_sent"),
|
||||
getattr(main_window, "textbox_tab_received"),
|
||||
getattr(main_window, "textbox_tab_system")
|
||||
]
|
||||
|
||||
switchTabsColor(
|
||||
target_widget=target_active_widget,
|
||||
tab_buttons=textbox_tabs,
|
||||
active_bg_color=settings.ctm.TEXTBOX_BG_COLOR,
|
||||
active_text_color=settings.ctm.SLS__PRESETS_TAB_ACTIVE_TEXT_COLOR,
|
||||
passive_bg_color=settings.ctm.TEXTBOX_TAB_BG_PASSIVE_COLOR,
|
||||
passive_text_color=settings.ctm.TEXTBOX_TAB_TEXT_PASSIVE_COLOR
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
# Text box
|
||||
main_window.main_bg_container.grid_rowconfigure(1, weight=1)
|
||||
main_window.main_textbox_container = CTkFrame(main_window.main_bg_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0)
|
||||
main_window.main_textbox_container.grid(row=1, column=0, sticky="nsew")
|
||||
|
||||
main_window.main_textbox_container.grid_columnconfigure(0,weight=1)
|
||||
main_window.main_textbox_container.grid_rowconfigure(0,weight=1)
|
||||
|
||||
main_window.textbox_switch_tabs_container = CTkFrame(main_window.main_topbar_center_container, corner_radius=0, fg_color=settings.ctm.MAIN_BG_COLOR, width=0, height=0)
|
||||
main_window.textbox_switch_tabs_container.place(relx=0.07, rely=1.15, anchor="sw")
|
||||
|
||||
main_window.textbox_switch_tabs_container.grid_columnconfigure((0,1,2,3), weight=1, uniform="textbox_tabs")
|
||||
|
||||
textbox_settings = [
|
||||
{
|
||||
"textbox_tab_attr_name": "textbox_tab_all",
|
||||
"command": switchToTextboxAll,
|
||||
"textbox_attr_name": "textbox_all",
|
||||
"textvariable": view_variable.VAR_LABEL_TEXTBOX_ALL
|
||||
},
|
||||
{
|
||||
"textbox_tab_attr_name": "textbox_tab_sent",
|
||||
"command": switchToTextboxSent,
|
||||
"textbox_attr_name": "textbox_sent",
|
||||
"textvariable": view_variable.VAR_LABEL_TEXTBOX_SENT
|
||||
},
|
||||
{
|
||||
"textbox_tab_attr_name": "textbox_tab_received",
|
||||
"command": switchToTextboxReceived,
|
||||
"textbox_attr_name": "textbox_received",
|
||||
"textvariable": view_variable.VAR_LABEL_TEXTBOX_RECEIVED
|
||||
},
|
||||
{
|
||||
"textbox_tab_attr_name": "textbox_tab_system",
|
||||
"command": switchToTextboxSystem,
|
||||
"textbox_attr_name": "textbox_system",
|
||||
"textvariable": view_variable.VAR_LABEL_TEXTBOX_SYSTEM
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
column=0
|
||||
for textbox_setting in textbox_settings:
|
||||
setattr(main_window, textbox_setting["textbox_tab_attr_name"],
|
||||
CTkFrame(
|
||||
main_window.textbox_switch_tabs_container,
|
||||
corner_radius=settings.uism.TEXTBOX_TAB_CORNER_RADIUS,
|
||||
fg_color=settings.ctm.TEXTBOX_TAB_BG_PASSIVE_COLOR,
|
||||
cursor="hand2",
|
||||
width=0,
|
||||
height=0
|
||||
)
|
||||
)
|
||||
target_widget = getattr(main_window, textbox_setting["textbox_tab_attr_name"])
|
||||
target_widget.grid(row=0, column=column, pady=0, padx=(0,2), sticky="ew")
|
||||
|
||||
|
||||
|
||||
target_widget.grid_columnconfigure((0,2), weight=1)
|
||||
setattr(main_window, "label_widget", CTkLabel(
|
||||
target_widget,
|
||||
textvariable=textbox_setting["textvariable"],
|
||||
corner_radius=0,
|
||||
font=CTkFont(family=settings.FONT_FAMILY, size=settings.uism.TEXTBOX_TAB_FONT_SIZE, weight="normal"),
|
||||
height=0,
|
||||
width=0,
|
||||
anchor="center",
|
||||
text_color=settings.ctm.TEXTBOX_TAB_TEXT_PASSIVE_COLOR,
|
||||
))
|
||||
label_widget = getattr(main_window, "label_widget")
|
||||
label_widget.grid(row=0, column=1, pady=settings.uism.TEXTBOX_TAB_PADY, padx=settings.uism.TEXTBOX_TAB_PADX)
|
||||
|
||||
bindEnterAndLeaveColor([target_widget, label_widget], settings.ctm.TEXTBOX_TAB_BG_HOVERED_COLOR, settings.ctm.TEXTBOX_TAB_BG_PASSIVE_COLOR)
|
||||
bindButtonPressColor([target_widget, label_widget], settings.ctm.TEXTBOX_TAB_BG_CLICKED_COLOR, settings.ctm.TEXTBOX_TAB_BG_PASSIVE_COLOR)
|
||||
|
||||
target_widget.passive_function = textbox_setting["command"]
|
||||
bindButtonReleaseFunction([target_widget, label_widget], textbox_setting["command"])
|
||||
|
||||
|
||||
|
||||
setattr(main_window, textbox_setting["textbox_attr_name"], CTkTextbox(
|
||||
main_window.main_textbox_container,
|
||||
corner_radius=settings.uism.TEXTBOX_CORNER_RADIUS,
|
||||
fg_color=settings.ctm.TEXTBOX_BG_COLOR,
|
||||
text_color="lime", # Textbox's text_color is set when printing. so this is for prevent from non-setting text_color like the gloves used in food factories are blue.
|
||||
wrap="word",
|
||||
))
|
||||
textbox_widget = getattr(main_window, textbox_setting["textbox_attr_name"])
|
||||
textbox_widget.grid(row=0, column=0, padx=settings.uism.TEXTBOX_PADX, pady=0, sticky="nsew")
|
||||
textbox_widget.grid_remove()
|
||||
textbox_widget.configure(state="disabled")
|
||||
|
||||
column+=1
|
||||
|
||||
# Set default active textbox tab
|
||||
main_window.current_active_textbox_tab = getattr(main_window, "textbox_tab_all")
|
||||
setDefaultActiveTab(
|
||||
active_tab_widget=main_window.current_active_textbox_tab,
|
||||
active_bg_color=settings.ctm.TEXTBOX_TAB_BG_ACTIVE_COLOR,
|
||||
active_text_color=settings.ctm.TEXTBOX_TAB_TEXT_ACTIVE_COLOR
|
||||
)
|
||||
|
||||
main_window.current_active_textbox = getattr(main_window, "textbox_all")
|
||||
main_window.current_active_textbox.grid()
|
||||
40
vrct_gui/splash_window/SplashWindow.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from customtkinter import CTkImage, CTkLabel, CTkToplevel
|
||||
from ..ui_utils import openImageKeepAspectRatio, getImageFileFromUiUtils, setGeometryToCenterOfScreen, fadeInAnimation
|
||||
|
||||
class SplashWindow(CTkToplevel):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.withdraw()
|
||||
self.overrideredirect(True)
|
||||
self.configure(fg_color="#292a2d")
|
||||
self.title("SplashWindow")
|
||||
self.wm_attributes("-toolwindow", True)
|
||||
|
||||
|
||||
sw=self.winfo_screenwidth()
|
||||
# sh=self.winfo_screenheight()
|
||||
|
||||
pw=int(sw/4)
|
||||
|
||||
self.grid_columnconfigure((0,2), weight=1)
|
||||
self.grid_rowconfigure((0,2), weight=1)
|
||||
(img, desired_width, height) = openImageKeepAspectRatio(getImageFileFromUiUtils("vrct_logo_for_dark_mode.png"), pw)
|
||||
label = CTkLabel(
|
||||
self,
|
||||
text=None,
|
||||
height=0,
|
||||
fg_color="#292a2d",
|
||||
image=CTkImage(img, size=(desired_width, height))
|
||||
)
|
||||
label.grid(row=1, column=1, padx=int(desired_width/7), pady=int(height/3))
|
||||
|
||||
|
||||
def showSplash(self):
|
||||
self.attributes("-alpha", 0)
|
||||
self.deiconify()
|
||||
setGeometryToCenterOfScreen(root_widget=self)
|
||||
fadeInAnimation(self, steps=5, interval=0.02)
|
||||
|
||||
|
||||
def destroySplash(self):
|
||||
self.destroy()
|
||||
1
vrct_gui/splash_window/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .SplashWindow import *
|
||||
485
vrct_gui/ui_managers/ColorThemeManager.py
Normal file
@@ -0,0 +1,485 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
class ColorThemeManager():
|
||||
def __init__(self, theme):
|
||||
self.main = SimpleNamespace()
|
||||
self.config_window = SimpleNamespace()
|
||||
self.selectable_language_window = SimpleNamespace()
|
||||
self.main_window_cover = SimpleNamespace()
|
||||
self.error_message_window = SimpleNamespace()
|
||||
self.confirmation_modal = SimpleNamespace()
|
||||
|
||||
# old one. But leave it here for now.
|
||||
# self.PRIMARY_100_COLOR = "#c4eac1"
|
||||
# self.PRIMARY_200_COLOR = "#9cdd98"
|
||||
# self.PRIMARY_300_COLOR = "#70d16c"
|
||||
# self.PRIMARY_400_COLOR = "#49c649"
|
||||
# self.PRIMARY_500_COLOR = "#0abb1d"
|
||||
# self.PRIMARY_600_COLOR = "#00ac11"
|
||||
# self.PRIMARY_650_COLOR = "#00A309"
|
||||
# self.PRIMARY_700_COLOR = "#009900"
|
||||
# self.PRIMARY_800_COLOR = "#008800"
|
||||
# self.PRIMARY_900_COLOR = "#006900"
|
||||
|
||||
|
||||
# new one.
|
||||
self.PRIMARY_100_COLOR = "#b7ded8"
|
||||
self.PRIMARY_200_COLOR = "#8acac0"
|
||||
self.PRIMARY_300_COLOR = "#61b4a7"
|
||||
self.PRIMARY_400_COLOR = "#48a495"
|
||||
self.PRIMARY_450_COLOR = "#429c8c"
|
||||
self.PRIMARY_500_COLOR = "#3b9483"
|
||||
self.PRIMARY_600_COLOR = "#368777"
|
||||
self.PRIMARY_650_COLOR = "#347f6f"
|
||||
self.PRIMARY_700_COLOR = "#317767"
|
||||
self.PRIMARY_750_COLOR = "#2F6F60"
|
||||
self.PRIMARY_800_COLOR = "#2c6759"
|
||||
self.PRIMARY_900_COLOR = "#214b3f"
|
||||
|
||||
|
||||
self.DARK_100_COLOR = "#f5f7fb"
|
||||
self.DARK_200_COLOR = "#f1f2f6"
|
||||
self.DARK_300_COLOR = "#e9eaee"
|
||||
self.DARK_350_COLOR = "#d8d9dd"
|
||||
self.DARK_400_COLOR = "#c7c8cc"
|
||||
self.DARK_450_COLOR = "#b8b9bd"
|
||||
self.DARK_500_COLOR = "#a9aaae"
|
||||
self.DARK_600_COLOR = "#7f8084"
|
||||
self.DARK_650_COLOR = "#75767a"
|
||||
self.DARK_700_COLOR = "#6a6c6f"
|
||||
self.DARK_725_COLOR = "#636467"
|
||||
self.DARK_750_COLOR = "#5b5c5f"
|
||||
self.DARK_775_COLOR = "#535457"
|
||||
self.DARK_800_COLOR = "#4b4c4f"
|
||||
self.DARK_825_COLOR = "#434447"
|
||||
self.DARK_850_COLOR = "#3a3b3e"
|
||||
self.DARK_863_COLOR = "#36373a"
|
||||
self.DARK_875_COLOR = "#323336"
|
||||
self.DARK_888_COLOR = "#2e2f32"
|
||||
self.DARK_900_COLOR = "#292a2d"
|
||||
self.DARK_925_COLOR = "#242528"
|
||||
self.DARK_950_COLOR = "#1f2022"
|
||||
self.DARK_975_COLOR = "#1a1b1d"
|
||||
self.DARK_1000_COLOR = "#151517" # THE DARKEST COLOR
|
||||
|
||||
|
||||
self.LIGHT_100_COLOR = "#f2f2f2" # THE LIGHTEST COLOR
|
||||
self.LIGHT_200_COLOR = "#e9e9e9"
|
||||
self.LIGHT_250_COLOR = "#e1e1e1"
|
||||
self.LIGHT_300_COLOR = "#d9d9d9"
|
||||
self.LIGHT_325_COLOR = "#d0d0d0"
|
||||
self.LIGHT_350_COLOR = "#c7c7c7"
|
||||
self.LIGHT_375_COLOR = "#bebebe"
|
||||
self.LIGHT_400_COLOR = "#b5b5b5"
|
||||
self.LIGHT_450_COLOR = "#a5a5a5"
|
||||
self.LIGHT_500_COLOR = "#959595"
|
||||
self.LIGHT_600_COLOR = "#6d6d6d"
|
||||
self.LIGHT_700_COLOR = "#5a5a5a"
|
||||
self.LIGHT_750_COLOR = "#515151"
|
||||
self.LIGHT_800_COLOR = "#3b3b3b"
|
||||
self.LIGHT_850_COLOR = "#323232"
|
||||
self.LIGHT_875_COLOR = "#2b2b2b"
|
||||
self.LIGHT_900_COLOR = "#1b1b1b"
|
||||
# self.LIGHT_925_COLOR = "#121212"
|
||||
# self.LIGHT_950_COLOR = "#0c0c0c"
|
||||
# self.LIGHT_975_COLOR = "#070707"
|
||||
self.LIGHT_1000_COLOR = "#010101"
|
||||
|
||||
|
||||
if theme == "Dark":
|
||||
self._createDarkModeColor()
|
||||
elif theme == "Light":
|
||||
self._createLightModeColor()
|
||||
|
||||
|
||||
def _createDarkModeColor(self):
|
||||
# Common
|
||||
self.main.BASIC_TEXT_COLOR = self.LIGHT_100_COLOR
|
||||
self.main.LABELS_TEXT_COLOR = self.main.BASIC_TEXT_COLOR
|
||||
|
||||
# Main
|
||||
self.main.MAIN_BG_COLOR = self.DARK_888_COLOR
|
||||
|
||||
self.main.TEXTBOX_BG_COLOR = self.DARK_900_COLOR
|
||||
self.main.TEXTBOX_TEXT_COLOR = self.main.BASIC_TEXT_COLOR
|
||||
self.main.TEXTBOX_TEXT_SUB_COLOR = self.DARK_450_COLOR
|
||||
self.main.TEXTBOX_SYSTEM_TAG_TEXT_COLOR = self.PRIMARY_300_COLOR
|
||||
self.main.TEXTBOX_SENT_TAG_TEXT_COLOR = "#6197b4"
|
||||
self.main.TEXTBOX_RECEIVED_TAG_TEXT_COLOR = "#a861b4"
|
||||
self.main.TEXTBOX_ERROR_TAG_TEXT_COLOR = "#c27583"
|
||||
self.main.TEXTBOX_TIMESTAMP_TEXT_COLOR = self.DARK_600_COLOR
|
||||
|
||||
self.main.TEXTBOX_TAB_BG_PASSIVE_COLOR = self.DARK_850_COLOR
|
||||
self.main.TEXTBOX_TAB_BG_ACTIVE_COLOR = self.main.TEXTBOX_BG_COLOR
|
||||
self.main.TEXTBOX_TAB_BG_HOVERED_COLOR = self.DARK_800_COLOR
|
||||
self.main.TEXTBOX_TAB_BG_CLICKED_COLOR = self.DARK_925_COLOR
|
||||
self.main.TEXTBOX_TAB_TEXT_ACTIVE_COLOR = self.main.BASIC_TEXT_COLOR
|
||||
self.main.TEXTBOX_TAB_TEXT_PASSIVE_COLOR = self.DARK_500_COLOR
|
||||
|
||||
self.main.TEXTBOX_ENTRY_TEXT_COLOR = self.DARK_300_COLOR
|
||||
self.main.TEXTBOX_ENTRY_TEXT_DISABLED_COLOR = self.DARK_500_COLOR
|
||||
self.main.TEXTBOX_ENTRY_BG_COLOR = self.DARK_875_COLOR
|
||||
self.main.TEXTBOX_ENTRY_BORDER_COLOR = self.DARK_750_COLOR
|
||||
self.main.TEXTBOX_ENTRY_PLACEHOLDER_COLOR = self.DARK_500_COLOR
|
||||
self.main.TEXTBOX_ENTRY_PLACEHOLDER_DISABLED_COLOR = self.DARK_700_COLOR
|
||||
|
||||
|
||||
|
||||
# Sidebar
|
||||
self.main.SIDEBAR_BG_COLOR = self.DARK_850_COLOR
|
||||
|
||||
# Sidebar Features
|
||||
self.main.SF__BG_COLOR = self.DARK_825_COLOR
|
||||
self.main.SF__HOVERED_BG_COLOR = self.DARK_800_COLOR
|
||||
self.main.SF__CLICKED_BG_COLOR = self.DARK_875_COLOR
|
||||
self.main.SF__TEXT_DISABLED_COLOR = self.DARK_500_COLOR
|
||||
|
||||
self.main.SF__SWITCH_BOX_BG_COLOR = self.DARK_775_COLOR
|
||||
self.main.SF__SWITCH_BOX_HOVERED_BG_COLOR = self.DARK_725_COLOR
|
||||
self.main.SF__SWITCH_BOX_CLICKED_BG_COLOR = self.DARK_825_COLOR
|
||||
self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR = self.PRIMARY_500_COLOR
|
||||
self.main.SF__SWITCH_BOX_ACTIVE_HOVERED_BG_COLOR = self.PRIMARY_400_COLOR
|
||||
self.main.SF__SWITCH_BOX_ACTIVE_CLICKED_BG_COLOR = self.PRIMARY_700_COLOR
|
||||
self.main.SF__SWITCH_BOX_DISABLE_BG_COLOR = self.PRIMARY_800_COLOR
|
||||
|
||||
self.main.SF__SWITCH_BOX_BUTTON_COLOR = self.DARK_400_COLOR
|
||||
# It's not working because It overrode internally.
|
||||
self.main.SF__SWITCH_BOX_BUTTON_HOVERED_COLOR = self.DARK_350_COLOR
|
||||
|
||||
self.main.SF__SELECTED_MARK_ACTIVE_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR
|
||||
self.main.SF__SELECTED_MARK_ACTIVE_HOVERED_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_HOVERED_BG_COLOR
|
||||
self.main.SF__SELECTED_MARK_ACTIVE_CLICKED_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_CLICKED_BG_COLOR
|
||||
self.main.SF__SELECTED_MARK_DISABLE_BG_COLOR = self.main.SF__SWITCH_BOX_DISABLE_BG_COLOR
|
||||
|
||||
|
||||
# Sidebar Languages Settings
|
||||
self.main.SLS__TITLE_TEXT_COLOR = self.DARK_400_COLOR
|
||||
|
||||
self.main.SLS__BG_COLOR = self.DARK_800_COLOR
|
||||
|
||||
self.main.SLS__PRESETS_TAB_BG_HOVERED_COLOR = self.DARK_825_COLOR
|
||||
self.main.SLS__PRESETS_TAB_BG_CLICKED_COLOR = self.DARK_875_COLOR
|
||||
self.main.SLS__PRESETS_TAB_BG_PASSIVE_COLOR = self.main.SIDEBAR_BG_COLOR
|
||||
self.main.SLS__PRESETS_TAB_BG_ACTIVE_COLOR = self.main.SLS__BG_COLOR
|
||||
self.main.SLS__PRESETS_TAB_ACTIVE_TEXT_COLOR_PASSIVE = self.DARK_600_COLOR
|
||||
self.main.SLS__PRESETS_TAB_ACTIVE_TEXT_COLOR = self.main.BASIC_TEXT_COLOR
|
||||
|
||||
self.main.SLS__BOX_BG_COLOR = self.DARK_825_COLOR
|
||||
self.main.SLS__BOX_SECTION_TITLE_TEXT_COLOR = self.DARK_400_COLOR
|
||||
self.main.SLS__BOX_ARROWS_TEXT_COLOR = self.DARK_500_COLOR
|
||||
|
||||
self.main.SLS__OPTIONMENU_BG_COLOR = self.DARK_888_COLOR
|
||||
self.main.SLS__OPTIONMENU_HOVERED_BG_COLOR = self.DARK_875_COLOR
|
||||
self.main.SLS__OPTIONMENU_CLICKED_BG_COLOR = self.DARK_900_COLOR
|
||||
|
||||
|
||||
self.main.CONFIG_BUTTON_BG_COLOR = self.main.SIDEBAR_BG_COLOR
|
||||
self.main.CONFIG_BUTTON_HOVERED_BG_COLOR = self.DARK_800_COLOR
|
||||
self.main.CONFIG_BUTTON_CLICKED_BG_COLOR = self.DARK_875_COLOR
|
||||
# self.main.CONFIG_BUTTON_DISABLE_COLOR = self.DARK_900_COLOR
|
||||
|
||||
self.main.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR = self.main.SIDEBAR_BG_COLOR
|
||||
self.main.MINIMIZE_SIDEBAR_BUTTON_HOVERED_BG_COLOR = self.DARK_800_COLOR
|
||||
self.main.MINIMIZE_SIDEBAR_BUTTON_CLICKED_BG_COLOR = self.DARK_900_COLOR
|
||||
# self.main.MINIMIZE_SIDEBAR_BUTTON_DISABLE_COLOR = self.DARK_900_COLOR
|
||||
|
||||
|
||||
|
||||
self.main.TOP_BAR_BUTTON_BG_COLOR = self.main.MAIN_BG_COLOR
|
||||
self.main.TOP_BAR_BUTTON_HOVERED_BG_COLOR = self.DARK_850_COLOR
|
||||
self.main.TOP_BAR_BUTTON_CLICKED_BG_COLOR = self.DARK_900_COLOR
|
||||
# self.main.TOP_BAR_BUTTON_DISABLE_COLOR = self.DARK_900_COLOR
|
||||
|
||||
self.main.UPDATE_AVAILABLE_BUTTON_BG_COLOR = self.main.TOP_BAR_BUTTON_BG_COLOR
|
||||
self.main.UPDATE_AVAILABLE_BUTTON_HOVERED_BG_COLOR = self.main.TOP_BAR_BUTTON_HOVERED_BG_COLOR
|
||||
self.main.UPDATE_AVAILABLE_BUTTON_CLICKED_BG_COLOR = self.main.TOP_BAR_BUTTON_CLICKED_BG_COLOR
|
||||
# self.main.UPDATE_AVAILABLE_BUTTON_DISABLE_COLOR = self.main.TOP_BAR_BUTTON_DISABLE_COLOR
|
||||
self.main.UPDATE_AVAILABLE_BUTTON_TEXT_COLOR = self.PRIMARY_300_COLOR
|
||||
|
||||
self.main.HELP_AND_INFO_BUTTON_BG_COLOR = self.main.TOP_BAR_BUTTON_BG_COLOR
|
||||
self.main.HELP_AND_INFO_BUTTON_HOVERED_BG_COLOR = self.main.TOP_BAR_BUTTON_HOVERED_BG_COLOR
|
||||
self.main.HELP_AND_INFO_BUTTON_CLICKED_BG_COLOR = self.main.TOP_BAR_BUTTON_CLICKED_BG_COLOR
|
||||
# self.main.HELP_AND_INFO_BUTTON_DISABLE_COLOR = self.main.TOP_BAR_BUTTON_DISABLE_COLOR
|
||||
|
||||
|
||||
|
||||
# Selectable Language Window
|
||||
self.selectable_language_window.BASIC_TEXT_COLOR = self.main.BASIC_TEXT_COLOR
|
||||
|
||||
self.selectable_language_window.MAIN_BG_COLOR = self.DARK_875_COLOR
|
||||
|
||||
self.selectable_language_window.GO_BACK_BUTTON_BG_COLOR = self.DARK_800_COLOR
|
||||
self.selectable_language_window.GO_BACK_BUTTON_BG_HOVERED_COLOR = self.DARK_750_COLOR
|
||||
self.selectable_language_window.GO_BACK_BUTTON_BG_CLICKED_COLOR = self.DARK_875_COLOR
|
||||
|
||||
|
||||
self.selectable_language_window.TOP_BG_COLOR = self.main.SIDEBAR_BG_COLOR
|
||||
self.selectable_language_window.TITLE_TEXT_COLOR = self.DARK_400_COLOR
|
||||
self.selectable_language_window.LANGUAGE_BUTTON_BG_COLOR = self.selectable_language_window.MAIN_BG_COLOR
|
||||
self.selectable_language_window.LANGUAGE_BUTTON_BG_HOVERED_COLOR = self.DARK_825_COLOR
|
||||
self.selectable_language_window.LANGUAGE_BUTTON_BG_CLICKED_COLOR = self.DARK_888_COLOR
|
||||
|
||||
|
||||
# Modal Window (Main Window)
|
||||
self.main_window_cover.TEXT_COLOR = self.LIGHT_100_COLOR
|
||||
|
||||
|
||||
self.confirmation_modal.MESSAGE_TEXT_COLOR = self.LIGHT_100_COLOR
|
||||
self.confirmation_modal.FAKE_BORDER_COLOR = self.DARK_600_COLOR
|
||||
self.confirmation_modal.BG_COLOR = self.DARK_800_COLOR
|
||||
self.confirmation_modal.CONFIRMATION_BUTTONS_TEXT_COLOR = self.LIGHT_100_COLOR
|
||||
|
||||
self.confirmation_modal.ACCEPT_BUTTON_BG_COLOR = self.PRIMARY_600_COLOR
|
||||
self.confirmation_modal.ACCEPT_BUTTON_HOVERED_BG_COLOR = self.PRIMARY_450_COLOR
|
||||
self.confirmation_modal.ACCEPT_BUTTON_CLICKED_BG_COLOR = self.PRIMARY_750_COLOR
|
||||
self.confirmation_modal.DENY_BUTTON_BG_COLOR = self.DARK_750_COLOR
|
||||
self.confirmation_modal.DENY_BUTTON_HOVERED_BG_COLOR = self.DARK_700_COLOR
|
||||
self.confirmation_modal.DENY_BUTTON_CLICKED_BG_COLOR = self.DARK_825_COLOR
|
||||
|
||||
|
||||
# Common
|
||||
self.config_window.BASIC_TEXT_COLOR = self.main.BASIC_TEXT_COLOR
|
||||
self.config_window.LABELS_TEXT_COLOR = self.config_window.BASIC_TEXT_COLOR
|
||||
self.config_window.LABELS_DESC_TEXT_COLOR = self.DARK_500_COLOR
|
||||
|
||||
self.config_window.LABELS_TEXT_DISABLED_COLOR = self.DARK_600_COLOR
|
||||
|
||||
|
||||
# Top bar
|
||||
self.config_window.TOP_BAR_BG_COLOR = self.DARK_850_COLOR
|
||||
|
||||
# Restart Button
|
||||
self.config_window.RESTART_BUTTON_BG_COLOR = self.PRIMARY_600_COLOR
|
||||
self.config_window.RESTART_BUTTON_HOVERED_BG_COLOR = self.PRIMARY_500_COLOR
|
||||
self.config_window.RESTART_BUTTON_CLICKED_BG_COLOR = self.PRIMARY_700_COLOR
|
||||
|
||||
|
||||
# Compact Mode
|
||||
self.config_window.COMPACT_MODE_SWITCH_BOX_BG_COLOR = self.DARK_775_COLOR
|
||||
self.config_window.COMPACT_MODE_SWITCH_BOX_ACTIVE_BG_COLOR = self.PRIMARY_500_COLOR
|
||||
self.config_window.COMPACT_MODE_SWITCH_BOX_BUTTON_COLOR = self.DARK_350_COLOR
|
||||
self.config_window.COMPACT_MODE_SWITCH_BOX_BUTTON_HOVERED_COLOR = self.DARK_300_COLOR
|
||||
|
||||
# Main
|
||||
self.config_window.MAIN_BG_COLOR = self.DARK_950_COLOR
|
||||
|
||||
# This is for fake border color
|
||||
self.config_window.SB__WRAPPER_BG_COLOR = self.DARK_750_COLOR
|
||||
|
||||
self.config_window.SB__BG_COLOR = self.DARK_888_COLOR
|
||||
|
||||
self.config_window.SB__OPTIONMENU_BG_COLOR = self.DARK_925_COLOR
|
||||
self.config_window.SB__OPTIONMENU_HOVERED_BG_COLOR = self.DARK_850_COLOR
|
||||
self.config_window.SB__OPTIONMENU_CLICKED_BG_COLOR = self.DARK_950_COLOR
|
||||
self.config_window.SB__DROPDOWN_MENU_WINDOW_BG_COLOR = self.config_window.MAIN_BG_COLOR
|
||||
self.config_window.SB__DROPDOWN_MENU_WINDOW_BORDER_COLOR = self.DARK_600_COLOR
|
||||
# self.config_window.SB__DROPDOWN_MENU_WINDOW_BG_COLOR = self.DARK_700_COLOR
|
||||
self.config_window.SB__DROPDOWN_MENU_BG_COLOR = self.DARK_875_COLOR
|
||||
self.config_window.SB__DROPDOWN_MENU_HOVERED_BG_COLOR = self.DARK_800_COLOR
|
||||
self.config_window.SB__DROPDOWN_MENU_CLICKED_BG_COLOR = self.DARK_900_COLOR
|
||||
|
||||
self.config_window.SB__SLIDER_BG_COLOR = self.DARK_700_COLOR
|
||||
self.config_window.SB__SLIDER_PROGRESS_BG_COLOR = self.DARK_500_COLOR
|
||||
self.config_window.SB__SLIDER_BUTTON_COLOR = self.DARK_700_COLOR
|
||||
self.config_window.SB__SLIDER_BUTTON_HOVERED_COLOR = self.DARK_600_COLOR
|
||||
|
||||
self.config_window.SB__SWITCH_BOX_BG_COLOR = self.DARK_800_COLOR
|
||||
self.config_window.SB__SWITCH_BOX_ACTIVE_BG_COLOR = self.PRIMARY_500_COLOR
|
||||
self.config_window.SB__SWITCH_BOX_BUTTON_COLOR = self.DARK_400_COLOR
|
||||
self.config_window.SB__SWITCH_BOX_BUTTON_HOVERED_COLOR = self.DARK_350_COLOR
|
||||
|
||||
self.config_window.SB__CHECKBOX_BORDER_COLOR = self.DARK_600_COLOR
|
||||
self.config_window.SB__CHECKBOX_HOVER_COLOR = self.DARK_800_COLOR
|
||||
self.config_window.SB__CHECKBOX_CHECKED_COLOR = self.PRIMARY_700_COLOR
|
||||
self.config_window.SB__CHECKBOX_CHECKMARK_COLOR = self.config_window.BASIC_TEXT_COLOR
|
||||
|
||||
self.config_window.SB__ENTRY_TEXT_COLOR = self.DARK_300_COLOR
|
||||
self.config_window.SB__ENTRY_BG_COLOR = self.DARK_863_COLOR
|
||||
self.config_window.SB__ENTRY_BORDER_COLOR = self.DARK_775_COLOR
|
||||
|
||||
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__PROGRESSBAR_BG_COLOR = self.DARK_800_COLOR
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__PROGRESSBAR_PROGRESS_BG_COLOR = self.PRIMARY_400_COLOR
|
||||
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_COLOR = self.PRIMARY_600_COLOR
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_HOVERED_COLOR = self.PRIMARY_400_COLOR
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_COLOR = self.DARK_800_COLOR
|
||||
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_COLOR = self.DARK_800_COLOR
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_HOVERED_COLOR = self.DARK_700_COLOR
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_CLICKED_COLOR = self.DARK_900_COLOR
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_DISABLED_COLOR = self.DARK_850_COLOR
|
||||
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_COLOR = self.PRIMARY_600_COLOR
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_HOVERED_COLOR = self.PRIMARY_500_COLOR
|
||||
self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_CLICKED_COLOR = self.PRIMARY_800_COLOR
|
||||
# self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_DISABLED_COLOR = self.PRIMARY_900_COLOR
|
||||
|
||||
|
||||
# Side menu
|
||||
self.config_window.SIDE_MENU_BG_COLOR = self.config_window.MAIN_BG_COLOR
|
||||
|
||||
self.config_window.SIDE_MENU_LABELS_BG_COLOR = self.config_window.SIDE_MENU_BG_COLOR
|
||||
self.config_window.SIDE_MENU_LABELS_BG_FOR_FAKE_BORDER_COLOR = self.config_window.SIDE_MENU_BG_COLOR
|
||||
self.config_window.SIDE_MENU_LABELS_HOVERED_BG_COLOR = self.DARK_850_COLOR
|
||||
self.config_window.SIDE_MENU_LABELS_CLICKED_BG_COLOR = self.PRIMARY_750_COLOR
|
||||
self.config_window.SIDE_MENU_LABELS_SELECTED_TEXT_COLOR = self.PRIMARY_200_COLOR
|
||||
|
||||
self.config_window.SIDE_MENU_SELECTED_MARK_ACTIVE_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR
|
||||
|
||||
self.config_window.NOW_VERSION_TEXT_COLOR = self.DARK_300_COLOR
|
||||
|
||||
# Error Message Window for Config Window
|
||||
# The color code [#bb4448] is a mixture of [#a9555c] and [#cc3333] (for a redder shade).
|
||||
self.config_window.SB__ERROR_MESSAGE_BG_COLOR = "#bb4448"
|
||||
self.config_window.SB__ERROR_MESSAGE_TEXT_COLOR = "#fff"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# def _createLightModeColor(self):
|
||||
# # Common
|
||||
# self.main.BASIC_TEXT_COLOR = self.DARK_1000_COLOR
|
||||
# self.main.LABELS_TEXT_COLOR = self.main.BASIC_TEXT_COLOR
|
||||
|
||||
# # Main
|
||||
# self.main.MAIN_BG_COLOR = self.LIGHT_300_COLOR
|
||||
|
||||
# self.main.TEXTBOX_BG_COLOR = self.LIGHT_200_COLOR
|
||||
# self.main.TEXTBOX_TEXT_COLOR = self.main.BASIC_TEXT_COLOR
|
||||
# self.main.TEXTBOX_TAB_BG_PASSIVE_COLOR = self.LIGHT_350_COLOR
|
||||
# self.main.TEXTBOX_TAB_BG_ACTIVE_COLOR = self.main.TEXTBOX_BG_COLOR
|
||||
# self.main.TEXTBOX_TAB_BG_HOVERED_COLOR = self.LIGHT_300_COLOR
|
||||
# self.main.TEXTBOX_TAB_BG_CLICKED_COLOR = self.LIGHT_350_COLOR
|
||||
# self.main.TEXTBOX_TAB_TEXT_ACTIVE_COLOR = self.main.BASIC_TEXT_COLOR
|
||||
# self.main.TEXTBOX_TAB_TEXT_PASSIVE_COLOR = self.LIGHT_600_COLOR
|
||||
|
||||
# self.main.TEXTBOX_ENTRY_TEXT_COLOR = self.LIGHT_800_COLOR
|
||||
# self.main.TEXTBOX_ENTRY_TEXT_DISABLED_COLOR = self.LIGHT_500_COLOR
|
||||
# self.main.TEXTBOX_ENTRY_BG_COLOR = self.LIGHT_325_COLOR
|
||||
# self.main.TEXTBOX_ENTRY_BORDER_COLOR = self.LIGHT_400_COLOR
|
||||
# self.main.TEXTBOX_ENTRY_PLACEHOLDER_COLOR = self.LIGHT_600_COLOR
|
||||
# self.main.TEXTBOX_ENTRY_PLACEHOLDER_DISABLED_COLOR = self.LIGHT_700_COLOR
|
||||
|
||||
|
||||
|
||||
# # Sidebar
|
||||
# self.main.SIDEBAR_BG_COLOR = self.LIGHT_350_COLOR
|
||||
|
||||
# # Sidebar Features
|
||||
# self.main.SF__BG_COLOR = self.LIGHT_375_COLOR
|
||||
# self.main.SF__HOVERED_BG_COLOR = self.LIGHT_300_COLOR
|
||||
# self.main.SF__CLICKED_BG_COLOR = self.LIGHT_200_COLOR
|
||||
# self.main.SF__TEXT_DISABLED_COLOR = self.LIGHT_500_COLOR
|
||||
|
||||
# self.main.SF__SWITCH_BOX_BG_COLOR = self.LIGHT_300_COLOR
|
||||
# self.main.SF__SWITCH_BOX_HOVERED_BG_COLOR = self.LIGHT_450_COLOR
|
||||
# self.main.SF__SWITCH_BOX_CLICKED_BG_COLOR = self.LIGHT_350_COLOR
|
||||
# self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR = self.PRIMARY_650_COLOR
|
||||
# self.main.SF__SWITCH_BOX_ACTIVE_HOVERED_BG_COLOR = self.PRIMARY_500_COLOR
|
||||
# self.main.SF__SWITCH_BOX_ACTIVE_CLICKED_BG_COLOR = self.PRIMARY_700_COLOR
|
||||
# self.main.SF__SWITCH_BOX_DISABLE_BG_COLOR = self.PRIMARY_900_COLOR
|
||||
|
||||
# self.main.SF__SELECTED_MARK_ACTIVE_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR
|
||||
# self.main.SF__SELECTED_MARK_ACTIVE_HOVERED_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_HOVERED_BG_COLOR
|
||||
# self.main.SF__SELECTED_MARK_ACTIVE_CLICKED_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_CLICKED_BG_COLOR
|
||||
# self.main.SF__SELECTED_MARK_DISABLE_BG_COLOR = self.main.SF__SWITCH_BOX_DISABLE_BG_COLOR
|
||||
|
||||
|
||||
# # Sidebar quick settings
|
||||
# self.main.SLS__TITLE_TEXT_COLOR = self.LIGHT_800_COLOR
|
||||
|
||||
# self.main.SLS__BG_COLOR = self.LIGHT_300_COLOR
|
||||
|
||||
# self.main.SLS__PRESETS_TAB_BG_HOVERED_COLOR = self.LIGHT_350_COLOR
|
||||
# self.main.SLS__PRESETS_TAB_BG_CLICKED_COLOR = self.LIGHT_800_COLOR
|
||||
# self.main.SLS__PRESETS_TAB_BG_PASSIVE_COLOR = self.main.SIDEBAR_BG_COLOR
|
||||
# self.main.SLS__PRESETS_TAB_BG_ACTIVE_COLOR = self.main.SLS__BG_COLOR
|
||||
# self.main.SLS__PRESETS_TAB_ACTIVE_TEXT_COLOR_PASSIVE = self.LIGHT_600_COLOR
|
||||
# self.main.SLS__PRESETS_TAB_ACTIVE_TEXT_COLOR = self.main.BASIC_TEXT_COLOR
|
||||
|
||||
# self.main.SLS__BOX_BG_COLOR = self.LIGHT_350_COLOR
|
||||
# self.main.SLS__BOX_SECTION_TITLE_TEXT_COLOR = self.LIGHT_800_COLOR
|
||||
# self.main.SLS__BOX_ARROWS_TEXT_COLOR = self.LIGHT_700_COLOR
|
||||
|
||||
# self.main.SLS__OPTIONMENU_BG_COLOR = self.LIGHT_500_COLOR
|
||||
|
||||
|
||||
# self.main.CONFIG_BUTTON_BG_COLOR = self.main.SIDEBAR_BG_COLOR
|
||||
# self.main.CONFIG_BUTTON_HOVERED_BG_COLOR = self.LIGHT_800_COLOR
|
||||
# self.main.CONFIG_BUTTON_CLICKED_BG_COLOR = self.LIGHT_900_COLOR
|
||||
# # self.main.CONFIG_BUTTON_DISABLE_COLOR = self.LIGHT_900_COLOR
|
||||
|
||||
# self.main.MINIMIZE_SIDEBAR_BUTTON_BG_COLOR = self.main.SIDEBAR_BG_COLOR
|
||||
# self.main.MINIMIZE_SIDEBAR_BUTTON_HOVERED_BG_COLOR = self.LIGHT_800_COLOR
|
||||
# self.main.MINIMIZE_SIDEBAR_BUTTON_CLICKED_BG_COLOR = self.LIGHT_900_COLOR
|
||||
# # self.main.MINIMIZE_SIDEBAR_BUTTON_DISABLE_COLOR = self.LIGHT_900_COLOR
|
||||
|
||||
# self.main.HELP_AND_INFO_BUTTON_BG_COLOR = self.main.MAIN_BG_COLOR
|
||||
# self.main.HELP_AND_INFO_BUTTON_HOVERED_BG_COLOR = self.LIGHT_350_COLOR
|
||||
# self.main.HELP_AND_INFO_BUTTON_CLICKED_BG_COLOR = self.LIGHT_450_COLOR
|
||||
# # self.main.HELP_AND_INFO_BUTTON_DISABLE_COLOR = self.LIGHT_900_COLOR
|
||||
|
||||
|
||||
# # Common
|
||||
# self.config_window.BASIC_TEXT_COLOR = self.main.BASIC_TEXT_COLOR
|
||||
# self.config_window.LABELS_TEXT_COLOR = self.config_window.BASIC_TEXT_COLOR
|
||||
# self.config_window.LABELS_DESC_TEXT_COLOR = self.DARK_500_COLOR
|
||||
|
||||
|
||||
# # Top bar
|
||||
# self.config_window.TOP_BAR_BG_COLOR = self.DARK_850_COLOR
|
||||
|
||||
|
||||
# # Main
|
||||
# self.config_window.MAIN_BG_COLOR = self.DARK_950_COLOR
|
||||
|
||||
# # This is for fake border color
|
||||
# self.config_window.SB__WRAPPER_BG_COLOR = self.DARK_750_COLOR
|
||||
|
||||
# self.config_window.SB__BG_COLOR = self.DARK_888_COLOR
|
||||
|
||||
# self.config_window.SB__OPTIONMENU_BG_COLOR = self.DARK_925_COLOR
|
||||
# self.config_window.SB__OPTIONMENU_HOVERED_BG_COLOR = self.DARK_875_COLOR
|
||||
|
||||
# self.config_window.SB__SLIDER_BUTTON_COLOR = self.DARK_700_COLOR
|
||||
# self.config_window.SB__SLIDER_BUTTON_HOVERED_COLOR = self.DARK_600_COLOR
|
||||
|
||||
# self.config_window.SB__SWITCH_BOX_BG_COLOR = self.main.SF__SWITCH_BOX_BG_COLOR
|
||||
# self.config_window.SB__SWITCH_BOX_ACTIVE_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR
|
||||
|
||||
# self.config_window.SB__CHECKBOX_BORDER_COLOR = self.DARK_500_COLOR
|
||||
# self.config_window.SB__CHECKBOX_HOVER_COLOR = self.DARK_800_COLOR
|
||||
# self.config_window.SB__CHECKBOX_CHECKED_COLOR = self.PRIMARY_700_COLOR
|
||||
# self.config_window.SB__CHECKBOX_CHECKMARK_COLOR = self.config_window.BASIC_TEXT_COLOR
|
||||
|
||||
# self.config_window.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_COLOR = self.PRIMARY_700_COLOR
|
||||
# self.config_window.SB__PROGRESSBAR_X_SLIDER__SLIDER_BUTTON_HOVERED_COLOR = self.PRIMARY_500_COLOR
|
||||
# self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_COLOR = self.DARK_800_COLOR
|
||||
|
||||
# self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_COLOR = self.DARK_800_COLOR
|
||||
# self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_HOVERED_COLOR = self.DARK_700_COLOR
|
||||
# self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_CLICKED_COLOR = self.DARK_900_COLOR
|
||||
# self.config_window.SB__PROGRESSBAR_X_SLIDER__PASSIVE_BUTTON_DISABLED_COLOR = self.DARK_850_COLOR
|
||||
|
||||
# self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_COLOR = self.PRIMARY_700_COLOR
|
||||
# self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_HOVERED_COLOR = self.PRIMARY_600_COLOR
|
||||
# self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_CLICKED_COLOR = self.PRIMARY_900_COLOR
|
||||
# # self.config_window.SB__PROGRESSBAR_X_SLIDER__ACTIVE_BUTTON_DISABLED_COLOR = self.PRIMARY_900_COLOR
|
||||
|
||||
|
||||
# # Side menu
|
||||
# self.config_window.SIDE_MENU_BG_COLOR = self.config_window.MAIN_BG_COLOR
|
||||
|
||||
# self.config_window.SIDE_MENU_LABELS_BG_COLOR = self.config_window.SIDE_MENU_BG_COLOR
|
||||
# self.config_window.SIDE_MENU_LABELS_BG_FOR_FAKE_BORDER_COLOR = self.config_window.SIDE_MENU_BG_COLOR
|
||||
# self.config_window.SIDE_MENU_LABELS_HOVERED_BG_COLOR = self.DARK_850_COLOR
|
||||
# self.config_window.SIDE_MENU_LABELS_CLICKED_BG_COLOR = self.PRIMARY_900_COLOR
|
||||
# self.config_window.SIDE_MENU_LABELS_SELECTED_TEXT_COLOR = self.PRIMARY_300_COLOR
|
||||
|
||||
# self.config_window.SIDE_MENU_SELECTED_MARK_ACTIVE_BG_COLOR = self.main.SF__SWITCH_BOX_ACTIVE_BG_COLOR
|
||||