From 49294030cee4f2bff19cce5cd6e37f7125d1bbe2 Mon Sep 17 00:00:00 2001 From: Roberto Date: Tue, 27 Jan 2026 14:37:55 +0000 Subject: [PATCH 1/6] Feat: added cancel page --- BlocksScreen/lib/panels/mainWindow.py | 48 ++++ BlocksScreen/lib/panels/printTab.py | 4 + BlocksScreen/lib/panels/widgets/cancelPage.py | 229 ++++++++++++++++++ .../lib/panels/widgets/jobStatusPage.py | 1 - 4 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 BlocksScreen/lib/panels/widgets/cancelPage.py diff --git a/BlocksScreen/lib/panels/mainWindow.py b/BlocksScreen/lib/panels/mainWindow.py index 32355803..9eb651d7 100644 --- a/BlocksScreen/lib/panels/mainWindow.py +++ b/BlocksScreen/lib/panels/mainWindow.py @@ -13,6 +13,7 @@ from lib.panels.printTab import PrintTab from lib.panels.utilitiesTab import UtilitiesTab from lib.panels.widgets.connectionPage import ConnectionPage +from lib.panels.widgets.cancelPage import CancelPage from lib.panels.widgets.popupDialogWidget import Popup from lib.printer import Printer from lib.ui.mainWindow_ui import Ui_MainWindow # With header @@ -65,6 +66,9 @@ class MainWindow(QtWidgets.QMainWindow): on_update_message: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( dict, name="on-update-message" ) + run_gcode_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="run_gcode" + ) call_load_panel = QtCore.pyqtSignal(bool, str, name="call-load-panel") def __init__(self): @@ -84,6 +88,17 @@ def __init__(self): self.conn_window = ConnectionPage(self, self.ws) self.up = UpdatePage(self) self.up.hide() + + self.cancelpage = CancelPage(self) + self.cancelpage.hide() + self.cancelpage.confirm_button.clicked.connect( + lambda: self.printPanel.print_start.emit( + self.printPanel.jobStatusPage_widget._current_file_name + ) + ) + self.cancelpage.refuse_button.clicked.connect( + lambda: self.handle_cancel_print(False) + ) self.installEventFilter(self.conn_window) self.printPanel = PrintTab( self.ui.printTab, self.file_data, self.ws, self.printer @@ -152,6 +167,8 @@ def __init__(self): self.query_object_list.connect(self.utilitiesPanel.on_object_list) self.printer.extruder_update.connect(self.on_extruder_update) self.printer.heater_bed_update.connect(self.on_heater_bed_update) + self.run_gcode_signal.connect(self.ws.api.run_gcode) + self.ui.main_content_widget.currentChanged.connect(slot=self.reset_tab_indexes) self.call_network_panel.connect(self.networkPanel.show_network_panel) self.conn_window.wifi_button_clicked.connect(self.call_network_panel.emit) @@ -196,6 +213,35 @@ def __init__(self): self.bo_ws_startup.emit() self.reset_tab_indexes() + def handle_cancel_print(self, show: bool = True): + """Slot for displaying update Panel""" + if not show: + self.cancelpage.hide() + self.run_gcode_signal.emit("SDCARD_RESET_FILE") + return + + self.cancelpage.setParent(self) + self.cancelpage.setGeometry(0, 0, self.width(), self.height()) + + self.cancelpage.raise_() + self.cancelpage.updateGeometry() + self.cancelpage.repaint() + self.cancelpage.show() + + thumbnails = self.printPanel.jobStatusPage_widget.thumbnail_graphics + last_thumb = ( + thumbnails[-1] + if len(thumbnails) > 0 + else QtGui.QPixmap( + "BlocksScreen/lib/ui/resources/media/logoblocks400x300.png" + ) + ) + self.cancelpage.set_file_name( + self.printPanel.jobStatusPage_widget._current_file_name + ) + print("ASKHJDGAS") + self.cancelpage.set_pixmap(last_thumb) + @QtCore.pyqtSlot(bool, str, name="show-load-page") def show_LoadScreen(self, show: bool = True, msg: str = ""): _sender = self.sender() @@ -734,6 +780,8 @@ def event(self, event: QtCore.QEvent) -> bool: events.PrintComplete.type(), events.PrintCancelled.type(), ): + if event.type() == events.PrintCancelled.type(): + self.handle_cancel_print() self.enable_tab_bar() self.ui.extruder_temp_display.clicked.disconnect() self.ui.bed_temp_display.clicked.disconnect() diff --git a/BlocksScreen/lib/panels/printTab.py b/BlocksScreen/lib/panels/printTab.py index 7431938e..960f2b30 100644 --- a/BlocksScreen/lib/panels/printTab.py +++ b/BlocksScreen/lib/panels/printTab.py @@ -64,6 +64,9 @@ class PrintTab(QtWidgets.QStackedWidget): ) call_load_panel = QtCore.pyqtSignal(bool, str, name="call-load-panel") + print_start: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="print_start" + ) _z_offset: float = 0.0 _active_z_offset: float = 0.0 _finish_print_handled: bool = False @@ -144,6 +147,7 @@ def __init__( self.file_data.on_request_fileinfo ) self.file_data.fileinfo.connect(self.jobStatusPage_widget.on_fileinfo) + self.print_start.connect(self.ws.api.start_print) self.jobStatusPage_widget.print_start.connect(self.ws.api.start_print) self.jobStatusPage_widget.print_resume.connect(self.ws.api.resume_print) self.jobStatusPage_widget.print_cancel.connect(self.handle_cancel_print) diff --git a/BlocksScreen/lib/panels/widgets/cancelPage.py b/BlocksScreen/lib/panels/widgets/cancelPage.py new file mode 100644 index 00000000..b2c617f8 --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/cancelPage.py @@ -0,0 +1,229 @@ +from lib.utils.blocks_button import BlocksCustomButton +from lib.utils.blocks_frame import BlocksCustomFrame +from lib.utils.icon_button import IconButton +from lib.utils.blocks_label import BlocksLabel +from PyQt6 import QtCore, QtGui, QtWidgets + + +class CancelPage(QtWidgets.QWidget): + """Update GUI Page, + retrieves from moonraker available clients and adds functionality + for updating or recovering them + """ + + def __init__(self, parent=None) -> None: + if parent: + super().__init__(parent) + else: + super().__init__() + self._setupUI() + self.confirm_button.clicked.connect(self.hide) + self.refuse_button.clicked.connect(self.hide) + self.setAttribute(QtCore.Qt.WidgetAttribute.WA_StyledBackground, True) + + def set_pixmap(self, pixmap: QtGui.QPixmap) -> None: + if not hasattr(self, "_scene"): + self._scene = QtWidgets.QGraphicsScene(self) + self.cf_thumbnail.setScene(self._scene) + + # Scene rectangle (available display area) + graphics_rect = self.cf_thumbnail.rect().toRectF() + + # Scale pixmap preserving aspect ratio + pixmap = pixmap.scaled( + graphics_rect.size().toSize(), + QtCore.Qt.AspectRatioMode.KeepAspectRatio, + QtCore.Qt.TransformationMode.SmoothTransformation, + ) + + adjusted_x = (graphics_rect.width() - pixmap.width()) / 2.0 + adjusted_y = (graphics_rect.height() - pixmap.height()) / 2.0 + + if not hasattr(self, "_pixmap_item"): + self._pixmap_item = QtWidgets.QGraphicsPixmapItem(pixmap) + self._scene.addItem(self._pixmap_item) + else: + self._pixmap_item.setPixmap(pixmap) + + self._pixmap_item.setPos(adjusted_x, adjusted_y) + self._scene.setSceneRect(graphics_rect) + + def set_file_name(self, file_name: str) -> None: + self.cf_file_name.setText(file_name) + + def _setupUI(self) -> None: + """Setup widget ui""" + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + ) + sizePolicy.setHorizontalStretch(1) + sizePolicy.setVerticalStretch(1) + sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) + self.setSizePolicy(sizePolicy) + self.setObjectName("cancelPage") + self.setStyleSheet( + """#cancelPage { + background-image: url(:/background/media/1st_background.png); + }""" + ) + self.setMinimumSize(QtCore.QSize(800, 480)) + self.setMaximumSize(QtCore.QSize(800, 480)) + self.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.cf_header_title = QtWidgets.QHBoxLayout() + self.cf_header_title.setObjectName("cf_header_title") + + self.spacer = QtWidgets.QSpacerItem( + 60, + 60, + QtWidgets.QSizePolicy.Policy.Fixed, + QtWidgets.QSizePolicy.Policy.Fixed, + ) + self.spacer.setGeometry(QtCore.QRect(0, 0, 60, 60)) + self.cf_header_title.addItem(self.spacer) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + self.cf_file_name = BlocksLabel(parent=self) + self.cf_file_name.setMinimumSize(QtCore.QSize(0, 60)) + self.cf_file_name.setMaximumSize(QtCore.QSize(16777215, 60)) + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + self.cf_file_name.setFont(font) + self.cf_file_name.setLayoutDirection(QtCore.Qt.LayoutDirection.RightToLeft) + self.cf_file_name.setSizePolicy(sizePolicy) + self.cf_file_name.setStyleSheet("background: transparent; color: white;") + self.cf_file_name.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.cf_file_name.setObjectName("cf_file_name") + self.cf_header_title.addWidget(self.cf_file_name) + + self.back_btn = IconButton(self) + self.back_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.back_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.back_btn.setFlat(True) + self.back_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") + ) + self.cf_header_title.addWidget( + self.back_btn, 0, QtCore.Qt.AlignmentFlag.AlignLeft + ) + + self.verticalLayout_4.addLayout(self.cf_header_title) + self.cf_content_vertical_layout = QtWidgets.QHBoxLayout() + self.cf_content_vertical_layout.setObjectName("cf_content_vertical_layout") + self.cf_content_horizontal_layout = QtWidgets.QVBoxLayout() + self.cf_content_horizontal_layout.setObjectName("cf_content_horizontal_layout") + self.info_frame = BlocksCustomFrame(parent=self) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + self.info_frame.setSizePolicy(sizePolicy) + + self.info_frame.setFrameShadow(QtWidgets.QFrame.Shadow.Raised) + + self.info_layout = QtWidgets.QVBoxLayout(self.info_frame) + + self.cf_info_tf = QtWidgets.QLabel(parent=self.info_frame) + self.cf_info_tf.setText("Print job was\ncancelled") + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(20) + + self.cf_info_tf.setFont(font) + self.cf_info_tf.setStyleSheet("background: transparent; color: white;") + + self.cf_info_tf.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.info_layout.addWidget(self.cf_info_tf) + + self.cf_info_tr = QtWidgets.QLabel(parent=self.info_frame) + font = QtGui.QFont() + font.setPointSize(15) + self.cf_info_tr.setFont(font) + self.cf_info_tr.setStyleSheet("background: transparent; color: white;") + self.cf_info_tr.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.cf_info_tr.setText("Do you want to reprint?") + self.info_layout.addWidget(self.cf_info_tr) + + self.cf_confirm_layout = QtWidgets.QVBoxLayout() + self.cf_confirm_layout.setSpacing(15) + + self.confirm_button = BlocksCustomButton(parent=self.info_frame) + self.confirm_button.setMinimumSize(QtCore.QSize(250, 70)) + self.confirm_button.setMaximumSize(QtCore.QSize(250, 70)) + font = QtGui.QFont("Momcake", 18) + self.confirm_button.setFont(font) + self.confirm_button.setFlat(True) + self.confirm_button.setProperty( + "icon_pixmap", QtGui.QPixmap(":/dialog/media/btn_icons/yes.svg") + ) + self.confirm_button.setText("Reprint") + # 2. Align buttons to the right + self.cf_confirm_layout.addWidget( + self.confirm_button, 0, QtCore.Qt.AlignmentFlag.AlignCenter + ) + + self.refuse_button = BlocksCustomButton(parent=self.info_frame) + self.refuse_button.setMinimumSize(QtCore.QSize(250, 70)) + self.refuse_button.setMaximumSize(QtCore.QSize(250, 70)) + self.refuse_button.setFont(font) + self.refuse_button.setFlat(True) + self.refuse_button.setProperty( + "icon_pixmap", QtGui.QPixmap(":/dialog/media/btn_icons/no.svg") + ) + self.refuse_button.setText("Ignore") + # 2. Align buttons to the right + self.cf_confirm_layout.addWidget( + self.refuse_button, 0, QtCore.Qt.AlignmentFlag.AlignCenter + ) + + self.info_layout.addLayout(self.cf_confirm_layout) + + self.cf_content_horizontal_layout.addWidget(self.info_frame) + + self.cf_content_vertical_layout.addLayout(self.cf_content_horizontal_layout) + self.cf_thumbnail = QtWidgets.QGraphicsView(self) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + sizePolicy.setHorizontalStretch(1) + sizePolicy.setVerticalStretch(1) + sizePolicy.setHeightForWidth(self.cf_thumbnail.sizePolicy().hasHeightForWidth()) + self.cf_thumbnail.setSizePolicy(sizePolicy) + self.cf_thumbnail.setMinimumSize(QtCore.QSize(400, 300)) + self.cf_thumbnail.setMaximumSize(QtCore.QSize(400, 300)) + self.cf_thumbnail.setStyleSheet( + "QGraphicsView{\nbackground-color: transparent;\n}" + ) + self.cf_thumbnail.setFrameShape(QtWidgets.QFrame.Shape.NoFrame) + self.cf_thumbnail.setFrameShadow(QtWidgets.QFrame.Shadow.Plain) + self.cf_thumbnail.setVerticalScrollBarPolicy( + QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff + ) + self.cf_thumbnail.setHorizontalScrollBarPolicy( + QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff + ) + self.cf_thumbnail.setSizeAdjustPolicy( + QtWidgets.QAbstractScrollArea.SizeAdjustPolicy.AdjustIgnored + ) + brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 0)) + brush.setStyle(QtCore.Qt.BrushStyle.NoBrush) + self.cf_thumbnail.setBackgroundBrush(brush) + self.cf_thumbnail.setRenderHints( + QtGui.QPainter.RenderHint.Antialiasing + | QtGui.QPainter.RenderHint.SmoothPixmapTransform + | QtGui.QPainter.RenderHint.TextAntialiasing + ) + self.cf_thumbnail.setViewportUpdateMode( + QtWidgets.QGraphicsView.ViewportUpdateMode.SmartViewportUpdate + ) + self.cf_thumbnail.setObjectName("cf_thumbnail") + self.cf_content_vertical_layout.addWidget( + self.cf_thumbnail, 0, QtCore.Qt.AlignmentFlag.AlignCenter + ) + self.verticalLayout_4.addLayout(self.cf_content_vertical_layout) diff --git a/BlocksScreen/lib/panels/widgets/jobStatusPage.py b/BlocksScreen/lib/panels/widgets/jobStatusPage.py index bd5bbb8c..8ae9161d 100644 --- a/BlocksScreen/lib/panels/widgets/jobStatusPage.py +++ b/BlocksScreen/lib/panels/widgets/jobStatusPage.py @@ -230,7 +230,6 @@ def _handle_print_state(self, state: str) -> None: elif lstate in invalid_states: if lstate != "standby": self.print_finish.emit() - self._current_file_name = "" self._internal_print_status = "" self.total_layers = "?" self.file_metadata.clear() From d3ede5d9b23b251eb68d6199f7e543f35b4da022 Mon Sep 17 00:00:00 2001 From: Roberto Date: Tue, 27 Jan 2026 14:45:09 +0000 Subject: [PATCH 2/6] Rev: removed back button --- BlocksScreen/lib/panels/widgets/cancelPage.py | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/BlocksScreen/lib/panels/widgets/cancelPage.py b/BlocksScreen/lib/panels/widgets/cancelPage.py index b2c617f8..bafd8cb4 100644 --- a/BlocksScreen/lib/panels/widgets/cancelPage.py +++ b/BlocksScreen/lib/panels/widgets/cancelPage.py @@ -1,6 +1,5 @@ from lib.utils.blocks_button import BlocksCustomButton from lib.utils.blocks_frame import BlocksCustomFrame -from lib.utils.icon_button import IconButton from lib.utils.blocks_label import BlocksLabel from PyQt6 import QtCore, QtGui, QtWidgets @@ -75,14 +74,6 @@ def _setupUI(self) -> None: self.cf_header_title = QtWidgets.QHBoxLayout() self.cf_header_title.setObjectName("cf_header_title") - self.spacer = QtWidgets.QSpacerItem( - 60, - 60, - QtWidgets.QSizePolicy.Policy.Fixed, - QtWidgets.QSizePolicy.Policy.Fixed, - ) - self.spacer.setGeometry(QtCore.QRect(0, 0, 60, 60)) - self.cf_header_title.addItem(self.spacer) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding, @@ -101,17 +92,6 @@ def _setupUI(self) -> None: self.cf_file_name.setObjectName("cf_file_name") self.cf_header_title.addWidget(self.cf_file_name) - self.back_btn = IconButton(self) - self.back_btn.setMinimumSize(QtCore.QSize(60, 60)) - self.back_btn.setMaximumSize(QtCore.QSize(60, 60)) - self.back_btn.setFlat(True) - self.back_btn.setProperty( - "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") - ) - self.cf_header_title.addWidget( - self.back_btn, 0, QtCore.Qt.AlignmentFlag.AlignLeft - ) - self.verticalLayout_4.addLayout(self.cf_header_title) self.cf_content_vertical_layout = QtWidgets.QHBoxLayout() self.cf_content_vertical_layout.setObjectName("cf_content_vertical_layout") From b1eb1c35dc0fb55028d7ce13da4fda111d34e2ae Mon Sep 17 00:00:00 2001 From: Roberto Date: Tue, 27 Jan 2026 15:25:58 +0000 Subject: [PATCH 3/6] add: hides cancel page --- BlocksScreen/lib/panels/mainWindow.py | 31 ++++++++++++------- BlocksScreen/lib/panels/printTab.py | 3 ++ .../lib/panels/widgets/connectionPage.py | 2 ++ .../lib/panels/widgets/jobStatusPage.py | 6 ++-- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/BlocksScreen/lib/panels/mainWindow.py b/BlocksScreen/lib/panels/mainWindow.py index 9eb651d7..cc1fbdb6 100644 --- a/BlocksScreen/lib/panels/mainWindow.py +++ b/BlocksScreen/lib/panels/mainWindow.py @@ -89,16 +89,7 @@ def __init__(self): self.up = UpdatePage(self) self.up.hide() - self.cancelpage = CancelPage(self) - self.cancelpage.hide() - self.cancelpage.confirm_button.clicked.connect( - lambda: self.printPanel.print_start.emit( - self.printPanel.jobStatusPage_widget._current_file_name - ) - ) - self.cancelpage.refuse_button.clicked.connect( - lambda: self.handle_cancel_print(False) - ) + self.conn_window.call_cancel_panel.connect(self.handle_cancel_print) self.installEventFilter(self.conn_window) self.printPanel = PrintTab( self.ui.printTab, self.file_data, self.ws, self.printer @@ -208,16 +199,33 @@ def __init__(self): self, LoadingOverlayWidget.AnimationGIF.DEFAULT ) self.loadscreen.add_widget(self.loadwidget) + + self.cancelpage = CancelPage(self) + self.cancelpage.hide() + self.cancelpage.confirm_button.clicked.connect( + lambda: self.printPanel.print_start.emit( + self.printPanel.jobStatusPage_widget._current_file_name + ) + ) + self.cancelpage.refuse_button.clicked.connect( + lambda: self.run_gcode_signal.emit("SDCARD_RESET_FILE") + ) + self.cancelpage.refuse_button.clicked.connect( + lambda: self.handle_cancel_print(False) + ) + + self.printPanel.call_cancel_panel.connect(self.handle_cancel_print) + if self.config.has_section("server"): # @ Start websocket connection with moonraker self.bo_ws_startup.emit() self.reset_tab_indexes() + @QtCore.pyqtSlot(bool, name="show-cancel-page") def handle_cancel_print(self, show: bool = True): """Slot for displaying update Panel""" if not show: self.cancelpage.hide() - self.run_gcode_signal.emit("SDCARD_RESET_FILE") return self.cancelpage.setParent(self) @@ -239,7 +247,6 @@ def handle_cancel_print(self, show: bool = True): self.cancelpage.set_file_name( self.printPanel.jobStatusPage_widget._current_file_name ) - print("ASKHJDGAS") self.cancelpage.set_pixmap(last_thumb) @QtCore.pyqtSlot(bool, str, name="show-load-page") diff --git a/BlocksScreen/lib/panels/printTab.py b/BlocksScreen/lib/panels/printTab.py index 960f2b30..14e3b77e 100644 --- a/BlocksScreen/lib/panels/printTab.py +++ b/BlocksScreen/lib/panels/printTab.py @@ -67,6 +67,7 @@ class PrintTab(QtWidgets.QStackedWidget): print_start: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( str, name="print_start" ) + call_cancel_panel = QtCore.pyqtSignal(bool, name="call-load-panel") _z_offset: float = 0.0 _active_z_offset: float = 0.0 _finish_print_handled: bool = False @@ -127,6 +128,7 @@ def __init__( self.file_data.request_file_list ) self.file_data.on_dirs.connect(self.filesPage_widget.on_directories) + self.filesPage_widget.request_dir_info[str].connect( self.file_data.request_dir_info[str] ) @@ -140,6 +142,7 @@ def __init__( self.jobStatusPage_widget.show_request.connect( lambda: self.change_page(self.indexOf(self.jobStatusPage_widget)) ) + self.jobStatusPage_widget.call_cancel_panel.connect(self.call_cancel_panel) self.jobStatusPage_widget.hide_request.connect( lambda: self.change_page(self.indexOf(self.print_page)) ) diff --git a/BlocksScreen/lib/panels/widgets/connectionPage.py b/BlocksScreen/lib/panels/widgets/connectionPage.py index 9403d290..a03e42dd 100644 --- a/BlocksScreen/lib/panels/widgets/connectionPage.py +++ b/BlocksScreen/lib/panels/widgets/connectionPage.py @@ -15,6 +15,7 @@ class ConnectionPage(QtWidgets.QFrame): firmware_restart_clicked = QtCore.pyqtSignal(name="firmware_restart_clicked") update_button_clicked = QtCore.pyqtSignal(bool, name="show-update-page") call_load_panel = QtCore.pyqtSignal(bool, str, name="call-load-panel") + call_cancel_panel = QtCore.pyqtSignal(bool, name="call-load-panel") def __init__(self, parent: QtWidgets.QWidget, ws: MoonWebSocket, /): super().__init__(parent) @@ -67,6 +68,7 @@ def showEvent(self, a0: QtCore.QEvent | None): """Handle show event""" self.ws.api.refresh_update_status() self.call_load_panel.emit(False, "") + self.call_cancel_panel.emit(False) return super().showEvent(a0) @QtCore.pyqtSlot(bool, name="on_klippy_connected") diff --git a/BlocksScreen/lib/panels/widgets/jobStatusPage.py b/BlocksScreen/lib/panels/widgets/jobStatusPage.py index 8ae9161d..63468efb 100644 --- a/BlocksScreen/lib/panels/widgets/jobStatusPage.py +++ b/BlocksScreen/lib/panels/widgets/jobStatusPage.py @@ -53,6 +53,7 @@ class JobStatusWidget(QtWidgets.QWidget): request_file_info: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( str, name="request_file_info" ) + call_cancel_panel = QtCore.pyqtSignal(bool, name="call-load-panel") _internal_print_status: str = "" _current_file_name: str = "" @@ -225,6 +226,7 @@ def _handle_print_state(self, state: str) -> None: ) self.pause_printing_btn.setEnabled(True) self.request_query_print_stats.emit({"print_stats": ["filename"]}) + self.call_cancel_panel.emit(False) self.show_request.emit() lstate = "start" elif lstate in invalid_states: @@ -234,8 +236,8 @@ def _handle_print_state(self, state: str) -> None: self.total_layers = "?" self.file_metadata.clear() self.hide_request.emit() - if hasattr(self, "thumbnail_view"): - getattr(self, "thumbnail_view").deleteLater() + # if hasattr(self, "thumbnail_view"): + # getattr(self, "thumbnail_view").deleteLater() # Send Event on Print state if hasattr(events, str("Print" + lstate.capitalize())): event_obj = getattr(events, str("Print" + lstate.capitalize())) From 621880731b192049fc45e20701805fad8785830f Mon Sep 17 00:00:00 2001 From: Roberto Date: Thu, 29 Jan 2026 16:34:36 +0000 Subject: [PATCH 4/6] Refactor: removed cancel page connection to printtab --- BlocksScreen/lib/panels/mainWindow.py | 35 ++++--------------- BlocksScreen/lib/panels/printTab.py | 4 --- .../lib/panels/widgets/jobStatusPage.py | 1 + 3 files changed, 8 insertions(+), 32 deletions(-) diff --git a/BlocksScreen/lib/panels/mainWindow.py b/BlocksScreen/lib/panels/mainWindow.py index cc1fbdb6..5dcecf43 100644 --- a/BlocksScreen/lib/panels/mainWindow.py +++ b/BlocksScreen/lib/panels/mainWindow.py @@ -200,20 +200,13 @@ def __init__(self): ) self.loadscreen.add_widget(self.loadwidget) - self.cancelpage = CancelPage(self) - self.cancelpage.hide() - self.cancelpage.confirm_button.clicked.connect( - lambda: self.printPanel.print_start.emit( - self.printPanel.jobStatusPage_widget._current_file_name - ) - ) - self.cancelpage.refuse_button.clicked.connect( - lambda: self.run_gcode_signal.emit("SDCARD_RESET_FILE") - ) - self.cancelpage.refuse_button.clicked.connect( - lambda: self.handle_cancel_print(False) - ) - + self.cancelpage = CancelPage(self,ws=self.ws) + self.cancelpage.request_file_info.connect(self.file_data.on_request_fileinfo) + self.cancelpage.run_gcode.connect(self.ws.api.run_gcode) + self.printer.print_stats_update[str, str].connect(self.cancelpage.on_print_stats_update) + self.printer.print_stats_update[str, dict].connect(self.cancelpage.on_print_stats_update) + self.printer.print_stats_update[str, float].connect(self.cancelpage.on_print_stats_update) + self.file_data.fileinfo.connect(self.cancelpage._show_screen_thumbnail) self.printPanel.call_cancel_panel.connect(self.handle_cancel_print) if self.config.has_section("server"): @@ -228,26 +221,12 @@ def handle_cancel_print(self, show: bool = True): self.cancelpage.hide() return - self.cancelpage.setParent(self) self.cancelpage.setGeometry(0, 0, self.width(), self.height()) - self.cancelpage.raise_() self.cancelpage.updateGeometry() self.cancelpage.repaint() self.cancelpage.show() - thumbnails = self.printPanel.jobStatusPage_widget.thumbnail_graphics - last_thumb = ( - thumbnails[-1] - if len(thumbnails) > 0 - else QtGui.QPixmap( - "BlocksScreen/lib/ui/resources/media/logoblocks400x300.png" - ) - ) - self.cancelpage.set_file_name( - self.printPanel.jobStatusPage_widget._current_file_name - ) - self.cancelpage.set_pixmap(last_thumb) @QtCore.pyqtSlot(bool, str, name="show-load-page") def show_LoadScreen(self, show: bool = True, msg: str = ""): diff --git a/BlocksScreen/lib/panels/printTab.py b/BlocksScreen/lib/panels/printTab.py index 14e3b77e..b28e52bd 100644 --- a/BlocksScreen/lib/panels/printTab.py +++ b/BlocksScreen/lib/panels/printTab.py @@ -64,9 +64,6 @@ class PrintTab(QtWidgets.QStackedWidget): ) call_load_panel = QtCore.pyqtSignal(bool, str, name="call-load-panel") - print_start: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( - str, name="print_start" - ) call_cancel_panel = QtCore.pyqtSignal(bool, name="call-load-panel") _z_offset: float = 0.0 _active_z_offset: float = 0.0 @@ -150,7 +147,6 @@ def __init__( self.file_data.on_request_fileinfo ) self.file_data.fileinfo.connect(self.jobStatusPage_widget.on_fileinfo) - self.print_start.connect(self.ws.api.start_print) self.jobStatusPage_widget.print_start.connect(self.ws.api.start_print) self.jobStatusPage_widget.print_resume.connect(self.ws.api.resume_print) self.jobStatusPage_widget.print_cancel.connect(self.handle_cancel_print) diff --git a/BlocksScreen/lib/panels/widgets/jobStatusPage.py b/BlocksScreen/lib/panels/widgets/jobStatusPage.py index 63468efb..f868c222 100644 --- a/BlocksScreen/lib/panels/widgets/jobStatusPage.py +++ b/BlocksScreen/lib/panels/widgets/jobStatusPage.py @@ -233,6 +233,7 @@ def _handle_print_state(self, state: str) -> None: if lstate != "standby": self.print_finish.emit() self._internal_print_status = "" + self._current_file_name = "" self.total_layers = "?" self.file_metadata.clear() self.hide_request.emit() From c2f0c5b37e9784b667b411e0b875ae282d3bc2ac Mon Sep 17 00:00:00 2001 From: Roberto Date: Thu, 29 Jan 2026 16:35:00 +0000 Subject: [PATCH 5/6] ADD: added logic to cancelPage --- BlocksScreen/lib/panels/widgets/cancelPage.py | 76 +++++++++++++++++-- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/BlocksScreen/lib/panels/widgets/cancelPage.py b/BlocksScreen/lib/panels/widgets/cancelPage.py index bafd8cb4..e426d720 100644 --- a/BlocksScreen/lib/panels/widgets/cancelPage.py +++ b/BlocksScreen/lib/panels/widgets/cancelPage.py @@ -2,24 +2,68 @@ from lib.utils.blocks_frame import BlocksCustomFrame from lib.utils.blocks_label import BlocksLabel from PyQt6 import QtCore, QtGui, QtWidgets +import typing +from lib.moonrakerComm import MoonWebSocket class CancelPage(QtWidgets.QWidget): """Update GUI Page, retrieves from moonraker available clients and adds functionality for updating or recovering them """ + request_file_info: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="request_file_info" + ) + reprint_start: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="reprint_start" + ) + run_gcode: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="run_gcode" + ) - def __init__(self, parent=None) -> None: - if parent: - super().__init__(parent) - else: - super().__init__() + def __init__(self, parent: QtWidgets.QWidget , ws: MoonWebSocket) -> None: + super().__init__(parent) + self.ws: MoonWebSocket = ws self._setupUI() - self.confirm_button.clicked.connect(self.hide) - self.refuse_button.clicked.connect(self.hide) + self.filename = "" + + self.reprint_start.connect(self.ws.api.start_print) + + self.confirm_button.clicked.connect(lambda: self._handle_accept()) + + self.refuse_button.clicked.connect(lambda: self._handle_refuse()) + self.setAttribute(QtCore.Qt.WidgetAttribute.WA_StyledBackground, True) + def _handle_accept(self): + self.run_gcode.emit("SDCARD_RESET_FILE") + self.reprint_start.emit(self.filename) + self.close() + + + def _handle_refuse(self): + self.close() + self.run_gcode.emit("SDCARD_RESET_FILE") + + + @QtCore.pyqtSlot(str, dict, name="on_print_stats_update") + @QtCore.pyqtSlot(str, float, name="on_print_stats_update") + @QtCore.pyqtSlot(str, str, name="on_print_stats_update") + def on_print_stats_update(self, field: str, value: dict | float | str) -> None: + if isinstance(value, str): + if "filename" in field: + self.filename = value + if self.isVisible: + self.set_file_name(value) + + + def show(self): + self.request_file_info.emit(self.filename) + + super().show() + + + def set_pixmap(self, pixmap: QtGui.QPixmap) -> None: if not hasattr(self, "_scene"): self._scene = QtWidgets.QGraphicsScene(self) @@ -50,6 +94,24 @@ def set_pixmap(self, pixmap: QtGui.QPixmap) -> None: def set_file_name(self, file_name: str) -> None: self.cf_file_name.setText(file_name) + + def _show_screen_thumbnail(self,dict): + try: + thumbnails = dict["thumbnail_images"] + + last_thumb = (QtGui.QPixmap.fromImage(thumbnails[-1])) + + if last_thumb.isNull(): + last_thumb = QtGui.QPixmap( + "BlocksScreen/lib/ui/resources/media/logoblocks400x300.png" + ) + except Exception as e: + print(e) + last_thumb = QtGui.QPixmap( + "BlocksScreen/lib/ui/resources/media/logoblocks400x300.png" + ) + self.set_pixmap(last_thumb) + def _setupUI(self) -> None: """Setup widget ui""" sizePolicy = QtWidgets.QSizePolicy( From 478bb8924bf6f7ef2fab12a223107dde8f17eb0c Mon Sep 17 00:00:00 2001 From: Roberto Date: Thu, 29 Jan 2026 16:43:10 +0000 Subject: [PATCH 6/6] refactor: ran ruff formatter --- BlocksScreen/lib/panels/mainWindow.py | 15 ++++++++++----- BlocksScreen/lib/panels/widgets/cancelPage.py | 16 ++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/BlocksScreen/lib/panels/mainWindow.py b/BlocksScreen/lib/panels/mainWindow.py index 5dcecf43..66f792de 100644 --- a/BlocksScreen/lib/panels/mainWindow.py +++ b/BlocksScreen/lib/panels/mainWindow.py @@ -200,12 +200,18 @@ def __init__(self): ) self.loadscreen.add_widget(self.loadwidget) - self.cancelpage = CancelPage(self,ws=self.ws) + self.cancelpage = CancelPage(self, ws=self.ws) self.cancelpage.request_file_info.connect(self.file_data.on_request_fileinfo) self.cancelpage.run_gcode.connect(self.ws.api.run_gcode) - self.printer.print_stats_update[str, str].connect(self.cancelpage.on_print_stats_update) - self.printer.print_stats_update[str, dict].connect(self.cancelpage.on_print_stats_update) - self.printer.print_stats_update[str, float].connect(self.cancelpage.on_print_stats_update) + self.printer.print_stats_update[str, str].connect( + self.cancelpage.on_print_stats_update + ) + self.printer.print_stats_update[str, dict].connect( + self.cancelpage.on_print_stats_update + ) + self.printer.print_stats_update[str, float].connect( + self.cancelpage.on_print_stats_update + ) self.file_data.fileinfo.connect(self.cancelpage._show_screen_thumbnail) self.printPanel.call_cancel_panel.connect(self.handle_cancel_print) @@ -227,7 +233,6 @@ def handle_cancel_print(self, show: bool = True): self.cancelpage.repaint() self.cancelpage.show() - @QtCore.pyqtSlot(bool, str, name="show-load-page") def show_LoadScreen(self, show: bool = True, msg: str = ""): _sender = self.sender() diff --git a/BlocksScreen/lib/panels/widgets/cancelPage.py b/BlocksScreen/lib/panels/widgets/cancelPage.py index e426d720..e16fb2e6 100644 --- a/BlocksScreen/lib/panels/widgets/cancelPage.py +++ b/BlocksScreen/lib/panels/widgets/cancelPage.py @@ -6,11 +6,13 @@ from lib.moonrakerComm import MoonWebSocket + class CancelPage(QtWidgets.QWidget): """Update GUI Page, retrieves from moonraker available clients and adds functionality for updating or recovering them """ + request_file_info: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( str, name="request_file_info" ) @@ -21,7 +23,7 @@ class CancelPage(QtWidgets.QWidget): str, name="run_gcode" ) - def __init__(self, parent: QtWidgets.QWidget , ws: MoonWebSocket) -> None: + def __init__(self, parent: QtWidgets.QWidget, ws: MoonWebSocket) -> None: super().__init__(parent) self.ws: MoonWebSocket = ws self._setupUI() @@ -39,12 +41,10 @@ def _handle_accept(self): self.run_gcode.emit("SDCARD_RESET_FILE") self.reprint_start.emit(self.filename) self.close() - def _handle_refuse(self): self.close() self.run_gcode.emit("SDCARD_RESET_FILE") - @QtCore.pyqtSlot(str, dict, name="on_print_stats_update") @QtCore.pyqtSlot(str, float, name="on_print_stats_update") @@ -56,13 +56,10 @@ def on_print_stats_update(self, field: str, value: dict | float | str) -> None: if self.isVisible: self.set_file_name(value) - def show(self): self.request_file_info.emit(self.filename) - - super().show() - + super().show() def set_pixmap(self, pixmap: QtGui.QPixmap) -> None: if not hasattr(self, "_scene"): @@ -94,12 +91,11 @@ def set_pixmap(self, pixmap: QtGui.QPixmap) -> None: def set_file_name(self, file_name: str) -> None: self.cf_file_name.setText(file_name) - - def _show_screen_thumbnail(self,dict): + def _show_screen_thumbnail(self, dict): try: thumbnails = dict["thumbnail_images"] - last_thumb = (QtGui.QPixmap.fromImage(thumbnails[-1])) + last_thumb = QtGui.QPixmap.fromImage(thumbnails[-1]) if last_thumb.isNull(): last_thumb = QtGui.QPixmap(