feat(gui,cli): 界面全面中文化并优化打包选项为紧凑网格布局
- gui.py: 全部用户可见文本直接写中文,选项区从 QFormLayout 改为 QGridLayout 两列布局,缩小窗口默认高度至720px,收紧控件间距 - cli.py: argparse 帮助文本和输出消息全部中文化 - docs: 新增 A1 SwapMod 换板 G-code 内容分析文档,按三类策略(基础/双轮抖板/安全换板)对比5个模板差异 - swap_gcode: 新增 LX_0.01.01 基础弹板模板
This commit is contained in:
+30
-30
@@ -17,12 +17,12 @@ from .paths import default_patch_config_path, default_swap_gcode_dir
|
||||
|
||||
def parse_item(values: list[str]) -> PlateJob:
|
||||
if len(values) != 2:
|
||||
raise argparse.ArgumentTypeError("Each --item needs a path and a copy count.")
|
||||
raise argparse.ArgumentTypeError("每个 --item 需要一个路径和一个份数。")
|
||||
path = Path(values[0])
|
||||
try:
|
||||
copies = int(values[1])
|
||||
except ValueError as exc:
|
||||
raise argparse.ArgumentTypeError(f"Invalid copy count: {values[1]}") from exc
|
||||
raise argparse.ArgumentTypeError(f"无效的份数:{values[1]}") from exc
|
||||
return PlateJob(path, copies)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ def build_command(args: argparse.Namespace) -> int:
|
||||
for input_path in args.inputs or []:
|
||||
jobs.append(PlateJob(Path(input_path), args.copies))
|
||||
if not jobs:
|
||||
raise SystemExit("No input 3MF file was provided.")
|
||||
raise SystemExit("未提供输入 3MF 文件。")
|
||||
cool_bed_temp = None if args.no_bed_cooldown else args.cool_bed
|
||||
options = BuildOptions(
|
||||
swap_gcode=args.swap_gcode,
|
||||
@@ -50,13 +50,13 @@ def build_command(args: argparse.Namespace) -> int:
|
||||
zip_compress_level=args.zip_level,
|
||||
)
|
||||
result = build_packed_3mf(jobs, options)
|
||||
print(f"Output: {result.output_3mf}")
|
||||
print(f"Plates: {result.plate_count}")
|
||||
print(f"G-code MD5: {result.gcode_md5}")
|
||||
print(f"输出:{result.output_3mf}")
|
||||
print(f"板数:{result.plate_count}")
|
||||
print(f"G-code MD5:{result.gcode_md5}")
|
||||
if result.total_prediction_seconds is not None:
|
||||
print(f"Source print time: {int(result.total_prediction_seconds)} seconds")
|
||||
print(f"源文件打印时间:{int(result.total_prediction_seconds)} 秒")
|
||||
if result.total_weight_grams is not None:
|
||||
print(f"Source filament weight: {result.total_weight_grams:.2f} g")
|
||||
print(f"源文件耗材重量:{result.total_weight_grams:.2f} g")
|
||||
return 0
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ def list_swap_gcode_command(args: argparse.Namespace) -> int:
|
||||
directory = Path(args.swap_gcode_dir) if args.swap_gcode_dir else default_swap_gcode_dir()
|
||||
files = list_swap_gcode_files(directory)
|
||||
if not files:
|
||||
print(f"No swap G-code files found in: {directory}")
|
||||
print(f"在 {directory} 中未找到换料 G-code 文件")
|
||||
return 0
|
||||
for path in files:
|
||||
print(path.name)
|
||||
@@ -74,32 +74,32 @@ def list_swap_gcode_command(args: argparse.Namespace) -> int:
|
||||
def create_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="a1-swap-mod-packer",
|
||||
description=f"{APP_TITLE} - Pack repeated Bambu A1 SwapMod plates into one 3MF job.",
|
||||
description=f"{APP_TITLE} - 将重复的 Bambu A1 SwapMod 面板打包为一个 3MF 作业。",
|
||||
)
|
||||
parser.add_argument("--version", action="version", version=f"{APP_NAME} {__version__}")
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
build = subparsers.add_parser("build", help="Build a packed 3MF file.")
|
||||
build.add_argument("inputs", nargs="*", help="Input 3MF files. Use --copies for the same copy count on all of them.")
|
||||
build.add_argument("--item", nargs=2, action="append", metavar=("PATH", "COPIES"), help="Add an input 3MF with its own copy count. Can be used multiple times.")
|
||||
build.add_argument("-o", "--output", required=True, help="Output 3MF path.")
|
||||
build.add_argument("--swap-gcode", required=True, help="Swap G-code file name in swap_gcode, or an explicit file path.")
|
||||
build.add_argument("--swap-gcode-dir", default=None, help=f"Template directory. Default: {default_swap_gcode_dir()}")
|
||||
build.add_argument("--copies", type=int, default=1, help="Copy count for positional input files.")
|
||||
build.add_argument("--cool-bed", type=int, default=45, help="Bed temperature to wait for before running the swap G-code.")
|
||||
build.add_argument("--no-bed-cooldown", action="store_true", help="Do not insert M190 before the swap code.")
|
||||
build.add_argument("--wait", type=int, default=45, help="Seconds to wait after plate ejection.")
|
||||
build.add_argument("--show-plate-number", action="store_true", help="Add 100 hours per plate number to M73 R values.")
|
||||
build.add_argument("--no-swap-after-final", action="store_true", help="Do not run the swap G-code after the last plate.")
|
||||
build.add_argument("--metadata-mode", choices=("source", "sum"), default="source", help="How to write slice_info prediction and weight.")
|
||||
build.add_argument("--line-ending", choices=("lf", "crlf"), default="crlf", help="Line ending for the generated G-code.")
|
||||
build.add_argument("--zip-level", type=int, choices=range(1, 10), default=DEFAULT_ZIP_COMPRESS_LEVEL, metavar="1-9", help="zlib-ng Deflate compression level for the output 3MF. Default: 7.")
|
||||
build.add_argument("--no-preview-label", action="store_true", help="Do not rewrite the preview image label/composite.")
|
||||
build.add_argument("--no-gcode-patches", action="store_true", help=f"Do not apply editable patches from {default_patch_config_path()}.")
|
||||
build = subparsers.add_parser("build", help="构建一个打包的 3MF 文件。")
|
||||
build.add_argument("inputs", nargs="*", help="输入 3MF 文件。使用 --copies 为所有文件设置相同的份数。")
|
||||
build.add_argument("--item", nargs=2, action="append", metavar=("PATH", "COPIES"), help="添加一个带有独立份数的输入 3MF 文件。可重复使用。")
|
||||
build.add_argument("-o", "--output", required=True, help="输出 3MF 路径。")
|
||||
build.add_argument("--swap-gcode", required=True, help="换料 G-code 文件名,位于 swap_gcode 中,或显式文件路径。")
|
||||
build.add_argument("--swap-gcode-dir", default=None, help=f"模板目录。默认值:{default_swap_gcode_dir()}")
|
||||
build.add_argument("--copies", type=int, default=1, help="位置参数输入文件的复制份数。")
|
||||
build.add_argument("--cool-bed", type=int, default=45, help="执行换料 G-code 前等待的床温。")
|
||||
build.add_argument("--no-bed-cooldown", action="store_true", help="不在换料代码前插入 M190。")
|
||||
build.add_argument("--wait", type=int, default=45, help="板弹射后等待的秒数。")
|
||||
build.add_argument("--show-plate-number", action="store_true", help="每板号向 M73 R 值增加 100 小时。")
|
||||
build.add_argument("--no-swap-after-final", action="store_true", help="最后一块板后不执行换料 G-code。")
|
||||
build.add_argument("--metadata-mode", choices=("source", "sum"), default="source", help="如何写入 slice_info 的 prediction 和 weight。")
|
||||
build.add_argument("--line-ending", choices=("lf", "crlf"), default="crlf", help="生成 G-code 的换行符。")
|
||||
build.add_argument("--zip-level", type=int, choices=range(1, 10), default=DEFAULT_ZIP_COMPRESS_LEVEL, metavar="1-9", help="输出 3MF 的 zlib-ng Deflate 压缩级别。默认值:7。")
|
||||
build.add_argument("--no-preview-label", action="store_true", help="不重写预览图标签/合成图。")
|
||||
build.add_argument("--no-gcode-patches", action="store_true", help=f"不应用来自 {default_patch_config_path()} 的可编辑补丁。")
|
||||
build.set_defaults(func=build_command)
|
||||
|
||||
list_cmd = subparsers.add_parser("list-swap-gcode", help="List files from the swap_gcode directory.")
|
||||
list_cmd.add_argument("--swap-gcode-dir", default=None, help=f"Template directory. Default: {default_swap_gcode_dir()}")
|
||||
list_cmd = subparsers.add_parser("list-swap-gcode", help="列出 swap_gcode 目录中的文件。")
|
||||
list_cmd.add_argument("--swap-gcode-dir", default=None, help=f"模板目录。默认值:{default_swap_gcode_dir()}")
|
||||
list_cmd.set_defaults(func=list_swap_gcode_command)
|
||||
return parser
|
||||
|
||||
@@ -110,7 +110,7 @@ def main(argv: list[str] | None = None) -> int:
|
||||
try:
|
||||
return int(args.func(args))
|
||||
except Exception as exc:
|
||||
print(f"Error: {exc}", file=sys.stderr)
|
||||
print(f"错误:{exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user