more improvements
This commit is contained in:
parent
f2c6a8ebf1
commit
38a0e8f03a
3 changed files with 393 additions and 335 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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("""
|
||||
<b>Performance Notes:</b><br>
|
||||
• Enable only the codes you need to reduce translation time and costs<br>
|
||||
• CODE408 can significantly increase costs as it translates comments<br>
|
||||
• Main dialogue codes (401, 405, 102) are typically required for story content<br>
|
||||
• 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 <br> Tags")
|
||||
self.br_flag_cb.setToolTip(
|
||||
"Use <br> 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
|
||||
|
|
|
|||
227
gui/wolf_tab.py
227
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}')
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue