Coverage for paintmaskanimator/progress.py: 95%
33 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-02 04:50 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-11-02 04:50 +0000
1"""Modal progress counter for long, frame-by-frame operations.
3Shared UI plumbing, not a feature: exports, scope runs, tween generation, layer
4merges and used-colour scans all show the same "n / total" dialog. It used to
5live inside ``main_window_line_ops.py``, which meant eight unrelated modules
6reached into the line-tool module for it. It is a free function set here so any
7of them can use it without depending on a feature module.
9``parent`` is the window the dialog is modal to.
10"""
11from __future__ import annotations
13from PySide6.QtCore import Qt
14from PySide6.QtWidgets import QApplication, QProgressDialog, QWidget
16from .i18n import tr
19def create_counter(
20 parent: QWidget, title: str, total: int, label: str | None = None,
21 cancellable: bool = False,
22) -> QProgressDialog:
23 """Show a modal counter dialog and return it."""
24 total = max(1, int(total))
25 dialog = QProgressDialog(
26 label or title,
27 tr("中止") if cancellable else "",
28 0,
29 total,
30 parent,
31 )
32 dialog.setWindowTitle(title)
33 if not cancellable:
34 dialog.setCancelButton(None)
35 dialog.setWindowModality(Qt.WindowModality.WindowModal)
36 dialog.setMinimumDuration(0)
37 dialog.setAutoClose(False)
38 dialog.setAutoReset(False)
39 dialog.setMinimumWidth(330)
40 dialog.setValue(0)
41 dialog.show()
42 QApplication.processEvents()
43 return dialog
46def update_counter(dialog: QProgressDialog | None, value: int, total: int, label: str) -> None:
47 """Advance the counter. A ``None`` dialog is a no-op, so callers need no guard."""
48 if dialog is None: 48 ↛ 49line 48 didn't jump to line 49 because the condition on line 48 was never true
49 return
50 value = max(0, min(int(total), int(value)))
51 dialog.setLabelText(f"{label}\n{value} / {int(total)}")
52 dialog.setValue(value)
53 QApplication.processEvents()
56def close_counter(dialog: QProgressDialog | None) -> None:
57 """Finish and dispose of the counter. A ``None`` dialog is a no-op."""
58 if dialog is None:
59 return
60 dialog.setValue(dialog.maximum())
61 dialog.close()
62 dialog.deleteLater()
63 QApplication.processEvents()