Cleaning up ui

This commit is contained in:
dazedanon 2025-10-25 16:08:49 -05:00
parent 3333e792f4
commit fcb10d9aad
4 changed files with 365 additions and 331 deletions

View file

@ -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):

View file

@ -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;
}
""")

View file

@ -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."""

View file

@ -89,7 +89,7 @@ CODE102 = True
# Optional
CODE101 = False
CODE408 = True
CODE408 = False
# Variables
CODE122 = False