Skip to content

feat: separated utilities ui into pages - #332

Open
Robert0Mart wants to merge 1 commit into
ref/standardize-ui-setupfrom
ref/utilitesTab-stackedWidget
Open

Robert0Mart wants to merge 1 commit into
ref/standardize-ui-setupfrom
ref/utilitesTab-stackedWidget

Conversation

@Robert0Mart

@Robert0Mart Robert0Mart commented Sep 7, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked PR — merge order

This PR is stacked on top of:

  1. refactor main window stacked widget #298
  2. refactor: separated control stacked widget into pages #299

Do not merge until #298 , #299 are merged first.

CI won't run here until the base becomes dev (after the parents merge).

Descirption

  • Refactor

Separated utitliesStacked.ui into pages

  • BlocksScreen/lib/panels/widgets/UtilitiesTab/InputShaPage.py
  • BlocksScreen/lib/panels/widgets/UtilitiesTab/axisMaintPage.py
  • BlocksScreen/lib/panels/widgets/UtilitiesTab/infoPage.py
  • BlocksScreen/lib/panels/widgets/UtilitiesTab/ledsPage.py
  • BlocksScreen/lib/panels/widgets/UtilitiesTab/routinePage.py
  • BlocksScreen/lib/panels/widgets/UtilitiesTab/troubleshootPage.py (cleaned setupUi)

deleted old UI

  • BlocksScreen/lib/ui/utilitiesStackedWidget.ui
  • BlocksScreen/lib/ui/utilitiesStackedWidget_ui.py

@Robert0Mart
Robert0Mart marked this pull request as ready for review September 7, 2026 13:41
@Robert0Mart Robert0Mart self-assigned this Sep 7, 2026

@gmmcosta15 gmmcosta15 left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's good

  • The 3072-line .ui and 1282-line generated file are gone; utilitiesTab.py is now ~340 lines of wiring.
  • Routine check is now a data-driven Step list. fan_steps/heater_steps/axis_steps are pure classmethods, much easier to follow and test than the old process_map/current_object state machine.
  • Axis moves are now absolute (G90) with far/middle taken from the real limits. The old code left the printer in G91 after Y/Z and parked X at a hardcoded X250.
  • abort() dedupes cleanups and turns heaters/fans off on back. Before, backing out mid-routine left the heater at 60.
  • LED slider fixed: setValue(round(white * 100 / 255)) (the old code fed 0-255 into a 0-100 slider). On/off buttons with synced enabled state are clearer than the toggle.
  • The single-LED shortcut moved into showEvent, so no more disconnect/reconnect of the utilities button.
  • InputShaper: _measurement removes the "%.0f" % "N/A" TypeError, and handle_ism_confirm guards a None item and a bad axis.
  • The troubleshoot placeholder ("idk whar to type this") is replaced with real support text.

1. routinePage.py:127: homing overlay stays up for 180s when the printer is already homed
Klipper never clears homed_axes on a re-home: homing.py _set_start_position marks the axes homed via set_position(..., homing_axes=...). So _home_dropped never flips, _home_settle never starts, and only the 180s _home_guard lowers the overlay. It hits the prologue G28, the final cleanup G28 and a back press mid-routine. idle_timeout goes Printing -> Ready when the script (G28 + M400 + moves) finishes, so use that instead:

# utilitiesTab
self.printer.idle_timeout_update[str, str].connect(self.routines_page.on_idle_state)

# routinePage
def on_idle_state(self, field: str, value: str) -> None:
    """Lower the homing screen once the homing script has finished."""
    if field != "state" or not self._homing:
        return
    if value == "Printing":
        self._home_dropped = True
    elif value == "Ready" and self._home_dropped:
        self._home_finished()

Keep _home_guard as the fallback.

2. utilitiesTab.py:89: manual input shaper no longer reachable
The old page had Automatic + Manual cards and the result list. Now the button only opens the auto popup, and is_page is logic=True and never added (# self.addWidget(self.is_page)), so ~250 lines of UI in InputShaPage are built for nothing. Either route to it:

self.addWidget(self.is_page)
self.up_input_shaper_btn.clicked.connect(lambda: self.change_page(self.indexOf(self.is_page)))

or say in the body that the removal is intended and drop the UI half plus the logic flag.

3. InputShaPage.py:156: is_aut_types never cleared, so the second auto run ends early
On the next run, the X recommendation already sees len == 2, so SAVE_CONFIG fires and the overlay drops while Y is still shaking. This was carried over, but it is a one-liner:

if gcode == "SHAPER_CALIBRATE":
    self.is_aut_types.clear()

4. routinePage.py:346: axis_steps ignores its axes param

for axis in axes:

5. routinePage.py:341: park_x comes from Y's midpoint but is applied to X
If this replaces the old X250, name it and comment why. If the goal is to centre X, middle already does that and the park move can go.

6. routinePage.py:90: back mid-axis-routine re-homes
abort() sends every cleanup, including the axis G28, so a back press starts a homing move (and the overlay from #1). Consider skipping motion cleanups on abort:

if step.cleanup and step.cleanup != "G28" and step.cleanup not in seen:

7. axisMaintPage.py:62: confirm popup shown twice
It is shown right away under the homing overlay, then again after 10s (the old code waited 20s). Drop line 62. A named method reads better than the set-returning lambda:

QtCore.QTimer.singleShot(10000, self._on_homed)

def _on_homed(self) -> None:
    self.call_load_panel.emit(False, "", False)
    self.answerPage.show()

Nit: initialise self.current_object: str | None = None in __init__.

8. ledsPage.py:81: update_led_values can KeyError
self.leds[str(self.current_led)] fails when current_led is None or the object list refreshed (the old code guarded this). Match set_led_state:

if (led_state := self.leds.get(str(self.current_led))) is None:
    return

9. InputShaPage.py:100: print() in production code
(#213 makes the same print -> logger.warning swap in the old utilitiesTab.handle_gcode_response, so the two will agree.)

_logger.warning("Invalid IS response format: %s", data)

10. utilitiesTab.py:103: axes_back_btn wired twice
AxisMaintPage already emits request_back on the same click, so the change_page lambda is a no-op. Remove lines 103-105.

11. utilitiesTab.py:17: dead code
Process (only AXIS left) is unused. request_available_objects_signal, request_numpad_signal and on_update_message are never emitted or connected here.

12. utilitiesTab.py:184: setupUi -> _setup_ui
Every new page from #315 uses _setup_ui; keep it consistent.

13. utilitiesTab.py:271/294/287: button setup inconsistencies
up_axes_btn and up_input_shaper_btn have no setObjectName. up_update_btn uses setPixmap while its siblings use setProperty("icon_pixmap", ...).

14. utilitiesTab.py:332 / routinePage.py:486: translation contexts
_translate("self", ...) and "controlStackedWidget" (copy-paste).

_translate("utilitiesTab", "Utilities")

15. routinePage.py:261: 60ºC uses º (U+00BA, ordinal)
Should be ° (U+00B0), as the old text had.

16. InputShaPage.py: rename loses history
inputshaperPage.py was deleted and InputShaPage.py added, which breaks blame. Keep the old name, or git mv it first. Deleting inputshaperPage.py gives modify/delete conflicts with #213, #245, #307, #314, #320 and #325 (all mine). InputShaPage already has #213's guards, so I'll resolve them by keeping the delete.

17. Missing docstrings (docstrcov)
InputShaPage.handle_is, routinePage.fan_steps, ledsPage.on_object_list and handle_led_button.

@Robert0Mart
Robert0Mart force-pushed the ref/utilitesTab-stackedWidget branch from 74af6b8 to 7937788 Compare September 24, 2026 16:02
@RobeMartins
RobeMartins force-pushed the ref/utilitesTab-stackedWidget branch from 7937788 to 28619ea Compare September 25, 2026 09:25

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants