Show a busy window while the solve runs

On OK the dialog closed and nothing appeared until the figures did,
which on a real board is minutes of looking like the plugin did
nothing. Put a small always-on-top window up for that stretch: the
stage now running, elapsed seconds, and Cancel.

Qt only repaints while the event loop runs and the solve owns the
thread, so the window pumps events itself - from inside the CG/AMG
iteration callback, which is where the time actually goes. That is
also where Cancel is noticed. The state is module-level because the
tick happens several frames deep in scipy/pyamg, and threading a
handle through those signatures for a progress bar is not worth it;
it stays inert until start(), so the standalone runner and the tests
are unaffected.

The window covers the figure work too, not just the solve: laying out
labels and writing four PNGs at full DPI is seconds on a real board -
10-15 of them on a large one - and closing before that left the same
silent gap one step later.
This commit is contained in:
2026-07-22 16:54:29 +07:00
parent d7c3089031
commit 979b69960f
7 changed files with 191 additions and 14 deletions
+4 -2
View File
@@ -34,7 +34,7 @@ import numpy as np
from scipy import sparse
from scipy.sparse import csgraph
from . import config, quadtree, skin
from . import config, progress, quadtree, skin
from . import solver as sv
from .errors import ConnectivityError
from .geometry import Problem
@@ -300,9 +300,11 @@ def run_solve_adaptive(problem: Problem, stack: RasterStack,
corr = np.zeros(len(edges.a))
faces = e_axis >= 0
fa, fb = edges.a[faces], edges.b[faces]
for _ in range(max(0, int(config.ADAPTIVE_CORRECTION_PASSES))):
passes = max(0, int(config.ADAPTIVE_CORRECTION_PASSES))
for p in range(passes):
if not faces.any():
break
progress.stage(f"correction pass {p + 1}/{passes} ...")
gx, gy = _leaf_gradients(N, fa, fb, cxg, cyg, Vflat)
gt = np.where(e_axis[faces] == 0, 0.5 * (gy[fa] + gy[fb]),
0.5 * (gx[fa] + gx[fb]))