spacr.qt.widgets.object_grid_binding¶
Keeping the per-object grid and the flat settings form saying the same thing.
The grid in spacr.qt.widgets.object_settings_grid edits VALUES; the
settings panel is a dictionary of WIDGETS, and the pipeline reads the widgets.
Mounting the grid without a binding would give a screen two answers to the
same question – the table showing what the user typed and collect()
still returning what the widget holds – and the run would silently use the
second one. That is a settings file that means something other than what it
looks like, which is worse than the flat form the grid replaces.
So the grid never becomes the source of truth. It is a VIEW that writes
through: every edit lands in the widget behind it, and the widget stays what
the pipeline reads. Nothing downstream of collect() learns that the grid
exists, so no settings file, notebook or spacr-run invocation changes.
WHY THE PANEL IS DUCK-TYPED. This asks for two methods – collect and
set_value_for_key – and not for a class. That keeps the binding testable
against a dictionary rather than against a built screen, and it is the whole
of what the binding needs.
Classes¶
Bind a per-object grid to the settings panel behind it. |
Module Contents¶
- class spacr.qt.widgets.object_grid_binding.ObjectGridBinding(grid, panel, parent=None)[source]¶
Bases:
PySide6.QtCore.QObjectBind a per-object grid to the settings panel behind it.
- Parameters:
grid – the
ObjectSettingsGridto drive.panel – anything offering
collect()andset_value_for_key(key, value).parent – parent object.
Bind a per-object grid to the settings panel beside it.
The re-entrancy guard is what stops the table visibly rebuilding under a cursor that is still in a cell: writing a value into a widget makes that widget emit, and a screen that reseeds the grid on every widget change would rebuild it mid-edit. No value depends on the guard – the write reads the grid once, before the first widget moves – so a reseed halfway cannot drop an edit either way.
- Parameters:
grid – the object settings grid.
panel – the settings panel it mirrors.
parent – parent object, or
None.
- follow_the_form() int[source]¶
Make the form’s own fields write INTO the table.
THE OTHER HALF OF A TWO-WAY BINDING, and the half that was missing: the grid wrote through to the widgets, but nothing told the grid when a widget moved, so a value changed anywhere else – the flat row for an object the table does not claim, a preset, the Live Preview, a settings file poured in – left the table showing the old answer.
WHY NOT JUST RESEED.
seedrebuilds the whole table, which is 30 ms on Mask and 100 ms once there are ten organelles. On atextChangedthat is per KEYSTROKE, and it would also take the cursor out of whatever cell was being typed into. One cell is written instead.- Returns:
how many widgets were newly connected.
- owned_keys() FrozenSet[str][source]¶
The settings keys the grid answers, as the panel now stands.
Read from the panel every time rather than remembered, because a panel hides the settings of an object whose channel names no plane and the grid must not claim a key that is no longer there.
Columns hidden because their channel is unset are still claimed, so their rows stay off the flat form; their channels are not claimed, because a hidden object’s channel on the form is how it is brought back.