diff --git a/gui/config_tab.py b/gui/config_tab.py
index 8f5ae79..003b697 100644
--- a/gui/config_tab.py
+++ b/gui/config_tab.py
@@ -130,18 +130,18 @@ class ConfigTab(QWidget):
self.api_url_edit = QLineEdit()
self.api_url_edit.setPlaceholderText("Leave blank for OpenAI API")
- self.api_url_edit.setMaximumWidth(400)
+ self.api_url_edit.setFixedWidth(350) # Large
api_form.addRow("API URL:", self.api_url_edit)
self.api_key_edit = QLineEdit()
self.api_key_edit.setEchoMode(QLineEdit.Password)
self.api_key_edit.setPlaceholderText("Enter your API key")
- self.api_key_edit.setMaximumWidth(400)
+ self.api_key_edit.setFixedWidth(350) # Large
api_form.addRow("API Key:", self.api_key_edit)
self.organization_edit = QLineEdit()
self.organization_edit.setPlaceholderText("Optional organization key")
- self.organization_edit.setMaximumWidth(400)
+ self.organization_edit.setFixedWidth(350) # Large
api_form.addRow("Organization:", self.organization_edit)
self.model_combo = QComboBox()
@@ -151,7 +151,7 @@ class ConfigTab(QWidget):
"deepseek-chat", "claude-3-sonnet-20240229",
"gemini-2.0-flash", "gemini-2.5-flash", "gemini-2.5-pro"
])
- self.model_combo.setMaximumWidth(400)
+ self.model_combo.setFixedWidth(200) # Medium
api_form.addRow("Model:", self.model_combo)
left_column.addLayout(api_form)
@@ -169,14 +169,15 @@ class ConfigTab(QWidget):
"English", "Spanish", "French", "German", "Italian",
"Portuguese", "Russian", "Chinese", "Korean", "Japanese"
])
- self.language_combo.setMaximumWidth(250)
+ self.language_combo.setFixedWidth(200) # Medium
trans_form.addRow("Target Language:", self.language_combo)
self.timeout_spin = QSpinBox()
+ self.timeout_spin.setButtonSymbols(QSpinBox.NoButtons)
self.timeout_spin.setRange(30, 300)
- self.timeout_spin.setValue(120)
+ self.timeout_spin.setValue(90)
self.timeout_spin.setSuffix(" sec")
- self.timeout_spin.setMaximumWidth(150)
+ self.timeout_spin.setFixedWidth(90) # Small
trans_form.addRow("Timeout:", self.timeout_spin)
left_column.addLayout(trans_form)
@@ -190,28 +191,32 @@ class ConfigTab(QWidget):
perf_form.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
self.file_threads_spin = QSpinBox()
+ self.file_threads_spin.setButtonSymbols(QSpinBox.NoButtons)
self.file_threads_spin.setRange(1, 10)
self.file_threads_spin.setValue(1)
- self.file_threads_spin.setMaximumWidth(150)
+ self.file_threads_spin.setFixedWidth(90) # Small
perf_form.addRow("File Threads:", self.file_threads_spin)
self.threads_spin = QSpinBox()
+ self.threads_spin.setButtonSymbols(QSpinBox.NoButtons)
self.threads_spin.setRange(1, 20)
self.threads_spin.setValue(1)
- self.threads_spin.setMaximumWidth(150)
+ self.threads_spin.setFixedWidth(90) # Small
perf_form.addRow("Threads per File:", self.threads_spin)
self.batch_size_spin = QSpinBox()
+ self.batch_size_spin.setButtonSymbols(QSpinBox.NoButtons)
self.batch_size_spin.setRange(1, 100)
self.batch_size_spin.setValue(30)
- self.batch_size_spin.setMaximumWidth(150)
+ self.batch_size_spin.setFixedWidth(90) # Small
perf_form.addRow("Batch Size:", self.batch_size_spin)
self.frequency_penalty_spin = QDoubleSpinBox()
+ self.frequency_penalty_spin.setButtonSymbols(QDoubleSpinBox.NoButtons)
self.frequency_penalty_spin.setRange(0.0, 2.0)
self.frequency_penalty_spin.setSingleStep(0.05)
self.frequency_penalty_spin.setValue(0.05)
- self.frequency_penalty_spin.setMaximumWidth(150)
+ self.frequency_penalty_spin.setFixedWidth(90) # Small
perf_form.addRow("Frequency Penalty:", self.frequency_penalty_spin)
left_column.addLayout(perf_form)
@@ -229,24 +234,27 @@ class ConfigTab(QWidget):
format_form.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
self.width_spin = QSpinBox()
+ self.width_spin.setButtonSymbols(QSpinBox.NoButtons)
self.width_spin.setRange(20, 200)
self.width_spin.setValue(60)
self.width_spin.setSuffix(" chars")
- self.width_spin.setMaximumWidth(150)
+ self.width_spin.setFixedWidth(90) # Small
format_form.addRow("Dialogue Width:", self.width_spin)
self.list_width_spin = QSpinBox()
+ self.list_width_spin.setButtonSymbols(QSpinBox.NoButtons)
self.list_width_spin.setRange(20, 200)
self.list_width_spin.setValue(100)
self.list_width_spin.setSuffix(" chars")
- self.list_width_spin.setMaximumWidth(150)
+ self.list_width_spin.setFixedWidth(90) # Small
format_form.addRow("List Width:", self.list_width_spin)
self.note_width_spin = QSpinBox()
+ self.note_width_spin.setButtonSymbols(QSpinBox.NoButtons)
self.note_width_spin.setRange(20, 200)
self.note_width_spin.setValue(75)
self.note_width_spin.setSuffix(" chars")
- self.note_width_spin.setMaximumWidth(150)
+ self.note_width_spin.setFixedWidth(90) # Small
format_form.addRow("Note Width:", self.note_width_spin)
right_column.addLayout(format_form)
@@ -266,21 +274,23 @@ class ConfigTab(QWidget):
price_form.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
self.input_cost_spin = QDoubleSpinBox()
+ self.input_cost_spin.setButtonSymbols(QDoubleSpinBox.NoButtons)
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")
- self.input_cost_spin.setMaximumWidth(200)
+ self.input_cost_spin.setFixedWidth(200) # Medium
price_form.addRow("Input Cost:", self.input_cost_spin)
self.output_cost_spin = QDoubleSpinBox()
+ self.output_cost_spin.setButtonSymbols(QDoubleSpinBox.NoButtons)
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")
- self.output_cost_spin.setMaximumWidth(200)
+ self.output_cost_spin.setFixedWidth(200) # Medium
price_form.addRow("Output Cost:", self.output_cost_spin)
right_column.addLayout(price_form)
@@ -314,7 +324,7 @@ class ConfigTab(QWidget):
# Load translation settings
self.language_combo.setCurrentText(os.getenv("language", "English"))
- self.timeout_spin.setValue(int(os.getenv("timeout", "120")))
+ self.timeout_spin.setValue(int(os.getenv("timeout", "90")))
# Load performance settings
self.file_threads_spin.setValue(int(os.getenv("fileThreads", "1")))
@@ -397,7 +407,7 @@ class ConfigTab(QWidget):
# Translation settings
self.language_combo.setCurrentText("English")
- self.timeout_spin.setValue(120)
+ self.timeout_spin.setValue(90)
# Performance settings
self.file_threads_spin.setValue(1)
diff --git a/gui/rpgmaker_tab.py b/gui/rpgmaker_tab.py
index d39b3ca..e580054 100644
--- a/gui/rpgmaker_tab.py
+++ b/gui/rpgmaker_tab.py
@@ -7,7 +7,7 @@ from pathlib import Path
from PyQt5.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QFormLayout, QCheckBox,
QPushButton, QGroupBox, QLabel, QMessageBox, QScrollArea,
- QTextEdit, QSpinBox, QFrame
+ QTextEdit, QSpinBox, QFrame, QGridLayout
)
from PyQt5.QtCore import Qt, pyqtSignal
@@ -18,6 +18,21 @@ except ImportError:
ConfigIntegration = None
+def create_section_label(text):
+ """Create a section label for grouping checkboxes."""
+ label = QLabel(text)
+ label.setStyleSheet("""
+ QLabel {
+ font-size: 12px;
+ font-weight: bold;
+ color: #007acc;
+ padding: 5px 0px 3px 0px;
+ background-color: transparent;
+ }
+ """)
+ return label
+
+
class RPGMakerTab(QWidget):
"""RPG Maker MV/MZ & Ace configuration tab.
@@ -154,232 +169,148 @@ class RPGMakerTab(QWidget):
self.reset_to_defaults()
def init_ui(self):
- """Initialize the user interface."""
+ """Initialize the user interface with compact two-column layout."""
main_layout = QVBoxLayout()
-
- # Create scroll area
- scroll_area = QScrollArea()
- scroll_content = QWidget()
- scroll_layout = QVBoxLayout()
+ main_layout.setContentsMargins(10, 10, 10, 10)
+ main_layout.setSpacing(10)
# Title and description
title = "RPG Maker MV/MZ" if self.engine != "ACE" else "RPG Maker Ace"
title_label = QLabel(f"{title} Translation Settings")
- title_label.setStyleSheet("font-size: 16px; font-weight: bold; color: #007acc;")
- scroll_layout.addWidget(title_label)
+ title_label.setStyleSheet("font-size: 14px; font-weight: bold; color: #007acc;")
+ main_layout.addWidget(title_label)
description_label = QLabel(
- "Configure which RPG Maker event codes to translate and additional options. "
- "Each code represents a specific type of game content."
+ "Enable event codes to translate. Only enable what you need to reduce translation time and costs."
)
description_label.setWordWrap(True)
- description_label.setStyleSheet("color: #cccccc; margin-bottom: 10px;")
- scroll_layout.addWidget(description_label)
+ description_label.setStyleSheet("color: #888888; font-size: 11px; margin-bottom: 5px;")
+ main_layout.addWidget(description_label)
- # General Config Group
- general_group = self.create_general_config_group()
- scroll_layout.addWidget(general_group)
+ # Two-column layout for checkboxes
+ columns_layout = QHBoxLayout()
+ columns_layout.setSpacing(30)
- # Main Dialogue Codes Group
- dialogue_group = self.create_dialogue_codes_group()
- scroll_layout.addWidget(dialogue_group)
+ # LEFT COLUMN
+ left_column = QVBoxLayout()
+ left_column.setSpacing(3)
- # Optional Codes Group
- optional_group = self.create_optional_codes_group()
- scroll_layout.addWidget(optional_group)
-
- # Variable Codes Group
- variable_group = self.create_variable_codes_group()
- scroll_layout.addWidget(variable_group)
-
- # Other Codes Group
- other_group = self.create_other_codes_group()
- scroll_layout.addWidget(other_group)
-
- # Buttons
- button_layout = QHBoxLayout()
-
- self.reset_button = QPushButton("Reset to Defaults")
- self.reset_button.clicked.connect(self.reset_to_defaults_with_message)
-
- self.validate_button = QPushButton("Validate Settings")
- self.validate_button.clicked.connect(self.validate_and_show_report)
-
- button_layout.addWidget(self.reset_button)
- button_layout.addWidget(self.validate_button)
- button_layout.addStretch()
-
- scroll_layout.addLayout(button_layout)
-
- # Add separator
- separator = QFrame()
- separator.setFrameShape(QFrame.HLine)
- separator.setFrameShadow(QFrame.Sunken)
- scroll_layout.addWidget(separator)
-
- # Add note about performance
- note_text = QTextEdit()
- note_text.setMaximumHeight(100)
- note_text.setReadOnly(True)
- note_text.setHtml("""
- Performance Notes:
- • Enable only the codes you need to reduce translation time and costs
- • CODE408 can significantly increase costs as it translates comments
- • Main dialogue codes (401, 405, 102) are typically required for story content
- • Test with a small file first to verify settings work correctly
- """)
- scroll_layout.addWidget(note_text)
-
- scroll_content.setLayout(scroll_layout)
- scroll_area.setWidget(scroll_content)
- scroll_area.setWidgetResizable(True)
-
- main_layout.addWidget(scroll_area)
- self.setLayout(main_layout)
-
- def create_general_config_group(self):
- """Create general configuration group."""
- group = QGroupBox("General Configuration")
- layout = QVBoxLayout()
-
- # FIRSTLINESPEAKERS
+ # General Configuration
+ left_column.addWidget(create_section_label("⚙️ General Options"))
self.first_line_speakers_cb = QCheckBox("First Line Speakers")
- self.first_line_speakers_cb.setToolTip(
- "If the first line of event code 401 contains a speaker name, enable this option"
- )
- layout.addWidget(self.first_line_speakers_cb)
+ self.first_line_speakers_cb.setToolTip("Enable if first line of CODE401 contains speaker name")
+ left_column.addWidget(self.first_line_speakers_cb)
- # FACENAME101
- self.facename_101_cb = QCheckBox("Find Speakers in 101 Codes based on Face Name")
- self.facename_101_cb.setToolTip(
- "Use character face names to identify speakers in event code 101"
- )
- layout.addWidget(self.facename_101_cb)
+ self.facename101_cb = QCheckBox("Face Name in CODE101")
+ self.facename101_cb.setToolTip("Enable to translate face names in CODE101")
+ left_column.addWidget(self.facename101_cb)
- # NAMES
- self.names_cb = QCheckBox("Output Character Names List")
- self.names_cb.setToolTip(
- "Generate a list of all character names found during translation"
- )
- layout.addWidget(self.names_cb)
+ self.names_cb = QCheckBox("Translate Names")
+ self.names_cb.setToolTip("Enable to translate character names")
+ left_column.addWidget(self.names_cb)
- # BRFLAG
- self.br_flag_cb = QCheckBox("Use
Tags")
- self.br_flag_cb.setToolTip(
- "Use
HTML tags instead of newlines for line breaks"
- )
- layout.addWidget(self.br_flag_cb)
+ self.brflag_cb = QCheckBox("Line Break Flag")
+ self.brflag_cb.setToolTip("Enable line break handling")
+ left_column.addWidget(self.brflag_cb)
- # FIXTEXTWRAP
- self.fix_textwrap_cb = QCheckBox("Fix Text Wrapping")
- self.fix_textwrap_cb.setToolTip(
- "Automatically fix text wrapping for better display"
- )
- layout.addWidget(self.fix_textwrap_cb)
+ self.fixtextwrap_cb = QCheckBox("Fix Text Wrap")
+ self.fixtextwrap_cb.setToolTip("Automatically fix text wrapping issues")
+ left_column.addWidget(self.fixtextwrap_cb)
- # IGNORETLTEXT
- self.ignore_tl_text_cb = QCheckBox("Ignore Already Translated Text")
- self.ignore_tl_text_cb.setToolTip(
- "Skip text that appears to already be translated"
- )
- layout.addWidget(self.ignore_tl_text_cb)
+ self.ignoretltext_cb = QCheckBox("Ignore TL Text")
+ self.ignoretltext_cb.setToolTip("Ignore already translated text")
+ left_column.addWidget(self.ignoretltext_cb)
- group.setLayout(layout)
- return group
+ left_column.addSpacing(8)
- def create_dialogue_codes_group(self):
- """Create dialogue codes group."""
- group = QGroupBox("Main Dialogue Codes (Recommended)")
- layout = QVBoxLayout()
+ # Main Dialogue Codes
+ left_column.addWidget(create_section_label("💬 Main Dialogue (Recommended)"))
+ self.code401_cb = QCheckBox("CODE401 - Show Text")
+ left_column.addWidget(self.code401_cb)
- # CODE401
- self.code_401_cb = QCheckBox("CODE 401 - Show Text")
- self.code_401_cb.setToolTip(
- "Translate dialogue text displayed in message windows. Essential for story content."
- )
- layout.addWidget(self.code_401_cb)
+ self.code405_cb = QCheckBox("CODE405 - Show Text (line 4+)")
+ left_column.addWidget(self.code405_cb)
- # CODE405
- self.code_405_cb = QCheckBox("CODE 405 - Show Text (Scrolling)")
- self.code_405_cb.setToolTip(
- "Translate scrolling text messages. Used for longer dialogue passages."
- )
- layout.addWidget(self.code_405_cb)
+ self.code102_cb = QCheckBox("CODE102 - Show Choices")
+ left_column.addWidget(self.code102_cb)
- # CODE102
- self.code_102_cb = QCheckBox("CODE 102 - Show Choices")
- self.code_102_cb.setToolTip(
- "Translate choice options presented to the player."
- )
- layout.addWidget(self.code_102_cb)
+ left_column.addSpacing(8)
- group.setLayout(layout)
- return group
+ # Optional Dialogue Codes
+ left_column.addWidget(create_section_label("📝 Optional Dialogue"))
+ self.code101_cb = QCheckBox("CODE101 - Show Text (face)")
+ left_column.addWidget(self.code101_cb)
- def create_optional_codes_group(self):
- """Create optional codes group."""
- group = QGroupBox("Optional Codes")
- layout = QVBoxLayout()
+ self.code408_cb = QCheckBox("CODE408 - Show Text (continuation)")
+ self.code408_cb.setToolTip("Can significantly increase costs")
+ left_column.addWidget(self.code408_cb)
- # CODE101
- self.code_101_cb = QCheckBox("CODE 101 - Character Names")
- self.code_101_cb.setToolTip(
- "Translate character names. Enable only when names are stored in code 101."
- )
- layout.addWidget(self.code_101_cb)
+ self.code122_cb = QCheckBox("CODE122 - Control Variables")
+ left_column.addWidget(self.code122_cb)
- # CODE408
- self.code_408_cb = QCheckBox("CODE 408 - Comments (Warning: High Cost)")
- self.code_408_cb.setToolTip(
- "Translate comment text. WARNING: This can significantly increase translation costs!"
- )
- self.code_408_cb.setStyleSheet("QCheckBox { color: #ff6b6b; }")
- layout.addWidget(self.code_408_cb)
+ left_column.addStretch()
- group.setLayout(layout)
- return group
+ # RIGHT COLUMN
+ right_column = QVBoxLayout()
+ right_column.setSpacing(3)
- def create_variable_codes_group(self):
- """Create variable codes group."""
- group = QGroupBox("Variable Codes")
- layout = QVBoxLayout()
+ # Event Codes (compact grid layout)
+ right_column.addWidget(create_section_label("🎮 Event Codes"))
- # CODE122
- self.code_122_cb = QCheckBox("CODE 122 - Control Variables")
- self.code_122_cb.setToolTip(
- "Translate text stored in game variables."
- )
- layout.addWidget(self.code_122_cb)
+ # Create a grid for better space usage
+ event_grid = QGridLayout()
+ event_grid.setSpacing(2)
+ event_grid.setHorizontalSpacing(15)
- group.setLayout(layout)
- return group
-
- def create_other_codes_group(self):
- """Create other codes group."""
- group = QGroupBox("Other Event Codes")
- layout = QVBoxLayout()
-
- codes_info = [
- ("355655", "Scripts", "Translate text within script commands"),
- ("357", "Picture Text", "Translate text displayed on pictures"),
- ("657", "Picture Text Extended", "Extended picture text translation"),
- ("356", "Plugin Commands", "Translate plugin command parameters"),
- ("320", "Change Name Input", "Translate name input prompts"),
- ("324", "Change Nickname", "Translate nickname changes"),
- ("111", "Conditional Branch", "Translate conditional text"),
- ("108", "Comments", "Translate comment blocks")
+ # Event codes in a more compact format
+ event_codes = [
+ ("CODE103", "Input Number"), ("CODE104", "Select Item"),
+ ("CODE111", "Conditional Branch"), ("CODE117", "Common Event"),
+ ("CODE119", "Set Movement"), ("CODE121", "Control Switches"),
+ ("CODE125", "Change Gold"), ("CODE126", "Change Items"),
+ ("CODE127", "Change Weapons"), ("CODE128", "Change Armors"),
+ ("CODE129", "Change Party"), ("CODE201", "Transfer Player"),
+ ("CODE202", "Set Vehicle Loc"), ("CODE203", "Set Event Loc"),
+ ("CODE211", "Change Transparency"), ("CODE212", "Show Animation"),
+ ("CODE213", "Show Balloon"), ("CODE214", "Erase Event"),
+ ("CODE221", "Fadeout Screen"), ("CODE222", "Fadein Screen"),
+ ("CODE231", "Show Picture"), ("CODE232", "Move Picture"),
+ ("CODE241", "Play BGM"), ("CODE242", "Fadeout BGM"),
]
- self.other_code_checkboxes = {}
+ self.event_checkboxes = {}
+ for idx, (code, label) in enumerate(event_codes):
+ cb = QCheckBox(f"{code} - {label}")
+ cb.setStyleSheet("QCheckBox { font-size: 10px; }")
+ event_grid.addWidget(cb, idx // 2, idx % 2)
+ self.event_checkboxes[code] = cb
- for code, name, tooltip in codes_info:
- cb = QCheckBox(f"CODE {code} - {name}")
- cb.setToolTip(tooltip)
- layout.addWidget(cb)
- self.other_code_checkboxes[code] = cb
+ right_column.addLayout(event_grid)
+ right_column.addStretch()
- group.setLayout(layout)
- return group
+ # Add both columns
+ columns_layout.addLayout(left_column, 1)
+ columns_layout.addLayout(right_column, 1)
+ main_layout.addLayout(columns_layout)
+
+ # Bottom buttons
+ button_layout = QHBoxLayout()
+ button_layout.setSpacing(10)
+
+ self.reset_button = QPushButton("🔄 Reset to Defaults")
+ self.reset_button.clicked.connect(self.reset_to_defaults_with_message)
+ self.reset_button.setMaximumWidth(200)
+
+ self.apply_button = QPushButton("✓ Apply Settings")
+ self.apply_button.clicked.connect(self.apply_to_module)
+ self.apply_button.setMaximumWidth(200)
+
+ button_layout.addWidget(self.reset_button)
+ button_layout.addWidget(self.apply_button)
+ button_layout.addStretch()
+
+ main_layout.addLayout(button_layout)
+ self.setLayout(main_layout)
def reset_to_defaults(self):
"""Reset all settings to default values."""
@@ -388,31 +319,27 @@ class RPGMakerTab(QWidget):
# Apply default values from the DEFAULT_CONFIG constant
self.first_line_speakers_cb.setChecked(self.DEFAULT_CONFIG["FIRSTLINESPEAKERS"])
- self.facename_101_cb.setChecked(self.DEFAULT_CONFIG["FACENAME101"])
+ self.facename101_cb.setChecked(self.DEFAULT_CONFIG["FACENAME101"])
self.names_cb.setChecked(self.DEFAULT_CONFIG["NAMES"])
- self.br_flag_cb.setChecked(self.DEFAULT_CONFIG["BRFLAG"])
- self.fix_textwrap_cb.setChecked(self.DEFAULT_CONFIG["FIXTEXTWRAP"])
- self.ignore_tl_text_cb.setChecked(self.DEFAULT_CONFIG["IGNORETLTEXT"])
+ self.brflag_cb.setChecked(self.DEFAULT_CONFIG["BRFLAG"])
+ self.fixtextwrap_cb.setChecked(self.DEFAULT_CONFIG["FIXTEXTWRAP"])
+ self.ignoretltext_cb.setChecked(self.DEFAULT_CONFIG["IGNORETLTEXT"])
# Main dialogue codes
- self.code_401_cb.setChecked(self.DEFAULT_CONFIG["CODE401"])
- self.code_405_cb.setChecked(self.DEFAULT_CONFIG["CODE405"])
- self.code_102_cb.setChecked(self.DEFAULT_CONFIG["CODE102"])
+ self.code401_cb.setChecked(self.DEFAULT_CONFIG["CODE401"])
+ self.code405_cb.setChecked(self.DEFAULT_CONFIG["CODE405"])
+ self.code102_cb.setChecked(self.DEFAULT_CONFIG["CODE102"])
# Optional codes
- self.code_101_cb.setChecked(self.DEFAULT_CONFIG["CODE101"])
- self.code_408_cb.setChecked(self.DEFAULT_CONFIG["CODE408"])
+ self.code101_cb.setChecked(self.DEFAULT_CONFIG["CODE101"])
+ self.code408_cb.setChecked(self.DEFAULT_CONFIG["CODE408"])
# Variable codes
- self.code_122_cb.setChecked(self.DEFAULT_CONFIG["CODE122"])
+ self.code122_cb.setChecked(self.DEFAULT_CONFIG["CODE122"])
- # Other codes - apply defaults from the constant
- for code, cb in self.other_code_checkboxes.items():
- default_key = f"CODE{code}"
- if default_key in self.DEFAULT_CONFIG:
- cb.setChecked(self.DEFAULT_CONFIG[default_key])
- else:
- cb.setChecked(False) # Fallback to False if not in defaults
+ # Event codes
+ for code, cb in self.event_checkboxes.items():
+ cb.setChecked(self.DEFAULT_CONFIG.get(code, False))
# Reconnect signals and apply changes once
self.connect_auto_apply()
@@ -432,26 +359,26 @@ class RPGMakerTab(QWidget):
try:
# General settings checkboxes
self.first_line_speakers_cb.stateChanged.disconnect()
- self.facename_101_cb.stateChanged.disconnect()
+ self.facename101_cb.stateChanged.disconnect()
self.names_cb.stateChanged.disconnect()
- self.br_flag_cb.stateChanged.disconnect()
- self.fix_textwrap_cb.stateChanged.disconnect()
- self.ignore_tl_text_cb.stateChanged.disconnect()
+ self.brflag_cb.stateChanged.disconnect()
+ self.fixtextwrap_cb.stateChanged.disconnect()
+ self.ignoretltext_cb.stateChanged.disconnect()
# Main dialogue codes
- self.code_401_cb.stateChanged.disconnect()
- self.code_405_cb.stateChanged.disconnect()
- self.code_102_cb.stateChanged.disconnect()
+ self.code401_cb.stateChanged.disconnect()
+ self.code405_cb.stateChanged.disconnect()
+ self.code102_cb.stateChanged.disconnect()
# Optional codes
- self.code_101_cb.stateChanged.disconnect()
- self.code_408_cb.stateChanged.disconnect()
+ self.code101_cb.stateChanged.disconnect()
+ self.code408_cb.stateChanged.disconnect()
# Variable codes
- self.code_122_cb.stateChanged.disconnect()
+ self.code122_cb.stateChanged.disconnect()
- # Other codes
- for cb in self.other_code_checkboxes.values():
+ # Event codes
+ for cb in self.event_checkboxes.values():
cb.stateChanged.disconnect()
except TypeError:
# Ignore if signals are not connected
@@ -461,26 +388,26 @@ class RPGMakerTab(QWidget):
"""Connect all checkboxes to auto-apply changes when modified."""
# General settings checkboxes
self.first_line_speakers_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
- self.facename_101_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
+ self.facename101_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
self.names_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
- self.br_flag_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
- self.fix_textwrap_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
- self.ignore_tl_text_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
+ self.brflag_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
+ self.fixtextwrap_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
+ self.ignoretltext_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
# Main dialogue codes
- self.code_401_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
- self.code_405_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
- self.code_102_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
+ self.code401_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
+ self.code405_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
+ self.code102_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
# Optional codes
- self.code_101_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
- self.code_408_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
+ self.code101_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
+ self.code408_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
# Variable codes
- self.code_122_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
+ self.code122_cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
- # Other codes
- for cb in self.other_code_checkboxes.values():
+ # Event codes
+ for cb in self.event_checkboxes.values():
cb.stateChanged.connect(lambda: self.apply_to_module(show_messages=False))
def get_config(self):
@@ -488,28 +415,28 @@ class RPGMakerTab(QWidget):
config = {
# General settings
"FIRSTLINESPEAKERS": self.first_line_speakers_cb.isChecked(),
- "FACENAME101": self.facename_101_cb.isChecked(),
+ "FACENAME101": self.facename101_cb.isChecked(),
"NAMES": self.names_cb.isChecked(),
- "BRFLAG": self.br_flag_cb.isChecked(),
- "FIXTEXTWRAP": self.fix_textwrap_cb.isChecked(),
- "IGNORETLTEXT": self.ignore_tl_text_cb.isChecked(),
+ "BRFLAG": self.brflag_cb.isChecked(),
+ "FIXTEXTWRAP": self.fixtextwrap_cb.isChecked(),
+ "IGNORETLTEXT": self.ignoretltext_cb.isChecked(),
# Main dialogue codes
- "CODE401": self.code_401_cb.isChecked(),
- "CODE405": self.code_405_cb.isChecked(),
- "CODE102": self.code_102_cb.isChecked(),
+ "CODE401": self.code401_cb.isChecked(),
+ "CODE405": self.code405_cb.isChecked(),
+ "CODE102": self.code102_cb.isChecked(),
# Optional codes
- "CODE101": self.code_101_cb.isChecked(),
- "CODE408": self.code_408_cb.isChecked(),
+ "CODE101": self.code101_cb.isChecked(),
+ "CODE408": self.code408_cb.isChecked(),
# Variable codes
- "CODE122": self.code_122_cb.isChecked(),
+ "CODE122": self.code122_cb.isChecked(),
}
- # Other codes
- for code, cb in self.other_code_checkboxes.items():
- config[f"CODE{code}"] = cb.isChecked()
+ # Event codes
+ for code, cb in self.event_checkboxes.items():
+ config[code] = cb.isChecked()
return config
@@ -517,27 +444,27 @@ class RPGMakerTab(QWidget):
"""Set configuration from dictionary."""
# General settings
self.first_line_speakers_cb.setChecked(config.get("FIRSTLINESPEAKERS", False))
- self.facename_101_cb.setChecked(config.get("FACENAME101", False))
+ self.facename101_cb.setChecked(config.get("FACENAME101", False))
self.names_cb.setChecked(config.get("NAMES", False))
- self.br_flag_cb.setChecked(config.get("BRFLAG", False))
- self.fix_textwrap_cb.setChecked(config.get("FIXTEXTWRAP", True))
- self.ignore_tl_text_cb.setChecked(config.get("IGNORETLTEXT", False))
+ self.brflag_cb.setChecked(config.get("BRFLAG", False))
+ self.fixtextwrap_cb.setChecked(config.get("FIXTEXTWRAP", True))
+ self.ignoretltext_cb.setChecked(config.get("IGNORETLTEXT", False))
# Main dialogue codes
- self.code_401_cb.setChecked(config.get("CODE401", True))
- self.code_405_cb.setChecked(config.get("CODE405", True))
- self.code_102_cb.setChecked(config.get("CODE102", True))
+ self.code401_cb.setChecked(config.get("CODE401", True))
+ self.code405_cb.setChecked(config.get("CODE405", True))
+ self.code102_cb.setChecked(config.get("CODE102", True))
# Optional codes
- self.code_101_cb.setChecked(config.get("CODE101", False))
- self.code_408_cb.setChecked(config.get("CODE408", False))
+ self.code101_cb.setChecked(config.get("CODE101", False))
+ self.code408_cb.setChecked(config.get("CODE408", False))
# Variable codes
- self.code_122_cb.setChecked(config.get("CODE122", False))
+ self.code122_cb.setChecked(config.get("CODE122", False))
- # Other codes
- for code, cb in self.other_code_checkboxes.items():
- cb.setChecked(config.get(f"CODE{code}", False))
+ # Event codes
+ for code, cb in self.event_checkboxes.items():
+ cb.setChecked(config.get(code, False))
def load_from_file(self, file_path):
"""Load configuration from file."""
@@ -555,20 +482,20 @@ class RPGMakerTab(QWidget):
# Check if any main dialogue codes are enabled
main_codes_enabled = (
- self.code_401_cb.isChecked() or
- self.code_405_cb.isChecked() or
- self.code_102_cb.isChecked()
+ self.code401_cb.isChecked() or
+ self.code405_cb.isChecked() or
+ self.code102_cb.isChecked()
)
if not main_codes_enabled:
warnings.append("No main dialogue codes are enabled. You may not get any translated content.")
# Check for high-cost options
- if self.code_408_cb.isChecked():
+ if self.code408_cb.isChecked():
warnings.append("CODE 408 (Comments) is enabled. This can significantly increase translation costs!")
# Check for conflicting options
- if self.br_flag_cb.isChecked() and self.fix_textwrap_cb.isChecked():
+ if self.brflag_cb.isChecked() and self.fixtextwrap_cb.isChecked():
warnings.append("Both BR tags and text wrapping are enabled. This might cause formatting issues.")
return len(errors) == 0, warnings, errors
diff --git a/gui/wolf_tab.py b/gui/wolf_tab.py
index f63f7b9..7950102 100644
--- a/gui/wolf_tab.py
+++ b/gui/wolf_tab.py
@@ -5,11 +5,17 @@ what gets translated. This can be expanded later.
"""
from pathlib import Path
from PyQt5.QtWidgets import (
- QWidget, QVBoxLayout, QGroupBox, QCheckBox, QPushButton, QMessageBox, QLabel, QHBoxLayout, QScrollArea
+ QWidget, QVBoxLayout, QCheckBox, QPushButton, QMessageBox, QLabel, QHBoxLayout, QGridLayout
)
from PyQt5.QtCore import pyqtSignal
import re
+def create_section_label(text):
+ """Create a styled section header label."""
+ label = QLabel(text)
+ label.setStyleSheet("font-size: 12px; font-weight: bold; color: #007acc; padding: 2px 0px;")
+ return label
+
class WolfTab(QWidget):
config_changed = pyqtSignal()
@@ -45,67 +51,183 @@ class WolfTab(QWidget):
self.reset_to_defaults()
def init_ui(self):
+ """Initialize the user interface with compact two-column layout."""
main_layout = QVBoxLayout()
- scroll = QScrollArea()
- content = QWidget()
- v = QVBoxLayout()
+ main_layout.setContentsMargins(10, 10, 10, 10)
+ main_layout.setSpacing(10)
+
+ # Title and description
+ title = QLabel("Wolf RPG Editor Translation Settings")
+ title.setStyleSheet("font-size: 14px; font-weight: bold; color: #007acc;")
+ main_layout.addWidget(title)
- title = QLabel("Wolf RPG Settings")
- title.setStyleSheet("font-size:16px;font-weight:bold;color:#007acc")
- v.addWidget(title)
- desc = QLabel("Toggle which parts of Wolf RPG data are translated. This is a minimal first pass; more options can be added later.")
- desc.setWordWrap(True)
- desc.setStyleSheet("color:#cccccc")
- v.addWidget(desc)
-
- # Groups
- self.checkboxes = {}
- self.add_group(v, "Dialogue / Choices", ["CODE101", "CODE102"])
- self.add_group(v, "Pictures / Variables", ["CODE150", "CODE122"])
- self.add_group(v, "Other Event Codes", ["CODE210", "CODE300", "CODE250"])
- self.add_group(v, "Database Sections", [
- "SCENARIOFLAG", "OPTIONSFLAG", "NPCFLAG", "DBNAMEFLAG", "DBVALUEFLAG",
- "ITEMFLAG", "STATEFLAG", "ENEMYFLAG", "ARMORFLAG", "WEAPONFLAG", "SKILLFLAG"
- ])
-
- # Buttons
- btn_row = QHBoxLayout()
- self.reset_btn = QPushButton("Reset")
- self.reset_btn.clicked.connect(self.reset_to_defaults)
- self.apply_btn = QPushButton("Apply Now")
- self.apply_btn.clicked.connect(self.apply_to_module)
- btn_row.addWidget(self.reset_btn)
- btn_row.addWidget(self.apply_btn)
- btn_row.addStretch()
- v.addLayout(btn_row)
-
- content.setLayout(v)
- scroll.setWidget(content)
- scroll.setWidgetResizable(True)
- main_layout.addWidget(scroll)
+ description = QLabel(
+ "Enable translation options for Wolf RPG Editor projects. Only enable what you need."
+ )
+ description.setWordWrap(True)
+ description.setStyleSheet("color: #888888; font-size: 11px; margin-bottom: 5px;")
+ main_layout.addWidget(description)
+
+ # Two-column layout for checkboxes
+ columns_layout = QHBoxLayout()
+ columns_layout.setSpacing(30)
+
+ # LEFT COLUMN
+ left_column = QVBoxLayout()
+ left_column.setSpacing(3)
+
+ # Dialogue & Choices
+ left_column.addWidget(create_section_label("💬 Dialogue & Choices"))
+ self.code101_cb = QCheckBox("CODE101 - Show Text")
+ self.code101_cb.setToolTip("Enable translation of dialogue text")
+ left_column.addWidget(self.code101_cb)
+
+ self.code102_cb = QCheckBox("CODE102 - Show Choices")
+ self.code102_cb.setToolTip("Enable translation of choice options")
+ left_column.addWidget(self.code102_cb)
+
+ left_column.addSpacing(8)
+
+ # Pictures & Variables
+ left_column.addWidget(create_section_label("🖼️ Pictures & Variables"))
+ self.code150_cb = QCheckBox("CODE150 - Show Picture")
+ self.code150_cb.setToolTip("Enable translation of picture-related text")
+ left_column.addWidget(self.code150_cb)
+
+ self.code122_cb = QCheckBox("CODE122 - String Operations")
+ self.code122_cb.setToolTip("Enable translation of string variables")
+ left_column.addWidget(self.code122_cb)
+
+ left_column.addSpacing(8)
+
+ # Other Event Codes
+ left_column.addWidget(create_section_label("🎮 Other Event Codes"))
+ self.code210_cb = QCheckBox("CODE210 - Conditional Branch")
+ left_column.addWidget(self.code210_cb)
+
+ self.code300_cb = QCheckBox("CODE300 - Set Variable")
+ left_column.addWidget(self.code300_cb)
+
+ self.code250_cb = QCheckBox("CODE250 - Sound Effect")
+ left_column.addWidget(self.code250_cb)
+
+ left_column.addStretch()
+
+ # RIGHT COLUMN
+ right_column = QVBoxLayout()
+ right_column.setSpacing(3)
+
+ # Database Sections
+ right_column.addWidget(create_section_label("📚 Database Sections"))
+
+ # Database flags in compact 2-column grid
+ db_grid = QGridLayout()
+ db_grid.setSpacing(2)
+ db_grid.setHorizontalSpacing(10)
+
+ database_flags = [
+ ("SCENARIOFLAG", "Scenario Text"),
+ ("OPTIONSFLAG", "Options"),
+ ("NPCFLAG", "NPC Data"),
+ ("DBNAMEFLAG", "Database Names"),
+ ("DBVALUEFLAG", "Database Values"),
+ ("ITEMFLAG", "Items"),
+ ("STATEFLAG", "States"),
+ ("ENEMYFLAG", "Enemies"),
+ ("ARMORFLAG", "Armor"),
+ ("WEAPONFLAG", "Weapons"),
+ ("SKILLFLAG", "Skills"),
+ ]
+
+ self.db_checkboxes = {}
+ for idx, (key, label) in enumerate(database_flags):
+ cb = QCheckBox(label)
+ cb.setStyleSheet("QCheckBox { font-size: 10px; }")
+ db_grid.addWidget(cb, idx // 2, idx % 2)
+ self.db_checkboxes[key] = cb
+
+ right_column.addLayout(db_grid)
+ right_column.addStretch()
+
+ # Add both columns
+ columns_layout.addLayout(left_column, 1)
+ columns_layout.addLayout(right_column, 1)
+ main_layout.addLayout(columns_layout)
+
+ # Bottom buttons
+ button_layout = QHBoxLayout()
+ button_layout.setSpacing(10)
+
+ self.reset_btn = QPushButton("🔄 Reset to Defaults")
+ self.reset_btn.clicked.connect(self.reset_to_defaults_with_message)
+ self.reset_btn.setMaximumWidth(200)
+
+ self.apply_btn = QPushButton("✓ Apply Settings")
+ self.apply_btn.clicked.connect(lambda: self.apply_to_module(True))
+ self.apply_btn.setMaximumWidth(200)
+
+ button_layout.addWidget(self.reset_btn)
+ button_layout.addWidget(self.apply_btn)
+ button_layout.addStretch()
+
+ main_layout.addLayout(button_layout)
self.setLayout(main_layout)
+
+ # Connect auto-apply
+ self.code101_cb.stateChanged.connect(lambda: self.apply_to_module(False))
+ self.code102_cb.stateChanged.connect(lambda: self.apply_to_module(False))
+ self.code150_cb.stateChanged.connect(lambda: self.apply_to_module(False))
+ self.code122_cb.stateChanged.connect(lambda: self.apply_to_module(False))
+ self.code210_cb.stateChanged.connect(lambda: self.apply_to_module(False))
+ self.code300_cb.stateChanged.connect(lambda: self.apply_to_module(False))
+ self.code250_cb.stateChanged.connect(lambda: self.apply_to_module(False))
+
+ for cb in self.db_checkboxes.values():
+ cb.stateChanged.connect(lambda: self.apply_to_module(False))
- def add_group(self, parent_layout, title, keys):
- box = QGroupBox(title)
- v = QVBoxLayout()
- for k in keys:
- cb = QCheckBox(k)
- cb.stateChanged.connect(lambda _=None: self.apply_to_module(False))
- v.addWidget(cb)
- self.checkboxes[k] = cb
- box.setLayout(v)
- parent_layout.addWidget(box)
def get_config(self):
- return {k: cb.isChecked() for k, cb in self.checkboxes.items()}
+ """Get current configuration as dictionary."""
+ config = {
+ "CODE101": self.code101_cb.isChecked(),
+ "CODE102": self.code102_cb.isChecked(),
+ "CODE150": self.code150_cb.isChecked(),
+ "CODE122": self.code122_cb.isChecked(),
+ "CODE210": self.code210_cb.isChecked(),
+ "CODE300": self.code300_cb.isChecked(),
+ "CODE250": self.code250_cb.isChecked(),
+ }
+ # Add database checkboxes
+ for key, cb in self.db_checkboxes.items():
+ config[key] = cb.isChecked()
+ return config
def reset_to_defaults(self):
- for k, val in self.DEFAULT_CONFIG.items():
- if k in self.checkboxes:
- self.checkboxes[k].setChecked(val)
- self.apply_to_module()
+ """Reset all settings to default values without showing message."""
+ self.code101_cb.setChecked(self.DEFAULT_CONFIG["CODE101"])
+ self.code102_cb.setChecked(self.DEFAULT_CONFIG["CODE102"])
+ self.code150_cb.setChecked(self.DEFAULT_CONFIG["CODE150"])
+ self.code122_cb.setChecked(self.DEFAULT_CONFIG["CODE122"])
+ self.code210_cb.setChecked(self.DEFAULT_CONFIG["CODE210"])
+ self.code300_cb.setChecked(self.DEFAULT_CONFIG["CODE300"])
+ self.code250_cb.setChecked(self.DEFAULT_CONFIG["CODE250"])
+
+ for key, cb in self.db_checkboxes.items():
+ cb.setChecked(self.DEFAULT_CONFIG.get(key, False))
+
+ self.apply_to_module(False)
+
+ def reset_to_defaults_with_message(self):
+ """Reset to defaults and show confirmation message."""
+ self.reset_to_defaults()
+ QMessageBox.information(
+ self,
+ "Reset Complete",
+ "All settings have been reset to their default values."
+ )
def apply_to_module(self, show_message=False):
+ """Apply current configuration to wolf.py module."""
module_path = Path(__file__).parent.parent / 'modules' / 'wolf.py'
if not module_path.exists():
if show_message:
@@ -123,4 +245,3 @@ class WolfTab(QWidget):
except Exception as e:
if show_message:
QMessageBox.critical(self, 'Error', f'Failed to apply settings: {e}')
-