diff --git a/gui/config_tab.py b/gui/config_tab.py index 196614b..8d89004 100644 --- a/gui/config_tab.py +++ b/gui/config_tab.py @@ -17,6 +17,7 @@ from dotenv import load_dotenv, set_key from gui.rpgmaker_tab import RPGMakerTab from gui.wolf_tab import WolfTab from gui.csv_tab import CSVTab +from gui.srpg_tab import SRPGTab def create_section_header(title): @@ -113,6 +114,12 @@ class ConfigTab(QWidget): btn_csv.clicked.connect(lambda: self.switch_page(4)) nav_layout.addWidget(btn_csv) self.nav_buttons.append(btn_csv) + + # SRPG Studio button + btn_srpg = self.create_nav_button("⚔️", "SRPG Studio") + btn_srpg.clicked.connect(lambda: self.switch_page(5)) + nav_layout.addWidget(btn_srpg) + self.nav_buttons.append(btn_srpg) nav_layout.addStretch() nav_bar.setLayout(nav_layout) @@ -139,6 +146,10 @@ class ConfigTab(QWidget): # Page 5: CSV Settings self.csv_tab = CSVTab() self.content_stack.addWidget(self.csv_tab) + + # Page 6: SRPG Studio Engine + self.srpg_tab = SRPGTab() + self.content_stack.addWidget(self.srpg_tab) # Add navigation bar and content to main layout main_layout.addWidget(nav_bar) diff --git a/gui/srpg_tab.py b/gui/srpg_tab.py new file mode 100644 index 0000000..36061a2 --- /dev/null +++ b/gui/srpg_tab.py @@ -0,0 +1,155 @@ +"""SRPG Studio configuration tab. + +Provides toggles for configurable flags in srpg.py so users can +enable/disable text-wrap fixing and skip-already-translated behaviour. +""" +from pathlib import Path +from PyQt5.QtWidgets import ( + QWidget, QVBoxLayout, QCheckBox, QPushButton, QMessageBox, QLabel, QHBoxLayout +) +from PyQt5.QtCore import pyqtSignal +import re + +try: + import set_defaults + CANONICAL_DEFAULTS = getattr(set_defaults, 'DEFAULTS', None) +except Exception: + CANONICAL_DEFAULTS = None + + +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 SRPGTab(QWidget): + config_changed = pyqtSignal() + + DEFAULT_CONFIG = { + "FIXTEXTWRAP": True, + "IGNORETLTEXT": False, + } + + def __init__(self): + super().__init__() + self.init_ui() + + defaults = CANONICAL_DEFAULTS if CANONICAL_DEFAULTS is not None else self.DEFAULT_CONFIG + self.set_config(defaults) + self.connect_auto_apply() + + def init_ui(self): + """Initialize the user interface.""" + main_layout = QVBoxLayout() + main_layout.setContentsMargins(15, 15, 15, 15) + main_layout.setSpacing(10) + + # Title + title = QLabel("SRPG Studio Translation Settings") + title.setStyleSheet("font-size: 15px; font-weight: bold; color: #007acc;") + main_layout.addWidget(title) + + description = QLabel( + "Configure translation options for SRPG Studio projects. " + "Changes are applied directly to modules/srpg.py." + ) + description.setWordWrap(True) + description.setStyleSheet("color: #888888; font-size: 10px; margin-bottom: 8px;") + main_layout.addWidget(description) + + # --- Text Formatting --- + main_layout.addWidget(create_section_label("📝 Text Formatting")) + + self.fixtextwrap_cb = QCheckBox("Fix Text Wrap") + self.fixtextwrap_cb.setToolTip( + "Re-wrap translated text to fit the configured dialogue width (WIDTH setting)" + ) + main_layout.addWidget(self.fixtextwrap_cb) + + # --- Translation Behaviour --- + main_layout.addWidget(create_section_label("🔄 Translation Behaviour")) + + self.ignoretltext_cb = QCheckBox("Ignore Already-Translated Text") + self.ignoretltext_cb.setToolTip( + "Skip lines that appear to have already been translated" + ) + main_layout.addWidget(self.ignoretltext_cb) + + main_layout.addStretch() + + # 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(180) + self.reset_btn.setMinimumHeight(32) + + button_layout.addWidget(self.reset_btn) + button_layout.addStretch() + + main_layout.addLayout(button_layout) + self.setLayout(main_layout) + + # ------------------------------------------------------------------ + # Public API + # ------------------------------------------------------------------ + + def get_config(self) -> dict: + """Return current configuration as a dictionary.""" + return { + "FIXTEXTWRAP": self.fixtextwrap_cb.isChecked(), + "IGNORETLTEXT": self.ignoretltext_cb.isChecked(), + } + + def set_config(self, config: dict): + """Set configuration from dictionary (does not write to module).""" + self.fixtextwrap_cb.setChecked(config.get("FIXTEXTWRAP", True)) + self.ignoretltext_cb.setChecked(config.get("IGNORETLTEXT", False)) + + def connect_auto_apply(self): + """Connect widget changes to auto-apply to srpg.py.""" + self.fixtextwrap_cb.stateChanged.connect(lambda: self.apply_to_module(False)) + self.ignoretltext_cb.stateChanged.connect(lambda: self.apply_to_module(False)) + + def reset_to_defaults(self): + """Reset all settings to defaults without showing a message.""" + defaults = ( + CANONICAL_DEFAULTS + if 'CANONICAL_DEFAULTS' in globals() and CANONICAL_DEFAULTS is not None + else self.DEFAULT_CONFIG + ) + self.set_config(defaults) + self.apply_to_module(False) + + def reset_to_defaults_with_message(self): + """Reset to defaults and show a 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: bool = False): + """Write current configuration back to modules/srpg.py.""" + module_path = Path(__file__).parent.parent / 'modules' / 'srpg.py' + if not module_path.exists(): + if show_message: + QMessageBox.critical(self, 'Error', 'srpg.py not found in modules directory.') + return + try: + content = module_path.read_text(encoding='utf-8') + for key, value in self.get_config().items(): + pattern = rf'^{key}\s*=\s*.*$' + content = re.sub(pattern, f'{key} = {value}', content, flags=re.MULTILINE) + module_path.write_text(content, encoding='utf-8') + self.config_changed.emit() + if show_message: + QMessageBox.information(self, 'Applied', 'SRPG Studio configuration applied to srpg.py.') + except Exception as e: + if show_message: + QMessageBox.critical(self, 'Error', f'Failed to apply settings: {e}') diff --git a/gui/translation_tab.py b/gui/translation_tab.py index c6b5b22..61d137d 100644 --- a/gui/translation_tab.py +++ b/gui/translation_tab.py @@ -1078,6 +1078,7 @@ class TranslationTab(QWidget): from modules.images import handleImages from modules.rpgmakerplugin import handlePlugin from modules.aquedi4 import handleAquedi4 + from modules.srpg import handleSRPG self.modules = [ ["RPG Maker MV/MZ", [".json"], handleMVMZ], @@ -1097,6 +1098,7 @@ class TranslationTab(QWidget): ["Images", [".png", ".jpg", ".jpeg"], handleImages], ["RPG Maker Plugin", [".js"], handlePlugin], ["Aquedi4 Prepared JSON", [".json"], handleAquedi4], + ["SRPG Studio", [".json"], handleSRPG], ] for module in self.modules: @@ -1121,6 +1123,8 @@ class TranslationTab(QWidget): self.engine_changed.emit("wolf") elif "mv/mz" in lowered: self.engine_changed.emit("mvmz") + elif "srpg" in lowered: + self.engine_changed.emit("srpg") # Update mode dropdown based on engine current_mode = self.mode_combo.currentText() diff --git a/modules/rpgmakermvmz.py b/modules/rpgmakermvmz.py index e8e910f..1ff4cee 100644 --- a/modules/rpgmakermvmz.py +++ b/modules/rpgmakermvmz.py @@ -124,7 +124,7 @@ FIXTEXTWRAP = True # IGNORETLTEXT: Skip Translated Text. IGNORETLTEXT = False # TLSYSTEMVARIABLES: Translate System Variables. (Optional but sometimes necessary. Can break stuff.) -TLSYSTEMVARIABLES = True +TLSYSTEMVARIABLES = False # TLSYSTEMSWITCHES: Translate System Switches. (Optional. Translates switch names in System.json.) TLSYSTEMSWITCHES = False # Join 408 codes into a single string like 401.