refactor(gui): 底部日志区改为弹窗展示构建结果
This commit is contained in:
+26
-43
@@ -346,7 +346,6 @@ class MainWindow(QMainWindow):
|
|||||||
self._updating_table = False # 防重入标记:表格正在批量更新中
|
self._updating_table = False # 防重入标记:表格正在批量更新中
|
||||||
self._loading_settings = True # 防重入标记:正在从设置恢复 UI 状态
|
self._loading_settings = True # 防重入标记:正在从设置恢复 UI 状态
|
||||||
self._settings = self.load_settings()
|
self._settings = self.load_settings()
|
||||||
self._shared_growth_enabled = False # 窗口高度足够时,文件区和日志区共享扩展空间
|
|
||||||
self.build_ui()
|
self.build_ui()
|
||||||
self.load_swap_gcode_to_combo()
|
self.load_swap_gcode_to_combo()
|
||||||
self.restore_settings_to_ui()
|
self.restore_settings_to_ui()
|
||||||
@@ -695,36 +694,16 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
root.addWidget(self.output_group)
|
root.addWidget(self.output_group)
|
||||||
|
|
||||||
# =====================================================================
|
|
||||||
# --- 日志区 ---
|
|
||||||
# =====================================================================
|
|
||||||
self.log = QTextEdit()
|
|
||||||
self.log.setReadOnly(True)
|
|
||||||
self.log.setMinimumHeight(80)
|
|
||||||
root.addWidget(self.log, 0)
|
|
||||||
|
|
||||||
self.setCentralWidget(central)
|
self.setCentralWidget(central)
|
||||||
self.success_toast = SuccessToast(central)
|
self.success_toast = SuccessToast(central)
|
||||||
self.update_vertical_growth_policy()
|
|
||||||
|
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# 窗口事件
|
# 窗口事件
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
|
|
||||||
def update_vertical_growth_policy(self) -> None:
|
def update_vertical_growth_policy(self) -> None:
|
||||||
"""根据窗口高度动态调整文件区和日志区的垂直扩展比例。
|
"""已废弃——底部日志区已移除。"""
|
||||||
|
pass
|
||||||
窗口高度 >= 980px 时,文件区和日志区按 4:1 共享扩展空间;
|
|
||||||
否则文件区独占扩展空间。
|
|
||||||
"""
|
|
||||||
if not hasattr(self, "root_layout") or not hasattr(self, "file_group") or not hasattr(self, "log"):
|
|
||||||
return
|
|
||||||
shared_growth = self.height() >= 980
|
|
||||||
if shared_growth == self._shared_growth_enabled:
|
|
||||||
return
|
|
||||||
self._shared_growth_enabled = shared_growth
|
|
||||||
self.root_layout.setStretchFactor(self.file_group, 4 if shared_growth else 1)
|
|
||||||
self.root_layout.setStretchFactor(self.log, 1 if shared_growth else 0)
|
|
||||||
|
|
||||||
def resizeEvent(self, event: QEvent) -> None:
|
def resizeEvent(self, event: QEvent) -> None:
|
||||||
"""窗口大小变化时,更新垂直扩展策略并刷新缩略图。"""
|
"""窗口大小变化时,更新垂直扩展策略并刷新缩略图。"""
|
||||||
@@ -874,8 +853,6 @@ class MainWindow(QMainWindow):
|
|||||||
index = self.swap_gcode_combo.findText(Path(str(current)).name)
|
index = self.swap_gcode_combo.findText(Path(str(current)).name)
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
self.swap_gcode_combo.setCurrentIndex(index)
|
self.swap_gcode_combo.setCurrentIndex(index)
|
||||||
if not files:
|
|
||||||
self.log.append(t("gui.log.no_swap_files", dir=str(default_swap_gcode_dir())))
|
|
||||||
|
|
||||||
def open_path(self, path: Path) -> None:
|
def open_path(self, path: Path) -> None:
|
||||||
"""跨平台打开文件或文件夹(Windows/Mac/Linux)。"""
|
"""跨平台打开文件或文件夹(Windows/Mac/Linux)。"""
|
||||||
@@ -1068,8 +1045,6 @@ class MainWindow(QMainWindow):
|
|||||||
added += 1
|
added += 1
|
||||||
else:
|
else:
|
||||||
skipped += 1
|
skipped += 1
|
||||||
if added or skipped:
|
|
||||||
self.log.append(t("gui.log.added_files", added=added, skipped=skipped))
|
|
||||||
self.update_total_summary()
|
self.update_total_summary()
|
||||||
self.update_output_preview()
|
self.update_output_preview()
|
||||||
|
|
||||||
@@ -1078,8 +1053,7 @@ class MainWindow(QMainWindow):
|
|||||||
path = Path(file_name)
|
path = Path(file_name)
|
||||||
try:
|
try:
|
||||||
summary = read_3mf_summary(path)
|
summary = read_3mf_summary(path)
|
||||||
except Exception as exc:
|
except Exception:
|
||||||
self.log.append(t("gui.log.skipped_file", path=str(path), reason=str(exc)))
|
|
||||||
return False
|
return False
|
||||||
row = self.table.rowCount()
|
row = self.table.rowCount()
|
||||||
self._updating_table = True
|
self._updating_table = True
|
||||||
@@ -1382,13 +1356,19 @@ class MainWindow(QMainWindow):
|
|||||||
zip_compress_level=int(self.zip_level_combo.currentData() or DEFAULT_ZIP_COMPRESS_LEVEL),
|
zip_compress_level=int(self.zip_level_combo.currentData() or DEFAULT_ZIP_COMPRESS_LEVEL),
|
||||||
)
|
)
|
||||||
|
|
||||||
def log_build_result(self, result: Any) -> None:
|
def _show_build_result_dialog(self, title: str, lines: list[str]) -> None:
|
||||||
"""将单次构建结果信息写入日志。"""
|
"""在弹出的对话框中展示构建结果信息。"""
|
||||||
self.log.append(t("gui.log.output", path=str(result.output_3mf)))
|
QMessageBox.information(self, title, "\n".join(lines))
|
||||||
self.log.append(t("gui.log.plates", count=result.plate_count))
|
|
||||||
self.log.append(t("gui.log.time", time=format_duration(result.total_prediction_seconds)))
|
def log_build_result(self, result: Any) -> list[str]:
|
||||||
self.log.append(t("gui.log.filament", filament=format_filament(result.total_weight_grams)))
|
"""返回单次构建结果的文本行列表。"""
|
||||||
self.log.append(t("gui.log.md5", md5=result.gcode_md5))
|
return [
|
||||||
|
t("gui.log.output", path=str(result.output_3mf)),
|
||||||
|
t("gui.log.plates", count=result.plate_count),
|
||||||
|
t("gui.log.time", time=format_duration(result.total_prediction_seconds)),
|
||||||
|
t("gui.log.filament", filament=format_filament(result.total_weight_grams)),
|
||||||
|
t("gui.log.md5", md5=result.gcode_md5),
|
||||||
|
]
|
||||||
|
|
||||||
def show_success_toast(self, message: str) -> None:
|
def show_success_toast(self, message: str) -> None:
|
||||||
"""显示构建成功的浮动提示条。"""
|
"""显示构建成功的浮动提示条。"""
|
||||||
@@ -1408,7 +1388,6 @@ class MainWindow(QMainWindow):
|
|||||||
self.build_combined_output(jobs)
|
self.build_combined_output(jobs)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
QMessageBox.critical(self, t("gui.dialog.warning.title"), str(exc))
|
QMessageBox.critical(self, t("gui.dialog.warning.title"), str(exc))
|
||||||
self.log.append(t("gui.log.build_error", path=type(exc).__name__, error=str(exc)))
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def build_combined_output(self, jobs: list[PlateJob]) -> None:
|
def build_combined_output(self, jobs: list[PlateJob]) -> None:
|
||||||
@@ -1416,7 +1395,7 @@ class MainWindow(QMainWindow):
|
|||||||
output_path = resolve_output_path(jobs, self.output_naming_options(), self.summary_for_path)
|
output_path = resolve_output_path(jobs, self.output_naming_options(), self.summary_for_path)
|
||||||
options = self.build_options_for_output(output_path)
|
options = self.build_options_for_output(output_path)
|
||||||
result = build_packed_3mf(jobs, options)
|
result = build_packed_3mf(jobs, options)
|
||||||
self.log_build_result(result)
|
self._show_build_result_dialog(t("gui.dialog.build_result.title"), self.log_build_result(result))
|
||||||
self.show_success_toast(t("gui.toast.combined_success"))
|
self.show_success_toast(t("gui.toast.combined_success"))
|
||||||
if self.clear_after_build_check.isChecked():
|
if self.clear_after_build_check.isChecked():
|
||||||
self.remove_all()
|
self.remove_all()
|
||||||
@@ -1424,7 +1403,6 @@ class MainWindow(QMainWindow):
|
|||||||
def build_individual_outputs(self, jobs: list[PlateJob]) -> None:
|
def build_individual_outputs(self, jobs: list[PlateJob]) -> None:
|
||||||
"""独立批处理模式:每行输入构建一个独立的输出 3MF,支持并行处理。"""
|
"""独立批处理模式:每行输入构建一个独立的输出 3MF,支持并行处理。"""
|
||||||
used_paths: set[Path] = set()
|
used_paths: set[Path] = set()
|
||||||
success_count = 0
|
|
||||||
errors: list[str] = []
|
errors: list[str] = []
|
||||||
tasks: list[IndividualBuildTask] = []
|
tasks: list[IndividualBuildTask] = []
|
||||||
for job in jobs:
|
for job in jobs:
|
||||||
@@ -1436,20 +1414,21 @@ class MainWindow(QMainWindow):
|
|||||||
options = self.build_options_for_output(output_path)
|
options = self.build_options_for_output(output_path)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
errors.append(f"{job.source_3mf.name}: {exc}")
|
errors.append(f"{job.source_3mf.name}: {exc}")
|
||||||
self.log.append(t("gui.log.build_error", path=str(job.source_3mf), error=str(exc)))
|
|
||||||
continue
|
continue
|
||||||
tasks.append(IndividualBuildTask(job, options))
|
tasks.append(IndividualBuildTask(job, options))
|
||||||
|
|
||||||
|
all_lines: list[str] = []
|
||||||
if tasks:
|
if tasks:
|
||||||
worker_count = individual_batch_worker_count(len(tasks))
|
worker_count = individual_batch_worker_count(len(tasks))
|
||||||
self.log.append(t("gui.log.building_individual", count=len(tasks), workers=worker_count))
|
all_lines.append(t("gui.log.building_individual", count=len(tasks), workers=worker_count))
|
||||||
batch_result = run_individual_batch_builds(tasks, max_workers=worker_count)
|
batch_result = run_individual_batch_builds(tasks, max_workers=worker_count)
|
||||||
for result in batch_result.results:
|
for result in batch_result.results:
|
||||||
self.log_build_result(result)
|
all_lines.extend(self.log_build_result(result))
|
||||||
|
all_lines.append("")
|
||||||
success_count = len(batch_result.results)
|
success_count = len(batch_result.results)
|
||||||
for failure in batch_result.failures:
|
for failure in batch_result.failures:
|
||||||
|
all_lines.append(t("gui.log.build_error", path=str(failure.job.source_3mf), error=str(failure.error)))
|
||||||
errors.append(f"{failure.job.source_3mf.name}: {failure.error}")
|
errors.append(f"{failure.job.source_3mf.name}: {failure.error}")
|
||||||
self.log.append(t("gui.log.build_error", path=str(failure.job.source_3mf), error=str(failure.error)))
|
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
QMessageBox.warning(
|
QMessageBox.warning(
|
||||||
@@ -1460,9 +1439,13 @@ class MainWindow(QMainWindow):
|
|||||||
+ ("\n..." if len(errors) > 8 else ""),
|
+ ("\n..." if len(errors) > 8 else ""),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
if all_lines:
|
||||||
|
self._show_build_result_dialog(t("gui.dialog.build_result.title"), all_lines)
|
||||||
self.show_success_toast(t("gui.toast.batch_success", count=success_count))
|
self.show_success_toast(t("gui.toast.batch_success", count=success_count))
|
||||||
if self.clear_after_build_check.isChecked():
|
if self.clear_after_build_check.isChecked():
|
||||||
self.remove_all()
|
self.remove_all()
|
||||||
|
if self.clear_after_build_check.isChecked():
|
||||||
|
self.remove_all()
|
||||||
|
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# 窗口级拖放事件
|
# 窗口级拖放事件
|
||||||
|
|||||||
@@ -94,5 +94,6 @@
|
|||||||
"format.unknown": "Unknown",
|
"format.unknown": "Unknown",
|
||||||
"gui.button.close": "Close",
|
"gui.button.close": "Close",
|
||||||
"gui.dialog.view_gcode.title": "View Swap G-code",
|
"gui.dialog.view_gcode.title": "View Swap G-code",
|
||||||
"gui.options.view_gcode": "View"
|
"gui.options.view_gcode": "View",
|
||||||
|
"gui.dialog.build_result.title": "Build Result"
|
||||||
}
|
}
|
||||||
@@ -94,5 +94,6 @@
|
|||||||
"gui.log.build_error": "构建 {path} 时出错:{error}",
|
"gui.log.build_error": "构建 {path} 时出错:{error}",
|
||||||
"format.unknown": "未知",
|
"format.unknown": "未知",
|
||||||
"gui.button.close": "关闭",
|
"gui.button.close": "关闭",
|
||||||
"gui.dialog.view_gcode.title": "查看换盘 G-code"
|
"gui.dialog.view_gcode.title": "查看换盘 G-code",
|
||||||
|
"gui.dialog.build_result.title": "构建结果"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user