Cleaning up ui
This commit is contained in:
parent
3333e792f4
commit
fcb10d9aad
4 changed files with 365 additions and 331 deletions
|
|
@ -1,5 +1,5 @@
|
|||
"""
|
||||
Configuration Tab - Handles environment variables and global settings
|
||||
Configuration Tab - Handles environment variables, global settings, and engine configurations
|
||||
"""
|
||||
|
||||
import os
|
||||
|
|
@ -8,14 +8,40 @@ from PyQt5.QtWidgets import (
|
|||
QWidget, QVBoxLayout, QHBoxLayout, QFormLayout, QLineEdit,
|
||||
QSpinBox, QDoubleSpinBox, QComboBox, QPushButton, QGroupBox,
|
||||
QLabel, QFileDialog, QMessageBox, QScrollArea, QTextEdit,
|
||||
QCheckBox, QApplication
|
||||
QCheckBox, QApplication, QTabWidget, QFrame
|
||||
)
|
||||
from PyQt5.QtCore import Qt, pyqtSignal
|
||||
from dotenv import load_dotenv, set_key
|
||||
|
||||
from gui.rpgmaker_tab import RPGMakerTab
|
||||
from gui.wolf_tab import WolfTab
|
||||
|
||||
|
||||
def create_section_header(title):
|
||||
"""Create a clean section header without boxes."""
|
||||
label = QLabel(title)
|
||||
label.setStyleSheet("""
|
||||
QLabel {
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
color: #007acc;
|
||||
padding: 8px 0px 5px 0px;
|
||||
background-color: transparent;
|
||||
}
|
||||
""")
|
||||
return label
|
||||
|
||||
def create_horizontal_line():
|
||||
"""Create a horizontal separator line."""
|
||||
line = QFrame()
|
||||
line.setFrameShape(QFrame.HLine)
|
||||
line.setFrameShadow(QFrame.Sunken)
|
||||
line.setStyleSheet("QFrame { color: #555555; margin: 5px 0px; }")
|
||||
return line
|
||||
|
||||
|
||||
class ConfigTab(QWidget):
|
||||
"""Configuration tab for managing environment variables and global settings."""
|
||||
"""Configuration tab for managing environment variables, global settings, and engine configs."""
|
||||
|
||||
config_changed = pyqtSignal()
|
||||
|
||||
|
|
@ -26,296 +52,268 @@ class ConfigTab(QWidget):
|
|||
self.load_from_env()
|
||||
|
||||
def init_ui(self):
|
||||
"""Initialize the user interface."""
|
||||
"""Initialize the user interface with tabs for different config categories."""
|
||||
main_layout = QVBoxLayout()
|
||||
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
# Create scroll area
|
||||
scroll_area = QScrollArea()
|
||||
scroll_content = QWidget()
|
||||
scroll_layout = QVBoxLayout()
|
||||
# Create tab widget for different configuration categories
|
||||
self.config_tabs = QTabWidget()
|
||||
|
||||
# API Configuration Group
|
||||
api_group = self.create_api_group()
|
||||
scroll_layout.addWidget(api_group)
|
||||
# Tab 1: API & Translation Settings
|
||||
api_tab = self.create_api_translation_tab()
|
||||
self.config_tabs.addTab(api_tab, "API & Translation")
|
||||
|
||||
# Translation Settings Group
|
||||
translation_group = self.create_translation_group()
|
||||
scroll_layout.addWidget(translation_group)
|
||||
# Tab 2: Performance & Formatting
|
||||
perf_tab = self.create_performance_formatting_tab()
|
||||
self.config_tabs.addTab(perf_tab, "Performance & Format")
|
||||
|
||||
# Performance Settings Group
|
||||
performance_group = self.create_performance_group()
|
||||
scroll_layout.addWidget(performance_group)
|
||||
# Tab 3: RPG Maker MV/MZ Engine
|
||||
self.mvmz_tab = RPGMakerTab("MVMZ")
|
||||
self.config_tabs.addTab(self.mvmz_tab, "RPG Maker MV/MZ")
|
||||
|
||||
# Text Formatting Group
|
||||
formatting_group = self.create_formatting_group()
|
||||
scroll_layout.addWidget(formatting_group)
|
||||
# Tab 4: RPG Maker Ace Engine
|
||||
self.ace_tab = RPGMakerTab("ACE")
|
||||
self.config_tabs.addTab(self.ace_tab, "RPG Maker Ace")
|
||||
|
||||
# Custom API Settings Group
|
||||
custom_api_group = self.create_custom_api_group()
|
||||
scroll_layout.addWidget(custom_api_group)
|
||||
# Tab 5: Wolf RPG Engine
|
||||
self.wolf_tab = WolfTab()
|
||||
self.config_tabs.addTab(self.wolf_tab, "Wolf RPG")
|
||||
|
||||
# UI Settings Group
|
||||
ui_group = self.create_ui_settings_group()
|
||||
scroll_layout.addWidget(ui_group)
|
||||
main_layout.addWidget(self.config_tabs)
|
||||
|
||||
# Buttons
|
||||
# Bottom buttons row
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.setSpacing(10)
|
||||
|
||||
self.save_button = QPushButton("Save Configuration")
|
||||
self.save_button = QPushButton("💾 Save Configuration")
|
||||
self.save_button.clicked.connect(self.save_to_env)
|
||||
self.save_button.setMinimumHeight(35)
|
||||
|
||||
self.load_button = QPushButton("Load from File")
|
||||
self.load_button = QPushButton("📂 Load from File")
|
||||
self.load_button.clicked.connect(self.load_from_file_dialog)
|
||||
self.load_button.setMinimumHeight(35)
|
||||
|
||||
self.reset_button = QPushButton("Reset to Defaults")
|
||||
self.reset_button = QPushButton("🔄 Reset to Defaults")
|
||||
self.reset_button.clicked.connect(self.reset_to_defaults)
|
||||
self.reset_button.setMinimumHeight(35)
|
||||
|
||||
button_layout.addWidget(self.save_button)
|
||||
button_layout.addWidget(self.load_button)
|
||||
button_layout.addWidget(self.reset_button)
|
||||
button_layout.addStretch()
|
||||
|
||||
scroll_layout.addLayout(button_layout)
|
||||
|
||||
scroll_content.setLayout(scroll_layout)
|
||||
scroll_area.setWidget(scroll_content)
|
||||
scroll_area.setWidgetResizable(True)
|
||||
|
||||
main_layout.addWidget(scroll_area)
|
||||
main_layout.addLayout(button_layout)
|
||||
self.setLayout(main_layout)
|
||||
|
||||
def create_api_translation_tab(self):
|
||||
"""Create compact API and translation settings tab."""
|
||||
widget = QWidget()
|
||||
scroll = QScrollArea()
|
||||
scroll.setWidgetResizable(True)
|
||||
scroll.setFrameShape(QFrame.NoFrame)
|
||||
|
||||
def create_api_group(self):
|
||||
"""Create API configuration group."""
|
||||
group = QGroupBox("API Configuration")
|
||||
layout = QFormLayout()
|
||||
content = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
layout.setSpacing(5)
|
||||
layout.setContentsMargins(10, 10, 10, 10)
|
||||
|
||||
# API Configuration Section
|
||||
layout.addWidget(create_section_header("🔑 API Configuration"))
|
||||
api_form = QFormLayout()
|
||||
api_form.setSpacing(5)
|
||||
api_form.setContentsMargins(0, 0, 0, 10)
|
||||
|
||||
# API URL
|
||||
self.api_url_edit = QLineEdit()
|
||||
self.api_url_edit.setPlaceholderText("Leave blank for OpenAI API")
|
||||
layout.addRow("API URL:", self.api_url_edit)
|
||||
api_form.addRow("API URL:", self.api_url_edit)
|
||||
|
||||
# API Key
|
||||
self.api_key_edit = QLineEdit()
|
||||
self.api_key_edit.setEchoMode(QLineEdit.Password)
|
||||
self.api_key_edit.setPlaceholderText("Enter your API key")
|
||||
layout.addRow("API Key:", self.api_key_edit)
|
||||
api_form.addRow("API Key:", self.api_key_edit)
|
||||
|
||||
# Organization
|
||||
self.organization_edit = QLineEdit()
|
||||
self.organization_edit.setPlaceholderText("Organization key")
|
||||
layout.addRow("Organization:", self.organization_edit)
|
||||
self.organization_edit.setPlaceholderText("Optional organization key")
|
||||
api_form.addRow("Organization:", self.organization_edit)
|
||||
|
||||
# Model
|
||||
self.model_combo = QComboBox()
|
||||
self.model_combo.setEditable(True)
|
||||
self.model_combo.addItems([
|
||||
"gpt-3.5-turbo",
|
||||
"gpt-3.5-turbo-1106",
|
||||
"gpt-4",
|
||||
"gpt-4-1106-preview",
|
||||
"gpt-4-turbo",
|
||||
"claude-3-sonnet-20240229",
|
||||
"claude-3-opus-20240229"
|
||||
"gpt-4.1-mini", "gpt-4.1", "gpt-5",
|
||||
"deepseek-chat", "claude-3-sonnet-20240229",
|
||||
"gemini-2.0-flash", "gemini-2.5-flash", "gemini-2.5-pro"
|
||||
])
|
||||
layout.addRow("Model:", self.model_combo)
|
||||
api_form.addRow("Model:", self.model_combo)
|
||||
|
||||
group.setLayout(layout)
|
||||
return group
|
||||
layout.addLayout(api_form)
|
||||
layout.addWidget(create_horizontal_line())
|
||||
|
||||
def create_translation_group(self):
|
||||
"""Create translation settings group."""
|
||||
group = QGroupBox("Translation Settings")
|
||||
layout = QFormLayout()
|
||||
# Translation Settings Section
|
||||
layout.addWidget(create_section_header("🌐 Translation Settings"))
|
||||
trans_form = QFormLayout()
|
||||
trans_form.setSpacing(5)
|
||||
trans_form.setContentsMargins(0, 0, 0, 10)
|
||||
|
||||
# Language
|
||||
self.language_combo = QComboBox()
|
||||
self.language_combo.addItems([
|
||||
"English", "Spanish", "French", "German", "Italian",
|
||||
"Portuguese", "Russian", "Chinese", "Korean", "Japanese"
|
||||
])
|
||||
layout.addRow("Target Language:", self.language_combo)
|
||||
trans_form.addRow("Target Language:", self.language_combo)
|
||||
|
||||
# Timeout
|
||||
self.timeout_spin = QSpinBox()
|
||||
self.timeout_spin.setRange(30, 300)
|
||||
self.timeout_spin.setValue(120)
|
||||
self.timeout_spin.setSuffix(" seconds")
|
||||
layout.addRow("Timeout:", self.timeout_spin)
|
||||
self.timeout_spin.setSuffix(" sec")
|
||||
trans_form.addRow("Timeout:", self.timeout_spin)
|
||||
|
||||
group.setLayout(layout)
|
||||
return group
|
||||
layout.addLayout(trans_form)
|
||||
layout.addWidget(create_horizontal_line())
|
||||
|
||||
def create_performance_group(self):
|
||||
"""Create performance settings group."""
|
||||
group = QGroupBox("Performance Settings")
|
||||
layout = QFormLayout()
|
||||
# UI Settings Section
|
||||
layout.addWidget(create_section_header("🎨 UI Settings"))
|
||||
ui_form = QFormLayout()
|
||||
ui_form.setSpacing(5)
|
||||
ui_form.setContentsMargins(0, 0, 0, 10)
|
||||
|
||||
# File Threads
|
||||
self.file_threads_spin = QSpinBox()
|
||||
self.file_threads_spin.setRange(1, 10)
|
||||
self.file_threads_spin.setValue(1)
|
||||
layout.addRow("File Threads:", self.file_threads_spin)
|
||||
|
||||
# Threads per File
|
||||
self.threads_spin = QSpinBox()
|
||||
self.threads_spin.setRange(1, 20)
|
||||
self.threads_spin.setValue(1)
|
||||
layout.addRow("Threads per File:", self.threads_spin)
|
||||
|
||||
# Batch Size
|
||||
self.batch_size_spin = QSpinBox()
|
||||
self.batch_size_spin.setRange(1, 100)
|
||||
self.batch_size_spin.setValue(10)
|
||||
layout.addRow("Batch Size:", self.batch_size_spin)
|
||||
|
||||
# Frequency Penalty
|
||||
self.frequency_penalty_spin = QDoubleSpinBox()
|
||||
self.frequency_penalty_spin.setRange(0.0, 2.0)
|
||||
self.frequency_penalty_spin.setSingleStep(0.1)
|
||||
self.frequency_penalty_spin.setValue(0.2)
|
||||
layout.addRow("Frequency Penalty:", self.frequency_penalty_spin)
|
||||
|
||||
group.setLayout(layout)
|
||||
return group
|
||||
|
||||
def create_formatting_group(self):
|
||||
"""Create text formatting settings group."""
|
||||
group = QGroupBox("Text Formatting")
|
||||
layout = QFormLayout()
|
||||
|
||||
# Dialogue Width
|
||||
self.width_spin = QSpinBox()
|
||||
self.width_spin.setRange(20, 200)
|
||||
self.width_spin.setValue(60)
|
||||
self.width_spin.setSuffix(" characters")
|
||||
layout.addRow("Dialogue Width:", self.width_spin)
|
||||
|
||||
# List Width
|
||||
self.list_width_spin = QSpinBox()
|
||||
self.list_width_spin.setRange(20, 200)
|
||||
self.list_width_spin.setValue(100)
|
||||
self.list_width_spin.setSuffix(" characters")
|
||||
layout.addRow("List Width:", self.list_width_spin)
|
||||
|
||||
# Note Width
|
||||
self.note_width_spin = QSpinBox()
|
||||
self.note_width_spin.setRange(20, 200)
|
||||
self.note_width_spin.setValue(75)
|
||||
self.note_width_spin.setSuffix(" characters")
|
||||
layout.addRow("Note Width:", self.note_width_spin)
|
||||
|
||||
group.setLayout(layout)
|
||||
return group
|
||||
|
||||
def create_custom_api_group(self):
|
||||
"""Create custom API settings group."""
|
||||
group = QGroupBox("Custom API Pricing")
|
||||
layout = QFormLayout()
|
||||
|
||||
# Input Cost
|
||||
self.input_cost_spin = QDoubleSpinBox()
|
||||
self.input_cost_spin.setRange(0.0, 1.0)
|
||||
self.input_cost_spin.setDecimals(4)
|
||||
self.input_cost_spin.setSingleStep(0.0001)
|
||||
self.input_cost_spin.setValue(0.002)
|
||||
self.input_cost_spin.setSuffix(" per 1K tokens")
|
||||
layout.addRow("Input Cost:", self.input_cost_spin)
|
||||
|
||||
# Output Cost
|
||||
self.output_cost_spin = QDoubleSpinBox()
|
||||
self.output_cost_spin.setRange(0.0, 1.0)
|
||||
self.output_cost_spin.setDecimals(4)
|
||||
self.output_cost_spin.setSingleStep(0.0001)
|
||||
self.output_cost_spin.setValue(0.002)
|
||||
self.output_cost_spin.setSuffix(" per 1K tokens")
|
||||
layout.addRow("Output Cost:", self.output_cost_spin)
|
||||
|
||||
group.setLayout(layout)
|
||||
return group
|
||||
|
||||
def create_ui_settings_group(self):
|
||||
"""Create UI settings group."""
|
||||
group = QGroupBox("User Interface Settings")
|
||||
layout = QFormLayout()
|
||||
|
||||
# Font Scale
|
||||
font_layout = QHBoxLayout()
|
||||
self.font_scale_spin = QDoubleSpinBox()
|
||||
self.font_scale_spin.setRange(0.5, 3.0)
|
||||
self.font_scale_spin.setSingleStep(0.1)
|
||||
self.font_scale_spin.setValue(1.0)
|
||||
self.font_scale_spin.setDecimals(1)
|
||||
self.font_scale_spin.setSuffix("x")
|
||||
self.font_scale_spin.setToolTip("Scale factor for all fonts in the GUI (1.0 = normal, 1.5 = 150% larger)")
|
||||
self.font_scale_spin.valueChanged.connect(self.on_font_scale_changed)
|
||||
|
||||
# Font scale presets
|
||||
font_layout = QHBoxLayout()
|
||||
font_layout.addWidget(self.font_scale_spin)
|
||||
|
||||
# Quick preset buttons
|
||||
small_btn = QPushButton("Small")
|
||||
small_btn.clicked.connect(lambda: self.font_scale_spin.setValue(0.8))
|
||||
small_btn.setMaximumWidth(60)
|
||||
# Quick preset buttons (smaller)
|
||||
for label, value in [("S", 0.8), ("M", 1.0), ("L", 1.5), ("XL", 2.0)]:
|
||||
btn = QPushButton(label)
|
||||
btn.clicked.connect(lambda checked, v=value: self.font_scale_spin.setValue(v))
|
||||
btn.setMaximumWidth(40)
|
||||
font_layout.addWidget(btn)
|
||||
|
||||
normal_btn = QPushButton("Normal")
|
||||
normal_btn.clicked.connect(lambda: self.font_scale_spin.setValue(1.0))
|
||||
normal_btn.setMaximumWidth(60)
|
||||
ui_form.addRow("Font Scale:", font_layout)
|
||||
|
||||
large_btn = QPushButton("Large")
|
||||
large_btn.clicked.connect(lambda: self.font_scale_spin.setValue(1.5))
|
||||
large_btn.setMaximumWidth(60)
|
||||
|
||||
xlarge_btn = QPushButton("X-Large")
|
||||
xlarge_btn.clicked.connect(lambda: self.font_scale_spin.setValue(2.0))
|
||||
xlarge_btn.setMaximumWidth(60)
|
||||
|
||||
font_layout.addWidget(small_btn)
|
||||
font_layout.addWidget(normal_btn)
|
||||
font_layout.addWidget(large_btn)
|
||||
font_layout.addWidget(xlarge_btn)
|
||||
|
||||
layout.addRow("Font Scale:", font_layout)
|
||||
|
||||
# DPI Awareness
|
||||
self.dpi_aware_cb = QCheckBox("High DPI Scaling")
|
||||
self.dpi_aware_cb.setToolTip("Enable automatic scaling for high DPI displays")
|
||||
self.dpi_aware_cb.setChecked(True)
|
||||
layout.addRow("", self.dpi_aware_cb)
|
||||
|
||||
# Theme selection
|
||||
self.theme_combo = QComboBox()
|
||||
self.theme_combo.addItems(["Dark", "Light", "System"])
|
||||
self.theme_combo.setCurrentText("Dark")
|
||||
layout.addRow("Theme:", self.theme_combo)
|
||||
ui_form.addRow("Theme:", self.theme_combo)
|
||||
|
||||
# Show font tip
|
||||
self.show_font_tip_cb = QCheckBox("Show font size tip on startup")
|
||||
self.show_font_tip_cb.setToolTip("Display helpful font sizing information when the GUI starts")
|
||||
self.show_font_tip_cb.setChecked(True)
|
||||
layout.addRow("", self.show_font_tip_cb)
|
||||
layout.addLayout(ui_form)
|
||||
layout.addStretch()
|
||||
|
||||
group.setLayout(layout)
|
||||
return group
|
||||
content.setLayout(layout)
|
||||
scroll.setWidget(content)
|
||||
|
||||
def on_font_scale_changed(self, value):
|
||||
"""Handle font scale change."""
|
||||
self.config_changed.emit()
|
||||
# Apply font scaling immediately
|
||||
self.apply_font_scaling(value)
|
||||
wrapper = QVBoxLayout()
|
||||
wrapper.setContentsMargins(0, 0, 0, 0)
|
||||
wrapper.addWidget(scroll)
|
||||
widget.setLayout(wrapper)
|
||||
return widget
|
||||
|
||||
def create_performance_formatting_tab(self):
|
||||
"""Create compact performance and formatting settings tab."""
|
||||
widget = QWidget()
|
||||
scroll = QScrollArea()
|
||||
scroll.setWidgetResizable(True)
|
||||
scroll.setFrameShape(QFrame.NoFrame)
|
||||
|
||||
def apply_font_scaling(self, scale_factor):
|
||||
"""Apply font scaling to the entire application."""
|
||||
app = QApplication.instance()
|
||||
if app:
|
||||
# Get the default font
|
||||
font = app.font()
|
||||
base_size = 9 # Base font size
|
||||
new_size = int(base_size * scale_factor)
|
||||
font.setPointSize(new_size)
|
||||
app.setFont(font)
|
||||
|
||||
# Emit signal to notify other components
|
||||
self.config_changed.emit()
|
||||
content = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
layout.setSpacing(5)
|
||||
layout.setContentsMargins(10, 10, 10, 10)
|
||||
|
||||
# Performance Settings Section
|
||||
layout.addWidget(create_section_header("⚡ Performance Settings"))
|
||||
perf_form = QFormLayout()
|
||||
perf_form.setSpacing(5)
|
||||
perf_form.setContentsMargins(0, 0, 0, 10)
|
||||
|
||||
self.file_threads_spin = QSpinBox()
|
||||
self.file_threads_spin.setRange(1, 10)
|
||||
self.file_threads_spin.setValue(1)
|
||||
perf_form.addRow("File Threads:", self.file_threads_spin)
|
||||
|
||||
self.threads_spin = QSpinBox()
|
||||
self.threads_spin.setRange(1, 20)
|
||||
self.threads_spin.setValue(1)
|
||||
perf_form.addRow("Threads per File:", self.threads_spin)
|
||||
|
||||
self.batch_size_spin = QSpinBox()
|
||||
self.batch_size_spin.setRange(1, 100)
|
||||
self.batch_size_spin.setValue(30)
|
||||
perf_form.addRow("Batch Size:", self.batch_size_spin)
|
||||
|
||||
self.frequency_penalty_spin = QDoubleSpinBox()
|
||||
self.frequency_penalty_spin.setRange(0.0, 2.0)
|
||||
self.frequency_penalty_spin.setSingleStep(0.05)
|
||||
self.frequency_penalty_spin.setValue(0.05)
|
||||
perf_form.addRow("Frequency Penalty:", self.frequency_penalty_spin)
|
||||
|
||||
layout.addLayout(perf_form)
|
||||
layout.addWidget(create_horizontal_line())
|
||||
|
||||
# Text Formatting Section
|
||||
layout.addWidget(create_section_header("📝 Text Formatting"))
|
||||
format_form = QFormLayout()
|
||||
format_form.setSpacing(5)
|
||||
format_form.setContentsMargins(0, 0, 0, 10)
|
||||
|
||||
self.width_spin = QSpinBox()
|
||||
self.width_spin.setRange(20, 200)
|
||||
self.width_spin.setValue(60)
|
||||
self.width_spin.setSuffix(" chars")
|
||||
format_form.addRow("Dialogue Width:", self.width_spin)
|
||||
|
||||
self.list_width_spin = QSpinBox()
|
||||
self.list_width_spin.setRange(20, 200)
|
||||
self.list_width_spin.setValue(100)
|
||||
self.list_width_spin.setSuffix(" chars")
|
||||
format_form.addRow("List Width:", self.list_width_spin)
|
||||
|
||||
self.note_width_spin = QSpinBox()
|
||||
self.note_width_spin.setRange(20, 200)
|
||||
self.note_width_spin.setValue(75)
|
||||
self.note_width_spin.setSuffix(" chars")
|
||||
format_form.addRow("Note Width:", self.note_width_spin)
|
||||
|
||||
layout.addLayout(format_form)
|
||||
layout.addWidget(create_horizontal_line())
|
||||
|
||||
# Custom API Pricing Section
|
||||
layout.addWidget(create_section_header("💰 Custom API Pricing"))
|
||||
price_form = QFormLayout()
|
||||
price_form.setSpacing(5)
|
||||
price_form.setContentsMargins(0, 0, 0, 10)
|
||||
|
||||
self.input_cost_spin = QDoubleSpinBox()
|
||||
self.input_cost_spin.setRange(0.0, 100.0)
|
||||
self.input_cost_spin.setDecimals(4)
|
||||
self.input_cost_spin.setSingleStep(0.1)
|
||||
self.input_cost_spin.setValue(2.0)
|
||||
self.input_cost_spin.setSuffix(" per 1M tokens")
|
||||
price_form.addRow("Input Cost:", self.input_cost_spin)
|
||||
|
||||
self.output_cost_spin = QDoubleSpinBox()
|
||||
self.output_cost_spin.setRange(0.0, 100.0)
|
||||
self.output_cost_spin.setDecimals(4)
|
||||
self.output_cost_spin.setSingleStep(0.1)
|
||||
self.output_cost_spin.setValue(8.0)
|
||||
self.output_cost_spin.setSuffix(" per 1M tokens")
|
||||
price_form.addRow("Output Cost:", self.output_cost_spin)
|
||||
|
||||
layout.addLayout(price_form)
|
||||
layout.addStretch()
|
||||
|
||||
content.setLayout(layout)
|
||||
scroll.setWidget(content)
|
||||
|
||||
wrapper = QVBoxLayout()
|
||||
wrapper.setContentsMargins(0, 0, 0, 0)
|
||||
wrapper.addWidget(scroll)
|
||||
widget.setLayout(wrapper)
|
||||
return widget
|
||||
|
||||
def load_from_env(self):
|
||||
"""Load configuration from .env file."""
|
||||
|
|
@ -326,7 +324,7 @@ class ConfigTab(QWidget):
|
|||
self.api_url_edit.setText(os.getenv("api", ""))
|
||||
self.api_key_edit.setText(os.getenv("key", ""))
|
||||
self.organization_edit.setText(os.getenv("organization", ""))
|
||||
self.model_combo.setCurrentText(os.getenv("model", "gpt-4"))
|
||||
self.model_combo.setCurrentText(os.getenv("model", "gpt-4.1"))
|
||||
|
||||
# Load translation settings
|
||||
self.language_combo.setCurrentText(os.getenv("language", "English"))
|
||||
|
|
@ -335,23 +333,21 @@ class ConfigTab(QWidget):
|
|||
# Load performance settings
|
||||
self.file_threads_spin.setValue(int(os.getenv("fileThreads", "1")))
|
||||
self.threads_spin.setValue(int(os.getenv("threads", "1")))
|
||||
self.batch_size_spin.setValue(int(os.getenv("batchsize", "10")))
|
||||
self.frequency_penalty_spin.setValue(float(os.getenv("frequency_penalty", "0.2")))
|
||||
self.batch_size_spin.setValue(int(os.getenv("batchsize", "30")))
|
||||
self.frequency_penalty_spin.setValue(float(os.getenv("frequency_penalty", "0.05")))
|
||||
|
||||
# Load formatting settings
|
||||
self.width_spin.setValue(int(os.getenv("width", "60")))
|
||||
self.list_width_spin.setValue(int(os.getenv("listWidth", "100")))
|
||||
self.note_width_spin.setValue(int(os.getenv("noteWidth", "80")))
|
||||
self.note_width_spin.setValue(int(os.getenv("noteWidth", "75")))
|
||||
|
||||
# Load custom API settings
|
||||
self.input_cost_spin.setValue(float(os.getenv("input_cost", "0.002")))
|
||||
self.output_cost_spin.setValue(float(os.getenv("output_cost", "0.002")))
|
||||
self.input_cost_spin.setValue(float(os.getenv("input_cost", "2.0")))
|
||||
self.output_cost_spin.setValue(float(os.getenv("output_cost", "8.0")))
|
||||
|
||||
# Load UI settings
|
||||
self.font_scale_spin.setValue(float(os.getenv("font_scale", "1.0")))
|
||||
self.dpi_aware_cb.setChecked(os.getenv("dpi_aware", "true").lower() == "true")
|
||||
self.theme_combo.setCurrentText(os.getenv("theme", "Dark"))
|
||||
self.show_font_tip_cb.setChecked(os.getenv("show_font_tip", "true").lower() == "true")
|
||||
|
||||
# Apply font scaling
|
||||
self.apply_font_scaling(self.font_scale_spin.value())
|
||||
|
|
@ -390,9 +386,7 @@ class ConfigTab(QWidget):
|
|||
|
||||
# Save UI settings
|
||||
set_key(self.env_file_path, "font_scale", str(self.font_scale_spin.value()))
|
||||
set_key(self.env_file_path, "dpi_aware", str(self.dpi_aware_cb.isChecked()).lower())
|
||||
set_key(self.env_file_path, "theme", self.theme_combo.currentText())
|
||||
set_key(self.env_file_path, "show_font_tip", str(self.show_font_tip_cb.isChecked()).lower())
|
||||
|
||||
QMessageBox.information(self, "Success", "Configuration saved successfully!")
|
||||
self.config_changed.emit()
|
||||
|
|
@ -434,26 +428,49 @@ class ConfigTab(QWidget):
|
|||
self.file_threads_spin.setValue(1)
|
||||
self.threads_spin.setValue(1)
|
||||
self.batch_size_spin.setValue(30)
|
||||
self.frequency_penalty_spin.setValue(0.2)
|
||||
self.frequency_penalty_spin.setValue(0.05)
|
||||
|
||||
# Formatting settings
|
||||
self.width_spin.setValue(60)
|
||||
self.list_width_spin.setValue(80)
|
||||
self.note_width_spin.setValue(85)
|
||||
self.list_width_spin.setValue(100)
|
||||
self.note_width_spin.setValue(75)
|
||||
|
||||
# Custom API settings
|
||||
self.input_cost_spin.setValue(0.002)
|
||||
self.output_cost_spin.setValue(0.002)
|
||||
self.input_cost_spin.setValue(2.0)
|
||||
self.output_cost_spin.setValue(8.0)
|
||||
|
||||
# UI settings
|
||||
self.font_scale_spin.setValue(1.0)
|
||||
self.dpi_aware_cb.setChecked(True)
|
||||
self.theme_combo.setCurrentText("Dark")
|
||||
self.show_font_tip_cb.setChecked(True)
|
||||
|
||||
# Reset engine tabs
|
||||
self.mvmz_tab.reset_to_defaults()
|
||||
self.ace_tab.reset_to_defaults()
|
||||
self.wolf_tab.reset_to_defaults()
|
||||
|
||||
# Apply font scaling
|
||||
self.apply_font_scaling(1.0)
|
||||
|
||||
def on_font_scale_changed(self, value):
|
||||
"""Handle font scale change."""
|
||||
self.config_changed.emit()
|
||||
# Apply font scaling immediately
|
||||
self.apply_font_scaling(value)
|
||||
|
||||
def apply_font_scaling(self, scale_factor):
|
||||
"""Apply font scaling to the entire application."""
|
||||
app = QApplication.instance()
|
||||
if app:
|
||||
# Get the default font
|
||||
font = app.font()
|
||||
base_size = 9 # Base font size
|
||||
new_size = int(base_size * scale_factor)
|
||||
font.setPointSize(new_size)
|
||||
app.setFont(font)
|
||||
|
||||
# Emit signal to notify other components
|
||||
self.config_changed.emit()
|
||||
|
||||
def get_config(self):
|
||||
"""Get current configuration as dictionary."""
|
||||
return {
|
||||
|
|
@ -473,9 +490,7 @@ class ConfigTab(QWidget):
|
|||
"input_cost": self.input_cost_spin.value(),
|
||||
"output_cost": self.output_cost_spin.value(),
|
||||
"font_scale": self.font_scale_spin.value(),
|
||||
"dpi_aware": self.dpi_aware_cb.isChecked(),
|
||||
"theme": self.theme_combo.currentText(),
|
||||
"show_font_tip": self.show_font_tip_cb.isChecked()
|
||||
"theme": self.theme_combo.currentText()
|
||||
}
|
||||
|
||||
def validate(self):
|
||||
|
|
|
|||
170
gui/main.py
170
gui/main.py
|
|
@ -18,9 +18,6 @@ from PyQt5.QtGui import QIcon, QFont, QPixmap, QScreen
|
|||
|
||||
# Import configuration widgets
|
||||
from gui.config_tab import ConfigTab
|
||||
from gui.engine_config_tab import EngineConfigTab
|
||||
from gui.log_viewer import LogViewer
|
||||
from gui.file_manager import FileManager
|
||||
from gui.translation_tab import TranslationTab
|
||||
|
||||
class DazedMTLGUI(QMainWindow):
|
||||
|
|
@ -132,9 +129,6 @@ class DazedMTLGUI(QMainWindow):
|
|||
central_widget = QWidget()
|
||||
self.setCentralWidget(central_widget)
|
||||
|
||||
# Create main splitter
|
||||
main_splitter = QSplitter(Qt.Horizontal)
|
||||
|
||||
# Create tab widget
|
||||
self.tab_widget = QTabWidget()
|
||||
self.tab_widget.setTabPosition(QTabWidget.North)
|
||||
|
|
@ -142,20 +136,9 @@ class DazedMTLGUI(QMainWindow):
|
|||
# Add tabs
|
||||
self.setup_tabs()
|
||||
|
||||
# Create log viewer
|
||||
self.log_viewer = LogViewer()
|
||||
|
||||
# Add widgets to splitter
|
||||
main_splitter.addWidget(self.tab_widget)
|
||||
main_splitter.addWidget(self.log_viewer)
|
||||
|
||||
# Set proportional sizes instead of fixed pixel sizes
|
||||
main_splitter.setStretchFactor(0, 2) # Main content gets 2/3
|
||||
main_splitter.setStretchFactor(1, 1) # Log viewer gets 1/3
|
||||
|
||||
# Set main layout
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(main_splitter)
|
||||
layout.addWidget(self.tab_widget)
|
||||
central_widget.setLayout(layout)
|
||||
|
||||
# Create menu bar
|
||||
|
|
@ -170,32 +153,7 @@ class DazedMTLGUI(QMainWindow):
|
|||
|
||||
# Translation Execution Tab (includes file management)
|
||||
self.translation_tab = TranslationTab(self)
|
||||
try:
|
||||
self.translation_tab.engine_changed.connect(self.show_engine_tab)
|
||||
except Exception:
|
||||
pass
|
||||
self.tab_widget.addTab(self.translation_tab, "Translation")
|
||||
|
||||
# Unified Engine Configuration Tab
|
||||
self.engine_config_tab = EngineConfigTab()
|
||||
self.tab_widget.addTab(self.engine_config_tab, "Engine Config")
|
||||
# Default to MV/MZ config on first load
|
||||
try:
|
||||
self.show_engine_tab("mvmz")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def show_engine_tab(self, engine: str):
|
||||
"""Select engine config tab and display appropriate engine sub-widget."""
|
||||
try:
|
||||
# Switch to Engine Config tab
|
||||
for i in range(self.tab_widget.count()):
|
||||
if self.tab_widget.tabText(i) == "Engine Config":
|
||||
self.tab_widget.setCurrentIndex(i)
|
||||
break
|
||||
self.engine_config_tab.show_engine(engine)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def on_config_changed(self):
|
||||
"""Handle configuration changes."""
|
||||
|
|
@ -307,7 +265,6 @@ class DazedMTLGUI(QMainWindow):
|
|||
try:
|
||||
# Load configuration from file
|
||||
self.config_tab.load_from_file(file_path)
|
||||
self.rpgmaker_tab.load_from_file(file_path)
|
||||
self.status_label.setText(f"Loaded project: {Path(file_path).name}")
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "Error", f"Failed to load project:\n{str(e)}")
|
||||
|
|
@ -324,9 +281,7 @@ class DazedMTLGUI(QMainWindow):
|
|||
if file_path:
|
||||
try:
|
||||
# Save configuration to file
|
||||
config_data = {}
|
||||
config_data.update(self.config_tab.get_config())
|
||||
config_data.update(self.rpgmaker_tab.get_config())
|
||||
config_data = self.config_tab.get_config()
|
||||
|
||||
import json
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
|
|
@ -348,7 +303,6 @@ class DazedMTLGUI(QMainWindow):
|
|||
|
||||
if reply == QMessageBox.Yes:
|
||||
self.config_tab.reset_to_defaults()
|
||||
self.rpgmaker_tab.reset_to_defaults()
|
||||
self.status_label.setText("Reset to defaults")
|
||||
|
||||
def validate_configuration(self):
|
||||
|
|
@ -356,13 +310,12 @@ class DazedMTLGUI(QMainWindow):
|
|||
try:
|
||||
# Validate configuration settings
|
||||
config_valid = self.config_tab.validate()
|
||||
rpgmaker_valid = self.rpgmaker_tab.validate()
|
||||
|
||||
if config_valid and rpgmaker_valid:
|
||||
if config_valid:
|
||||
QMessageBox.information(self, "Validation", "Configuration is valid!")
|
||||
self.status_label.setText("Configuration validated")
|
||||
else:
|
||||
QMessageBox.warning(self, "Validation", "Configuration has issues. Check the log for details.")
|
||||
QMessageBox.warning(self, "Validation", "Configuration has issues. Check the warnings.")
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "Validation Error", f"Failed to validate configuration:\n{str(e)}")
|
||||
|
|
@ -433,7 +386,7 @@ def main():
|
|||
app.setApplicationVersion("1.0")
|
||||
app.setOrganizationName("DazedTranslations")
|
||||
|
||||
# Apply dark theme (optional)
|
||||
# Apply dark theme with cleaner, more compact styling
|
||||
app.setStyleSheet("""
|
||||
QMainWindow {
|
||||
background-color: #2b2b2b;
|
||||
|
|
@ -446,13 +399,15 @@ def main():
|
|||
QTabWidget::pane {
|
||||
border: 1px solid #555555;
|
||||
background-color: #3c3c3c;
|
||||
padding: 5px;
|
||||
}
|
||||
QTabBar::tab {
|
||||
background-color: #555555;
|
||||
color: #ffffff;
|
||||
padding: 8px 12px;
|
||||
padding: 8px 16px;
|
||||
margin-right: 2px;
|
||||
border: 1px solid #666666;
|
||||
border-bottom: none;
|
||||
}
|
||||
QTabBar::tab:selected {
|
||||
background-color: #007acc;
|
||||
|
|
@ -463,26 +418,28 @@ def main():
|
|||
color: #ffffff;
|
||||
}
|
||||
QGroupBox {
|
||||
font-weight: bold;
|
||||
border: 2px solid #555555;
|
||||
border-radius: 5px;
|
||||
margin: 10px 0px;
|
||||
padding-top: 10px;
|
||||
font-weight: normal;
|
||||
border: 1px solid #444444;
|
||||
border-radius: 3px;
|
||||
margin-top: 8px;
|
||||
padding: 8px;
|
||||
color: #ffffff;
|
||||
background-color: #3c3c3c;
|
||||
background-color: transparent;
|
||||
}
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
left: 10px;
|
||||
padding: 0 5px 0 5px;
|
||||
subcontrol-position: top left;
|
||||
left: 8px;
|
||||
padding: 2px 5px;
|
||||
color: #007acc;
|
||||
background-color: transparent;
|
||||
background-color: #2b2b2b;
|
||||
font-weight: bold;
|
||||
}
|
||||
QPushButton {
|
||||
background-color: #0078d4;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 6px 12px;
|
||||
padding: 7px 14px;
|
||||
border-radius: 3px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
@ -492,10 +449,15 @@ def main():
|
|||
QPushButton:pressed {
|
||||
background-color: #005a9e;
|
||||
}
|
||||
QPushButton:disabled {
|
||||
background-color: #404040;
|
||||
color: #888888;
|
||||
}
|
||||
QCheckBox {
|
||||
color: #ffffff;
|
||||
spacing: 5px;
|
||||
spacing: 6px;
|
||||
background-color: transparent;
|
||||
padding: 2px;
|
||||
}
|
||||
QCheckBox::indicator {
|
||||
width: 16px;
|
||||
|
|
@ -504,112 +466,142 @@ def main():
|
|||
QCheckBox::indicator:unchecked {
|
||||
background-color: #404040;
|
||||
border: 1px solid #555555;
|
||||
border-radius: 2px;
|
||||
}
|
||||
QCheckBox::indicator:checked {
|
||||
background-color: #0078d4;
|
||||
border: 1px solid #0078d4;
|
||||
border-radius: 2px;
|
||||
}
|
||||
QLabel {
|
||||
color: #ffffff;
|
||||
background-color: transparent;
|
||||
padding: 2px;
|
||||
}
|
||||
QLineEdit {
|
||||
background-color: #404040;
|
||||
color: #ffffff;
|
||||
border: 1px solid #555555;
|
||||
padding: 4px;
|
||||
padding: 5px 8px;
|
||||
border-radius: 2px;
|
||||
selection-background-color: #007acc;
|
||||
}
|
||||
QLineEdit:focus {
|
||||
border: 2px solid #007acc;
|
||||
border: 1px solid #007acc;
|
||||
}
|
||||
QSpinBox, QDoubleSpinBox {
|
||||
background-color: #404040;
|
||||
color: #ffffff;
|
||||
border: 1px solid #555555;
|
||||
padding: 4px;
|
||||
padding: 5px 8px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
QSpinBox:focus, QDoubleSpinBox:focus {
|
||||
border: 2px solid #007acc;
|
||||
border: 1px solid #007acc;
|
||||
}
|
||||
QSpinBox::up-button, QDoubleSpinBox::up-button {
|
||||
background-color: #555555;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
QSpinBox::down-button, QDoubleSpinBox::down-button {
|
||||
background-color: #555555;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
QComboBox {
|
||||
background-color: #404040;
|
||||
color: #ffffff;
|
||||
border: 1px solid #555555;
|
||||
padding: 4px;
|
||||
padding: 5px 8px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
QComboBox:focus {
|
||||
border: 2px solid #007acc;
|
||||
border: 1px solid #007acc;
|
||||
}
|
||||
QComboBox::drop-down {
|
||||
border: none;
|
||||
background-color: #555555;
|
||||
width: 20px;
|
||||
}
|
||||
QComboBox::down-arrow {
|
||||
image: none;
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-top: 4px solid #ffffff;
|
||||
border-top: 5px solid #ffffff;
|
||||
margin-right: 5px;
|
||||
}
|
||||
QComboBox QAbstractItemView {
|
||||
background-color: #404040;
|
||||
color: #ffffff;
|
||||
selection-background-color: #007acc;
|
||||
border: 1px solid #555555;
|
||||
padding: 3px;
|
||||
}
|
||||
QTextEdit {
|
||||
background-color: #1e1e1e;
|
||||
color: #ffffff;
|
||||
border: 1px solid #555555;
|
||||
selection-background-color: #007acc;
|
||||
padding: 5px;
|
||||
}
|
||||
QTextEdit:focus {
|
||||
border: 1px solid #007acc;
|
||||
}
|
||||
QScrollArea {
|
||||
background-color: #2b2b2b;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
QScrollBar:vertical {
|
||||
background-color: #404040;
|
||||
background-color: #2b2b2b;
|
||||
width: 12px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
}
|
||||
QScrollBar::handle:vertical {
|
||||
background-color: #666666;
|
||||
background-color: #555555;
|
||||
border-radius: 6px;
|
||||
min-height: 20px;
|
||||
margin: 2px;
|
||||
}
|
||||
QScrollBar::handle:vertical:hover {
|
||||
background-color: #007acc;
|
||||
}
|
||||
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
|
||||
height: 0px;
|
||||
}
|
||||
QScrollBar:horizontal {
|
||||
background-color: #404040;
|
||||
background-color: #2b2b2b;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
}
|
||||
QScrollBar::handle:horizontal {
|
||||
background-color: #666666;
|
||||
background-color: #555555;
|
||||
border-radius: 6px;
|
||||
min-width: 20px;
|
||||
margin: 2px;
|
||||
}
|
||||
QScrollBar::handle:horizontal:hover {
|
||||
background-color: #007acc;
|
||||
}
|
||||
QTreeWidget {
|
||||
QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {
|
||||
width: 0px;
|
||||
}
|
||||
QListWidget {
|
||||
background-color: #1e1e1e;
|
||||
color: #ffffff;
|
||||
border: 1px solid #555555;
|
||||
selection-background-color: #007acc;
|
||||
padding: 3px;
|
||||
}
|
||||
QTreeWidget::item {
|
||||
padding: 4px;
|
||||
QListWidget::item {
|
||||
padding: 5px;
|
||||
border-bottom: 1px solid #333333;
|
||||
}
|
||||
QTreeWidget::item:selected {
|
||||
QListWidget::item:selected {
|
||||
background-color: #007acc;
|
||||
color: #ffffff;
|
||||
}
|
||||
QTreeWidget::item:hover {
|
||||
QListWidget::item:hover {
|
||||
background-color: #404040;
|
||||
}
|
||||
QHeaderView::section {
|
||||
|
|
@ -629,6 +621,7 @@ def main():
|
|||
border-radius: 3px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
height: 20px;
|
||||
}
|
||||
QProgressBar::chunk {
|
||||
background-color: #007acc;
|
||||
|
|
@ -652,16 +645,19 @@ def main():
|
|||
border: 1px solid #555555;
|
||||
}
|
||||
QMenu::item {
|
||||
padding: 6px 12px;
|
||||
padding: 6px 20px;
|
||||
}
|
||||
QMenu::item:selected {
|
||||
background-color: #007acc;
|
||||
}
|
||||
QFrame[frameShape="4"] {
|
||||
QFrame[frameShape="4"], QFrame[frameShape="5"] {
|
||||
color: #555555;
|
||||
}
|
||||
QFrame[frameShape="5"] {
|
||||
color: #555555;
|
||||
QSplitter::handle {
|
||||
background-color: #555555;
|
||||
}
|
||||
QSplitter::handle:hover {
|
||||
background-color: #007acc;
|
||||
}
|
||||
""")
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ from PyQt5.QtWidgets import (
|
|||
)
|
||||
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QThread, QMutex, QProcess
|
||||
from PyQt5.QtGui import QFont
|
||||
from gui.log_viewer import LogViewer
|
||||
|
||||
|
||||
class TranslationWorker(QThread):
|
||||
|
|
@ -475,6 +476,11 @@ class TranslationTab(QWidget):
|
|||
|
||||
def setup_ui(self):
|
||||
"""Set up the user interface."""
|
||||
# Create main splitter to separate translation controls from log viewer
|
||||
main_splitter = QSplitter(Qt.Horizontal)
|
||||
|
||||
# Left side - translation controls
|
||||
left_widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
layout.setSpacing(15)
|
||||
|
||||
|
|
@ -561,7 +567,24 @@ class TranslationTab(QWidget):
|
|||
button_layout.addWidget(self.stop_button)
|
||||
button_layout.addStretch()
|
||||
layout.addLayout(button_layout)
|
||||
self.setLayout(layout)
|
||||
left_widget.setLayout(layout)
|
||||
|
||||
# Right side - translation history log viewer
|
||||
self.translation_log_viewer = LogViewer()
|
||||
|
||||
# Add both to splitter
|
||||
main_splitter.addWidget(left_widget)
|
||||
main_splitter.addWidget(self.translation_log_viewer)
|
||||
|
||||
# Set proportional sizes (translation controls: 60%, log viewer: 40%)
|
||||
main_splitter.setStretchFactor(0, 3)
|
||||
main_splitter.setStretchFactor(1, 2)
|
||||
|
||||
# Set main layout for this tab
|
||||
tab_layout = QVBoxLayout()
|
||||
tab_layout.addWidget(main_splitter)
|
||||
tab_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.setLayout(tab_layout)
|
||||
|
||||
def setup_module_list(self):
|
||||
"""Set up the module selection list."""
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ CODE102 = True
|
|||
|
||||
# Optional
|
||||
CODE101 = False
|
||||
CODE408 = True
|
||||
CODE408 = False
|
||||
|
||||
# Variables
|
||||
CODE122 = False
|
||||
|
|
|
|||
Loading…
Reference in a new issue