Repository navigation
fix(ui): stop multi-select position spin from re-triggering the move - #594
Merged
Merged
Conversation
Stepping the X/Y position spin row with several items selected hung the application in an endless move loop between the old and new position. Two defects compound: - DocItemPropertiesWidget refreshed synchronously on every item matrix change. A multi-item move executes one command per item, so the refresh read the group bounding box mid-transaction while only part of the move had been applied, and wrote that intermediate value back into the spin row. - Programmatic spin row writes did not record the value in _last_emitted_value, so the entry text update that GTK delivers asynchronously was treated as a user edit and re-entered _on_x_changed with the opposite value. The panel now refreshes once on idle after the notifications settle, and programmatic sets mark their value as echoed so the deferred notification dedupes. Typing a value mostly escaped the loop because text and adjustment agree at emission time; the +/- buttons reliably hung.
The module-level DISPLAY guard used allow_module_level=False, which raises a collection error instead of skipping and aborted the whole Windows test run at collection time. Guard the skip on Linux like test_mainwindow.py does and pass allow_module_level=True.
🤖 Estimated LLM implementation costReplayed each of the 2 commits in this pull request and counted the code lines each commit added or rewrote:
Added lines by language: Python 131 Full estimate
Cost model: ≈10 tokens per code line at $15/Mtok output and $3/Mtok input (assuming heavy prompt caching); input ≈ 15× output for conversation replay; a review round ≈ 42,000 tokens; a failed CI run ≈ 21,000 tokens; file reads capped at 20 kB each. Active window from first commit to merge: <1 day.
|
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stepping the X/Y Position spin row (e.g. clicking
+) with several items selected hung the application in an endless move loop: the items ping-ponged between the old and new position at 100% CPU. Typing a value usually escaped the loop, which is why it appeared tied to the+/-buttons.Root cause
Two defects compound:
DocItemPropertiesWidgetrefreshed the panel synchronously on every item matrix change. A multi-item move (set_position_group) executes one command per item, so the refresh read the group bounding box mid-transaction — while only part of the move had been applied — and wrote that intermediate value back into the spin row. For a two-item selection the intermediate position alternates between old and new on each read.set_value/set_value_in_base_units) did not record the value in_last_emitted_value. GTK delivers the entry text update asynchronously, so the deferrednotify::textwas treated as a user edit, re-entering_on_x_changedwith the opposite value — closing the loop.This is pre-existing on
main; it was surfaced by a tester while evaluating #587 (sketches are irrelevant — any two selected items do it), but #587 does not touch the affected code.Fix
DocItemPropertiesWidget._on_item_data_changednow schedules one coalescedGLib.idle_addrefresh instead of refreshing synchronously per signal, so the panel only observes the settled post-transaction state (this also collapses N redundant refresh passes per multi-item command into one).SpinRow.set_valueandUnitSpinRow.set_value_in_base_unitsrecord_last_emitted_value, so the deferred GTK change notification is recognized as an echo of the programmatic set and deduped instead of re-triggering the transform handler.Testing
tests/ui_gtk/doceditor/test_multi_select_position_spin.py(ui-marked, full window): selects two workpieces, steps the X row three times, asserts both the row and the model settle exactly 3 mm ahead. Without the fix it hangs and is killed by the built-in watchdog; with the fix it passes in ~3.5 s.mainwith a traced full-window repro under xvfb (watchdog stack dumps) before fixing; the fix was also verified against the feat: position workpieces relative to a chosen origin #587 branch build.pixi run lintclean;pixi run uitestfortests/ui_gtk/doceditor/(104 tests) and the spin-row/varset suites (125 tests) pass; headless transform/asset command suites pass.