diff --git a/a1_swap_mod_packer/gui.py b/a1_swap_mod_packer/gui.py index c1cdea5..c8f50a6 100644 --- a/a1_swap_mod_packer/gui.py +++ b/a1_swap_mod_packer/gui.py @@ -34,6 +34,7 @@ try: QAbstractItemView, QCheckBox, QComboBox, + QDialog, QFileDialog, QFormLayout, QGridLayout, @@ -512,10 +513,13 @@ class MainWindow(QMainWindow): self.swap_gcode_combo.setMinimumWidth(240) self.swap_gcode_combo.setMaximumWidth(440) self.refresh_button = QPushButton(t("gui.options.refresh")) + self.view_gcode_button = QPushButton(t("gui.options.view_gcode")) self.open_folder_button = QPushButton(t("gui.options.open_folder")) self.refresh_button.setFixedWidth(self.refresh_button.sizeHint().width()) + self.view_gcode_button.setFixedWidth(self.view_gcode_button.sizeHint().width()) self.open_folder_button.setFixedWidth(self.open_folder_button.sizeHint().width()) self.refresh_button.clicked.connect(self.load_swap_gcode_to_combo) + self.view_gcode_button.clicked.connect(self.view_swap_gcode) self.open_folder_button.clicked.connect(self.open_swap_gcode_folder) # 默认份数 @@ -619,6 +623,7 @@ class MainWindow(QMainWindow): grid.addWidget(self.swap_gcode_combo, 0, 1, 1, 2) swap_btn_row = QHBoxLayout() swap_btn_row.addWidget(self.refresh_button) + swap_btn_row.addWidget(self.view_gcode_button) swap_btn_row.addWidget(self.open_folder_button) swap_btn_row.addStretch(1) grid.addLayout(swap_btn_row, 0, 3) @@ -889,6 +894,35 @@ class MainWindow(QMainWindow): folder.mkdir(parents=True, exist_ok=True) self.open_path(folder) + def view_swap_gcode(self) -> None: + """在弹出的只读窗口中展示当前选中的换盘 G-code 内容。""" + gcode_path = self.swap_gcode_combo.currentData() + if not gcode_path: + return + try: + text = Path(gcode_path).read_text(encoding="utf-8-sig", errors="replace") + except OSError as exc: + QMessageBox.warning(self, t("gui.dialog.warning.title"), str(exc)) + return + + dialog = QDialog(self) + dialog.setWindowTitle(t("gui.dialog.view_gcode.title") + " - " + Path(gcode_path).name) + dialog.resize(700, 480) + layout = QVBoxLayout(dialog) + editor = QTextEdit() + editor.setReadOnly(True) + font = QFont("Consolas", 10) + editor.setFont(font) + editor.setText(text) + layout.addWidget(editor) + close_btn = QPushButton(t("gui.button.close")) + close_btn.clicked.connect(dialog.close) + btn_row = QHBoxLayout() + btn_row.addStretch(1) + btn_row.addWidget(close_btn) + layout.addLayout(btn_row) + dialog.exec() + def open_patch_config(self) -> None: """打开 G-code 补丁配置文件。""" path = default_patch_config_path() @@ -1490,9 +1524,11 @@ class MainWindow(QMainWindow): self.options_group.setTitle(t("gui.options.group.title")) self.refresh_button.setText(t("gui.options.refresh")) self.open_folder_button.setText(t("gui.options.open_folder")) + self.view_gcode_button.setText(t("gui.options.view_gcode")) # 重新计算按钮宽度以适应翻译后的文本长度 self.refresh_button.setFixedWidth(self.refresh_button.sizeHint().width()) self.open_folder_button.setFixedWidth(self.open_folder_button.sizeHint().width()) + self.view_gcode_button.setFixedWidth(self.view_gcode_button.sizeHint().width()) self.bed_cooldown_check.setText(t("gui.options.bed_cooldown")) self.eject_wait_check.setText(t("gui.options.eject_wait")) self.show_plate_number_check.setText(t("gui.options.plate_number")) diff --git a/a1_swap_mod_packer/i18n/en.json b/a1_swap_mod_packer/i18n/en.json index dee5998..889b4fb 100644 --- a/a1_swap_mod_packer/i18n/en.json +++ b/a1_swap_mod_packer/i18n/en.json @@ -1,6 +1,5 @@ { "_lang": "English", - "gui.file_group.title": "Input 3MF Files", "gui.file_group.table.header.order": "Order", "gui.file_group.table.header.file": "3MF File", @@ -15,18 +14,15 @@ "gui.file_group.table.tooltip_base_filament": "Base filament: {filament}", "gui.file_group.total_summary": "Total: {plates} plate(s) | Time: {time} | Filament: {filament}", "gui.file_group.total_summary.empty": "Total: 0 plates | Time: 0s | Filament: 0.00 g", - "gui.button.add_3mf": "Add 3MF", "gui.button.remove": "Remove", "gui.button.remove_all": "Remove All", "gui.button.apply_copies": "Apply Default Copies to Selected", "gui.button.build": "Build 3MF", - "gui.preview.title": "Selected Thumbnail", "gui.preview.select_hint": "Select an input file", "gui.preview.no_image": "No preview image", "gui.preview.unavailable": "Preview unavailable", - "gui.options.group.title": "Packing Options", "gui.options.swap_gcode.label": "Swap G-code", "gui.options.refresh": "Refresh", @@ -60,7 +56,6 @@ "gui.options.skip_duplicates": "Skip duplicate file paths when adding inputs", "gui.options.input_handling": "Input handling", "gui.options.language": "Language", - "gui.output.group.title": "Output", "gui.output.dir.label": "Output directory", "gui.output.dir.placeholder": "Leave empty to write next to the input file", @@ -71,7 +66,6 @@ "gui.output.filename_rule.help.tooltip": "Show filename token help", "gui.output.preview": "Preview", "gui.output.batch_preview": "{first} | {count} output file(s)", - "gui.dialog.individual_batch.title": "Individual Batch Mode", "gui.dialog.individual_batch.text": "Individual batch mode treats every input row as a separate build.\n\nExample: if you add 20 single-plate 3MF files and set copies to 5, Build 3MF will create 20 separate packed files. Each output contains only that source file repeated 5 times.\n\nThis is useful for quickly batch-converting many independent 3MF jobs into multi-copy SwapMod packs. It does not combine all input files into one 3MF.", "gui.dialog.filename_help.title": "Output Filename Rule", @@ -85,10 +79,8 @@ "gui.dialog.add_files_title": "Add 3MF files", "gui.dialog.file_filter.3mf": "3MF files (*.3mf)", "gui.dialog.file_filter.all": "All files (*)", - "gui.toast.combined_success": "The packed 3MF file was created.", "gui.toast.batch_success": "Created {count} packed 3MF file(s).", - "gui.log.added_files": "Added {added} input file(s). Skipped {skipped}.", "gui.log.skipped_file": "Skipped {path}: {reason}", "gui.log.no_swap_files": "No swap G-code files found in {dir}", @@ -99,6 +91,8 @@ "gui.log.filament": "Estimated source filament: {filament}", "gui.log.md5": "G-code MD5: {md5}", "gui.log.build_error": "Error building {path}: {error}", - - "format.unknown": "Unknown" -} + "format.unknown": "Unknown", + "gui.button.close": "Close", + "gui.dialog.view_gcode.title": "View Swap G-code", + "gui.options.view_gcode": "View" +} \ No newline at end of file diff --git a/a1_swap_mod_packer/i18n/zh_CN.json b/a1_swap_mod_packer/i18n/zh_CN.json index 57969bc..69ad335 100644 --- a/a1_swap_mod_packer/i18n/zh_CN.json +++ b/a1_swap_mod_packer/i18n/zh_CN.json @@ -1,6 +1,5 @@ { "_lang": "简体中文", - "gui.file_group.title": "输入 3MF 文件", "gui.file_group.table.header.order": "顺序", "gui.file_group.table.header.file": "3MF 文件", @@ -15,22 +14,20 @@ "gui.file_group.table.tooltip_base_filament": "基础耗材:{filament}", "gui.file_group.total_summary": "合计:{plates} 板 | 时间:{time} | 耗材:{filament}", "gui.file_group.total_summary.empty": "合计:0 板 | 时间:0s | 耗材:0.00 g", - "gui.button.add_3mf": "添加 3MF", "gui.button.remove": "移除", "gui.button.remove_all": "全部移除", "gui.button.apply_copies": "应用默认份数至选中行", "gui.button.build": "构建 3MF", - "gui.preview.title": "选中文件的缩略图", "gui.preview.select_hint": "选择一个输入文件", "gui.preview.no_image": "无预览图", "gui.preview.unavailable": "预览不可用", - "gui.options.group.title": "打包选项", "gui.options.swap_gcode.label": "换盘 G-code", "gui.options.refresh": "刷新", "gui.options.open_folder": "打开文件夹", + "gui.options.view_gcode": "查看", "gui.options.default_copies": "新输入的默认份数", "gui.options.bed_cooldown": "等待热床降温", "gui.options.bed_cooldown.label": "热床降温", @@ -60,7 +57,6 @@ "gui.options.skip_duplicates": "添加输入时跳过重复文件路径", "gui.options.input_handling": "输入处理", "gui.options.language": "语言", - "gui.output.group.title": "输出", "gui.output.dir.label": "输出目录", "gui.output.dir.placeholder": "留空则写入输入文件所在目录", @@ -71,7 +67,6 @@ "gui.output.filename_rule.help.tooltip": "显示文件名标记帮助", "gui.output.preview": "预览", "gui.output.batch_preview": "{first} | {count} 个输出文件", - "gui.dialog.individual_batch.title": "独立批处理模式", "gui.dialog.individual_batch.text": "独立批处理模式将每一行输入作为独立的构建任务。\n\n示例:如果你添加了 20 个单板 3MF 文件并设置份数为 5,点击\"构建 3MF\"将创建 20 个独立的打包文件。每个输出文件仅包含该源文件重复 5 次的内容。\n\n这个功能适用于快速将大量独立的 3MF 作业批量转换为多份数的 SwapMod 包。它不会将所有输入文件合并到一个 3MF 中。", "gui.dialog.filename_help.title": "输出文件名规则", @@ -85,10 +80,8 @@ "gui.dialog.add_files_title": "添加 3MF 文件", "gui.dialog.file_filter.3mf": "3MF 文件 (*.3mf)", "gui.dialog.file_filter.all": "所有文件 (*)", - "gui.toast.combined_success": "已创建打包的 3MF 文件。", "gui.toast.batch_success": "已创建 {count} 个打包的 3MF 文件。", - "gui.log.added_files": "已添加 {added} 个输入文件。跳过 {skipped} 个。", "gui.log.skipped_file": "已跳过 {path}:{reason}", "gui.log.no_swap_files": "在 {dir} 中未找到换盘 G-code 文件", @@ -99,6 +92,7 @@ "gui.log.filament": "预估源文件耗材:{filament}", "gui.log.md5": "G-code MD5:{md5}", "gui.log.build_error": "构建 {path} 时出错:{error}", - - "format.unknown": "未知" -} + "format.unknown": "未知", + "gui.button.close": "关闭", + "gui.dialog.view_gcode.title": "查看换盘 G-code" +} \ No newline at end of file