Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions BlocksScreen/lib/panels/mainWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand All @@ -84,6 +88,8 @@ def __init__(self):
self.conn_window = ConnectionPage(self, self.ws)
self.up = UpdatePage(self)
self.up.hide()

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
Expand Down Expand Up @@ -152,6 +158,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)
Expand Down Expand Up @@ -191,11 +199,40 @@ def __init__(self):
self, LoadingOverlayWidget.AnimationGIF.DEFAULT
)
self.loadscreen.add_widget(self.loadwidget)

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"):
# @ 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()
return

self.cancelpage.setGeometry(0, 0, self.width(), self.height())
self.cancelpage.raise_()
self.cancelpage.updateGeometry()
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()
Expand Down Expand Up @@ -734,6 +771,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()
Expand Down
3 changes: 3 additions & 0 deletions BlocksScreen/lib/panels/printTab.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class PrintTab(QtWidgets.QStackedWidget):
)
call_load_panel = QtCore.pyqtSignal(bool, str, name="call-load-panel")

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
Expand Down Expand Up @@ -124,6 +125,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]
)
Expand All @@ -137,6 +139,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))
)
Expand Down
267 changes: 267 additions & 0 deletions BlocksScreen/lib/panels/widgets/cancelPage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
from lib.utils.blocks_button import BlocksCustomButton
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: QtWidgets.QWidget, ws: MoonWebSocket) -> None:
super().__init__(parent)
self.ws: MoonWebSocket = ws
self._setupUI()
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)
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 _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(
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")

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.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)
2 changes: 2 additions & 0 deletions BlocksScreen/lib/panels/widgets/connectionPage.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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")
Expand Down
Loading
Loading