feat(gui): 新增重新打包3MF按钮,选择解压目录自动更新MD5并打包

This commit is contained in:
2026-07-30 14:32:53 +08:00
parent d362b2280a
commit c43faeb5a2
3 changed files with 71 additions and 2 deletions
+59
View File
@@ -499,6 +499,10 @@ class MainWindow(QMainWindow):
self.skip_duplicates_check = QCheckBox(t("gui.options.skip_duplicates"))
self.skip_duplicates_check.setChecked(True)
# 重新打包解压的 3MF
self.repack_3mf_button = QPushButton(t("gui.options.repack_3mf"))
self.repack_3mf_button.clicked.connect(self.repack_3mf_folder)
# 标签列固定宽度(左对齐),控件列自动对齐(stretch=1 平分空间)
grid.setColumnMinimumWidth(0, 120)
grid.setColumnMinimumWidth(2, 90)
@@ -552,6 +556,9 @@ class MainWindow(QMainWindow):
# 第 6 行:构建成功后清空输入列表(独立一行)
grid.addWidget(self.clear_after_build_check, 6, 1, 1, 3)
# 第 7 行:重新打包 3MF
grid.addWidget(self.repack_3mf_button, 7, 1, 1, 3)
root.addWidget(self.options_group)
# =====================================================================
@@ -809,6 +816,57 @@ class MainWindow(QMainWindow):
return
self.open_path(path)
def repack_3mf_folder(self) -> None:
"""选择解压后的3MF文件夹,自动更新MD5并重新打包为.3mf"""
import hashlib
import re
import os
import zipfile
folder = QFileDialog.getExistingDirectory(self, t("gui.dialog.repack_select_folder"))
if not folder:
return
src_dir = Path(folder)
ct_path = src_dir / "[Content_Types].xml"
if not ct_path.exists():
QMessageBox.warning(self, t("gui.dialog.warning.title"), t("gui.dialog.repack_no_content_types"))
return
try:
# 更新所有 plate_N.gcode.md5
gcode_re = re.compile(r"^(.+[/\\])?Metadata[/\\]plate_(\d+)\.gcode$")
metadata_dir = src_dir / "Metadata"
if metadata_dir.is_dir():
for gcode_file in sorted(metadata_dir.glob("plate_*.gcode")):
if not gcode_re.match(str(gcode_file)):
continue
h = hashlib.md5()
with open(gcode_file, "rb") as f:
h.update(f.read())
md5_path = Path(str(gcode_file) + ".md5")
md5_path.write_text(h.hexdigest(), encoding="ascii")
# 打包:[Content_Types].xml 必须是第一个条目
output = src_dir.parent / (src_dir.name.rstrip("/\\") + ".3mf")
with zipfile.ZipFile(output, "w", zipfile.ZIP_DEFLATED) as z:
z.write(ct_path, "[Content_Types].xml")
for root, _dirs, files in os.walk(str(src_dir)):
for fn in files:
fp = Path(root) / fn
arcname = fp.relative_to(src_dir).as_posix()
if arcname == "[Content_Types].xml":
continue
z.write(str(fp), arcname)
QMessageBox.information(
self,
t("gui.dialog.repack_success.title"),
t("gui.dialog.repack_success.text", path=str(output)),
)
except Exception as exc:
QMessageBox.critical(self, t("gui.dialog.warning.title"), str(exc))
# =========================================================================
# 文件输入管理(表格行操作)
# =========================================================================
@@ -1421,6 +1479,7 @@ class MainWindow(QMainWindow):
self.skip_duplicates_check.setText(t("gui.options.skip_duplicates"))
self.bed_cooldown_suffix_label.setText(t("gui.options.bed_cooldown.suffix"))
self.wait_suffix_label.setText(t("gui.options.wait_suffix"))
self.repack_3mf_button.setText(t("gui.options.repack_3mf"))
# 元数据下拉框
self.metadata_combo.setItemText(0, t("gui.options.metadata.source"))
+6 -1
View File
@@ -95,5 +95,10 @@
"gui.button.close": "Close",
"gui.dialog.view_gcode.title": "View Swap G-code",
"gui.options.view_gcode": "View",
"gui.dialog.build_result.title": "Build Result"
"gui.dialog.build_result.title": "Build Result",
"gui.options.repack_3mf": "Repack 3MF",
"gui.dialog.repack_select_folder": "Select unpacked 3MF folder",
"gui.dialog.repack_success.title": "Repack Complete",
"gui.dialog.repack_success.text": "3MF has been repacked:\n{path}",
"gui.dialog.repack_no_content_types": "[Content_Types].xml not found. Not a valid unpacked 3MF directory."
}
+6 -1
View File
@@ -95,5 +95,10 @@
"format.unknown": "未知",
"gui.button.close": "关闭",
"gui.dialog.view_gcode.title": "查看换盘 G-code",
"gui.dialog.build_result.title": "构建结果"
"gui.dialog.build_result.title": "构建结果",
"gui.options.repack_3mf": "重新打包 3MF",
"gui.dialog.repack_select_folder": "选择解压后的 3MF 文件夹",
"gui.dialog.repack_success.title": "重新打包完成",
"gui.dialog.repack_success.text": "已重新打包为 3MF 文件:\n{path}",
"gui.dialog.repack_no_content_types": "未找到 [Content_Types].xml,不是有效的 3MF 解压目录。"
}