feat(gui): 新增重新打包3MF按钮,选择解压目录自动更新MD5并打包
This commit is contained in:
@@ -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"))
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
@@ -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 解压目录。"
|
||||
}
|
||||
Reference in New Issue
Block a user