Skip to content

refactor: separated control stacked widget into pages - #299

Open
Robert0Mart wants to merge 2 commits into
ref/mainwindow-stackedwidgetfrom
ref/controlTab-stackedWidget
Open

Robert0Mart wants to merge 2 commits into
ref/mainwindow-stackedwidgetfrom
ref/controlTab-stackedWidget

Conversation

@Robert0Mart

Copy link
Copy Markdown
Collaborator

Description

  • Refactor

BlocksScreen/lib/panels/controlTab.py

  • separated its pages into their own Page with logic
  • added setup UI

BlocksScreen/lib/panels/mainWindow.py

  • updated arguments

BlocksScreen/lib/panels/widgets/ControlTab/printcorePage.py

  • moved page

BlocksScreen/lib/panels/widgets/ControlTab/probeHelperPage.py

  • renamed method

BlocksScreen/lib/panels/widgets/ControlTab/axisPage.py
BlocksScreen/lib/panels/widgets/ControlTab/extruderPage.py
BlocksScreen/lib/panels/widgets/ControlTab/fansPage.py
BlocksScreen/lib/panels/widgets/ControlTab/temperaturePage.py

  • ControlTab Pages with their own logic and setup UI

BlocksScreen/lib/ui/controlStackedWidget.ui
BlocksScreen/lib/ui/controlStackedWidget_ui.py

  • deleted unused files after separating pages

@Robert0Mart Robert0Mart added the Refactor Enhancing code's readability, maintainability, and extensibility while addressing technical debt. label Aug 13, 2026
@Robert0Mart
Robert0Mart force-pushed the ref/controlTab-stackedWidget branch from 16f61b6 to 90444fa Compare August 13, 2026 16:27
@Robert0Mart
Robert0Mart requested a review from HugoCLSC August 13, 2026 16:46
@Robert0Mart
Robert0Mart marked this pull request as ready for review August 13, 2026 16:46
@Robert0Mart Robert0Mart mentioned this pull request Aug 13, 2026
1 task
@gmmcosta15

Copy link
Copy Markdown
Collaborator

Two bugs found, both with suggested fixes:

  1. Dead code in AxisPage.on_toolhead_update (lib/panels/widgets/ControlTab/axisPage.py)

if values[0] == "252,50" and values[1] == "250" and values[2] == "50":
self.call_load_panel.emit(False, "", False)

values are floats (per the .2f/.3f formatting right above), so this string comparison never matches. The branch is unreachable. The literals also look like a typo ("252,50" uses a comma).

Suggested fix, using a tolerance instead of exact equality:

import math
...
if (
math.isclose(values[0], 252.50, abs_tol=0.01)
and math.isclose(values[1], 250, abs_tol=0.01)
and math.isclose(values[2], 50, abs_tol=0.01)
):
self.call_load_panel.emit(False, "", False)

  1. Wrong objectName in ExtruderPage._setup_ui (lib/panels/widgets/ControlTab/extruderPage.py)

self.setObjectName("fans_page")

Copy-paste leftover from FansPage, overwrites the "extruder_page" name set in init. Fix:

self.setObjectName("extruder_page")

Rest of the extraction (axis/extruder/temperature/fans logic, signal wiring, create_display_button removal) looks correct.

@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

  • Removes ~8k lines of generated controlStackedWidget.ui/_ui.py, each page now owns its own UI and logic
  • AxisPage, ExtruderPage, FansPage, TemperaturePage talk through signals (request_back, run_gcode_signal), no more reaching into self.panel.*
  • _connect_temp_displays suppresses each disconnect() separately; on dev one failing disconnect skipped the bed one
  • The true-zero reasoning (QGridLayout remembering the old cell) is written down, which saves the next person the investigation
  • CRLF line endings in controlTab.py are preserved, so the diff stays reviewable
  • printcorePage/probeHelperPage moved as pure renames (100%/99% similarity), and the mainWindow consumers are updated

1. ControlTab/extruderPage.py:163: extrude_page becomes an empty orphan window, so the paintEvent refresh never runs
self.extrude_page has no parent. widget.setLayout(self.verticalLayout) (L481) takes its layout and all the child widgets, which leaves extrude_page as an empty hidden top-level widget. So paintEvent L153 self.extrude_page.isVisible() is always False and the label never refreshes. Checked with an offscreen repro.

def _setup_ui(self) -> None:
    self.setObjectName("extruder_page")
    self.verticalLayout = QtWidgets.QVBoxLayout(self)  # no widget, no extrude_page
    ...
def paintEvent(self, a0):
    if self.isVisible():
        self.exp_info_label.setText(self.extrude_page_message)
    return super().paintEvent(a0)

2. widget = QWidget(parent=self) + widget.setLayout(...) in all 4 pages moves the page layout into a fixed-size child
axisPage.py:134/514, fansPage.py:120/208, temperaturePage.py:115/294, extruderPage.py:159/481. Qt moves the layout off the page, so the page stops resizing with the stack and there's one extra widget per page. Put the layout on self and delete widget:

self.verticalLayout = QtWidgets.QVBoxLayout(self)
# delete: widget = QtWidgets.QWidget(parent=self) / widget.setGeometry(...) / widget.setLayout(...)

3. ControlTab/temperaturePage.py:42: numpad is wired before printer_config with limits that don't match
On dev the displays stayed unconnected until config arrived. Here L42 uses 370/120 while the on_printer_config fallbacks are 300/100 (L51/L53). Also secondary_text starts as "", so tapping before the first target update (e.g. Klippy not ready) runs round(float("")) at L67/L76: the tap is swallowed and a crash-log entry is written.

_E_LIMITS, _B_LIMITS = (0, 300), (0, 100)
self._connect_temp_displays(*_E_LIMITS, *_B_LIMITS)
...
round(float(self.extruder_temp_display.secondary_text or 0)),

4. controlTab.py:201: typo "Montion"

self.cp_header_title.setText("Motion")

5. controlTab.py: dead members after the split
L31 request_numpad_signal and L48 request_numpad have no users left (the temperature page emits its own signal straight to on_numpad_request). L75 self.timers = [] is never read.

# delete request_numpad_signal, request_numpad, self.timers

6. controlTab.py:402-435: blank is added/removed in two places, and the docstring says the opposite
The docstring says widgets aren't moved between cells, but L422/L432 and _button_change L235/L282 both call addWidget/removeWidget(self.blank) on every call. Rows are already pinned by setRowMinimumHeight (L588-590). Add it once, then only toggle visibility:

# _setup_ui, same cell as cp_button_5 (hidden widgets take no space)
self.cp_content_layout.addWidget(self.blank, 2, 0, 1, 1)
self.blank.hide()

def _show_blank(self, on: bool) -> None:
    self.blank.setVisible(on)
    self.cp_button_5.setVisible(not on)

Also cut the docstring to one line.

7. controlTab.py:530-612: six copy-pasted button blocks, and their icons/texts get overwritten right away
The placeholder icons (routine, input_shaper, info, LEDs at L554-585) and texts (L605-612) are replaced by showEvent -> _button_change(False). Build the buttons in a loop and keep labels/icons in a table in one place:

self.cp_buttons = [self._grid_button(root, r, c) for r in range(3) for c in range(2)]
_MENU = {
    False: [("Motion\nControl", ":/.../motion.svg", lambda: self._button_change(True)), ...],
    True: [...],
}
for btn, (text, icon, slot) in zip(self.cp_buttons, _MENU[active]):
    btn.setText(text); btn.setPixmap(QtGui.QPixmap(icon)); btn.clicked.connect(slot)

8. controlTab.py: pyuic leftovers
L473 self.resize(710, 410) does nothing on a stacked page, L602 setWindowTitle(..., "StackedWidget"), L169 # # @ object temperature change clicked. The _translate("controlStackedWidget", ...) context now points at a deleted .ui (optional: plain strings or self.tr).

# delete L169, L473, L602

9. ControlTab/axisPage.py:265/317: both button groups are named "extrude_select_length_group"
Copy-paste. Also objectName is set twice (L21 "axis_page", L137 "move_axis_page"; same in extruderPage.py:29/162), and self.update() in __init__ (axisPage L24, extruderPage L33) does nothing before the page is shown.

self.axis_select_length_group.setObjectName("axis_select_length_group")
self.axis_select_speed_group.setObjectName("axis_select_speed_group")

10. ControlTab/extruderPage.py:83/126/139: slot decorators don't match the methods
@pyqtSlot(str) is on handle_extrusion(self, extrude: bool). The toggle slots declare (bool, PyQt_PyObject, int) but take (caller, value), caller is never used, and the docstrings mention checked.

@QtCore.pyqtSlot(bool, name="handle-extrusion")
def handle_extrusion(self, extrude: bool) -> None: ...

for btn, v in ((self.extrude_select_length_10_btn, 10), ...):
    btn.toggled.connect(lambda on, v=v: on and self._set_length(v))

11. ControlTab/extruderPage.py:117-123: self.timers grows by one QTimer per extrude press
Timers are appended and never removed, and an earlier timer can set "Ready" in the middle of a later move. Use one restartable timer:

self._ready_timer = QtCore.QTimer(self, singleShot=True)
self._ready_timer.timeout.connect(lambda: self.exp_info_label.setText("Ready"))
...
self._ready_timer.start(int(self.extrude_length / self.extrude_feedrate + 2) * 1000)

12. ControlTab/fansPage.py:82-88: dead branch and a value that gets overwritten
hasattr(card, "continue_clicked") is always true (it's a class signal). If it ever failed, del card only drops the name and the widget stays in fans_content_layout (added at L80). L88 f"{new_value}%" is overwritten by L104-105. The L113 docstring says 0-255, but the slider is 0-100.

card = OptionCard(self, name, name, icon)
card.setObjectName(name)
self.fans_content_layout.addWidget(card)
card.setMode(True)
card.continue_clicked.connect(...)

13. Signal names differ between the new pages
FansPage.request_back_button vs request_back on the other three, and ExtruderPage names its gcode signal "run_gcode" while the rest use "run-gcode". Pick one of each:

request_back = QtCore.pyqtSignal(name="request-back")
run_gcode_signal = QtCore.pyqtSignal(str, name="run-gcode")

14. Orphans to clean up
lib/ui/fansPage.ui and lib/ui/fansPage_ui.py have no importers (already orphaned on dev; this PR deletes the last related module). tests/widgets/test_slider_page_request_unit.py:39/44 still mentions controlStackedWidget_ui.

git rm BlocksScreen/lib/ui/fansPage.ui BlocksScreen/lib/ui/fansPage_ui.py

@RobeMartins
RobeMartins force-pushed the ref/controlTab-stackedWidget branch from be8cbfe to fd6202f Compare September 24, 2026 14:15

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

Refactor Enhancing code's readability, maintainability, and extensibility while addressing technical debt.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants