diff --git a/BlocksScreen.cfg b/BlocksScreen.cfg index 42ab150b..8ebdb0d7 100644 --- a/BlocksScreen.cfg +++ b/BlocksScreen.cfg @@ -3,7 +3,11 @@ host: localhost port: 7125 [screensaver] -timeout: 5000 +timeout: 600000 [usb_manager] gcodes_dir: ~/printer_data/gcodes/ + +[hotspot] +ssid: PrinterHotspot +password: 123456789 diff --git a/BlocksScreen/lib/panels/controlTab.py b/BlocksScreen/lib/panels/controlTab.py index be84c8bc..aabd922c 100644 --- a/BlocksScreen/lib/panels/controlTab.py +++ b/BlocksScreen/lib/panels/controlTab.py @@ -2,20 +2,26 @@ import re import typing -from functools import partial -from helper_methods import normalize from lib.moonrakerComm import MoonWebSocket from lib.panels.widgets.numpadPage import CustomNumpad -from lib.panels.widgets.optionCardWidget import OptionCard -from lib.panels.widgets.popupDialogWidget import Popup -from lib.panels.widgets.printcorePage import SwapPrintcorePage -from lib.panels.widgets.probeHelperPage import ProbeHelper from lib.panels.widgets.slider_selector_page import SliderPage + +from lib.panels.widgets.ControlTab.printcorePage import SwapPrintcorePage +from lib.panels.widgets.ControlTab.probeHelperPage import ProbeHelper +from lib.panels.widgets.ControlTab.fansPage import FansPage +from lib.panels.widgets.ControlTab.temperaturePage import TemperaturePage + +from lib.panels.widgets.ControlTab.axisPage import AxisPage +from lib.panels.widgets.ControlTab.extruderPage import ExtruderPage from lib.printer import Printer -from lib.ui.controlStackedWidget_ui import Ui_controlStackedWidget -from lib.utils.display_button import DisplayButton + from PyQt6 import QtCore, QtGui, QtWidgets +from lib.utils.blocks_button import BlocksCustomButton +from lib.utils.icon_button import IconButton +import logging + +logger = logging.getLogger(__name__) class ControlTab(QtWidgets.QStackedWidget): @@ -47,8 +53,6 @@ class ControlTab(QtWidgets.QStackedWidget): ) call_load_panel = QtCore.pyqtSignal(bool, str, name="call-load-panel") toggle_conn_page = QtCore.pyqtSignal(bool, name="call-load-panel") - tune_display_buttons: dict = {} - card_options: dict = {} def __init__( self, @@ -58,42 +62,64 @@ def __init__( /, ) -> None: super().__init__(parent) - self.panel = Ui_controlStackedWidget() - self.panel.setupUi(self) - - self.popup = Popup(self) + self.setupUi() + self.back_button.clicked.connect(lambda: self._button_change(False)) self.ws: MoonWebSocket = ws self.printer: Printer = printer self.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) self.timers = [] self.ztilt_state = False - self.extruder_info: dict = {} - self.bed_info: dict = {} - self.toolhead_info: dict = {} - self.extrude_length: int = 10 - self.extrude_feedrate: int = 2 - self.extrude_page_message: str = "" - self.move_length: float = 1.0 - self.move_speed: float = 25.0 + self.probe_helper_page = ProbeHelper(self) + self.addWidget(self.probe_helper_page) self.probe_helper_page.toggle_conn_page.connect(self.toggle_conn_page) self.probe_helper_page.disable_popups.connect(self.disable_popups) - self.addWidget(self.probe_helper_page) self.probe_helper_page.call_load_panel.connect(self.call_load_panel) + self.printcores_page = SwapPrintcorePage(self) self.addWidget(self.printcores_page) + self.fans_page = FansPage(self) + self.addWidget(self.fans_page) + self.fans_page.request_back_button.connect(self.request_back_button) + self.fans_page.run_gcode_signal.connect(self.run_gcode_signal) + self.fans_page.request_slider_page.connect(self.on_slidePage_request) + self.sliderPage = SliderPage(self) self.addWidget(self.sliderPage) - self.sliderPage.request_back.connect(self.back_button) + self.sliderPage.request_back.connect(self.request_back_button) + + self.axis_page = AxisPage(self) + self.addWidget(self.axis_page) + self.axis_page.request_back.connect(self.request_back_button) + self.axis_page.run_gcode_signal.connect(self.run_gcode_signal) + self.axis_page.call_load_panel.connect(self.call_load_panel) + self.printer.toolhead_update[str, list].connect( + self.axis_page.on_toolhead_update + ) + + self.extruder_page = ExtruderPage(self, printer) + self.addWidget(self.extruder_page) + self.extruder_page.request_back.connect(self.request_back_button) + self.extruder_page.run_gcode_signal.connect(self.run_gcode_signal) + + self.temperature_page = TemperaturePage(self) + self.addWidget(self.temperature_page) + self.temperature_page.request_back.connect(self.request_back_button) + self.temperature_page.request_numpad.connect(self.on_numpad_request) + self.temperature_page.run_gcode_signal.connect(self.run_gcode_signal) + + self.numpadPage = CustomNumpad(self) + self.numpadPage.request_back.connect(self.request_back_button) + self.addWidget(self.numpadPage) self.probe_helper_page.request_page_view.connect( - partial(self.change_page, self.indexOf(self.probe_helper_page)) + lambda: self.change_page(self.indexOf(self.probe_helper_page)) ) self.probe_helper_page.query_printer_object.connect(self.ws.api.object_query) self.probe_helper_page.run_gcode_signal.connect(self.ws.api.run_gcode) - self.probe_helper_page.request_back.connect(self.back_button) + self.probe_helper_page.request_back.connect(self.request_back_button) self.printer.print_stats_update[str, str].connect( self.probe_helper_page.on_print_stats_update ) @@ -123,259 +149,138 @@ def __init__( self.printer.gcode_response.connect( self.probe_helper_page.handle_gcode_response ) - self.printer.toolhead_update[str, list].connect(self.on_toolhead_update) - self.printer.extruder_update.connect(self.on_extruder_update) - self.printer.heater_bed_update.connect(self.on_heater_bed_update) - self.panel.cp_motion_btn.clicked.connect( - partial(self.change_page, self.indexOf(self.panel.motion_page)) - ) - self.panel.cp_temperature_btn.clicked.connect( - partial(self.change_page, self.indexOf(self.panel.temperature_page)) - ) - self.panel.cp_fans_btn.clicked.connect( - partial(self.change_page, self.indexOf(self.panel.fans_page)) - ) - self.panel.fans_back_btn.clicked.connect(self.back_button) - self.panel.cp_switch_print_core_btn.clicked.connect(self.show_swapcore) - self.panel.cp_nozzles_calibration_btn.clicked.connect( - partial(self.change_page, self.indexOf(self.probe_helper_page)) + self.printer.extruder_update.connect(self.temperature_page.on_extruder_update) + self.printer.heater_bed_update.connect( + self.temperature_page.on_heater_bed_update ) - self.panel.motion_extrude_btn.clicked.connect( - partial(self.change_page, self.indexOf(self.panel.extrude_page)) - ) - self.panel.motion_move_axis_btn.clicked.connect( - partial(self.change_page, self.indexOf(self.panel.move_axis_page)) - ) - self.panel.mp_back_btn.clicked.connect(self.back_button) - self.panel.motion_auto_home_btn.clicked.connect( - partial(self.run_gcode_signal.emit, "G28\nM400") - ) - self.panel.motion_disable_steppers_btn.clicked.connect( - partial(self.run_gcode_signal.emit, "M84\nM400") - ) - self.panel.exp_back_btn.clicked.connect(self.back_button) - self.panel.extrude_select_length_10_btn.toggled.connect( - partial( - self.handle_toggle_extrude_length, - caller=self.panel.extrude_select_length_10_btn, - value=10, + + self.run_gcode_signal.connect(self.ws.api.run_gcode) + # # @ object temperature change clicked + self.printcores_page.pc_accept.clicked.connect(self.handle_swapcore) + + self.ws.klippy_state_signal.connect(self.on_klippy_status) + self.ws.klippy_state_signal.connect(self.probe_helper_page.on_klippy_status) + self.printer.on_printcore_update.connect(self.handle_printcoreupdate) + self.printer.gcode_response.connect(self._handle_gcode_response) + self.printer.z_tilt_update.connect(self._handle_z_tilt_object_update) + + self.cp_button_6.hide() + + self.printer.fan_update[str, str, float].connect( + self.fans_page.on_fan_object_update + ) + self.printer.fan_update[str, str, int].connect( + self.fans_page.on_fan_object_update + ) + self._button_change(False) + + def _button_change(self, active: bool): + for btn in [ + self.cp_button_1, + self.cp_button_2, + self.cp_button_3, + self.cp_button_4, + self.cp_button_5, + self.cp_button_6, + ]: + try: + btn.clicked.disconnect() + except Exception as e: + logger.error(e) + if active: + self.cp_header_title.setText("Montion") + self.cp_button_1.setText("Auto Home") + + self.cp_button_1.setPixmap( + QtGui.QPixmap(":/motion/media/btn_icons/home_all.svg") ) - ) - self.panel.extrude_select_length_50_btn.toggled.connect( - partial( - self.handle_toggle_extrude_length, - caller=self.panel.extrude_select_length_50_btn, - value=50, + self.cp_button_1.clicked.connect( + lambda: self.run_gcode_signal.emit("G28\nM400") ) - ) - self.panel.extrude_select_length_100_btn.toggled.connect( - partial( - self.handle_toggle_extrude_length, - caller=self.panel.extrude_select_length_100_btn, - value=100, + self.cp_button_2.setText("Disable\nSteppers") + self.cp_button_2.clicked.connect( + lambda: self.run_gcode_signal.emit("M84\nM400") ) - ) - self.panel.extrude_select_feedrate_2_btn.toggled.connect( - partial( - self.handle_toggle_extrude_feedrate, - caller=self.panel.extrude_select_feedrate_2_btn, - value=2, + self.cp_button_2.setPixmap( + QtGui.QPixmap(":/motion/media/btn_icons/disable_steppers.svg") ) - ) - self.panel.extrude_select_feedrate_5_btn.toggled.connect( - partial( - self.handle_toggle_extrude_feedrate, - caller=self.panel.extrude_select_feedrate_5_btn, - value=5, + self.cp_button_3.setText("Axis") + self.cp_button_3.clicked.connect( + lambda: self.change_page(self.indexOf(self.axis_page)) ) - ) - self.panel.extrude_select_feedrate_10_btn.toggled.connect( - partial( - self.handle_toggle_extrude_feedrate, - caller=self.panel.extrude_select_feedrate_10_btn, - value=10, + self.cp_button_3.setPixmap( + QtGui.QPixmap(":/motion/media/btn_icons/axis_maintenance.svg") ) - ) - self.panel.mva_select_length_1_btn.toggled.connect( - partial(self.handle_select_move_length, value=1.0) - ) - self.panel.mva_select_length_10_btn.toggled.connect( - partial(self.handle_select_move_length, value=10.0) - ) - self.panel.mva_select_length_100_btn.toggled.connect( - partial(self.handle_select_move_length, value=100.0) - ) - self.panel.mva_select_speed_25_btn.toggled.connect( - partial(self.handle_select_move_speed, value=25.0) - ) - self.panel.mva_select_speed_50_btn.toggled.connect( - partial(self.handle_select_move_speed, value=50.0) - ) - self.panel.mva_select_speed_100_btn.toggled.connect( - partial(self.handle_select_move_speed, value=100.0) - ) - self.panel.exp_extrude_btn.clicked.connect( - partial(self.handle_extrusion, True) - ) # True for extrusion - self.panel.exp_unextrude_btn.clicked.connect( - partial(self.handle_extrusion, False) - ) # False for retraction - # Move Axis - self.panel.mva_back_btn.clicked.connect(self.back_button) - self.panel.mva_home_x_btn.clicked.connect( - partial(self.run_gcode_signal.emit, "G28 X\nM400") - ) - self.panel.mva_home_y_btn.clicked.connect( - partial(self.run_gcode_signal.emit, "G28 Y\nM400") - ) - self.panel.mva_home_z_btn.clicked.connect( - partial(self.run_gcode_signal.emit, "G28 Z\nM400") - ) - self.panel.mva_home_all_btn.clicked.connect( - partial(self.run_gcode_signal.emit, "G28\nM400") - ) - self.panel.mva_up_btn.clicked.connect(partial(self.handle_move_axis, "Y")) - self.panel.mva_down_btn.clicked.connect(partial(self.handle_move_axis, "Y-")) - self.panel.mva_right_btn.clicked.connect(partial(self.handle_move_axis, "X")) - self.panel.mva_left_btn.clicked.connect(partial(self.handle_move_axis, "X-")) - self.panel.mva_z_up.clicked.connect( - partial(self.handle_move_axis, "Z-") # Move nozzle closer to bed - ) - self.panel.mva_z_down.clicked.connect( - partial(self.handle_move_axis, "Z") # Move nozzle away from bed - ) - self.panel.temp_back_button.clicked.connect(self.back_button) - self.panel.printer_settings_back_btn.clicked.connect(self.back_button) - self.run_gcode_signal.connect(self.ws.api.run_gcode) - # @ object temperature change clicked - self.numpadPage = CustomNumpad(self) - self.numpadPage.request_back.connect(self.request_back_button) - self.addWidget(self.numpadPage) + self.cp_button_4.setText("Extruder") + self.cp_button_4.setPixmap( + QtGui.QPixmap(":/extruder_related/media/btn_icons/extrude.svg") + ) + self.cp_button_4.clicked.connect( + lambda: self.change_page(self.indexOf(self.extruder_page)) + ) + + self.back_button.show() + self.Hblank.show() - self.panel.extruder_temp_display.clicked.connect( - lambda: self.request_numpad[str, int, "PyQt_PyObject", int, int].emit( - "Extruder Temperature", - int(round(float(self.panel.extruder_temp_display.secondary_text))), - self.on_numpad_change, - 0, - 370, # TODO: Get this value from printer objects + self.cp_content_layout.addWidget(self.blank) + self.cp_button_5.hide() + self.blank.show() + else: + self.cp_header_title.setText("Control") + + self.cp_button_1.setText("Motion\nControl") + self.cp_button_1.setPixmap( + QtGui.QPixmap(":/motion/media/btn_icons/axis_maintenance.svg") ) - ) - self.panel.bed_temp_display.clicked.connect( - lambda: self.request_numpad[str, int, "PyQt_PyObject", int, int].emit( - "Bed Temperature", - int(round(float(self.panel.bed_temp_display.secondary_text))), - self.on_numpad_change, - 0, - 120, # TODO: Get this value from printer objects + self.cp_button_1.clicked.connect(lambda: self._button_change(True)) + + self.cp_button_2.setText("Temp.\nControl") + self.cp_button_2.setPixmap( + QtGui.QPixmap(":/temperature_related/media/btn_icons/temperature.svg") + ) + self.cp_button_2.clicked.connect( + lambda: self.change_page(self.indexOf(self.temperature_page)) ) - ) - self.request_numpad[str, int, "PyQt_PyObject", int, int].connect( - self.on_numpad_request - ) - self.panel.cooldown_btn.clicked.connect( - lambda: self.run_gcode_signal.emit( - "SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET=0\n\ - SET_HEATER_TEMPERATURE HEATER=extruder TARGET=0" + self.cp_button_3.setText("Nozzle\nCalibration") + self.cp_button_3.setPixmap( + QtGui.QPixmap(":/z_levelling/media/btn_icons/bed_levelling.svg") + ) + self.cp_button_3.clicked.connect( + lambda: self.change_page(self.indexOf(self.probe_helper_page)) ) - ) - self.path = { - "fan_cage": QtGui.QPixmap(":/fan_related/media/btn_icons/fan_cage.svg"), - "blower": QtGui.QPixmap(":/fan_related/media/btn_icons/blower.svg"), - "fan": QtGui.QPixmap(":/fan_related/media/btn_icons/fan.svg"), - } + self.cp_button_4.setText("Z-Tilt") + self.cp_button_4.setPixmap( + QtGui.QPixmap(":/z_levelling/media/btn_icons/bed_levelling.svg") + ) + self.cp_button_4.clicked.connect(lambda: self.handle_ztilt()) - self.panel.cp_z_tilt_btn.clicked.connect(lambda: self.handle_ztilt()) + self.cp_button_5.setText("Fans") + self.cp_button_5.setPixmap( + QtGui.QPixmap(":/temperature_related/media/btn_icons/fan.svg") + ) + self.cp_button_5.clicked.connect( + lambda: self.change_page(self.indexOf(self.fans_page)) + ) - self.printcores_page.pc_accept.clicked.connect(self.handle_swapcore) + self.cp_button_6.clicked.connect(self.show_swapcore) - self.ws.klippy_state_signal.connect(self.on_klippy_status) - self.ws.klippy_state_signal.connect(self.probe_helper_page.on_klippy_status) - self.printer.on_printcore_update.connect(self.handle_printcoreupdate) - self.printer.gcode_response.connect(self._handle_gcode_response) - self.printer.z_tilt_update.connect(self._handle_z_tilt_object_update) - # self.panel.cp_printer_settings_btn.hide() - self.panel.temperature_cooldown_btn.hide() - self.panel.cooldown_btn.hide() - self.panel.cp_switch_print_core_btn.hide() + self.back_button.hide() + self.Hblank.hide() + self.cp_button_5.show() + self.cp_content_layout.removeWidget(self.blank) + self.blank.hide() + self.repaint() - self.printer.fan_update[str, str, float].connect(self.on_fan_object_update) - self.printer.fan_update[str, str, int].connect(self.on_fan_object_update) + def showEvent(self, a0: QtGui.QShowEvent | None) -> None: + self._button_change(False) + return super().showEvent(a0) def _handle_z_tilt_object_update(self, value, state): if state: self.call_load_panel.emit(False, "") - @QtCore.pyqtSlot(str, str, float, name="on_fan_update") - @QtCore.pyqtSlot(str, str, int, name="on_fan_update") - def on_fan_object_update( - self, name: str, field: str, new_value: int | float - ) -> None: - """Slot that receives updates from fan objects. - - Args: - name (str): Fan object name - field (str): Field name - new_value (int | float): New value for the field - """ - if "speed" not in field: - return - - fields = name.split() - first_field = fields[0] - second_field = fields[1] if len(fields) > 1 else None - name = second_field.replace("_", " ") if second_field else name - - fan_card = self.tune_display_buttons.get(name) - if fan_card is None and first_field in ( - "fan", - "fan_generic", - ): - icon = self.path.get("fan") - if second_field: - second_field = second_field.lower() - pattern_blower = r"(?:^|_)(?:blower|auxiliary)(?:_|$)" - pattern_exhaust = r"(?:^|_)exhaust(?:_|$)" - if re.search(pattern_blower, second_field): - icon = self.path.get("blower") - elif re.search(pattern_exhaust, second_field): - icon = self.path.get("fan_cage") - - card = OptionCard(self, name, str(name), icon) # type: ignore - card.setObjectName(str(name)) - - # Add card to layout and record reference - self.card_options[name] = card - self.panel.fans_content_layout.addWidget(card) - - # If the card doesn't have expected UI properties, discard it - if not hasattr(card, "continue_clicked"): - del card - self.card_options.pop(name, None) - return - - card.setMode(True) - card.secondtext.setText(f"{new_value}%") - card.continue_clicked.connect( - lambda: self.on_slidePage_request( - str(name), - card.secondtext.text().replace("%", ""), - self.on_slider_change, - 0, - 100, - ) - ) - - self.tune_display_buttons[name] = card - self.update() - fan_card = card - - if fan_card: - value_percent = new_value * 100 if new_value <= 1 else new_value - fan_card.secondtext.setText(f"{value_percent:.0f}%") - @QtCore.pyqtSlot(str, int, "PyQt_PyObject", name="on_slidePage_request") @QtCore.pyqtSlot(str, int, "PyQt_PyObject", int, int, name="on_slidePage_request") def on_slidePage_request( @@ -386,6 +291,10 @@ def on_slidePage_request( min_value: int = 0, max_value: int = 100, ) -> None: + try: + self.sliderPage.value_selected.disconnect() + except Exception as e: + logger.error(e) self.sliderPage.value_selected.connect(callback) self.sliderPage.set_name(name) self.sliderPage.set_slider_position(int(current_value)) @@ -393,39 +302,6 @@ def on_slidePage_request( self.sliderPage.set_slider_maximum(max_value) self.change_page(self.indexOf(self.sliderPage)) - @QtCore.pyqtSlot(str, int, name="on_slider_change") - def on_slider_change(self, name: str, new_value: int) -> None: - if "speed" in name.lower(): - self.speed_factor_override = new_value / 100 - self.run_gcode_signal.emit(f"M220 S{new_value}") - if name.lower() == "fan": - self.run_gcode_signal.emit( - f"M106 S{int(round((normalize(float(new_value / 100), 0.0, 1.0, 0, 255))))}" - ) # [0, 255] Range - else: - name = name.replace(" ", "_") - self.run_gcode_signal.emit( - f'SET_FAN_SPEED FAN="{name}" SPEED={float(new_value / 100.00)}' - ) # [0.0, 1.0] Range - - def create_display_button(self, name: str) -> DisplayButton: - """Create and return a DisplayButton - - Args: - name (str): Name for the display button - - Returns: - DisplayButton: The created DisplayButton object - """ - display_button = DisplayButton() - display_button.setObjectName(str(name + "_display")) - display_button.setMinimumSize(QtCore.QSize(150, 50)) - display_button.setMaximumSize(QtCore.QSize(150, 80)) - font = QtGui.QFont() - font.setPointSize(16) - display_button.setFont(font) - return display_button - def handle_printcoreupdate(self, value: dict): if value["swapping"] == "idle": return @@ -515,178 +391,181 @@ def on_numpad_request( self.numpadPage.set_max_value(max_value) self.change_page(self.indexOf(self.numpadPage)) - @QtCore.pyqtSlot(str, int, name="on-numpad-change") - def on_numpad_change(self, name: str, new_value: int) -> None: - """Handles inputted numpad values""" - if "bed" in name.lower(): - name = "heater_bed" - elif "extruder" in name.lower(): - name = "extruder" - self.run_gcode_signal.emit( - f"SET_HEATER_TEMPERATURE HEATER={name} TARGET={new_value}" - ) - def change_page(self, index): """Handles changing page""" self.request_change_page.emit(2, index) - def back_button(self): - """Handle back button click""" - self.request_back_button.emit() - - def register_timed_callback(self, time: int, callback: callable) -> None: - """Registers timed callback and starts the timeout""" - _timer = QtCore.QTimer() - _timer.setSingleShot(True) - _timer.timeout.connect(callback) - _timer.start(int(time)) - self.timers.append(_timer) - - @QtCore.pyqtSlot(bool, "PyQt_PyObject", int, name="select-extrude-feedrate") - def handle_toggle_extrude_feedrate(self, checked: bool, caller, value: int) -> None: - """Slot to change the extruder feedrate, mainly used for toggle buttons - - Args: - checked (bool): Button checked state - caller (PyQtObject): The button that called this slot - value (int): New value for the extruder feedrate - """ - if value == self.extrude_feedrate: - return - self.extrude_feedrate = value - - @QtCore.pyqtSlot(bool, "PyQt_PyObject", int, name="select-extrude-length") - def handle_toggle_extrude_length(self, checked: bool, caller, value: int) -> None: - """Slot that changes the extrude length, mainly used for toggle buttons - - Args: - checked (bool): Button checked state - caller (PyQtObject): The button that called this slot - value (int): New value for the extrude length - """ - if self.extrude_length == value: - return - self.extrude_length = value - - @QtCore.pyqtSlot(bool, float, name="handle-select-move-speed") - def handle_select_move_speed(self, checked: bool, value: float) -> None: - """Slot that changes the move speed of manual move commands, mainly used - for toggle buttons - - Args: - checked (bool): Button checked state - value (float): New move speed value - """ - if self.move_speed == value: - return - self.move_speed = value - - @QtCore.pyqtSlot(bool, float, name="handle-select-move-length") - def handle_select_move_length(self, checked: bool, value: float) -> None: - """Slot that changes the move length of manual move commands, - mainly used for toggle buttons - - - Args: - checked (bool): Button checked state - value (float): New length value - """ - if self.move_length == value: - return - self.move_length = value - - @QtCore.pyqtSlot(str, name="handle-extrusion") - def handle_extrusion(self, extrude: bool) -> None: - """Slot that requests an extrusion/unextrusion move - - Args: - extrude (bool): If True extrudes otherwise unextrudes. - """ - can_extrude = bool(self.printer.heaters_object["extruder"]["can_extrude"]) - if not can_extrude: - self.extrude_page_message = "Temperature too cold to extrude" - self.panel.exp_info_label.setText(self.extrude_page_message) - return - if extrude: - self.run_gcode_signal.emit( - f"M83\nG1 E{self.extrude_length} F{self.extrude_feedrate * 60}\nM82\nM400" - ) - self.extrude_page_message = "Extruding" - self.panel.exp_info_label.setText(self.extrude_page_message) - else: - self.run_gcode_signal.emit( - f"M83\nG1 E-{self.extrude_length} F{self.extrude_feedrate * 60}\nM82\nM400" - ) - self.extrude_page_message = "Retracting" - self.panel.exp_info_label.setText(self.extrude_page_message) - # This block of code schedules a method to be called in x amount of milliseconds - _sch_time_s = float( - self.extrude_length / self.extrude_feedrate - ) # calculate the amount of time it'll take for the operation - self.extrude_page_message = "Ready" - self.register_timed_callback( - int(_sch_time_s + 2.0) * 1000, # In milliseconds - lambda: self.panel.exp_info_label.setText(self.extrude_page_message), - ) - - @QtCore.pyqtSlot(str, name="handle-move-axis") - def handle_move_axis(self, axis: str) -> None: - """Slot that requests manual move command - - Args: - axis (str): String that contains one of the following axis ` - ['X', - 'X-' - ,'Y' - ,'Y-' - ,'Z' - ,'Z-']`. [^1] - - --- - - [^1]: The **-** symbol indicates the negative direction for that axis - - """ - if axis not in ["X", "X-", "Y", "Y-", "Z", "Z-"]: - return - self.run_gcode_signal.emit( - f"G91\nG0 {axis}{float(self.move_length)} F{float(self.move_speed * 60)}\nG90\nM400" - ) + def setupUi(self): + self.resize(710, 410) + self.blank = QtWidgets.QWidget() + self.blank.setMinimumSize(QtCore.QSize(250, 80)) + self.blank.setMaximumSize(QtCore.QSize(250, 80)) + + self.Hblank = QtWidgets.QWidget(parent=self) + self.Hblank.setMinimumSize(QtCore.QSize(60, 60)) + self.Hblank.setMaximumSize(QtCore.QSize(60, 60)) + + widget = QtWidgets.QWidget() + widget.setMinimumSize(QtCore.QSize(710, 410)) + widget.setMaximumSize(QtCore.QSize(710, 410)) + self.setObjectName("control_page") + self.verticalLayout = QtWidgets.QVBoxLayout() + self.verticalLayout.setObjectName("verticalLayout") + self.cp_header_layout = QtWidgets.QHBoxLayout() + self.cp_header_layout.setObjectName("cp_header_layout") + + self.cp_header_layout.addWidget(self.Hblank) + self.cp_header_title = QtWidgets.QLabel(parent=self) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + QtWidgets.QSizePolicy.Policy.Fixed, + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth( + self.cp_header_title.sizePolicy().hasHeightForWidth() + ) + self.cp_header_title.setSizePolicy(sizePolicy) + self.cp_header_title.setMinimumSize(QtCore.QSize(300, 60)) + self.cp_header_title.setMaximumSize(QtCore.QSize(16777215, 60)) + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + font.setBold(True) + font.setWeight(75) + self.cp_header_title.setFont(font) + self.cp_header_title.setStyleSheet("background: transparent; color: white;") + self.cp_header_title.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.cp_header_title.setObjectName("cp_header_title") + self.cp_header_layout.addWidget(self.cp_header_title) + + self.back_button = IconButton(parent=self) + self.back_button.setPixmap(QtGui.QPixmap(":/ui/media/btn_icons/back.svg")) + self.back_button.setMinimumSize(QtCore.QSize(60, 60)) + self.back_button.setMaximumSize(QtCore.QSize(60, 60)) + self.cp_header_layout.addWidget(self.back_button) + + self.verticalLayout.addLayout(self.cp_header_layout) + self.cp_content_layout = QtWidgets.QGridLayout() + self.cp_content_layout.setObjectName("cp_content_layout") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Fixed + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) - @QtCore.pyqtSlot(str, list, name="on-toolhead-update") - def on_toolhead_update(self, field: str, values: list) -> None: - """Handles updated from toolhead printer object""" - if field == "position": - self.panel.mva_x_value_label.setText(f"{values[0]:.2f}") - self.panel.mva_y_value_label.setText(f"{values[1]:.2f}") - self.panel.mva_z_value_label.setText(f"{values[2]:.3f}") - - if values[0] == "252,50" and values[1] == "250" and values[2] == "50": - self.call_load_panel.emit(False, "") - self.toolhead_info.update({f"{field}": values}) - - @QtCore.pyqtSlot(str, str, float, name="on-extruder-update") - def on_extruder_update( - self, extruder_name: str, field: str, new_value: float - ) -> None: - """Handles updates from extruder printer object""" - if extruder_name == "extruder" and field == "temperature": - self.panel.extruder_temp_display.setText(f"{new_value:.1f}") - if extruder_name == "extruder" and field == "target": - self.panel.extruder_temp_display.secondary_text = f"{new_value:.1f}" - self.extruder_info.update({f"{extruder_name}": {f"{field}": new_value}}) - - @QtCore.pyqtSlot(str, str, float, name="on-heater-bed-update") - def on_heater_bed_update(self, name: str, field: str, new_value: float) -> None: - """Handles updated from heater_bed printer object""" - if field == "temperature": - self.panel.bed_temp_display.setText(f"{new_value:.1f}") - if field == "target": - self.panel.bed_temp_display.secondary_text = f"{new_value:.1f}" - self.bed_info.update({f"{name}": {f"{field}": new_value}}) - - def paintEvent(self, a0: QtGui.QPaintEvent) -> None: - """Handles ControlTab Widget painting""" - if self.panel.extrude_page.isVisible(): - self.panel.exp_info_label.setText(self.extrude_page_message) - return super().paintEvent(a0) + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(19) + font.setItalic(False) + font.setStyleStrategy(QtGui.QFont.StyleStrategy.PreferAntialias) + + self.cp_button_1 = BlocksCustomButton(parent=self) + self.cp_button_1.setSizePolicy(sizePolicy) + self.cp_button_1.setMinimumSize(QtCore.QSize(250, 80)) + self.cp_button_1.setMaximumSize(QtCore.QSize(250, 80)) + self.cp_button_1.setFont(font) + self.cp_button_1.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.NoContextMenu) + self.cp_button_1.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.cp_button_1.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/motion/media/btn_icons/axis_maintenance.svg"), + ) + self.cp_button_1.setObjectName("cp_button_1") + + self.cp_content_layout.addWidget(self.cp_button_1, 0, 0, 1, 1) + + self.cp_button_2 = BlocksCustomButton(parent=self) + self.cp_button_2.setSizePolicy(sizePolicy) + self.cp_button_2.setMinimumSize(QtCore.QSize(10, 80)) + self.cp_button_2.setMaximumSize(QtCore.QSize(250, 80)) + self.cp_button_2.setFont(font) + self.cp_button_2.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.NoContextMenu) + self.cp_button_2.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.cp_button_2.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/temperature_related/media/btn_icons/temperature.svg"), + ) + self.cp_button_2.setObjectName("cp_button_2") + + self.cp_content_layout.addWidget(self.cp_button_2, 0, 1, 1, 1) + + self.cp_button_3 = BlocksCustomButton(parent=self) + self.cp_button_3.setSizePolicy(sizePolicy) + self.cp_button_3.setMinimumSize(QtCore.QSize(10, 80)) + self.cp_button_3.setMaximumSize(QtCore.QSize(250, 80)) + self.cp_button_3.setFont(font) + self.cp_button_3.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.NoContextMenu) + self.cp_button_3.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.cp_button_3.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/z_levelling/media/btn_icons/bed_levelling.svg"), + ) + self.cp_button_3.setObjectName("cp_button_3") + + self.cp_content_layout.addWidget(self.cp_button_3, 1, 0, 1, 1) + + self.cp_button_4 = BlocksCustomButton(parent=self) + self.cp_button_4.setSizePolicy(sizePolicy) + self.cp_button_4.setMinimumSize(QtCore.QSize(10, 80)) + self.cp_button_4.setMaximumSize(QtCore.QSize(250, 80)) + self.cp_button_4.setFont(font) + self.cp_button_4.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.NoContextMenu) + self.cp_button_4.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.cp_button_4.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/z_levelling/media/btn_icons/bed_levelling.svg"), + ) + self.cp_button_4.setObjectName("cp_button_4") + + self.cp_content_layout.addWidget(self.cp_button_4, 1, 1, 1, 1) + + self.cp_button_5 = BlocksCustomButton(parent=self) + self.cp_button_5.setSizePolicy(sizePolicy) + self.cp_button_5.setMinimumSize(QtCore.QSize(10, 80)) + self.cp_button_5.setMaximumSize(QtCore.QSize(250, 80)) + self.cp_button_5.setFont(font) + self.cp_button_5.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.NoContextMenu) + self.cp_button_5.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.cp_button_5.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/temperature_related/media/btn_icons/fan.svg"), + ) + self.cp_button_5.setObjectName("cp_button_5") + + self.cp_content_layout.addWidget(self.cp_button_5, 2, 0, 1, 1) + + self.cp_button_6 = BlocksCustomButton(parent=self) + self.cp_button_6.setSizePolicy(sizePolicy) + self.cp_button_6.setMinimumSize(QtCore.QSize(10, 80)) + self.cp_button_6.setMaximumSize(QtCore.QSize(250, 80)) + self.cp_button_6.setFont(font) + self.cp_button_6.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.NoContextMenu) + self.cp_button_6.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.cp_button_6.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/extruder_related/media/btn_icons/switch_print_core.svg"), + ) + self.cp_button_6.setObjectName("cp_button_6") + + self.cp_content_layout.addWidget(self.cp_button_6, 2, 1, 1, 1) + self.verticalLayout.addLayout(self.cp_content_layout) + widget.setLayout(self.verticalLayout) + self.addWidget(widget) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.setWindowTitle(_translate("controlStackedWidget", "StackedWidget")) + self.cp_header_title.setText(_translate("controlStackedWidget", "Control")) + + self.cp_button_1.setText(_translate("controlStackedWidget", "Motion\nControl")) + self.cp_button_2.setText(_translate("controlStackedWidget", "Temp.\nControl")) + self.cp_button_3.setText( + _translate("controlStackedWidget", "Nozzle\nCalibration") + ) + self.cp_button_4.setText(_translate("controlStackedWidget", "Z-Tilt")) + self.cp_button_5.setText(_translate("controlStackedWidget", "Fans")) + self.cp_button_6.setText(_translate("controlStackedWidget", "Swap\nPrint Core")) diff --git a/BlocksScreen/lib/panels/mainWindow.py b/BlocksScreen/lib/panels/mainWindow.py index 12fbc628..393d9397 100644 --- a/BlocksScreen/lib/panels/mainWindow.py +++ b/BlocksScreen/lib/panels/mainWindow.py @@ -15,11 +15,11 @@ from lib.panels.printTab import PrintTab from lib.panels.utilitiesTab import UtilitiesTab from lib.panels.widgets.basePopup import BasePopup -from lib.panels.widgets.cancelPage import CancelPage -from lib.panels.widgets.connectionPage import ConnectionPage +from lib.panels.widgets.MainWindow.cancelPage import CancelPage +from lib.panels.widgets.MainWindow.connectionPage import ConnectionPage from lib.panels.widgets.loadWidget import LoadingOverlayWidget -from lib.panels.widgets.notificationPage import NotificationPage -from lib.panels.widgets.updatePage import UpdatePage +from lib.panels.widgets.MainWindow.notificationPage import NotificationPage +from lib.panels.widgets.MainWindow.updatePage import UpdatePage from lib.printer import Printer from lib.ui.mainWindow_ui import Ui_MainWindow # With header from lib.ui.resources.background_resources_rc import * @@ -156,20 +156,19 @@ def __init__(self): self.filamentPanel.request_change_page.connect(slot=self.global_change_page) self.controlPanel.request_back_button.connect(slot=self.global_back) self.controlPanel.request_change_page.connect(slot=self.global_change_page) - self.utilitiesPanel.request_back.connect(slot=self.global_back) + self.utilitiesPanel.request_back_button.connect(slot=self.global_back) self.utilitiesPanel.request_change_page.connect(slot=self.global_change_page) - self.utilitiesPanel.update_available.connect(self.on_update_available) self.ui.notification_btn.clicked.connect(self.notiPage.show_notification_panel) self.ui.extruder_temp_display.clicked.connect( lambda: self.global_change_page( self.ui.main_content_widget.indexOf(self.ui.controlTab), - self.controlPanel.indexOf(self.controlPanel.panel.temperature_page), + self.controlPanel.indexOf(self.controlPanel.temperature_page), ) ) self.ui.bed_temp_display.clicked.connect( lambda: self.global_change_page( self.ui.main_content_widget.indexOf(self.ui.controlTab), - self.controlPanel.indexOf(self.controlPanel.panel.temperature_page), + self.controlPanel.indexOf(self.controlPanel.temperature_page), ) ) self.ui.filament_type_icon.clicked.connect( @@ -341,13 +340,13 @@ def on_cancel_print(self): self.ui.extruder_temp_display.clicked.connect( lambda: self.global_change_page( self.ui.main_content_widget.indexOf(self.ui.controlTab), - self.controlPanel.indexOf(self.controlPanel.panel.temperature_page), + self.controlPanel.indexOf(self.controlPanel.temperature_page), ) ) self.ui.bed_temp_display.clicked.connect( lambda: self.global_change_page( self.ui.main_content_widget.indexOf(self.ui.controlTab), - self.controlPanel.indexOf(self.controlPanel.panel.temperature_page), + self.controlPanel.indexOf(self.controlPanel.temperature_page), ) ) @@ -859,13 +858,13 @@ def event(self, event: QtCore.QEvent) -> bool: self.ui.extruder_temp_display.clicked.connect( lambda: self.global_change_page( self.ui.main_content_widget.indexOf(self.ui.controlTab), - self.controlPanel.indexOf(self.controlPanel.panel.temperature_page), + self.controlPanel.indexOf(self.controlPanel.temperature_page), ) ) self.ui.bed_temp_display.clicked.connect( lambda: self.global_change_page( self.ui.main_content_widget.indexOf(self.ui.controlTab), - self.controlPanel.indexOf(self.controlPanel.panel.temperature_page), + self.controlPanel.indexOf(self.controlPanel.temperature_page), ) ) return False diff --git a/BlocksScreen/lib/panels/printTab.py b/BlocksScreen/lib/panels/printTab.py index 65927aae..a08d81a0 100644 --- a/BlocksScreen/lib/panels/printTab.py +++ b/BlocksScreen/lib/panels/printTab.py @@ -6,15 +6,15 @@ from configfile import BlocksScreenConfig, get_configparser from lib.files import Files from lib.moonrakerComm import MoonWebSocket -from lib.panels.widgets.babystepPage import BabystepPage +from lib.panels.widgets.PrintTab.babystepPage import BabystepPage from lib.panels.widgets.basePopup import BasePopup -from lib.panels.widgets.confirmPage import ConfirmWidget -from lib.panels.widgets.filesPage import FilesPage -from lib.panels.widgets.jobStatusPage import JobStatusWidget +from lib.panels.widgets.PrintTab.confirmPage import ConfirmWidget +from lib.panels.widgets.PrintTab.filesPage import FilesPage +from lib.panels.widgets.PrintTab.jobStatusPage import JobStatusWidget from lib.panels.widgets.numpadPage import CustomNumpad -from lib.panels.widgets.sensorsPanel import SensorsWindow +from lib.panels.widgets.PrintTab.sensorsPanel import SensorsWindow from lib.panels.widgets.slider_selector_page import SliderPage -from lib.panels.widgets.tunePage import TuneWidget +from lib.panels.widgets.PrintTab.tunePage import TuneWidget from lib.printer import Printer from lib.utils.blocks_button import BlocksCustomButton from lib.utils.display_button import DisplayButton diff --git a/BlocksScreen/lib/panels/utilitiesTab.py b/BlocksScreen/lib/panels/utilitiesTab.py index 6cff5f27..1f1261cf 100644 --- a/BlocksScreen/lib/panels/utilitiesTab.py +++ b/BlocksScreen/lib/panels/utilitiesTab.py @@ -1,46 +1,22 @@ import typing -from dataclasses import dataclass +from PyQt6 import QtCore, QtGui, QtWidgets from enum import Enum, auto -from functools import partial - from lib.moonrakerComm import MoonWebSocket -from lib.panels.widgets.troubleshootPage import TroubleshootPage from lib.printer import Printer -from lib.ui.utilitiesStackedWidget_ui import Ui_utilitiesStackedWidget from lib.utils.blocks_button import BlocksCustomButton -from lib.utils.toggleAnimatedButton import ToggleAnimatedButton -from PyQt6 import QtCore, QtGui, QtWidgets - -from lib.panels.widgets.optionCardWidget import OptionCard -from lib.panels.widgets.inputshaperPage import InputShaperPage from lib.panels.widgets.basePopup import BasePopup +from lib.panels.widgets.UtilitiesTab.infoPage import InfoPage +from lib.panels.widgets.UtilitiesTab.ledsPage import LedsPage +from lib.panels.widgets.UtilitiesTab.ledssliderPage import LedsSliderPage +from lib.panels.widgets.UtilitiesTab.troubleshootPage import TroubleshootPage +from lib.panels.widgets.UtilitiesTab.inputshaperPage import InputShaperPage +from lib.panels.widgets.UtilitiesTab.inputshaperResultPage import InputShaperResultsPage +from lib.panels.widgets.UtilitiesTab.axismaintPage import AxisMaintenancePage +from lib.panels.widgets.UtilitiesTab.routineCheckPage import RoutineCheckPage +from lib.panels.widgets.UtilitiesTab.rc_page import RoutineCheckAnswerPage +import logging -import re - - -@dataclass -class LedState: - """Represents the state of an LED light.""" - - led_type: str - red: int = 0 - green: int = 0 - blue: int = 0 - white: int = 255 - state: str = "on" - - def get_gcode(self, name: str) -> str: - """Generates the G-code command for the current state.""" - if self.state == "off": - return f"SET_LED LED={name} RED=0 GREEN=0 BLUE=0 WHITE=0" - if self.led_type == "white": - return f"SET_LED LED={name} WHITE={self.white / 255:.2f}" - # Default to RGB - return ( - f"SET_LED LED={name} RED={self.red / 255:.2f} " - f"GREEN={self.green / 255:.2f} BLUE={self.blue / 255:.2f} " - f"WHITE={self.white / 255:.2f}" - ) +logger = logging.getLogger(__name__) class Process(Enum): @@ -52,42 +28,23 @@ class Process(Enum): class UtilitiesTab(QtWidgets.QStackedWidget): - request_back: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( - name="request-back" - ) + request_back_button = QtCore.pyqtSignal(name="request-back-button") + request_change_page: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( int, int, name="request-change-page" ) - request_available_objects_signal: typing.ClassVar[QtCore.pyqtSignal] = ( - QtCore.pyqtSignal(name="get-available-objects") - ) run_gcode_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( str, name="run-gcode" ) - request_numpad_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( - int, - str, - str, - "PyQt_PyObject", - QtWidgets.QStackedWidget, - name="request-numpad", - ) subscribe_config: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( [list, "PyQt_PyObject"], [str, "PyQt_PyObject"], name="on-subscribe-config", ) - on_update_message: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( - dict, name="handle-update-message" - ) - - update_available: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( - bool, name="update-available" - ) - show_update_page: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( bool, name="show-update-page" ) + on_object_list = QtCore.pyqtSignal(list, name="on-object-list") call_load_panel = QtCore.pyqtSignal(bool, str, name="call-load-panel") def __init__( @@ -95,577 +52,321 @@ def __init__( ) -> None: super().__init__(parent) - self.panel = Ui_utilitiesStackedWidget() - self.panel.setupUi(self) + self._setupUi() self.ws = ws self.printer: Printer = printer self.troubleshoot_page: TroubleshootPage = TroubleshootPage(self) - # --- State Variables --- - self.objects: dict = { - "fans": {}, - "axis": {"x": "indf", "y": "indf", "z": "indf"}, - "bheat": {"Bed_Heater": "indf"}, - "extrude": {"extruder": "indf"}, - "leds": {}, - } - self.x_inputshaper: dict = {} - self.stepper_limits: dict = {} - - self.current_object: typing.Optional[str] = None - self.current_process: typing.Optional[Process] = None - self.axis_in: str = "x" - self.amount: int = 1 - self.tb: bool = False - self.cg = None - self.aut: bool = False - - # --- UI Setup --- + self.run_gcode_signal.connect(self.ws.api.run_gcode) + self.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) - self.panel.update_btn.clicked.connect( - lambda: self.show_update_page[bool].emit(False) + + self.info_page = InfoPage(self) + self.addWidget(self.info_page) + self.info_page.request_back.connect(self.request_back_button) + + self.leds_slider_page = LedsSliderPage(self) + self.addWidget(self.leds_slider_page) + self.leds_slider_page.run_gcode_signal.connect(self.run_gcode_signal) + self.leds_slider_page.request_back.connect( + lambda: self.request_back_button.emit() ) + self.leds_slider_page.request_change_page.connect(self.change_page) - self.is_page = InputShaperPage(self) - self.is_page.call_load_panel.connect(self.call_load_panel) + self.leds_page = LedsPage(self) + self.addWidget(self.leds_page) + self.on_object_list.connect(self.leds_page.on_object_list) + self.leds_page.request_ledslider_page.connect(self.on_leds_slider_request) + self.leds_page.request_back.connect(lambda: self.request_back_button.emit()) + + self.is_page = InputShaperResultsPage(self) self.addWidget(self.is_page) + self.printer.gcode_response.connect(self.is_page.handle_gcode_response) + self.is_page.call_load_panel.connect(self.call_load_panel) + self.is_page.run_gcode_signal.connect(self.run_gcode_signal) - self.dialog_page = BasePopup(self, dialog=True, floating=True) - self.addWidget(self.dialog_page) - - # --- Back Buttons --- - for button in ( - self.panel.leds_back_btn, - self.panel.info_back_btn, - self.panel.leds_slider_back_btn, - self.panel.input_shaper_back_btn, - self.panel.routine_check_back_btn, - self.is_page.update_back_btn, - ): - button.clicked.connect(self.back_button) - - # --- Page Navigation --- - self._connect_page_change(self.panel.utilities_axes_btn, self.panel.axes_page) - self._connect_page_change( - self.panel.utilities_input_shaper_btn, self.panel.input_shaper_page + self.input_shaper_page = InputShaperPage(self) + self.addWidget(self.input_shaper_page) + self.input_shaper_page.request_is_results_page.connect( + lambda: self.change_page(self.indexOf(self.is_page)) ) - self._connect_page_change(self.panel.utilities_info_btn, self.panel.info_page) - self._connect_page_change( - self.panel.utilities_routine_check_btn, self.panel.routines_page + self.input_shaper_page.request_back_button.connect(lambda: self.change_page(0)) + self.input_shaper_page.run_gcode_signal.connect(self.run_gcode_signal) + self.input_shaper_page.call_load_panel.connect(self.call_load_panel) + self.input_shaper_page.set_aut.connect(self.is_page.set_aut) + + self.axis_page = AxisMaintenancePage(self) + self.addWidget(self.axis_page) + self.axis_page.request_back_button.connect(self.request_back_button) + self.axis_page.set_dialog_popup.connect(self.set_dialog_axismaintenace_popup) + self.axis_page.show_waiting_page.connect(self.show_waiting_page) + self.axis_page.call_load_panel.connect(self.call_load_panel) + self.axis_page.run_gcode_signal.connect(self.run_gcode_signal) + + self.routine_check_page = RoutineCheckPage(self) + self.addWidget(self.routine_check_page) + self.routine_check_page.run_gcode_signal.connect(self.run_gcode_signal) + self.routine_check_page.request_back_button.connect(self.request_back_button) + self.on_object_list.connect(self.routine_check_page.on_object_list) + self.routine_check_page.set_rc_page.connect(self.set_rc_page) + self.routine_check_page.show_waiting_page.connect(self.show_waiting_page) + self.routine_check_page.request_troubleshoot_page.connect( + self.troubleshoot_request ) - self._connect_page_change(self.panel.am_cancel, self.panel.utilities_page) - self._connect_page_change(self.panel.axes_back_btn, self.panel.utilities_page) - self._connect_page_change( - self.troubleshoot_page.tb_back_btn, self.panel.utilities_page + self.rc_page = RoutineCheckAnswerPage(self) + self.addWidget(self.rc_page) + self.rc_page.on_rc_asnwer.connect(self.routine_check_page.on_routine_answer) + self.rc_page.request_back_button.connect(self.request_back_button) + + self.utilities_info_btn.clicked.connect( + lambda: self.change_page(self.indexOf(self.info_page)) + ) + self.utilities_leds_btn.clicked.connect( + lambda: self.change_page(self.indexOf(self.leds_page)) + ) + self.utilities_axes_btn.clicked.connect( + lambda: self.change_page(self.indexOf(self.axis_page)) ) + self.utilities_routine_check_btn.clicked.connect( + lambda: self.change_page(self.indexOf(self.routine_check_page)) + ) + self.utilities_input_shaper_btn.clicked.connect( + lambda: self.change_page(self.indexOf(self.input_shaper_page)) + ) + + self.update_btn.clicked.connect(lambda: self.show_update_page[bool].emit(False)) - # --- Routines --- - self.panel.rc_fans.clicked.connect(partial(self.run_routine, Process.FAN)) - self.panel.rc_bheat.clicked.connect( - partial(self.run_routine, Process.BED_HEATER) + self.is_page.action_btn.clicked.connect( + lambda: self.change_page(self.indexOf(self.input_shaper_page)) ) - self.panel.rc_ext.clicked.connect(partial(self.run_routine, Process.EXTRUDER)) - self.panel.rc_axis.clicked.connect(partial(self.run_routine, Process.AXIS)) - self.panel.rc_no.clicked.connect(self.on_routine_answer) - self.panel.rc_yes.clicked.connect(self.on_routine_answer) - - # --- Axis Maintenance --- - self.panel.axis_x_btn.clicked.connect(partial(self.axis_maintenance, "x")) - self.panel.axis_y_btn.clicked.connect(partial(self.axis_maintenance, "y")) - self.panel.axis_z_btn.clicked.connect(partial(self.axis_maintenance, "z")) - - self.panel.toggle_led_button.state = ToggleAnimatedButton.State.ON - - # --- LEDs --- - # self.panel.leds_r_slider.sliderReleased.connect(self.update_led_values) - # self.panel.leds_g_slider.sliderReleased.connect(self.update_led_values) - # self.panel.leds_b_slider.sliderReleased.connect(self.update_led_values) - self.panel.leds_w_slider.sliderReleased.connect(self.update_led_values) - self.panel.toggle_led_button.clicked.connect(self.toggle_led_state) - - # --- Websocket/Printer Signals --- - self.run_gcode_signal.connect(self.ws.api.run_gcode) - self.is_page.run_gcode_signal.connect(self.ws.api.run_gcode) + + self.dialogpopup = BasePopup(self, False, True) + self.addWidget(self.dialogpopup) + self.subscribe_config[str, "PyQt_PyObject"].connect( self.printer.on_subscribe_config ) self.subscribe_config[list, "PyQt_PyObject"].connect( self.printer.on_subscribe_config ) - self.printer.gcode_response.connect(self.handle_gcode_response) - # --- Initialize Printer Communication --- self.printer.printer_config.connect(self.on_printer_config_received) - self.printer.gcode_move_update.connect(self.on_gcode_move_update) - - self.panel.update_btn.setPixmap( - QtGui.QPixmap(":/system/media/btn_icons/update-software-icon.svg") - ) - # ---- Input Shaper ---- - self.automatic_is = OptionCard( - self, - "Automatic\nInput Shaper", - "Automatic Input Shaper", - QtGui.QPixmap(":/input_shaper/media/btn_icons/input_shaper_auto.svg"), - ) # type: ignore - self.automatic_is.setObjectName("Automatic_IS_Card") - self.panel.is_content_layout.addWidget( - self.automatic_is, alignment=QtCore.Qt.AlignmentFlag.AlignHCenter - ) - self.automatic_is.continue_clicked.connect( - lambda: self.handle_is("SHAPER_CALIBRATE") - ) + def on_leds_slider_request(self, led, name=str, single=bool): + """request leds slider page to show - self.manual_is = OptionCard( - self, - "Manual\nInput Shaper", - "Manual Input Shaper", - QtGui.QPixmap(":/input_shaper/media/btn_icons/input_shaper_manual.svg"), - ) # type: ignore - self.manual_is.setObjectName("Manual_IS_Card") - self.panel.is_content_layout.addWidget( - self.manual_is, alignment=QtCore.Qt.AlignmentFlag.AlignHCenter + Args: + led (_type_): led + name (_type_, optional): Leds name. Defaults to str. + single (_type_, optional): if its only 1 led. Defaults to bool. + """ + self.change_page(self.indexOf(self.leds_slider_page)) + self.leds_slider_page.set_slider( + led_state=led, name=str(name), single=bool(single) ) - self.manual_is.continue_clicked.connect(lambda: self.handle_is("")) - self.is_types: dict = {} - self.is_aut_types: dict = {} - self.dialog_page.accepted.connect( - lambda: self.handle_is("SHAPER_CALIBRATE AXIS=Y") - ) - self.dialog_page.rejected.connect( - lambda: self.handle_is("SHAPER_CALIBRATE AXIS=X") - ) + def on_printer_config_received(self, config: dict) -> None: + """Handle printer configuration""" + for axis in ("x", "y", "z"): + self.subscribe_config[str, "PyQt_PyObject"].emit( + f"stepper_{axis}", self.axis_page.on_object_config + ) - self.is_page.action_btn.clicked.connect( - lambda: self.change_page(self.indexOf(self.panel.input_shaper_page)) - ) + def set_rc_page(self, title: str, message: str): + """sets routine check title and message - def handle_gcode_response(self, data: list[str]) -> None: + Args: + title (str): The title + message (str): message """ - Parses a Klipper Input Shaper console message and updates self.is_types. - """ - - if not isinstance(data, list) or len(data) != 1 or not isinstance(data[0], str): - print( - f"WARNING: Invalid input format. Expected a list with one string. Received: {data}" - ) - return + self.rc_page.setTitle(title) + self.rc_page.setMessage(message) - message = data[0] + @QtCore.pyqtSlot(str, "PyQt_PyObject", name="set-dialog-popup") + def set_dialog_axismaintenace_popup(self, label: str, callback): + """Set text on routine page""" + self.dialogpopup.set_message(label) + try: + self.dialogpopup.disconnect() + except Exception as e: + logger.error(e) + self.dialogpopup.accepted.connect(callback) - pattern_fitted = re.compile( - r"Fitted shaper '(?P\w+)' frequency = (?P[\d\.]+) Hz \(vibrations = (?P[\d\.]+)%" - ) - match_fitted = pattern_fitted.search(message) - - if match_fitted: - name = match_fitted.group("name") - freq = float(match_fitted.group("freq")) - vib = float(match_fitted.group("vib")) - current_data = self.is_types.get(name, {}) - current_data.update( - { - "frequency": freq, - "vibration": vib, - "max_accel": current_data.get("max_accel", 0.0), - } + @QtCore.pyqtSlot(str, int, bool, name="show-waiting-page") + def show_waiting_page(self, label: str, time_ms: int, popup: bool): + """Show placeholder page""" + self.call_load_panel.emit(True, label) + if popup: + QtCore.QTimer.singleShot(time_ms, lambda: self.dialogpopup.open()) + else: + QtCore.QTimer.singleShot( + time_ms, lambda: self.change_page(self.indexOf(self.rc_page)) ) - self.is_types[name] = current_data - - return - pattern_accel = re.compile( - r"To avoid too much smoothing with '(?P\w+)', suggested max_accel <= (?P[\d\.]+) mm/sec\^2" - ) - match_accel = pattern_accel.search(message) - if match_accel: - name = match_accel.group("name") - accel = float(match_accel.group("accel")) + @QtCore.pyqtSlot(name="request-troubleshoot-page") + def troubleshoot_request(self) -> None: + """Show troubleshoot page""" + self.troubleshoot_page.show() - if name in self.is_types and isinstance(self.is_types[name], dict): - self.is_types[name]["max_accel"] = accel - else: - self.is_types[name] = self.is_types.get(name, {}) - self.is_types[name]["max_accel"] = accel - return + def change_page(self, index: int): + """Request change page by index""" + self.request_change_page.emit(3, index) - pattern_recommended = re.compile( - r"Recommended shaper_type_(?P[xy]) = (?P\w+), shaper_freq_(?P=axis) = (?P[\d\.]+) Hz" + def _setupUi(self): + self.resize(710, 410) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Minimum ) - match_recommended = pattern_recommended.search(message) - if match_recommended: - axis = match_recommended.group("axis") - recommended_type = match_recommended.group("type") - self.is_types["Axis"] = axis - if self.aut: - self.is_aut_types[axis] = recommended_type - if len(self.is_aut_types) == 2: - self.run_gcode_signal.emit("SAVE_CONFIG") - self.call_load_panel.emit(False, "") - self.aut = False - return - return - - reordered = {recommended_type: self.is_types[recommended_type]} - for key, value in self.is_types.items(): - if key not in ("suggested_type", recommended_type, "Axis"): - reordered[key] = value - - self.is_page.set_type_dictionary(self.is_types) - first_key = next(iter(reordered.keys()), None) - for key in reordered.keys(): - if key == first_key: - self.is_page.add_type_entry(key, "Recommended type") - else: - self.is_page.add_type_entry(key) - - self.is_page.build_model_list() - self.call_load_panel.emit(False, "") - return - - def handle_is(self, gcode: str) -> None: - if gcode == "SHAPER_CALIBRATE": - self.run_gcode_signal.emit("G28\nM400") - self.aut = True - self.run_gcode_signal.emit(gcode) - elif gcode == "": - self.dialog_page.confirm_background_color("#dfdfdf") - self.dialog_page.cancel_background_color("#dfdfdf") - self.dialog_page.cancel_font_color("#000000") - self.dialog_page.confirm_font_color("#000000") - self.dialog_page.cancel_button_text("X axis") - self.dialog_page.confirm_button_text("Y axis") - self.dialog_page.set_message( - "Select the axis you want to execute the input shaper on:" - ) - self.dialog_page.show() - return - else: - self.run_gcode_signal.emit("G28\nM400") - self.run_gcode_signal.emit(gcode) - self.change_page(self.indexOf(self.is_page)) - - self.call_load_panel.emit(True, "Running Input Shaper...") - - @QtCore.pyqtSlot(list, name="on_object_list") - def on_object_list(self, object_list: list) -> None: - """Handle receiving printer object list""" - self.cg = object_list - for obj in self.cg: - base_name = obj.split()[0] - - # Only accept 'fan_generic' or 'fan' - if base_name == "fan_generic" or base_name == "fan": - self.objects["fans"][obj] = "indef" - self._update_leds_from_config() - - @QtCore.pyqtSlot(dict, name="on_object_config") - @QtCore.pyqtSlot(list, name="on_object_config") - def on_object_config(self, config: typing.Union[dict, list]) -> None: - """Handle receiving printer object configurations""" - if not config: - return - config_items = [config] if isinstance(config, dict) else config - for item in config_items: - for key, value in item.items(): - if ( - key.startswith("stepper_") - and isinstance(value, dict) - and key not in self.stepper_limits - ): - pos_min = value.get("position_min") - pos_max = value.get("position_max") - if pos_min is not None or pos_max is not None: - self.stepper_limits[key] = { - "min": float(pos_min) - if pos_min is not None - else -float("inf"), - "max": float(pos_max) - if pos_max is not None - else float("inf"), - } + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) + self.setSizePolicy(sizePolicy) + self.setMinimumSize(QtCore.QSize(710, 410)) + self.setMaximumSize(QtCore.QSize(710, 410)) + + widget = QtWidgets.QWidget() + widget.setMinimumSize(QtCore.QSize(710, 410)) + widget.setMaximumSize(QtCore.QSize(710, 410)) + widget.setObjectName("utilities_page") + self.verticalLayout = QtWidgets.QVBoxLayout(self) + self.verticalLayout.setObjectName("verticalLayout") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + font.setBold(True) + font.setWeight(75) + + self.utilities_header_layout = QtWidgets.QHBoxLayout() + self.utilities_header_layout.setObjectName("utilities_header_layout") + + self.utilities_title_label = QtWidgets.QLabel(parent=self) + self.utilities_title_label.setSizePolicy(sizePolicy) + self.utilities_title_label.setMinimumSize(QtCore.QSize(0, 60)) + self.utilities_title_label.setMaximumSize(QtCore.QSize(16777215, 60)) + self.utilities_title_label.setFont(font) + self.utilities_title_label.setStyleSheet( + "background: transparent; color: white;" + ) + self.utilities_title_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.utilities_title_label.setObjectName("utilities_title_label") - def on_printer_config_received(self, config: dict) -> None: - """Handle printer configuration""" - for axis in ("x", "y", "z"): - self.subscribe_config[str, "PyQt_PyObject"].emit( - f"stepper_{axis}", self.on_object_config - ) + self.utilities_header_layout.addWidget(self.utilities_title_label) + self.verticalLayout.addLayout(self.utilities_header_layout) + self.utilities_content_layout = QtWidgets.QGridLayout() - @QtCore.pyqtSlot(str, list, name="on_gcode_move_update") - def on_gcode_move_update(self, name: str, value: list) -> None: - """Handle gcode move""" - if not value: - return - if name == "gcode_position": - ... - - def run_routine(self, process: Process): - """Run check routine for available processes""" - self.current_process = process - routine_configs = { - Process.FAN: ("fans", "fan is spinning"), - Process.AXIS: ("axis", "axis is moving"), - Process.BED_HEATER: ("bheat", "bed is heating"), - Process.EXTRUDER: ("extrude", "extruder is being tested"), - } - if process not in routine_configs: - return - obj_key, message = routine_configs[process] - obj_list = list(self.objects.get(obj_key, {}).keys()) - if not self._advance_routine_object(obj_list): - if self.tb: - self.troubleshoot_request() - self.tb = False - else: - self.change_page(self.indexOf(self.panel.utilities_page)) - - if process == Process.FAN: - self.run_gcode_signal.emit("M107") - return - - message = f"Please check if the {self.current_object} is functioning correctly." - if process == Process.AXIS: - message = f"Please ensure the {self.current_object} axis moves correctly." - elif process in [Process.BED_HEATER, Process.EXTRUDER]: - message = "Please check if the temperature reaches 60°C. \n you may need to wait a few moments." - - self.set_routine_check_page( - f"Running routine for: {self.current_object}", message + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Expanding, ) - self.show_waiting_page( - self.indexOf(self.panel.rc_page), - f"Please check if the {message}", - 10000 if process == Process.AXIS else 0, + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(19) + + self.utilities_content_layout.setObjectName("utilities_content_layout") + self.utilities_axes_btn = BlocksCustomButton(parent=self) + self.utilities_axes_btn.setSizePolicy(sizePolicy) + self.utilities_axes_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.utilities_axes_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.utilities_axes_btn.setFont(font) + self.utilities_axes_btn.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/motion/media/btn_icons/axis_maintenance.svg"), ) - self._send_routine_gcode() - - def _advance_routine_object(self, obj_list: list) -> bool: - if not obj_list: - is_first_run = self.current_object is None - self.current_object = obj_list[0] if is_first_run and obj_list else "done" - return is_first_run - if self.current_object not in obj_list: - if self.current_process == Process.AXIS: - self.run_gcode_signal.emit("G28") - self.current_object = obj_list[0] - return True - try: - current_index = obj_list.index(self.current_object) - if current_index + 1 < len(obj_list): - self.current_object = obj_list[current_index + 1] - return True - else: - self.current_object = None - return False - except ValueError: - self.current_object = obj_list[0] - return True - - def on_routine_answer(self) -> None: - """Handle routine ongoing process""" - if self.current_process is None or self.current_object is None: - return - if self.sender() == self.panel.rc_yes: - answer = "yes" - else: - answer = "no" - self.tb = True - process_map = { - Process.FAN: ("fans", self.current_object), - Process.AXIS: ("axis", self.current_object), - Process.BED_HEATER: ("bheat", "Bed_Heater"), - Process.EXTRUDER: ("extrude", "extruder"), - } - if self.current_process in process_map: - obj_key, item_key = process_map[self.current_process] - self.objects[obj_key][item_key] = answer - if self.current_process in [Process.BED_HEATER, Process.EXTRUDER]: - self.run_gcode_signal.emit("TURN_OFF_HEATERS") - self.run_routine(self.current_process) - elif self.current_process == Process.AXIS_MAINTENANCE: - if answer == "yes": - self._run_axis_maintenance_gcode(self.current_object) - else: - self.change_page(self.indexOf(self.panel.axes_page)) - - def _send_routine_gcode(self): - """Send the correct G-code for the current process and object.""" - if self.current_process == Process.FAN: - fan_name = self.current_object or next(iter(self.objects["fans"]), None) - if fan_name: - if fan_name == "fan": - self.run_gcode_signal.emit("M106 S255\nM400") - else: - self.run_gcode_signal.emit( - f"SET_FAN_SPEED FAN={fan_name} SPEED=0.8\nM400" - ) - - return - - gcode_map = { - Process.BED_HEATER: "SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET=60", - Process.EXTRUDER: "SET_HEATER_TEMPERATURE HEATER=extruder TARGET=60", - (Process.AXIS, "x"): "G91\nG1 X50 F700\nG1 X-50 F700", - (Process.AXIS, "y"): "G91\nG1 Y50 F700\nG1 Y-50 F700", - (Process.AXIS, "z"): "G91\nG1 Z50 F600\nG1 Z-50 F600", - } - - key = ( - (self.current_process, self.current_object) - if self.current_process == Process.AXIS - else self.current_process + self.utilities_axes_btn.setObjectName("utilities_axes_btn") + + self.utilities_content_layout.addWidget(self.utilities_axes_btn, 1, 1, 1, 1) + + self.update_btn = BlocksCustomButton(parent=self) + self.update_btn.setSizePolicy(sizePolicy) + self.update_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.update_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.update_btn.setFont(font) + self.update_btn.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/system/media/btn_icons/update-software-icon.svg"), ) - if gcode := gcode_map.get(key): - self.run_gcode_signal.emit(f"{gcode}\nM400") - - def set_routine_check_page(self, title: str, label: str): - """Set text on routine page""" - self.panel.rc_tittle.setText(title) - self.panel.rc_label.setText(label) - - def update_led_values(self) -> None: - """Update led state and color values""" - if self.current_object not in self.objects["leds"]: - return - led_state: LedState = self.objects["leds"][self.current_object] - led_state.white = int(self.panel.leds_w_slider.value() * 255 / 100) - self.save_led_state() - - def _update_leds_from_config(self): - layout = self.panel.leds_content_layout - - while layout.count(): - if (child := layout.takeAt(0)) and child.widget(): - child.widget().deleteLater() # type: ignore - - led_names = [] - if not self.cg: - return - - # Collect LED names - for obj in self.cg: - if "led" in obj: - try: - name = obj.split()[1] - led_names.append(name) - self.objects["leds"][name] = LedState(led_type="white") - except IndexError: - pass - - max_columns = 3 - buttons = [] # store references to created buttons - - # Create LED buttons - for i, name in enumerate(led_names): - if self.panel.leds_widget: - button = BlocksCustomButton() - button.setFixedSize(200, 70) - button.setText(name) - button.setProperty("class", "menu_btn") - button.setPixmap(QtGui.QPixmap(":/ui/media/btn_icons/LEDs.svg")) - row, col = divmod(i, max_columns) - layout.addWidget(button, row, col) - button.clicked.connect(partial(self.handle_led_button, name)) - buttons.append(button) - - if len(buttons) == 1: - self.panel.utilities_leds_btn.clicked.connect( - partial(self.handle_led_button, led_names[0]) - ) - else: - self._connect_page_change( - self.panel.utilities_leds_btn, self.panel.leds_page - ) + self.update_btn.setObjectName("update_btn") - def toggle_led_state(self) -> None: - """Toggle leds""" - if self.current_object not in self.objects["leds"]: - return - led_state: LedState = self.objects["leds"][self.current_object] - if led_state.state == "off": - led_state.state = "on" - self.panel.toggle_led_button.state = ToggleAnimatedButton.State.ON - else: - led_state.state = "off" - self.panel.toggle_led_button.state = ToggleAnimatedButton.State.OFF - self.save_led_state() - - def handle_led_button(self, name: str) -> None: - """Handle led button clicked""" - self.current_object = name - led_state: LedState = self.objects["leds"].get(name) - if not led_state: - return - is_rgb = led_state.led_type == "rgb" - self.panel.leds_w_slider.setVisible(not is_rgb) - self.panel.leds_w_slider.setValue(led_state.white) - self.change_page(self.indexOf(self.panel.leds_slider_page)) - - def save_led_state(self): - """Save led state""" - if self.current_object: - if self.current_object in self.objects["leds"]: - led_state: LedState = self.objects["leds"][self.current_object] - self.run_gcode_signal.emit(led_state.get_gcode(self.current_object)) - - def axis_maintenance(self, axis: str) -> None: - """Routine, checks axis movement for printer debugging""" - self.current_process = Process.AXIS_MAINTENANCE - self.current_object = axis - self.run_gcode_signal.emit(f"G28 {axis.upper()}\nM400") - self.set_routine_check_page( - "Axis Maintenance", - f"Insert oil on the {axis.upper()} axis before confirming.", + self.utilities_content_layout.addWidget(self.update_btn, 2, 0, 1, 1) + self.utilities_routine_check_btn = BlocksCustomButton(parent=self) + self.utilities_routine_check_btn.setSizePolicy(sizePolicy) + self.utilities_routine_check_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.utilities_routine_check_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.utilities_routine_check_btn.setFont(font) + self.utilities_routine_check_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/routine.svg") ) - self.show_waiting_page( - self.indexOf(self.panel.rc_page), - f"Homing {axis.upper()} axis...", - 5000, + self.utilities_routine_check_btn.setObjectName("utilities_routine_check_btn") + + self.utilities_content_layout.addWidget( + self.utilities_routine_check_btn, 1, 0, 1, 1 ) - def _run_axis_maintenance_gcode(self, axis: str): - stepper_key = f"stepper_{axis}" - if stepper_key in self.stepper_limits: - max_pos = self.stepper_limits[stepper_key].get("max", 20) - distance = int(max_pos) - 20 - self.run_gcode_signal.emit( - f"G1 {axis.upper()}{distance} F3000\nM400\nG28 {axis.upper()}\nM400" - ) - self.show_waiting_page( - self.indexOf(self.panel.axes_page), - f"Running maintenance cycle on {axis.upper()} axis...", - 5000, - ) - else: - self.change_page(self.indexOf(self.panel.axes_page)) + self.utilities_input_shaper_btn = BlocksCustomButton(parent=self) + self.utilities_input_shaper_btn.setSizePolicy(sizePolicy) + self.utilities_input_shaper_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.utilities_input_shaper_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.utilities_input_shaper_btn.setFont(font) + self.utilities_input_shaper_btn.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/input_shaper/media/btn_icons/input_shaper.svg"), + ) + self.utilities_input_shaper_btn.setObjectName("utilities_input_shaper_btn") - def troubleshoot_request(self) -> None: - """Show troubleshoot page""" - self.troubleshoot_page.show() + self.utilities_content_layout.addWidget( + self.utilities_input_shaper_btn, 2, 1, 1, 1 + ) - def show_waiting_page(self, page_to_go_to: int, label: str, time_ms: int): - """Show placeholder page""" - self.call_load_panel.emit(True, label) - QtCore.QTimer.singleShot(time_ms, lambda: self.change_page(page_to_go_to)) + self.utilities_info_btn = BlocksCustomButton(parent=self) + self.utilities_info_btn.setSizePolicy(sizePolicy) + self.utilities_info_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.utilities_info_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.utilities_info_btn.setFont(font) + self.utilities_info_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/info.svg") + ) - def _connect_page_change(self, button: QtWidgets.QWidget, page: QtWidgets.QWidget): - if isinstance(button, QtWidgets.QAbstractButton): - button.clicked.connect(lambda: self.change_page(self.indexOf(page))) + self.utilities_info_btn.setObjectName("utilities_info_btn") - def change_page(self, index: int): - """Request change page by index""" - self.call_load_panel.emit(False, "") - self.troubleshoot_page.hide() - if index < self.count(): - self.request_change_page.emit(3, index) - - @QtCore.pyqtSlot(name="request-back") - def back_button(self) -> None: - """Request back""" - self.request_back.emit() + self.utilities_content_layout.addWidget(self.utilities_info_btn, 0, 0, 1, 1) + self.utilities_leds_btn = BlocksCustomButton(parent=self) + self.utilities_leds_btn.setSizePolicy(sizePolicy) + self.utilities_leds_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.utilities_leds_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.utilities_leds_btn.setFont(font) + self.utilities_leds_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/LEDs.svg") + ) + self.utilities_leds_btn.setObjectName("utilities_leds_btn") + self.utilities_content_layout.addWidget(self.utilities_leds_btn, 0, 1, 1, 1) + + self.verticalLayout.addLayout(self.utilities_content_layout) + + widget.setLayout(self.verticalLayout) + self.addWidget(widget) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.setWindowTitle(_translate("self", "StackedWidget")) + self.utilities_title_label.setText(_translate("self", "Utilities")) + self.utilities_axes_btn.setText(_translate("self", "Axis\nMaint.")) + self.update_btn.setText(_translate("self", "Update")) + self.utilities_routine_check_btn.setText(_translate("self", "Routine\nCheck")) + self.utilities_input_shaper_btn.setText(_translate("self", "Input\nShaper")) + self.utilities_info_btn.setText(_translate("self", "Info")) + self.utilities_leds_btn.setText(_translate("self", "LED's")) diff --git a/BlocksScreen/lib/panels/widgets/ControlTab/axisPage.py b/BlocksScreen/lib/panels/widgets/ControlTab/axisPage.py new file mode 100644 index 00000000..84d2ae4e --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/ControlTab/axisPage.py @@ -0,0 +1,580 @@ +import typing + +from PyQt6 import QtCore, QtGui, QtWidgets + +from lib.utils.check_button import BlocksCustomCheckButton +from lib.utils.icon_button import IconButton + + +class AxisPage(QtWidgets.QWidget): + run_gcode_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="run_gcode" + ) + request_back = QtCore.pyqtSignal(name="request_back") + + call_load_panel = QtCore.pyqtSignal(bool, str, name="call-load-panel") + + def __init__(self, parent: QtWidgets.QWidget) -> None: + super().__init__(parent) + + self.setObjectName("probe_offset_page") + self._setupUi() + + self.update() + + self.move_length: float = 1.0 + self.move_speed: float = 25.0 + + self.mva_back_btn.clicked.connect(self.request_back.emit) + self.mva_home_x_btn.clicked.connect( + lambda: self.run_gcode_signal.emit("G28 X\nM400") + ) + self.mva_home_y_btn.clicked.connect( + lambda: self.run_gcode_signal.emit("G28 Y\nM400") + ) + self.mva_home_z_btn.clicked.connect( + lambda: self.run_gcode_signal.emit("G28 Z\nM400") + ) + self.mva_home_all_btn.clicked.connect( + lambda: self.run_gcode_signal.emit("G28\nM400") + ) + + self.mva_up_btn.clicked.connect(lambda: self.handle_move_axis("Y")) + self.mva_down_btn.clicked.connect(lambda: self.handle_move_axis("Y-")) + self.mva_right_btn.clicked.connect(lambda: self.handle_move_axis("X")) + self.mva_left_btn.clicked.connect(lambda: self.handle_move_axis("X-")) + self.mva_z_up.clicked.connect( + lambda: self.handle_move_axis("Z-") # Move nozzle closer to bed + ) + self.mva_z_down.clicked.connect( + lambda: self.handle_move_axis("Z") # Move nozzle away from bed + ) + + self.mva_select_length_1_btn.toggled.connect( + lambda checked: self.handle_select_move_length(checked, value=1.0) + ) + self.mva_select_length_10_btn.toggled.connect( + lambda checked: self.handle_select_move_length(checked, value=10.0) + ) + self.mva_select_length_100_btn.toggled.connect( + lambda checked: self.handle_select_move_length(checked, value=100.0) + ) + self.mva_select_speed_25_btn.toggled.connect( + lambda checked: self.handle_select_move_speed(checked, value=25.0) + ) + self.mva_select_speed_50_btn.toggled.connect( + lambda checked: self.handle_select_move_speed(checked, value=50.0) + ) + self.mva_select_speed_100_btn.toggled.connect( + lambda checked: self.handle_select_move_speed(checked, value=100.0) + ) + + @QtCore.pyqtSlot(bool, float, name="handle-select-move-speed") + def handle_select_move_speed(self, checked: bool, value: float) -> None: + """Slot that changes the move speed of manual move commands, mainly used + for toggle buttons + + Args: + checked (bool): Button checked state + value (float): New move speed value + """ + if self.move_speed == value: + return + self.move_speed = value + + @QtCore.pyqtSlot(bool, float, name="handle-select-move-length") + def handle_select_move_length(self, checked: bool, value: float) -> None: + """Slot that changes the move length of manual move commands, + mainly used for toggle buttons + + + Args: + checked (bool): Button checked state + value (float): New length value + """ + if self.move_length == value: + return + self.move_length = value + + @QtCore.pyqtSlot(str, name="handle-move-axis") + def handle_move_axis(self, axis: str) -> None: + """Slot that requests manual move command + + Args: + axis (str): String that contains one of the following axis ` + ['X', + 'X-' + ,'Y' + ,'Y-' + ,'Z' + ,'Z-']`. [^1] + + --- + + [^1]: The **-** symbol indicates the negative direction for that axis + + """ + if axis not in ["X", "X-", "Y", "Y-", "Z", "Z-"]: + return + self.run_gcode_signal.emit( + f"G91\nG0 {axis}{float(self.move_length)} F{float(self.move_speed * 60)}\nG90\nM400" + ) + + @QtCore.pyqtSlot(str, list, name="on-toolhead-update") + def on_toolhead_update(self, field: str, values: list) -> None: + """Handles updated from toolhead printer object""" + if field == "position": + self.mva_x_value_label.setText(f"{values[0]:.2f}") + self.mva_y_value_label.setText(f"{values[1]:.2f}") + self.mva_z_value_label.setText(f"{values[2]:.3f}") + + if values[0] == "252,50" and values[1] == "250" and values[2] == "50": + self.call_load_panel.emit(False, "") + + def _setupUi(self) -> None: + widget = QtWidgets.QWidget(parent=self) + widget.setMinimumSize(QtCore.QSize(710, 410)) + widget.setMaximumSize(QtCore.QSize(710, 410)) + self.setObjectName("move_axis_page") + self.verticalLayout = QtWidgets.QVBoxLayout(self) + self.verticalLayout.setObjectName("verticalLayout") + self.mva_header_layout = QtWidgets.QHBoxLayout() + self.mva_header_layout.setObjectName("mva_header_layout") + spacerItem2 = QtWidgets.QSpacerItem( + 60, + 20, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.mva_header_layout.addItem(spacerItem2) + self.mva_title_label = QtWidgets.QLabel(parent=self) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth( + self.mva_title_label.sizePolicy().hasHeightForWidth() + ) + self.mva_title_label.setSizePolicy(sizePolicy) + self.mva_title_label.setMinimumSize(QtCore.QSize(0, 0)) + self.mva_title_label.setMaximumSize(QtCore.QSize(16777215, 60)) + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + self.mva_title_label.setFont(font) + self.mva_title_label.setStyleSheet("background: transparent; color: white;") + self.mva_title_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.mva_title_label.setObjectName("mva_title_label") + self.mva_header_layout.addWidget(self.mva_title_label) + + self.mva_back_btn = IconButton(parent=self) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed + ) + self.mva_back_btn.setSizePolicy(sizePolicy) + self.mva_back_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_back_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_back_btn.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.mva_back_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") + ) + self.mva_back_btn.setObjectName("mva_back_btn") + self.mva_header_layout.addWidget( + self.mva_back_btn, + 0, + QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter, + ) + + self.verticalLayout.addLayout(self.mva_header_layout) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.mva_home_axis_layout = QtWidgets.QVBoxLayout() + self.mva_home_axis_layout.setContentsMargins(5, 5, 5, 5) + self.mva_home_axis_layout.setObjectName("mva_home_axis_layout") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + ) + sizePolicy.setHorizontalStretch(1) + sizePolicy.setVerticalStretch(1) + + self.mva_home_x_btn = IconButton(parent=self) + self.mva_home_x_btn.setSizePolicy(sizePolicy) + self.mva_home_x_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_home_x_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_home_x_btn.setObjectName("mva_home_x_btn") + self.mva_home_x_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/motion/media/btn_icons/home_x.svg") + ) + self.mva_home_axis_layout.addWidget( + self.mva_home_x_btn, 0, QtCore.Qt.AlignmentFlag.AlignHCenter + ) + + self.mva_home_y_btn = IconButton(parent=self) + self.mva_home_y_btn.setSizePolicy(sizePolicy) + self.mva_home_y_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_home_y_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_home_y_btn.setObjectName("mva_home_y_btn") + self.mva_home_y_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/motion/media/btn_icons/home_y.svg") + ) + self.mva_home_axis_layout.addWidget( + self.mva_home_y_btn, 0, QtCore.Qt.AlignmentFlag.AlignHCenter + ) + + self.mva_home_z_btn = IconButton(parent=self) + self.mva_home_z_btn.setSizePolicy(sizePolicy) + self.mva_home_z_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_home_z_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_home_z_btn.setObjectName("mva_home_z_btn") + self.mva_home_z_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/motion/media/btn_icons/home_z.svg") + ) + self.mva_home_axis_layout.addWidget( + self.mva_home_z_btn, 0, QtCore.Qt.AlignmentFlag.AlignHCenter + ) + + self.mva_home_all_btn = IconButton(parent=self) + self.mva_home_all_btn.setSizePolicy(sizePolicy) + self.mva_home_all_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_home_all_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_home_all_btn.setObjectName("mva_home_all_btn") + self.mva_home_all_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/motion/media/btn_icons/home_all.svg") + ) + self.mva_home_axis_layout.addWidget( + self.mva_home_all_btn, 0, QtCore.Qt.AlignmentFlag.AlignHCenter + ) + + self.horizontalLayout_2.addLayout(self.mva_home_axis_layout) + self.verticalLayout_6 = QtWidgets.QVBoxLayout() + self.verticalLayout_6.setObjectName("verticalLayout_6") + self.label_2 = QtWidgets.QLabel(parent=self) + self.label_2.setMaximumSize(QtCore.QSize(16777215, 20)) + font = QtGui.QFont() + font.setPointSize(14) + self.label_2.setFont(font) + self.label_2.setStyleSheet("color:white") + self.label_2.setObjectName("label_2") + self.verticalLayout_6.addWidget(self.label_2) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + + self.axis_select_length_group = QtWidgets.QButtonGroup(self) + self.axis_select_length_group.setObjectName("extrude_select_length_group") + + self.mva_select_length_1_btn = BlocksCustomCheckButton(parent=self) + self.mva_select_length_1_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_length_1_btn.setMaximumSize(QtCore.QSize(90, 90)) + self.mva_select_length_1_btn.setFont(font) + self.mva_select_length_1_btn.setCheckable(True) + self.mva_select_length_1_btn.setChecked(True) + self.mva_select_length_1_btn.setAutoExclusive(True) + self.mva_select_length_1_btn.setObjectName("mva_select_length_1_btn") + self.axis_select_length_group.addButton(self.mva_select_length_1_btn) + self.horizontalLayout_3.addWidget(self.mva_select_length_1_btn) + + self.mva_select_length_10_btn = BlocksCustomCheckButton(parent=self) + self.mva_select_length_10_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_length_10_btn.setMaximumSize(QtCore.QSize(90, 90)) + self.mva_select_length_10_btn.setFont(font) + self.mva_select_length_10_btn.setCheckable(True) + self.mva_select_length_10_btn.setAutoExclusive(True) + self.mva_select_length_10_btn.setObjectName("mva_select_length_10_btn") + self.axis_select_length_group.addButton(self.mva_select_length_10_btn) + self.horizontalLayout_3.addWidget(self.mva_select_length_10_btn) + + self.mva_select_length_100_btn = BlocksCustomCheckButton(parent=self) + self.mva_select_length_100_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_length_100_btn.setMaximumSize(QtCore.QSize(90, 90)) + self.mva_select_length_100_btn.setFont(font) + self.mva_select_length_100_btn.setAutoExclusive(True) + self.mva_select_length_100_btn.setCheckable(True) + self.mva_select_length_100_btn.setObjectName("mva_select_length_100_btn") + self.axis_select_length_group.addButton(self.mva_select_length_100_btn) + self.horizontalLayout_3.addWidget(self.mva_select_length_100_btn) + + self.verticalLayout_6.addLayout(self.horizontalLayout_3) + self.label = QtWidgets.QLabel(parent=self) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) + self.label.setSizePolicy(sizePolicy) + self.label.setMaximumSize(QtCore.QSize(16777215, 20)) + + self.label.setFont(font) + self.label.setStyleSheet("color:white") + self.label.setObjectName("label") + self.verticalLayout_6.addWidget(self.label) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + + self.axis_select_speed_group = QtWidgets.QButtonGroup(self) + self.axis_select_speed_group.setObjectName("extrude_select_length_group") + + self.mva_select_speed_25_btn = BlocksCustomCheckButton(parent=self) + self.mva_select_speed_25_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_speed_25_btn.setMaximumSize(QtCore.QSize(90, 90)) + self.mva_select_speed_25_btn.setFont(font) + self.mva_select_speed_25_btn.setCheckable(True) + self.mva_select_speed_25_btn.setChecked(True) + self.mva_select_speed_25_btn.setAutoExclusive(True) + self.mva_select_speed_25_btn.setObjectName("mva_select_speed_25_btn") + self.axis_select_speed_group.addButton(self.mva_select_speed_25_btn) + self.horizontalLayout_4.addWidget(self.mva_select_speed_25_btn) + + self.mva_select_speed_50_btn = BlocksCustomCheckButton(parent=self) + self.mva_select_speed_50_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_speed_50_btn.setMaximumSize(QtCore.QSize(90, 90)) + self.mva_select_speed_50_btn.setFont(font) + self.mva_select_speed_50_btn.setCheckable(True) + self.mva_select_speed_50_btn.setAutoExclusive(True) + self.mva_select_speed_50_btn.setObjectName("mva_select_speed_50_btn") + self.axis_select_speed_group.addButton(self.mva_select_speed_50_btn) + self.horizontalLayout_4.addWidget(self.mva_select_speed_50_btn) + + self.mva_select_speed_100_btn = BlocksCustomCheckButton(parent=self) + self.mva_select_speed_100_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_speed_100_btn.setMaximumSize(QtCore.QSize(90, 90)) + self.mva_select_speed_100_btn.setFont(font) + self.mva_select_speed_100_btn.setCheckable(True) + self.mva_select_speed_100_btn.setAutoExclusive(True) + self.mva_select_speed_100_btn.setObjectName("mva_select_speed_100_btn") + self.axis_select_speed_group.addButton(self.mva_select_speed_100_btn) + self.horizontalLayout_4.addWidget(self.mva_select_speed_100_btn) + + self.verticalLayout_6.addLayout(self.horizontalLayout_4) + self.horizontalLayout_2.addLayout(self.verticalLayout_6) + self.horizontalLayout_5 = QtWidgets.QHBoxLayout() + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.gridLayout_2 = QtWidgets.QGridLayout() + self.gridLayout_2.setContentsMargins(0, 5, 0, 5) + self.gridLayout_2.setObjectName("gridLayout_2") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum + ) + sizePolicy.setHorizontalStretch(1) + sizePolicy.setVerticalStretch(1) + + self.mva_left_btn = IconButton(parent=self) + self.mva_left_btn.setSizePolicy(sizePolicy) + self.mva_left_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_left_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_left_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/left_arrow.svg") + ) + self.mva_left_btn.setObjectName("mva_left_btn") + self.gridLayout_2.addWidget( + self.mva_left_btn, 1, 0, 1, 1, QtCore.Qt.AlignmentFlag.AlignRight + ) + + self.mva_right_btn = IconButton(parent=self) + self.mva_right_btn.setSizePolicy(sizePolicy) + self.mva_right_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_right_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_right_btn.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/arrow_icons/media/btn_icons/right_arrow.svg"), + ) + self.mva_right_btn.setObjectName("mva_right_btn") + self.gridLayout_2.addWidget( + self.mva_right_btn, 1, 2, 1, 1, QtCore.Qt.AlignmentFlag.AlignLeft + ) + + self.mva_down_btn = IconButton(parent=self) + self.mva_down_btn.setSizePolicy(sizePolicy) + self.mva_down_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_down_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_down_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/down_arrow.svg") + ) + self.mva_down_btn.setObjectName("mva_down_btn") + self.gridLayout_2.addWidget( + self.mva_down_btn, 2, 1, 1, 1, QtCore.Qt.AlignmentFlag.AlignTop + ) + + self.mva_up_btn = IconButton(parent=self) + self.mva_up_btn.setSizePolicy(sizePolicy) + self.mva_up_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_up_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_up_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/up_arrow.svg") + ) + self.mva_up_btn.setObjectName("mva_up_btn") + self.gridLayout_2.addWidget( + self.mva_up_btn, 0, 1, 1, 1, QtCore.Qt.AlignmentFlag.AlignBottom + ) + + self.mva_middle = IconButton(parent=self) + self.mva_middle.setSizePolicy(sizePolicy) + self.mva_middle.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_middle.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_middle.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/center_arrows.svg") + ) + self.mva_middle.setObjectName("mva_middle") + + self.gridLayout_2.addWidget(self.mva_middle, 1, 1, 1, 1) + self.horizontalLayout_5.addLayout(self.gridLayout_2) + + self.mva_z_layout = QtWidgets.QVBoxLayout() + self.mva_z_layout.setObjectName("mva_z_layout") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + ) + sizePolicy.setHorizontalStretch(1) + sizePolicy.setVerticalStretch(1) + + self.mva_z_up = IconButton(parent=self) + self.mva_z_up.setSizePolicy(sizePolicy) + self.mva_z_up.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_z_up.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_z_up.setIconSize(QtCore.QSize(16, 16)) + self.mva_z_up.setProperty( + "icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/up_arrow.svg") + ) + self.mva_z_up.setObjectName("mva_z_up") + self.mva_z_layout.addWidget( + self.mva_z_up, 0, QtCore.Qt.AlignmentFlag.AlignHCenter + ) + + self.mva_z_down = IconButton(parent=self) + self.mva_z_down.setSizePolicy(sizePolicy) + self.mva_z_down.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_z_down.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_z_down.setProperty( + "icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/down_arrow.svg") + ) + self.mva_z_down.setObjectName("mva_z_down") + self.mva_z_layout.addWidget( + self.mva_z_down, 0, QtCore.Qt.AlignmentFlag.AlignHCenter + ) + + self.horizontalLayout_5.addLayout(self.mva_z_layout) + self.horizontalLayout_2.addLayout(self.horizontalLayout_5) + self.verticalLayout.addLayout(self.horizontalLayout_2) + self.horizontalLayout_6 = QtWidgets.QHBoxLayout() + self.horizontalLayout_6.setObjectName("horizontalLayout_6") + self.mva_x_label = QtWidgets.QLabel(parent=self) + self.mva_x_label.setEnabled(True) + + self.mva_x_label.setFont(font) + self.mva_x_label.setStyleSheet("background: transparent; color: white;") + self.mva_x_label.setObjectName("mva_x_label") + self.horizontalLayout_6.addWidget( + self.mva_x_label, 0, QtCore.Qt.AlignmentFlag.AlignRight + ) + self.mva_x_value_label = QtWidgets.QLabel(parent=self) + self.mva_x_value_label.setEnabled(True) + + self.mva_x_value_label.setFont(font) + self.mva_x_value_label.setStyleSheet("background: transparent; color: white;") + self.mva_x_value_label.setObjectName("mva_x_value_label") + self.horizontalLayout_6.addWidget(self.mva_x_value_label) + self.mva_y_label = QtWidgets.QLabel(parent=self) + self.mva_y_label.setEnabled(True) + + self.mva_y_label.setFont(font) + self.mva_y_label.setStyleSheet("background: transparent; color: white;") + self.mva_y_label.setObjectName("mva_y_label") + self.horizontalLayout_6.addWidget( + self.mva_y_label, 0, QtCore.Qt.AlignmentFlag.AlignRight + ) + self.mva_y_value_label = QtWidgets.QLabel(parent=self) + self.mva_y_value_label.setEnabled(True) + + self.mva_y_value_label.setFont(font) + self.mva_y_value_label.setStyleSheet("background: transparent; color: white;") + self.mva_y_value_label.setObjectName("mva_y_value_label") + self.horizontalLayout_6.addWidget(self.mva_y_value_label) + self.mva_z_label = QtWidgets.QLabel(parent=self) + self.mva_z_label.setEnabled(True) + + self.mva_z_label.setFont(font) + self.mva_z_label.setStyleSheet("background: transparent; color: white;") + self.mva_z_label.setObjectName("mva_z_label") + self.horizontalLayout_6.addWidget( + self.mva_z_label, 0, QtCore.Qt.AlignmentFlag.AlignRight + ) + self.mva_z_value_label = QtWidgets.QLabel(parent=self) + self.mva_z_value_label.setEnabled(True) + + self.mva_z_value_label.setFont(font) + self.mva_z_value_label.setStyleSheet("background: transparent; color: white;") + self.mva_z_value_label.setObjectName("mva_z_value_label") + self.horizontalLayout_6.addWidget(self.mva_z_value_label) + self.verticalLayout.addLayout(self.horizontalLayout_6) + widget.setLayout(self.verticalLayout) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.mva_x_label.setText(_translate("controlStackedWidget", "X:")) + self.mva_y_label.setText(_translate("controlStackedWidget", "Y:")) + self.mva_z_label.setText(_translate("controlStackedWidget", "Z:")) + self.mva_z_value_label.setText(_translate("controlStackedWidget", "0")) + self.mva_y_value_label.setText(_translate("controlStackedWidget", "0")) + self.mva_x_value_label.setText(_translate("controlStackedWidget", "0")) + self.mva_title_label.setText(_translate("controlStackedWidget", "Move Axis")) + self.mva_title_label.setProperty( + "class", _translate("controlStackedWidget", "title_text") + ) + self.mva_back_btn.setText(_translate("controlStackedWidget", "Back")) + self.mva_back_btn.setProperty( + "class", _translate("controlStackedWidget", "menu_btn") + ) + self.mva_back_btn.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) + self.mva_z_up.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) + self.mva_z_down.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) + self.mva_home_x_btn.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) + self.mva_home_y_btn.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) + self.mva_home_z_btn.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) + self.mva_home_all_btn.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) + self.mva_select_speed_25_btn.setText(_translate("controlStackedWidget", "25")) + self.mva_select_speed_50_btn.setText(_translate("controlStackedWidget", "50")) + self.mva_select_speed_100_btn.setText(_translate("controlStackedWidget", "100")) + self.label.setText(_translate("controlStackedWidget", "Move Speed mm/s")) + self.mva_select_length_1_btn.setText(_translate("controlStackedWidget", "1")) + self.mva_select_length_10_btn.setText(_translate("controlStackedWidget", "10")) + self.mva_select_length_100_btn.setText( + _translate("controlStackedWidget", "100") + ) + self.label_2.setText(_translate("controlStackedWidget", "Move Length mm")) + self.mva_left_btn.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) + self.mva_right_btn.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) + self.mva_down_btn.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) + self.mva_up_btn.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) + self.mva_middle.setProperty( + "button_type", _translate("controlStackedWidget", "icon") + ) diff --git a/BlocksScreen/lib/panels/widgets/ControlTab/extruderPage.py b/BlocksScreen/lib/panels/widgets/ControlTab/extruderPage.py new file mode 100644 index 00000000..06a36e0a --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/ControlTab/extruderPage.py @@ -0,0 +1,500 @@ +import typing + +from PyQt6 import QtCore, QtGui, QtWidgets + +from lib.utils.check_button import BlocksCustomCheckButton +from lib.utils.icon_button import IconButton +from lib.utils.blocks_label import BlocksLabel +from lib.utils.blocks_button import BlocksCustomButton +from lib.printer import Printer + + +class ExtruderPage(QtWidgets.QWidget): + run_gcode_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="run_gcode" + ) + + request_back = QtCore.pyqtSignal(name="request-back-button") + + def __init__( + self, + parent: QtWidgets.QWidget, + printer: Printer, + ) -> None: + super().__init__(parent) + + self.setObjectName("probe_offset_page") + self._setupUi() + + self.update() + + self.printer: Printer = printer + self.timers = [] + self.extrude_length: int = 10 + self.extrude_feedrate: int = 2 + self.extrude_page_message: str = "" + + self.exp_extrude_btn.clicked.connect( + lambda: self.handle_extrusion(True) + ) # True for extrusion + self.exp_unextrude_btn.clicked.connect( + lambda: self.handle_extrusion(False) + ) # False for retraction + + self.exp_back_btn.clicked.connect(self.request_back.emit) + self.extrude_select_length_10_btn.toggled.connect( + lambda: self.handle_toggle_extrude_length( + caller=self.extrude_select_length_10_btn, value=10 + ) + ) + self.extrude_select_length_50_btn.toggled.connect( + lambda: self.handle_toggle_extrude_length( + caller=self.extrude_select_length_50_btn, value=50 + ) + ) + self.extrude_select_length_100_btn.toggled.connect( + lambda: self.handle_toggle_extrude_length( + caller=self.extrude_select_length_100_btn, value=100 + ) + ) + self.extrude_select_feedrate_2_btn.toggled.connect( + lambda: self.handle_toggle_extrude_feedrate( + caller=self.extrude_select_feedrate_2_btn, value=2 + ) + ) + self.extrude_select_feedrate_5_btn.toggled.connect( + lambda: self.handle_toggle_extrude_feedrate( + caller=self.extrude_select_feedrate_5_btn, value=5 + ) + ) + self.extrude_select_feedrate_10_btn.toggled.connect( + lambda: self.handle_toggle_extrude_feedrate( + caller=self.extrude_select_feedrate_10_btn, value=10 + ) + ) + + @QtCore.pyqtSlot(str, name="handle-extrusion") + def handle_extrusion(self, extrude: bool) -> None: + """Slot that requests an extrusion/unextrusion move + + Args: + extrude (bool): If True extrudes otherwise unextrudes. + """ + can_extrude = bool(self.printer.heaters_object["extruder"]["can_extrude"]) + if not can_extrude: + self.extrude_page_message = "Temperature too cold to extrude" + self.exp_info_label.setText(self.extrude_page_message) + return + if extrude: + self.run_gcode_signal.emit( + f"M83\nG1 E{self.extrude_length} F{self.extrude_feedrate * 60}\nM82\nM400" + ) + self.extrude_page_message = "Extruding" + self.exp_info_label.setText(self.extrude_page_message) + else: + self.run_gcode_signal.emit( + f"M83\nG1 E-{self.extrude_length} F{self.extrude_feedrate * 60}\nM82\nM400" + ) + self.extrude_page_message = "Retracting" + self.exp_info_label.setText(self.extrude_page_message) + # This block of code schedules a method to be called in x amount of milliseconds + _sch_time_s = float( + self.extrude_length / self.extrude_feedrate + ) # calculate the amount of time it'll take for the operation + self.extrude_page_message = "Ready" + self.register_timed_callback( + int(_sch_time_s + 2.0) * 1000, # In milliseconds + lambda: self.exp_info_label.setText(self.extrude_page_message), + ) + + def register_timed_callback(self, time: int, callback: callable) -> None: + """Registers timed callback and starts the timeout""" + _timer = QtCore.QTimer() + _timer.setSingleShot(True) + _timer.timeout.connect(callback) + _timer.start(int(time)) + self.timers.append(_timer) + + @QtCore.pyqtSlot(bool, "PyQt_PyObject", int, name="select-extrude-feedrate") + def handle_toggle_extrude_feedrate(self, caller, value: int) -> None: + """Slot to change the extruder feedrate, mainly used for toggle buttons + + Args: + checked (bool): Button checked state + caller (PyQtObject): The button that called this slot + value (int): New value for the extruder feedrate + """ + if value == self.extrude_feedrate: + return + self.extrude_feedrate = value + + @QtCore.pyqtSlot(bool, "PyQt_PyObject", int, name="select-extrude-length") + def handle_toggle_extrude_length(self, caller, value: int) -> None: + """Slot that changes the extrude length, mainly used for toggle buttons + + Args: + checked (bool): Button checked state + caller (PyQtObject): The button that called this slot + value (int): New value for the extrude length + """ + if self.extrude_length == value: + return + self.extrude_length = value + + def paintEvent(self, a0: QtGui.QPaintEvent | None) -> None: + if self.extrude_page.isVisible(): + self.exp_info_label.setText(self.extrude_page_message) + return super().paintEvent(a0) + + def _setupUi(self) -> None: + widget = QtWidgets.QWidget(parent=self) + widget.setMinimumSize(QtCore.QSize(710, 410)) + widget.setMaximumSize(QtCore.QSize(710, 410)) + self.setObjectName("fans_page") + self.extrude_page = QtWidgets.QWidget() + self.extrude_page.setMinimumSize(QtCore.QSize(710, 400)) + self.extrude_page.setMaximumSize(QtCore.QSize(720, 420)) + self.extrude_page.setObjectName("extrude_page") + self.verticalLayout = QtWidgets.QVBoxLayout(self.extrude_page) + self.verticalLayout.setObjectName("verticalLayout") + spacerItem = QtWidgets.QSpacerItem( + 20, + 24, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem) + self.exp_header_layout = QtWidgets.QHBoxLayout() + self.exp_header_layout.setObjectName("exp_header_layout") + spacerItem1 = QtWidgets.QSpacerItem( + 60, + 60, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.exp_header_layout.addItem(spacerItem1) + self.exp_title_label = QtWidgets.QLabel(parent=self.extrude_page) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth( + self.exp_title_label.sizePolicy().hasHeightForWidth() + ) + self.exp_title_label.setSizePolicy(sizePolicy) + self.exp_title_label.setMinimumSize(QtCore.QSize(0, 60)) + self.exp_title_label.setMaximumSize(QtCore.QSize(16777215, 60)) + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + self.exp_title_label.setFont(font) + self.exp_title_label.setStyleSheet("background: transparent; color: white;") + self.exp_title_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.exp_title_label.setObjectName("exp_title_label") + self.exp_header_layout.addWidget(self.exp_title_label) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(20) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.exp_back_btn = IconButton(parent=self.extrude_page) + + self.exp_back_btn.setSizePolicy(sizePolicy) + self.exp_back_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.exp_back_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.exp_back_btn.setFont(font) + self.exp_back_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") + ) + self.exp_back_btn.setObjectName("exp_back_btn") + + self.exp_header_layout.addWidget( + self.exp_back_btn, + 0, + QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter, + ) + self.verticalLayout.addLayout(self.exp_header_layout) + self.exp_vertical_content_layout = QtWidgets.QVBoxLayout() + self.exp_vertical_content_layout.setContentsMargins(5, 5, 5, 5) + self.exp_vertical_content_layout.setObjectName("exp_vertical_content_layout") + + font = QtGui.QFont() + font.setPointSize(14) + + self.exp_length_group_box = QtWidgets.QGroupBox(parent=self.extrude_page) + self.exp_length_group_box.setMinimumSize(QtCore.QSize(0, 80)) + self.exp_length_group_box.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.exp_length_group_box.setFont(font) + self.exp_length_group_box.setStyleSheet("color:white") + self.exp_length_group_box.setAlignment( + QtCore.Qt.AlignmentFlag.AlignLeading + | QtCore.Qt.AlignmentFlag.AlignLeft + | QtCore.Qt.AlignmentFlag.AlignVCenter + ) + self.exp_length_group_box.setFlat(True) + self.exp_length_group_box.setObjectName("exp_length_group_box") + + self.layoutWidget = QtWidgets.QWidget(parent=self.exp_length_group_box) + self.layoutWidget.setGeometry(QtCore.QRect(0, 20, 681, 61)) + self.layoutWidget.setObjectName("layoutWidget") + self.exp_length_content_layout = QtWidgets.QHBoxLayout(self.layoutWidget) + self.exp_length_content_layout.setContentsMargins(5, 5, 5, 5) + self.exp_length_content_layout.setSpacing(5) + self.exp_length_content_layout.setObjectName("exp_length_content_layout") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + font = QtGui.QFont() + font.setPointSize(16) + font.setWeight(50) + + self.extrude_select_length_group = QtWidgets.QButtonGroup(self) + self.extrude_select_length_group.setObjectName("extrude_select_length_group") + + self.extrude_select_length_10_btn = BlocksCustomCheckButton( + parent=self.layoutWidget + ) + self.extrude_select_length_10_btn.setSizePolicy(sizePolicy) + self.extrude_select_length_10_btn.setFont(font) + self.extrude_select_length_10_btn.setCheckable(True) + self.extrude_select_length_10_btn.setChecked(True) + self.extrude_select_length_10_btn.setObjectName("extrude_select_length_10_btn") + + self.extrude_select_length_group.addButton(self.extrude_select_length_10_btn) + self.exp_length_content_layout.addWidget(self.extrude_select_length_10_btn) + + self.extrude_select_length_50_btn = BlocksCustomCheckButton( + parent=self.layoutWidget + ) + self.extrude_select_length_50_btn.setSizePolicy(sizePolicy) + self.extrude_select_length_50_btn.setFont(font) + self.extrude_select_length_50_btn.setCheckable(True) + self.extrude_select_length_50_btn.setObjectName("extrude_select_length_50_btn") + + self.extrude_select_length_group.addButton(self.extrude_select_length_50_btn) + self.exp_length_content_layout.addWidget(self.extrude_select_length_50_btn) + + self.extrude_select_length_100_btn = BlocksCustomCheckButton( + parent=self.layoutWidget + ) + self.extrude_select_length_100_btn.setSizePolicy(sizePolicy) + self.extrude_select_length_100_btn.setFont(font) + self.extrude_select_length_100_btn.setCheckable(True) + self.extrude_select_length_100_btn.setObjectName( + "extrude_select_length_100_btn" + ) + + self.extrude_select_length_group.addButton(self.extrude_select_length_100_btn) + self.exp_length_content_layout.addWidget(self.extrude_select_length_100_btn) + self.exp_vertical_content_layout.addWidget(self.exp_length_group_box) + + font = QtGui.QFont() + font.setPointSize(14) + + self.exp_feedrate_group_box = QtWidgets.QGroupBox(parent=self.extrude_page) + self.exp_feedrate_group_box.setMinimumSize(QtCore.QSize(0, 80)) + self.exp_feedrate_group_box.setFont(font) + self.exp_feedrate_group_box.setStyleSheet("color:white") + self.exp_feedrate_group_box.setObjectName("exp_feedrate_group_box") + + self.layoutWidget1 = QtWidgets.QWidget(parent=self.exp_feedrate_group_box) + self.layoutWidget1.setGeometry(QtCore.QRect(0, 19, 681, 61)) + self.layoutWidget1.setObjectName("layoutWidget1") + + self.exp_feedrate_content_layout = QtWidgets.QHBoxLayout(self.layoutWidget1) + self.exp_feedrate_content_layout.setContentsMargins(5, 5, 5, 5) + self.exp_feedrate_content_layout.setSpacing(5) + self.exp_feedrate_content_layout.setObjectName("exp_feedrate_content_layout") + + font = QtGui.QFont() + font.setPointSize(16) + font.setBold(False) + font.setWeight(50) + + self.extrude_select_feedrate_group = QtWidgets.QButtonGroup(self) + self.extrude_select_feedrate_group.setObjectName( + "extrude_select_feedrate_group" + ) + + self.extrude_select_feedrate_2_btn = BlocksCustomCheckButton( + parent=self.layoutWidget1 + ) + self.extrude_select_feedrate_2_btn.setSizePolicy(sizePolicy) + self.extrude_select_feedrate_2_btn.setFont(font) + self.extrude_select_feedrate_2_btn.setCheckable(True) + self.extrude_select_feedrate_2_btn.setChecked(True) + self.extrude_select_feedrate_2_btn.setObjectName( + "extrude_select_feedrate_2_btn" + ) + + self.extrude_select_feedrate_group.addButton(self.extrude_select_feedrate_2_btn) + self.exp_feedrate_content_layout.addWidget(self.extrude_select_feedrate_2_btn) + + self.extrude_select_feedrate_5_btn = BlocksCustomCheckButton( + parent=self.layoutWidget1 + ) + self.extrude_select_feedrate_5_btn.setSizePolicy(sizePolicy) + self.extrude_select_feedrate_5_btn.setFont(font) + self.extrude_select_feedrate_5_btn.setCheckable(True) + self.extrude_select_feedrate_5_btn.setObjectName( + "extrude_select_feedrate_5_btn" + ) + + self.extrude_select_feedrate_group.addButton(self.extrude_select_feedrate_5_btn) + self.exp_feedrate_content_layout.addWidget(self.extrude_select_feedrate_5_btn) + + self.extrude_select_feedrate_10_btn = BlocksCustomCheckButton( + parent=self.layoutWidget1 + ) + self.extrude_select_feedrate_10_btn.setSizePolicy(sizePolicy) + self.extrude_select_feedrate_10_btn.setFont(font) + self.extrude_select_feedrate_10_btn.setCheckable(True) + self.extrude_select_feedrate_10_btn.setObjectName( + "extrude_select_feedrate_10_btn" + ) + self.extrude_select_feedrate_group.addButton( + self.extrude_select_feedrate_10_btn + ) + self.exp_feedrate_content_layout.addWidget(self.extrude_select_feedrate_10_btn) + self.exp_vertical_content_layout.addWidget(self.exp_feedrate_group_box) + + self.exp_movement_content_layout = QtWidgets.QVBoxLayout() + self.exp_movement_content_layout.setContentsMargins(-1, 5, -1, -1) + self.exp_movement_content_layout.setSpacing(0) + self.exp_movement_content_layout.setObjectName("exp_movement_content_layout") + + self.exp_buttons_layout = QtWidgets.QHBoxLayout() + self.exp_buttons_layout.setContentsMargins(5, 5, 5, 5) + self.exp_buttons_layout.setObjectName("exp_buttons_layout") + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(20) + font.setItalic(False) + font.setStyleStrategy(QtGui.QFont.StyleStrategy.PreferAntialias) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + ) + self.exp_unextrude_btn = BlocksCustomButton(parent=self.extrude_page) + self.exp_unextrude_btn.setSizePolicy(sizePolicy) + self.exp_unextrude_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.exp_unextrude_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.exp_unextrude_btn.setFont(font) + self.exp_unextrude_btn.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/extruder_related/media/btn_icons/extrude.svg"), + ) + self.exp_unextrude_btn.setObjectName("exp_unextrude_btn") + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(16) + + self.exp_buttons_layout.addWidget(self.exp_unextrude_btn) + self.exp_nozzle_icon_label = BlocksLabel(parent=self.extrude_page) + self.exp_nozzle_icon_label.setMinimumSize(QtCore.QSize(60, 60)) + self.exp_nozzle_icon_label.setMaximumSize(QtCore.QSize(60, 60)) + self.exp_nozzle_icon_label.setFont(font) + self.exp_nozzle_icon_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.exp_nozzle_icon_label.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/extruder_related/media/btn_icons/nozzle.svg"), + ) + self.exp_nozzle_icon_label.setObjectName("exp_nozzle_icon_label") + self.exp_buttons_layout.addWidget(self.exp_nozzle_icon_label) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(20) + font.setItalic(False) + font.setStyleStrategy(QtGui.QFont.StyleStrategy.PreferAntialias) + + self.exp_extrude_btn = BlocksCustomButton(parent=self.extrude_page) + self.exp_extrude_btn.setSizePolicy(sizePolicy) + self.exp_extrude_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.exp_extrude_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.exp_extrude_btn.setFont(font) + self.exp_extrude_btn.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/extruder_related/media/btn_icons/extrude.svg"), + ) + self.exp_extrude_btn.setObjectName("exp_extrude_btn") + + self.exp_buttons_layout.addWidget(self.exp_extrude_btn) + self.exp_movement_content_layout.addLayout(self.exp_buttons_layout) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Minimum + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + font = QtGui.QFont() + font.setFamily("Montserrat") + font.setPointSize(14) + + self.exp_info_layout = QtWidgets.QHBoxLayout() + self.exp_info_layout.setContentsMargins(5, 5, 5, 5) + self.exp_info_layout.setObjectName("exp_info_layout") + + self.exp_info_label = QtWidgets.QLabel(parent=self.extrude_page) + self.exp_info_label.setSizePolicy(sizePolicy) + self.exp_info_label.setFont(font) + self.exp_info_label.setStyleSheet("background: transparent; color: white;") + self.exp_info_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.exp_info_label.setObjectName("exp_info_label") + self.exp_info_layout.addWidget(self.exp_info_label) + self.exp_movement_content_layout.addLayout(self.exp_info_layout) + self.exp_movement_content_layout.setStretch(1, 1) + self.exp_vertical_content_layout.addLayout(self.exp_movement_content_layout) + self.exp_vertical_content_layout.setStretch(2, 1) + self.verticalLayout.addLayout(self.exp_vertical_content_layout) + widget.setLayout(self.verticalLayout) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.exp_title_label.setText(_translate("controlStackedWidget", "Extrude")) + self.exp_back_btn.setText(_translate("controlStackedWidget", "Back")) + self.exp_length_group_box.setTitle( + _translate("controlStackedWidget", "Extrude Length (mm)") + ) + self.extrude_select_length_10_btn.setText( + _translate("controlStackedWidget", "10") + ) + self.extrude_select_length_50_btn.setText( + _translate("controlStackedWidget", "50") + ) + self.extrude_select_length_100_btn.setText( + _translate("controlStackedWidget", "100") + ) + self.exp_feedrate_group_box.setTitle( + _translate("controlStackedWidget", "Extrude Feedrate (mm/s)") + ) + self.extrude_select_feedrate_2_btn.setText( + _translate("controlStackedWidget", "2") + ) + self.extrude_select_feedrate_5_btn.setText( + _translate("controlStackedWidget", "5") + ) + self.extrude_select_feedrate_10_btn.setText( + _translate("controlStackedWidget", "10") + ) + self.exp_unextrude_btn.setText(_translate("controlStackedWidget", "Retract")) + self.exp_extrude_btn.setText(_translate("controlStackedWidget", "Extrude")) + self.exp_info_label.setText( + _translate("controlStackedWidget", "Nozzle heating to extrude") + ) diff --git a/BlocksScreen/lib/panels/widgets/ControlTab/fansPage.py b/BlocksScreen/lib/panels/widgets/ControlTab/fansPage.py new file mode 100644 index 00000000..c71b9588 --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/ControlTab/fansPage.py @@ -0,0 +1,219 @@ +import typing +import re +from lib.utils.icon_button import IconButton +from helper_methods import normalize + +from PyQt6 import QtCore, QtGui, QtWidgets + +from lib.panels.widgets.optionCardWidget import OptionCard + + +class FansPage(QtWidgets.QWidget): + tune_display_buttons: dict = {} + card_options: dict = {} + + request_slider_page = QtCore.pyqtSignal( + str, int, "PyQt_PyObject", int, int, name="on_slidePage_request" + ) + request_back_button = QtCore.pyqtSignal(name="request-back-button") + + run_gcode_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="run-gcode" + ) + + def __init__( + self, + parent: typing.Optional["QtWidgets.QWidget"], + ) -> None: + super(FansPage, self).__init__(parent) + + self._setup_ui() + self.fans_back_btn.clicked.connect(self.request_back_button.emit) + + self.path = { + "fan_cage": QtGui.QPixmap(":/fan_related/media/btn_icons/fan_cage.svg"), + "blower": QtGui.QPixmap(":/fan_related/media/btn_icons/blower.svg"), + "fan": QtGui.QPixmap(":/fan_related/media/btn_icons/fan.svg"), + } + + @QtCore.pyqtSlot(str, str, float, name="on_fan_update") + @QtCore.pyqtSlot(str, str, int, name="on_fan_update") + def on_fan_object_update( + self, name: str, field: str, new_value: int | float + ) -> None: + """Slot that receives updates from fan objects. + + Args: + name (str): Fan object name + field (str): Field name + new_value (int | float): New value for the field + """ + if "speed" not in field: + return + + fields = name.split() + first_field = fields[0] + second_field = fields[1] if len(fields) > 1 else None + name = second_field.replace("_", " ") if second_field else name + + fan_card = self.tune_display_buttons.get(name) + if fan_card is None and first_field in ( + "fan", + "fan_generic", + ): + icon = self.path.get("fan") + if second_field: + second_field = second_field.lower() + pattern_blower = r"(?:^|_)(?:blower|auxiliary)(?:_|$)" + pattern_exhaust = r"(?:^|_)exhaust(?:_|$)" + if re.search(pattern_blower, second_field): + icon = self.path.get("blower") + elif re.search(pattern_exhaust, second_field): + icon = self.path.get("fan_cage") + + card = OptionCard(self, name, str(name), icon) # type: ignore + card.setObjectName(str(name)) + + # Add card to layout and record reference + self.card_options[name] = card + self.fans_content_layout.addWidget(card) + + # If the card doesn't have expected UI properties, discard it + if not hasattr(card, "continue_clicked"): + del card + self.card_options.pop(name, None) + return + + card.setMode(True) + card.secondtext.setText(f"{new_value}%") + card.continue_clicked.connect( + lambda: self.request_slider_page.emit( + str(name), + int(card.secondtext.text().replace("%", "")), + self.on_slider_change, + 0, + 100, + ) + ) + + self.tune_display_buttons[name] = card + self.update() + fan_card = card + + if fan_card: + value_percent = new_value * 100 if new_value <= 1 else new_value + fan_card.secondtext.setText(f"{value_percent:.0f}%") + + @QtCore.pyqtSlot(str, int, name="on_slider_change") + def on_slider_change(self, name: str, new_value: int) -> None: + """ + Slider change handler + Args: + name (str): fan name + new_value (int): value from 0 to 255 to set fans speed + """ + if "speed" in name.lower(): + self.speed_factor_override = new_value / 100 + self.run_gcode_signal.emit(f"M220 S{new_value}") + if name.lower() == "fan": + self.run_gcode_signal.emit( + f"M106 S{int(round((normalize(float(new_value / 100), 0.0, 1.0, 0, 255))))}" + ) # [0, 255] Range + else: + name = name.replace(" ", "_") + self.run_gcode_signal.emit( + f'SET_FAN_SPEED FAN="{name}" SPEED={float(new_value / 100.00)}' + ) # [0.0, 1.0] Range + + def _setup_ui(self) -> None: + self.setObjectName("fans_page") + widget = QtWidgets.QWidget(parent=self) + widget.setGeometry(QtCore.QRect(0, 0, 720, 420)) + + self.verticalLayout = QtWidgets.QVBoxLayout(self) + self.verticalLayout.setObjectName("verticalLayout") + + spacerItem9 = QtWidgets.QSpacerItem( + 20, + 24, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem9) + + self.fans_header_layout = QtWidgets.QHBoxLayout() + self.fans_header_layout.setObjectName("fans_header_layout") + + spacerItem10 = QtWidgets.QSpacerItem( + 60, + 20, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.fans_header_layout.addItem(spacerItem10) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.fans_title_label = QtWidgets.QLabel(parent=self) + self.fans_title_label.setSizePolicy(sizePolicy) + self.fans_title_label.setFont(font) + self.fans_title_label.setStyleSheet("background: transparent; color: white;") + self.fans_title_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.fans_title_label.setObjectName("fans_title_label") + self.fans_header_layout.addWidget(self.fans_title_label) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(20) + font.setStyleStrategy(QtGui.QFont.StyleStrategy.PreferAntialias) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.fans_back_btn = IconButton(parent=self) + self.fans_back_btn.setSizePolicy(sizePolicy) + self.fans_back_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.fans_back_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.fans_back_btn.setFont(font) + self.fans_back_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") + ) + self.fans_back_btn.setObjectName("fans_back_btn") + + self.fans_header_layout.addWidget(self.fans_back_btn) + self.verticalLayout.addLayout(self.fans_header_layout) + spacerItem11 = QtWidgets.QSpacerItem( + 20, + 111, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + + self.verticalLayout.addItem(spacerItem11) + + self.fans_content_layout = QtWidgets.QHBoxLayout() + self.fans_content_layout.setObjectName("fans_content_layout") + self.verticalLayout.addLayout(self.fans_content_layout) + + self.verticalLayout.addItem(spacerItem11) + + widget.setLayout(self.verticalLayout) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.fans_title_label.setText(_translate("controlStackedWidget", "Fans")) + self.fans_back_btn.setText(_translate("controlStackedWidget", "Back")) diff --git a/BlocksScreen/lib/panels/widgets/printcorePage.py b/BlocksScreen/lib/panels/widgets/ControlTab/printcorePage.py similarity index 100% rename from BlocksScreen/lib/panels/widgets/printcorePage.py rename to BlocksScreen/lib/panels/widgets/ControlTab/printcorePage.py diff --git a/BlocksScreen/lib/panels/widgets/probeHelperPage.py b/BlocksScreen/lib/panels/widgets/ControlTab/probeHelperPage.py similarity index 99% rename from BlocksScreen/lib/panels/widgets/probeHelperPage.py rename to BlocksScreen/lib/panels/widgets/ControlTab/probeHelperPage.py index fe2fa180..a3c5d5f9 100644 --- a/BlocksScreen/lib/panels/widgets/probeHelperPage.py +++ b/BlocksScreen/lib/panels/widgets/ControlTab/probeHelperPage.py @@ -439,6 +439,7 @@ def handle_start_tool(self, sender: typing.Type[OptionCard]) -> None: if "eddy" in sender.name: # type:ignore self.call_load_panel.emit(True, "Preparing Eddy Current Calibration...") self.toggle_conn_page.emit(False) + self._move_to_pos(self.z_offset_safe_xy[0], self.z_offset_safe_xy[1], 100) self.run_gcode_signal.emit( f"LDC_CALIBRATE_DRIVE_CURRENT CHIP={sender.name.split(' ')[1]}" # type:ignore ) @@ -528,8 +529,15 @@ def on_manual_probe_update(self, update: dict) -> None: # if update.get("z_position_lower"): # f"{update.get('z_position_lower'):.4f} mm" - is_active = update.get("is_active", False) - if is_active and not self.isVisible(): + is_active = update.get("is_active", None) + if update.get("z_position_upper"): + self.old_offset_info.setText(f"{update.get('z_position_upper'):.4f} mm") + if update.get("z_position"): + self.current_offset_info.setText(f"{update.get('z_position'):.4f} mm") + + if not is_active: + return + if not self.isVisible(): self.request_page_view.emit() # Shared state updates self.helper_initialize = False @@ -541,11 +549,6 @@ def on_manual_probe_update(self, update: dict) -> None: else: self._show_option_cards() - if update.get("z_position_upper"): - self.old_offset_info.setText(f"{update.get('z_position_upper'):.4f} mm") - if update.get("z_position"): - self.current_offset_info.setText(f"{update.get('z_position'):.4f} mm") - @QtCore.pyqtSlot(list, name="handle_gcode_response") def handle_gcode_response(self, data: list) -> None: """Parses responses from gcodes diff --git a/BlocksScreen/lib/panels/widgets/ControlTab/temperaturePage.py b/BlocksScreen/lib/panels/widgets/ControlTab/temperaturePage.py new file mode 100644 index 00000000..94c05e30 --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/ControlTab/temperaturePage.py @@ -0,0 +1,287 @@ +import typing + +from lib.utils.icon_button import IconButton +from lib.utils.display_button import DisplayButton +from lib.utils.blocks_button import BlocksCustomButton + +from PyQt6 import QtCore, QtGui, QtWidgets + + +class TemperaturePage(QtWidgets.QWidget): + request_back = QtCore.pyqtSignal(name="request-back-button") + + run_gcode_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="run-gcode" + ) + request_numpad: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, + int, + "PyQt_PyObject", + int, + int, + name="request-numpad", + ) + + def __init__( + self, + parent: typing.Optional["QtWidgets.QWidget"], + ) -> None: + super(TemperaturePage, self).__init__(parent) + + self._setup_ui() + + self.temp_back_button.clicked.connect(self.request_back.emit) + + self.cooldown_btn.hide() + self.temperature_cooldown_btn.hide() + + self.extruder_temp_display.clicked.connect( + lambda: self.request_numpad.emit( + "Extruder Temperature", + int(round(float(self.extruder_temp_display.secondary_text))), + self.on_numpad_change, + 0, + 370, # TODO: Get this value from printer objects + ) + ) + self.bed_temp_display.clicked.connect( + lambda: self.request_numpad[str, int, "PyQt_PyObject", int, int].emit( + "Bed Temperature", + int(round(float(self.bed_temp_display.secondary_text))), + self.on_numpad_change, + 0, + 120, # TODO: Get this value from printer objects + ) + ) + + @QtCore.pyqtSlot(str, int, name="on-numpad-change") + def on_numpad_change(self, name: str, new_value: int) -> None: + """Handles inputted numpad values""" + if "bed" in name.lower(): + name = "heater_bed" + elif "extruder" in name.lower(): + name = "extruder" + self.run_gcode_signal.emit( + f"SET_HEATER_TEMPERATURE HEATER={name} TARGET={new_value}" + ) + + @QtCore.pyqtSlot(str, str, float, name="on-extruder-update") + def on_extruder_update( + self, extruder_name: str, field: str, new_value: float + ) -> None: + """Handles updates from extruder printer object""" + if extruder_name == "extruder" and field == "temperature": + self.extruder_temp_display.setText(f"{new_value:.1f}") + if extruder_name == "extruder" and field == "target": + self.extruder_temp_display.secondary_text = f"{new_value:.1f}" + + @QtCore.pyqtSlot(str, str, float, name="on-heater-bed-update") + def on_heater_bed_update(self, name: str, field: str, new_value: float) -> None: + """Handles updated from heater_bed printer object""" + if field == "temperature": + self.bed_temp_display.setText(f"{new_value:.1f}") + if field == "target": + self.bed_temp_display.secondary_text = f"{new_value:.1f}" + + def _setup_ui(self) -> None: + self.setObjectName("fans_page") + widget = QtWidgets.QWidget(parent=self) + widget.setGeometry(QtCore.QRect(0, 0, 720, 420)) + self.setObjectName("temperature_page") + self.verticalLayout = QtWidgets.QVBoxLayout(self) + self.verticalLayout.setObjectName("verticalLayout") + spacerItem3 = QtWidgets.QSpacerItem( + 20, + 24, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem3) + + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + + spacerItem4 = QtWidgets.QSpacerItem( + 60, + 20, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.horizontalLayout.addItem(spacerItem4) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + font.setBold(True) + font.setWeight(75) + + self.temp_header_title = QtWidgets.QLabel(parent=self) + self.temp_header_title.setSizePolicy(sizePolicy) + self.temp_header_title.setMaximumSize(QtCore.QSize(16777215, 60)) + self.temp_header_title.setFont(font) + self.temp_header_title.setLayoutDirection(QtCore.Qt.LayoutDirection.RightToLeft) + self.temp_header_title.setStyleSheet("background: transparent; color: white;") + self.temp_header_title.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.temp_header_title.setObjectName("temp_header_title") + self.horizontalLayout.addWidget(self.temp_header_title) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.temp_back_button = IconButton(parent=self) + self.temp_back_button.setSizePolicy(sizePolicy) + self.temp_back_button.setMinimumSize(QtCore.QSize(60, 60)) + self.temp_back_button.setMaximumSize(QtCore.QSize(60, 60)) + self.temp_back_button.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") + ) + self.temp_back_button.setObjectName("temp_back_button") + + self.horizontalLayout.addWidget(self.temp_back_button) + self.verticalLayout.addLayout(self.horizontalLayout) + + spacerItem5 = QtWidgets.QSpacerItem( + 20, + 35, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem5) + + self.gridLayout = QtWidgets.QGridLayout() + self.gridLayout.setContentsMargins(5, 5, 5, 5) + self.gridLayout.setSpacing(0) + self.gridLayout.setObjectName("gridLayout") + + self.tp_content_horizontal_layout = QtWidgets.QHBoxLayout() + self.tp_content_horizontal_layout.setSizeConstraint( + QtWidgets.QLayout.SizeConstraint.SetMinimumSize + ) + self.tp_content_horizontal_layout.setContentsMargins(5, 5, 5, 5) + self.tp_content_horizontal_layout.setSpacing(5) + self.tp_content_horizontal_layout.setObjectName("tp_content_horizontal_layout") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Fixed + ) + sizePolicy.setHorizontalStretch(1) + sizePolicy.setVerticalStretch(1) + + font = QtGui.QFont() + font.setPointSize(11) + + self.extruder_temp_display = DisplayButton(parent=self) + self.extruder_temp_display.setSizePolicy(sizePolicy) + self.extruder_temp_display.setMinimumSize(QtCore.QSize(200, 60)) + self.extruder_temp_display.setMaximumSize(QtCore.QSize(120, 60)) + self.extruder_temp_display.setFont(font) + self.extruder_temp_display.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/extruder_related/media/btn_icons/nozzle.svg"), + ) + self.extruder_temp_display.setObjectName("extruder_temp_display") + self.tp_content_horizontal_layout.addWidget(self.extruder_temp_display) + + self.bed_temp_display = DisplayButton(parent=self) + self.bed_temp_display.setSizePolicy(sizePolicy) + self.bed_temp_display.setMinimumSize(QtCore.QSize(200, 60)) + self.bed_temp_display.setMaximumSize(QtCore.QSize(120, 60)) + self.bed_temp_display.setFont(font) + self.bed_temp_display.setProperty( + "icon_pixmap", + QtGui.QPixmap( + ":/temperature_related/media/btn_icons/temperature_plate.svg" + ), + ) + self.bed_temp_display.setObjectName("bed_temp_display") + + self.tp_content_horizontal_layout.addWidget(self.bed_temp_display) + self.gridLayout.addLayout(self.tp_content_horizontal_layout, 0, 0, 1, 2) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(19) + font.setItalic(False) + font.setStyleStrategy(QtGui.QFont.StyleStrategy.PreferAntialias) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Fixed + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.cooldown_btn = BlocksCustomButton(parent=self) + self.cooldown_btn.setSizePolicy(sizePolicy) + self.cooldown_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.cooldown_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.cooldown_btn.setFont(font) + self.cooldown_btn.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.cooldown_btn.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/temperature_related/media/btn_icons/cooldown.svg"), + ) + self.cooldown_btn.setObjectName("cooldown_btn") + + self.gridLayout.addWidget(self.cooldown_btn, 2, 1, 1, 1) + spacerItem6 = QtWidgets.QSpacerItem( + 20, + 50, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.gridLayout.addItem(spacerItem6, 1, 0, 1, 2) + + self.temperature_cooldown_btn = BlocksCustomButton(parent=self) + self.temperature_cooldown_btn.setSizePolicy(sizePolicy) + self.temperature_cooldown_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.temperature_cooldown_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.temperature_cooldown_btn.setFont(font) + self.temperature_cooldown_btn.setLayoutDirection( + QtCore.Qt.LayoutDirection.LeftToRight + ) + self.temperature_cooldown_btn.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/temperature_related/media/btn_icons/heatsoak_icon.svg"), + ) + self.temperature_cooldown_btn.setObjectName("temperature_cooldown_btn") + self.gridLayout.addWidget(self.temperature_cooldown_btn, 2, 0, 1, 1) + + self.verticalLayout.addLayout(self.gridLayout) + spacerItem7 = QtWidgets.QSpacerItem( + 20, + 8, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem7) + + widget.setLayout(self.verticalLayout) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.temp_header_title.setText( + _translate("controlStackedWidget", "Temperature") + ) + self.temp_back_button.setText(_translate("controlStackedWidget", "Back")) + self.extruder_temp_display.setProperty( + "button_type", _translate("controlStackedWidget", "secondary_display") + ) + self.bed_temp_display.setProperty( + "button_type", _translate("controlStackedWidget", "secondary_display") + ) + self.cooldown_btn.setText(_translate("controlStackedWidget", "Cooldown")) + self.temperature_cooldown_btn.setText( + _translate("controlStackedWidget", "Heatsoak") + ) diff --git a/BlocksScreen/lib/panels/widgets/cancelPage.py b/BlocksScreen/lib/panels/widgets/MainWindow/cancelPage.py similarity index 100% rename from BlocksScreen/lib/panels/widgets/cancelPage.py rename to BlocksScreen/lib/panels/widgets/MainWindow/cancelPage.py diff --git a/BlocksScreen/lib/panels/widgets/connectionPage.py b/BlocksScreen/lib/panels/widgets/MainWindow/connectionPage.py similarity index 100% rename from BlocksScreen/lib/panels/widgets/connectionPage.py rename to BlocksScreen/lib/panels/widgets/MainWindow/connectionPage.py diff --git a/BlocksScreen/lib/panels/widgets/notificationPage.py b/BlocksScreen/lib/panels/widgets/MainWindow/notificationPage.py similarity index 100% rename from BlocksScreen/lib/panels/widgets/notificationPage.py rename to BlocksScreen/lib/panels/widgets/MainWindow/notificationPage.py diff --git a/BlocksScreen/lib/panels/widgets/updatePage.py b/BlocksScreen/lib/panels/widgets/MainWindow/updatePage.py similarity index 100% rename from BlocksScreen/lib/panels/widgets/updatePage.py rename to BlocksScreen/lib/panels/widgets/MainWindow/updatePage.py diff --git a/BlocksScreen/lib/panels/widgets/babystepPage.py b/BlocksScreen/lib/panels/widgets/PrintTab/babystepPage.py similarity index 100% rename from BlocksScreen/lib/panels/widgets/babystepPage.py rename to BlocksScreen/lib/panels/widgets/PrintTab/babystepPage.py diff --git a/BlocksScreen/lib/panels/widgets/confirmPage.py b/BlocksScreen/lib/panels/widgets/PrintTab/confirmPage.py similarity index 100% rename from BlocksScreen/lib/panels/widgets/confirmPage.py rename to BlocksScreen/lib/panels/widgets/PrintTab/confirmPage.py diff --git a/BlocksScreen/lib/panels/widgets/filesPage.py b/BlocksScreen/lib/panels/widgets/PrintTab/filesPage.py similarity index 100% rename from BlocksScreen/lib/panels/widgets/filesPage.py rename to BlocksScreen/lib/panels/widgets/PrintTab/filesPage.py diff --git a/BlocksScreen/lib/panels/widgets/jobStatusPage.py b/BlocksScreen/lib/panels/widgets/PrintTab/jobStatusPage.py similarity index 100% rename from BlocksScreen/lib/panels/widgets/jobStatusPage.py rename to BlocksScreen/lib/panels/widgets/PrintTab/jobStatusPage.py diff --git a/BlocksScreen/lib/panels/widgets/sensorWidget.py b/BlocksScreen/lib/panels/widgets/PrintTab/sensorWidget.py similarity index 100% rename from BlocksScreen/lib/panels/widgets/sensorWidget.py rename to BlocksScreen/lib/panels/widgets/PrintTab/sensorWidget.py diff --git a/BlocksScreen/lib/panels/widgets/sensorsPanel.py b/BlocksScreen/lib/panels/widgets/PrintTab/sensorsPanel.py similarity index 99% rename from BlocksScreen/lib/panels/widgets/sensorsPanel.py rename to BlocksScreen/lib/panels/widgets/PrintTab/sensorsPanel.py index df63cfb5..03bc8285 100644 --- a/BlocksScreen/lib/panels/widgets/sensorsPanel.py +++ b/BlocksScreen/lib/panels/widgets/PrintTab/sensorsPanel.py @@ -1,6 +1,6 @@ import typing -from lib.panels.widgets.sensorWidget import SensorWidget +from lib.panels.widgets.PrintTab.sensorWidget import SensorWidget from lib.utils.blocks_frame import BlocksCustomFrame from lib.utils.icon_button import IconButton from lib.utils.list_model import EntryDelegate, EntryListModel, ListItem diff --git a/BlocksScreen/lib/panels/widgets/tunePage.py b/BlocksScreen/lib/panels/widgets/PrintTab/tunePage.py similarity index 100% rename from BlocksScreen/lib/panels/widgets/tunePage.py rename to BlocksScreen/lib/panels/widgets/PrintTab/tunePage.py diff --git a/BlocksScreen/lib/panels/widgets/UtilitiesTab/axismaintPage.py b/BlocksScreen/lib/panels/widgets/UtilitiesTab/axismaintPage.py new file mode 100644 index 00000000..7fa22390 --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/UtilitiesTab/axismaintPage.py @@ -0,0 +1,251 @@ +import typing + +from PyQt6 import QtCore, QtGui, QtWidgets + +from lib.utils.blocks_button import BlocksCustomButton +from lib.utils.icon_button import IconButton + + +class AxisMaintenancePage(QtWidgets.QWidget): + request_back_button = QtCore.pyqtSignal(name="request-back-button") + + run_gcode_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="run-gcode" + ) + set_dialog_popup = QtCore.pyqtSignal(str, "PyQt_PyObject", name="set-dialog-popup") + + show_waiting_page = QtCore.pyqtSignal(str, int, bool, name="show-waiting-page") + + call_load_panel = QtCore.pyqtSignal(bool, str, name="call-load-panel") + + def __init__( + self, + parent: typing.Optional["QtWidgets.QWidget"], + ) -> None: + super(AxisMaintenancePage, self).__init__(parent) + self._setup_ui() + + self.axes_back_btn.clicked.connect(self.request_back_button) + self.axis_x_btn.clicked.connect(lambda: self.axis_maintenance("x")) + self.axis_y_btn.clicked.connect(lambda: self.axis_maintenance("y")) + self.axis_z_btn.clicked.connect(lambda: self.axis_maintenance("z")) + + self.stepper_limits: dict = {} + + @QtCore.pyqtSlot(dict, name="on_object_config") + @QtCore.pyqtSlot(list, name="on_object_config") + def on_object_config(self, config: typing.Union[dict, list]) -> None: + """Handle receiving printer object configurations""" + if not config: + return + config_items = [config] if isinstance(config, dict) else config + for item in config_items: + for key, value in item.items(): + if ( + key.startswith("stepper_") + and isinstance(value, dict) + and key not in self.stepper_limits + ): + pos_min = value.get("position_min") + pos_max = value.get("position_max") + if pos_min is not None or pos_max is not None: + self.stepper_limits[key] = { + "min": float(pos_min) + if pos_min is not None + else -float("inf"), + "max": float(pos_max) + if pos_max is not None + else float("inf"), + } + + def axis_maintenance(self, axis: str) -> None: + """Routine, checks axis movement for printer debugging""" + self.c_axis = axis + self.run_gcode_signal.emit("G28\nM400") + self.set_dialog_popup.emit( + f"Insert oil on the {axis.upper()} axis before confirming.", + self.dialog_asnwer, + ) + self.show_waiting_page.emit(f"Homing {axis.upper()} axis...", 5000, True) + + def dialog_asnwer(self): + self.call_load_panel.emit(False, "") + + stepper_key = f"stepper_{self.c_axis}" + if stepper_key in self.stepper_limits: + max_pos = self.stepper_limits[stepper_key].get("max", 20) + distance = int(max_pos) - 20 + self.run_gcode_signal.emit("G90") + if self.c_axis != "x": + self.run_gcode_signal.emit("G1 X20 F3000\nM400") + + if self.c_axis == "y": + self.run_gcode_signal.emit( + f"G1 {self.c_axis.upper()}10 F3000\nM400\nG28\nM400" + ) + else: + self.run_gcode_signal.emit( + f"G1 {self.c_axis.upper()}{distance - 10} F3000\nM400\nG28\nM400" + ) + + def _setup_ui(self) -> None: + self.setObjectName("axes_page") + widget = QtWidgets.QWidget(parent=self) + widget.setGeometry(QtCore.QRect(0, 0, 720, 420)) + + self.verticalLayout = QtWidgets.QVBoxLayout(self) + self.verticalLayout.setObjectName("verticalLayout") + spacerItem12 = QtWidgets.QSpacerItem( + 20, + 24, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem12) + self.lcd_settings_header_layout = QtWidgets.QHBoxLayout() + self.lcd_settings_header_layout.setObjectName("lcd_settings_header_layout") + spacerItem13 = QtWidgets.QSpacerItem( + 60, + 20, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.lcd_settings_header_layout.addItem(spacerItem13) + self.lcd_settings_title_label = QtWidgets.QLabel(parent=self) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth( + self.lcd_settings_title_label.sizePolicy().hasHeightForWidth() + ) + self.lcd_settings_title_label.setSizePolicy(sizePolicy) + self.lcd_settings_title_label.setMaximumSize(QtCore.QSize(16777215, 60)) + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + self.lcd_settings_title_label.setFont(font) + self.lcd_settings_title_label.setStyleSheet( + "background: transparent; color: white;" + ) + self.lcd_settings_title_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.lcd_settings_title_label.setObjectName("lcd_settings_title_label") + self.lcd_settings_header_layout.addWidget(self.lcd_settings_title_label) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.axes_back_btn = IconButton(parent=self) + self.axes_back_btn.setSizePolicy(sizePolicy) + self.axes_back_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.axes_back_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.axes_back_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") + ) + self.axes_back_btn.setObjectName("axes_back_btn") + self.lcd_settings_header_layout.addWidget(self.axes_back_btn) + self.verticalLayout.addLayout(self.lcd_settings_header_layout) + + spacerItem14 = QtWidgets.QSpacerItem( + 20, + 40, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + self.verticalLayout.addItem(spacerItem14) + self.lcd_settings_content_layout = QtWidgets.QGridLayout() + self.lcd_settings_content_layout.setObjectName("lcd_settings_content_layout") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(19) + font.setItalic(False) + font.setStyleStrategy(QtGui.QFont.StyleStrategy.PreferAntialias) + + self.axis_x_btn = BlocksCustomButton(parent=self) + self.axis_x_btn.setSizePolicy(sizePolicy) + self.axis_x_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.axis_x_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.axis_x_btn.setFont(font) + self.axis_x_btn.setObjectName("axis_x_btn") + self.lcd_settings_content_layout.addWidget( + self.axis_x_btn, + 0, + 0, + 1, + 4, + QtCore.Qt.AlignmentFlag.AlignHCenter | QtCore.Qt.AlignmentFlag.AlignVCenter, + ) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + + self.axis_z_btn = BlocksCustomButton(parent=self) + self.axis_z_btn.setSizePolicy(sizePolicy) + self.axis_z_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.axis_z_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.axis_z_btn.setFont(font) + self.axis_z_btn.setObjectName("axis_z_btn") + self.horizontalLayout_2.addWidget(self.axis_z_btn) + + self.axis_y_btn = BlocksCustomButton(parent=self) + self.axis_y_btn.setSizePolicy(sizePolicy) + self.axis_y_btn.setMinimumSize(QtCore.QSize(250, 80)) + self.axis_y_btn.setMaximumSize(QtCore.QSize(250, 80)) + self.axis_y_btn.setFont(font) + self.axis_y_btn.setObjectName("axis_y_btn") + self.horizontalLayout_2.addWidget(self.axis_y_btn) + self.lcd_settings_content_layout.addLayout(self.horizontalLayout_2, 1, 0, 1, 4) + self.verticalLayout.addLayout(self.lcd_settings_content_layout) + spacerItem15 = QtWidgets.QSpacerItem( + 20, + 40, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + self.verticalLayout.addItem(spacerItem15) + + widget.setLayout(self.verticalLayout) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.lcd_settings_title_label.setText( + _translate("utilitiesStackedWidget", "Axis Maintenance") + ) + self.lcd_settings_title_label.setProperty( + "class", _translate("utilitiesStackedWidget", "title_text") + ) + self.axes_back_btn.setText(_translate("utilitiesStackedWidget", "Back")) + self.axes_back_btn.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) + self.axes_back_btn.setProperty( + "button_type", _translate("utilitiesStackedWidget", "icon") + ) + self.axis_x_btn.setText(_translate("utilitiesStackedWidget", "X")) + self.axis_x_btn.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) + self.axis_x_btn.setProperty( + "button_type", _translate("utilitiesStackedWidget", "normal") + ) + self.axis_z_btn.setText(_translate("utilitiesStackedWidget", "Z")) + self.axis_z_btn.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) + self.axis_y_btn.setText(_translate("utilitiesStackedWidget", "Y")) + self.axis_y_btn.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) diff --git a/BlocksScreen/lib/panels/widgets/UtilitiesTab/infoPage.py b/BlocksScreen/lib/panels/widgets/UtilitiesTab/infoPage.py new file mode 100644 index 00000000..7b5e1b25 --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/UtilitiesTab/infoPage.py @@ -0,0 +1,135 @@ +import typing + +from PyQt6 import QtCore, QtGui, QtWidgets + +from lib.utils.blocks_frame import BlocksCustomFrame +from lib.utils.icon_button import IconButton + + +class InfoPage(QtWidgets.QWidget): + request_back: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + name="request_back" + ) + + def __init__( + self, + parent: typing.Optional["QtWidgets.QWidget"], + ) -> None: + """info page for utilities tab + + Args: + parent (typing.Optional["QtWidgets.QWidget"]): Parent + """ + super(InfoPage, self).__init__(parent) + + self._setup_ui() + + self.info_back_btn.clicked.connect(self.request_back.emit) + + def _setup_ui(self) -> None: + self.setObjectName("info_page") + widget = QtWidgets.QWidget(parent=self) + widget.setGeometry(QtCore.QRect(0, 0, 720, 420)) + + self.verticalLayout = QtWidgets.QVBoxLayout(self) + self.verticalLayout.setObjectName("verticalLayout") + spacerItem = QtWidgets.QSpacerItem( + 20, + 24, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem) + + self.info_header_layout = QtWidgets.QHBoxLayout() + self.info_header_layout.setObjectName("info_header_layout") + spacerItem1 = QtWidgets.QSpacerItem( + 60, + 60, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.info_header_layout.addItem(spacerItem1) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.info_title_label = QtWidgets.QLabel(parent=self) + self.info_title_label.setSizePolicy(sizePolicy) + self.info_title_label.setMaximumSize(QtCore.QSize(16777215, 60)) + self.info_title_label.setFont(font) + self.info_title_label.setStyleSheet("background: transparent; color: white;") + self.info_title_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.info_title_label.setObjectName("info_title_label") + self.info_header_layout.addWidget(self.info_title_label) + + self.info_back_btn = IconButton(parent=self) + self.info_back_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.info_back_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.info_back_btn.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.info_back_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") + ) + self.info_back_btn.setObjectName("info_back_btn") + self.info_header_layout.addWidget(self.info_back_btn) + self.verticalLayout.addLayout(self.info_header_layout) + + self.info_content_layout = QtWidgets.QVBoxLayout() + self.info_content_layout.setObjectName("info_content_layout") + + self.frame = BlocksCustomFrame(parent=self) + self.frame.setMinimumSize(QtCore.QSize(350, 260)) + self.frame.setMaximumSize(QtCore.QSize(350, 290)) + self.frame.setObjectName("frame") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Preferred, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + font = QtGui.QFont() + font.setPointSize(20) + + self.kv_label = QtWidgets.QLabel(parent=self.frame) + self.kv_label.setGeometry(QtCore.QRect(0, 10, 351, 81)) + self.kv_label.setSizePolicy(sizePolicy) + self.kv_label.setFont(font) + self.kv_label.setStyleSheet("color:white") + self.kv_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.kv_label.setObjectName("kv_label") + + self.smth_label = QtWidgets.QLabel(parent=self.frame) + self.smth_label.setGeometry(QtCore.QRect(0, 110, 351, 81)) + self.smth_label.setSizePolicy(sizePolicy) + self.smth_label.setFont(font) + self.smth_label.setStyleSheet("color:white") + self.smth_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.smth_label.setObjectName("smth_label") + + self.info_content_layout.addWidget( + self.frame, 0, QtCore.Qt.AlignmentFlag.AlignHCenter + ) + self.verticalLayout.addLayout(self.info_content_layout) + + widget.setLayout(self.verticalLayout) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.info_title_label.setText(_translate("utilitiesStackedWidget", "Info")) + self.info_back_btn.setText(_translate("utilitiesStackedWidget", "Back")) + self.kv_label.setText( + _translate("utilitiesStackedWidget", "Model: Blocks RF50") + ) + self.smth_label.setText( + _translate("utilitiesStackedWidget", "www.blockstec.com ") + ) diff --git a/BlocksScreen/lib/panels/widgets/UtilitiesTab/inputshaperPage.py b/BlocksScreen/lib/panels/widgets/UtilitiesTab/inputshaperPage.py new file mode 100644 index 00000000..b8d701dd --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/UtilitiesTab/inputshaperPage.py @@ -0,0 +1,163 @@ +import typing +from lib.panels.widgets.basePopup import BasePopup +from lib.utils.icon_button import IconButton + +from PyQt6 import QtCore, QtGui, QtWidgets + +from lib.panels.widgets.optionCardWidget import OptionCard + + +class InputShaperPage(QtWidgets.QWidget): + request_back_button = QtCore.pyqtSignal(name="request-back-button") + + run_gcode_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="run-gcode" + ) + request_is_results_page = QtCore.pyqtSignal(name="request-is-results-page") + + call_load_panel = QtCore.pyqtSignal(bool, str, name="call-load-panel") + + set_aut = QtCore.pyqtSignal(bool, name="set-aut") + + def __init__( + self, + parent: typing.Optional["QtWidgets.QWidget"], + ) -> None: + super(InputShaperPage, self).__init__(parent) + + self._setup_ui() + self.input_shaper_back_btn.clicked.connect(self.request_back_button.emit) + + self.automatic_is = OptionCard( + self, + "Automatic\nInput Shaper", + "Automatic Input Shaper", + QtGui.QPixmap(":/input_shaper/media/btn_icons/input_shaper_auto.svg"), + ) # type: ignore + self.automatic_is.setObjectName("Automatic_IS_Card") + self.is_content_layout.addWidget( + self.automatic_is, alignment=QtCore.Qt.AlignmentFlag.AlignHCenter + ) + self.automatic_is.continue_clicked.connect( + lambda: self.handle_is("SHAPER_CALIBRATE") + ) + + self.manual_is = OptionCard( + self, + "Manual\nInput Shaper", + "Manual Input Shaper", + QtGui.QPixmap(":/input_shaper/media/btn_icons/input_shaper_manual.svg"), + ) # type: ignore + self.manual_is.setObjectName("Manual_IS_Card") + self.is_content_layout.addWidget( + self.manual_is, alignment=QtCore.Qt.AlignmentFlag.AlignHCenter + ) + self.manual_is.continue_clicked.connect(lambda: self.handle_is("")) + + self.dialog_page = BasePopup(self, dialog=True, floating=True) + + self.dialog_page.accepted.connect( + lambda: self.handle_is("SHAPER_CALIBRATE AXIS=Y") + ) + self.dialog_page.rejected.connect( + lambda: self.handle_is("SHAPER_CALIBRATE AXIS=X") + ) + + def handle_is(self, gcode: str) -> None: + """handles choosed input shapper + + Args: + gcode (str): gcode to run + """ + if gcode == "SHAPER_CALIBRATE": + self.run_gcode_signal.emit("G28\nM400") + self.set_aut.emit(True) + self.run_gcode_signal.emit(gcode) + self.request_is_results_page.emit() + elif gcode == "": + self.dialog_page.confirm_background_color("#dfdfdf") + self.dialog_page.cancel_background_color("#dfdfdf") + self.dialog_page.cancel_font_color("#000000") + self.dialog_page.confirm_font_color("#000000") + self.dialog_page.cancel_button_text("X axis") + self.dialog_page.confirm_button_text("Y axis") + self.dialog_page.set_message( + "Select the axis you want to execute the input shaper on:" + ) + self.dialog_page.show() + return + else: + self.set_aut.emit(False) + self.run_gcode_signal.emit("G28\nM400") + self.run_gcode_signal.emit(gcode) + self.request_is_results_page.emit() + + self.call_load_panel.emit(True, "Running Input Shaper...") + + def _setup_ui(self) -> None: + self.setObjectName("input_shaper_page") + widget = QtWidgets.QWidget(parent=self) + widget.setGeometry(QtCore.QRect(0, 0, 720, 420)) + + self.verticalLayout = QtWidgets.QVBoxLayout(self) + self.verticalLayout.setObjectName("verticalLayout") + + spacerItem16 = QtWidgets.QSpacerItem( + 20, + 24, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem16) + self.is_header_layout = QtWidgets.QHBoxLayout() + self.is_header_layout.setObjectName("is_header_layout") + + spacerItem17 = QtWidgets.QSpacerItem( + 60, + 0, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.is_header_layout.addItem(spacerItem17) + + self.label_2 = QtWidgets.QLabel(parent=self) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth()) + self.label_2.setSizePolicy(sizePolicy) + self.label_2.setMaximumSize(QtCore.QSize(16777215, 60)) + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + self.label_2.setFont(font) + self.label_2.setStyleSheet("background: transparent; color: white;") + self.label_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.label_2.setObjectName("label_2") + self.is_header_layout.addWidget(self.label_2) + + self.input_shaper_back_btn = IconButton(parent=self) + + self.input_shaper_back_btn.setSizePolicy(sizePolicy) + self.input_shaper_back_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.input_shaper_back_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.input_shaper_back_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") + ) + self.input_shaper_back_btn.setObjectName("input_shaper_back_btn") + + self.is_header_layout.addWidget(self.input_shaper_back_btn) + self.verticalLayout.addLayout(self.is_header_layout) + self.is_content_layout = QtWidgets.QHBoxLayout() + self.is_content_layout.setObjectName("is_content_layout") + self.verticalLayout.addLayout(self.is_content_layout) + widget.setLayout(self.verticalLayout) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.label_2.setText(_translate("utilitiesStackedWidget", "Input Shaper")) + self.input_shaper_back_btn.setText(_translate("utilitiesStackedWidget", "Back")) diff --git a/BlocksScreen/lib/panels/widgets/inputshaperPage.py b/BlocksScreen/lib/panels/widgets/UtilitiesTab/inputshaperResultPage.py similarity index 83% rename from BlocksScreen/lib/panels/widgets/inputshaperPage.py rename to BlocksScreen/lib/panels/widgets/UtilitiesTab/inputshaperResultPage.py index ead82cfb..50cfccd2 100644 --- a/BlocksScreen/lib/panels/widgets/inputshaperPage.py +++ b/BlocksScreen/lib/panels/widgets/UtilitiesTab/inputshaperResultPage.py @@ -2,12 +2,18 @@ from lib.utils.blocks_frame import BlocksCustomFrame from lib.utils.icon_button import IconButton from lib.utils.list_model import EntryDelegate, EntryListModel, ListItem +import logging + +import re + from PyQt6 import QtCore, QtGui, QtWidgets import typing +logger = logging.getLogger(__name__) + -class InputShaperPage(QtWidgets.QWidget): +class InputShaperResultsPage(QtWidgets.QWidget): """Update GUI Page, retrieves from moonraker available clients and adds functionality for updating or recovering them @@ -25,10 +31,7 @@ def __init__(self, parent=None) -> None: super().__init__() self._setupUI() self.selected_item: ListItem | None = None - self.ongoing_update: bool = False self.type_dict: dict = {} - self.repeated_request_status = QtCore.QTimer() - self.repeated_request_status.setInterval(2000) # every 2 seconds self.model = EntryListModel() self.model.setParent(self.update_buttons_list_widget) self.entry_delegate = EntryDelegate() @@ -39,20 +42,103 @@ def __init__(self, parent=None) -> None: self.action_btn.clicked.connect(self.handle_ism_confirm) - def handle_update_end(self) -> None: - """Handles update end signal - (closes loading page, returns to normal operation) + self.is_types: dict = {} + self.is_aut_types: dict = {} + self.aut = True + + @QtCore.pyqtSlot(bool, name="set-aut") + def set_aut(self, aut: bool): + """Sets if its automatic input shapper or not + + Args: + aut (bool): Toggle Aut """ - self.call_load_panel.emit(False, "Updating...") - self.repeated_request_status.stop() - self.build_model_list() + self.aut = aut - def handle_ongoing_update(self) -> None: - """Handled ongoing update signal, - calls loading page (blocks user interaction) + def handle_gcode_response(self, data: list[str]) -> None: + """ + Parses a Klipper Input Shaper console message and updates self.is_types. """ - self.call_load_panel.emit(True, "Updating...") - self.repeated_request_status.start(2000) + if not self.isVisible(): + return + if not isinstance(data, list) or len(data) != 1 or not isinstance(data[0], str): + logger.error( + f"WARNING: Invalid input format. Expected a list with one string. Received: {data}" + ) + + return + + message = data[0] + + pattern_fitted = re.compile( + r"Fitted shaper '(?P\w+)' frequency = (?P[\d\.]+) Hz \(vibrations = (?P[\d\.]+)%" + ) + match_fitted = pattern_fitted.search(message) + + if match_fitted: + name = match_fitted.group("name") + freq = float(match_fitted.group("freq")) + vib = float(match_fitted.group("vib")) + current_data = self.is_types.get(name, {}) + current_data.update( + { + "frequency": freq, + "vibration": vib, + "max_accel": current_data.get("max_accel", 0.0), + } + ) + self.is_types[name] = current_data + + return + pattern_accel = re.compile( + r"To avoid too much smoothing with '(?P\w+)', suggested max_accel <= (?P[\d\.]+) mm/sec\^2" + ) + match_accel = pattern_accel.search(message) + + if match_accel: + name = match_accel.group("name") + accel = float(match_accel.group("accel")) + + if name in self.is_types and isinstance(self.is_types[name], dict): + self.is_types[name]["max_accel"] = accel + else: + self.is_types[name] = self.is_types.get(name, {}) + self.is_types[name]["max_accel"] = accel + return + + pattern_recommended = re.compile( + r"Recommended shaper_type_(?P[xy]) = (?P\w+), shaper_freq_(?P=axis) = (?P[\d\.]+) Hz" + ) + match_recommended = pattern_recommended.search(message) + if match_recommended: + axis = match_recommended.group("axis") + recommended_type = match_recommended.group("type") + self.is_types["Axis"] = axis + if self.aut: + self.is_aut_types[axis] = recommended_type + if len(self.is_aut_types) == 2: + self.run_gcode_signal.emit("SAVE_CONFIG") + self.call_load_panel.emit(False, "") + self.aut = False + return + return + + reordered = {recommended_type: self.is_types[recommended_type]} + for key, value in self.is_types.items(): + if key not in ("suggested_type", recommended_type, "Axis"): + reordered[key] = value + + self.set_type_dictionary(self.is_types) + first_key = next(iter(reordered.keys()), None) + for key in reordered.keys(): + if key == first_key: + self.add_type_entry(key, "Recommended type") + else: + self.add_type_entry(key) + + self.build_model_list() + self.call_load_panel.emit(False, "") + return def reset_view_model(self) -> None: """Clears items from ListView @@ -66,10 +152,6 @@ def deleteLater(self) -> None: self.reset_view_model() return super().deleteLater() - def showEvent(self, a0: QtGui.QShowEvent | None) -> None: - """Re-add clients to update list""" - return super().showEvent(a0) - def build_model_list(self) -> None: """Builds the model list (`self.model`) containing updatable clients""" self.update_buttons_list_widget.blockSignals(True) @@ -104,6 +186,7 @@ def on_item_clicked(self, item: ListItem) -> None: self.action_btn.show() def handle_ism_confirm(self) -> None: + """Handles action button""" current_info = self.type_dict.get(self.currentItem.text, {}) frequency = current_info.get("frequency", "N/A") if self.type_dict["Axis"] == "x": diff --git a/BlocksScreen/lib/panels/widgets/UtilitiesTab/ledsPage.py b/BlocksScreen/lib/panels/widgets/UtilitiesTab/ledsPage.py new file mode 100644 index 00000000..1095e4e1 --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/UtilitiesTab/ledsPage.py @@ -0,0 +1,198 @@ +import typing +from lib.utils.icon_button import IconButton + +from PyQt6 import QtCore, QtGui, QtWidgets + + +from lib.utils.blocks_button import BlocksCustomButton + + +class LedState: + """Represents the state of an LED light.""" + + led_type: str + red: int = 0 + green: int = 0 + blue: int = 0 + white: int = 255 + state: str = "on" + + def get_gcode(self, name: str) -> str: + """Generates the G-code command for the current state.""" + if self.state == "off": + return f"SET_LED LED={name} RED=0 GREEN=0 BLUE=0 WHITE=0" + if self.led_type == "white": + return f"SET_LED LED={name} WHITE={self.white / 255:.2f}" + # Default to RGB + return ( + f"SET_LED LED={name} RED={self.red / 255:.2f} " + f"GREEN={self.green / 255:.2f} BLUE={self.blue / 255:.2f} " + f"WHITE={self.white / 255:.2f}" + ) + + +class LedsPage(QtWidgets.QWidget): + request_back: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + name="request_back" + ) + request_ledslider_page = QtCore.pyqtSignal( + LedState, str, bool, name="request-ledslider-page" + ) + + def __init__( + self, + parent: typing.Optional["QtWidgets.QWidget"], + ) -> None: + super(LedsPage, self).__init__(parent) + + self._setup_ui() + self.leds = {} + self.leds_back_btn.clicked.connect(self.request_back) + + def showEvent(self, a0: QtGui.QShowEvent | None) -> None: + if self.singleLed: + self.handle_led_button(self.singleLed) + return super().showEvent(a0) + + @QtCore.pyqtSlot(list, name="on_object_list") + def on_object_list(self, object_list: list) -> None: + """Handle receiving printer object list""" + + layout = self.leds_content_layout + + while layout.count(): + if (child := layout.takeAt(0)) and child.widget(): + child.widget().deleteLater() # type: ignore + + led_names = [] + if not object_list: + return + + # Collect LED names + for obj in object_list: + if "led" in obj: + try: + name = obj.split()[1] + led_names.append(name) + self.leds[name] = LedState() + self.leds[name].led_type = "white" + except IndexError: + pass + + max_columns = 3 + buttons = [] + + # Create LED buttons + for i, name in enumerate(led_names): + if self.leds_widget: + button = BlocksCustomButton() + button.setFixedSize(200, 70) + button.setText(name) + button.setPixmap(QtGui.QPixmap(":/ui/media/btn_icons/LEDs.svg")) + row, col = divmod(i, max_columns) + layout.addWidget(button, row, col) + button.clicked.connect(lambda: self.handle_led_button(name)) + buttons.append(button) + + if len(buttons) == 1: + self.singleLed = name + else: + self.singleLed = None + + def handle_led_button(self, name: str) -> None: + """Handle led button clicked""" + self.current_object = name + led_state: LedState = self.leds.get(name) + if not led_state: + return + + self.request_ledslider_page.emit( + led_state, name, True if self.singleLed else False + ) + + def _setup_ui(self) -> None: + + self.setObjectName("fans_page") + widget = QtWidgets.QWidget(parent=self) + widget.setGeometry(QtCore.QRect(0, 0, 720, 420)) + + self.verticalLayout = QtWidgets.QVBoxLayout(self) + self.verticalLayout.setObjectName("verticalLayout") + spacerItem2 = QtWidgets.QSpacerItem( + 20, + 24, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem2) + self.leds_header_layout = QtWidgets.QHBoxLayout() + self.leds_header_layout.setObjectName("leds_header_layout") + spacerItem3 = QtWidgets.QSpacerItem( + 60, + 20, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.leds_header_layout.addItem(spacerItem3) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + + self.leds_title_label = QtWidgets.QLabel(parent=self) + self.leds_title_label.setSizePolicy(sizePolicy) + self.leds_title_label.setFont(font) + self.leds_title_label.setStyleSheet("background: transparent; color: white;") + self.leds_title_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.leds_title_label.setObjectName("leds_title_label") + self.leds_header_layout.addWidget(self.leds_title_label) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.leds_back_btn = IconButton(parent=self) + self.leds_back_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.leds_back_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.leds_back_btn.setFont(font) + self.leds_back_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") + ) + self.leds_back_btn.setObjectName("leds_back_btn") + + self.leds_header_layout.addWidget(self.leds_back_btn) + + self.verticalLayout.addLayout(self.leds_header_layout) + spacerItem4 = QtWidgets.QSpacerItem( + 20, + 40, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + self.verticalLayout.addItem(spacerItem4) + self.leds_content_layout = QtWidgets.QGridLayout() + self.leds_content_layout.setObjectName("leds_content_layout") + + self.leds_widget = QtWidgets.QWidget(parent=self) + self.leds_widget.setObjectName("leds_widget") + self.leds_content_layout.addWidget(self.leds_widget, 0, 0, 1, 1) + + self.verticalLayout.addLayout(self.leds_content_layout) + self.verticalLayout.addItem(spacerItem4) + + widget.setLayout(self.verticalLayout) + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.leds_title_label.setText(_translate("utilitiesStackedWidget", "LED's")) + self.leds_back_btn.setText(_translate("utilitiesStackedWidget", "Back")) diff --git a/BlocksScreen/lib/panels/widgets/UtilitiesTab/ledssliderPage.py b/BlocksScreen/lib/panels/widgets/UtilitiesTab/ledssliderPage.py new file mode 100644 index 00000000..67127794 --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/UtilitiesTab/ledssliderPage.py @@ -0,0 +1,213 @@ +import typing +from lib.utils.icon_button import IconButton + +from PyQt6 import QtCore, QtGui, QtWidgets + +from lib.utils.blocks_slider import BlocksSlider +from lib.utils.toggleAnimatedButton import ToggleAnimatedButton + + +class LedsSliderPage(QtWidgets.QWidget): + request_back: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + name="request_back" + ) + + run_gcode_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="run-gcode" + ) + request_change_page: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + int, name="request-change-page" + ) + + def __init__( + self, + parent: typing.Optional["QtWidgets.QWidget"], + ) -> None: + super(LedsSliderPage, self).__init__(parent) + + self._setup_ui() + + self.leds_w_slider.sliderReleased.connect(self.update_led_values) + self.leds_slider_back_btn.clicked.connect(self.handle_back) + + self.toggle_led_button.state = ToggleAnimatedButton.State.ON + self.toggle_led_button.repaint() + self.toggle_led_button.clicked.connect(self.toggle_led_state) + + def update_led_values(self) -> None: + """Update led state and color values""" + if not self.current_object: + return + self.current_object.white = int(self.leds_w_slider.value() * 255 / 100) + self.save_led_state() + + def set_slider(self, led_state: any, name: str, single: bool): + self.leds_w_slider.setValue(led_state.white) + self.leds_slider_tittle_label.setText(name) + + self.led_name = name + self.current_object = led_state + self.singleled = single + + def handle_back(self): + if self.singleled: + self.request_change_page.emit(0) + else: + self.request_back.emit() + + def toggle_led_state(self) -> None: + """Toggle leds""" + if not self.current_object: + return + + led_state = self.current_object + if led_state.state == "off": + led_state.state = "on" + self.toggle_led_button.state = ToggleAnimatedButton.State.ON + else: + led_state.state = "off" + self.toggle_led_button.state = ToggleAnimatedButton.State.OFF + self.save_led_state() + + def save_led_state(self): + """Save led state""" + self.run_gcode_signal.emit(self.current_object.get_gcode(self.led_name)) + + def _setup_ui(self) -> None: + self.setObjectName("leds_slider_page") + widget = QtWidgets.QWidget(parent=self) + widget.setGeometry(QtCore.QRect(0, 0, 720, 420)) + + self.toggle_led_button = ToggleAnimatedButton(parent=self) + self.toggle_led_button.setGeometry(QtCore.QRect(70, 120, 100, 50)) + self.toggle_led_button.setMinimumSize(QtCore.QSize(100, 50)) + self.toggle_led_button.setMaximumSize(QtCore.QSize(100, 16777215)) + self.toggle_led_button.setObjectName("toggle_led_button") + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(11) + + self.label_4 = QtWidgets.QLabel(parent=self) + self.label_4.setGeometry(QtCore.QRect(170, 150, 31, 16)) + self.label_4.setFont(font) + self.label_4.setStyleSheet("color:white") + self.label_4.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.label_4.setObjectName("label_4") + + self.label_5 = QtWidgets.QLabel(parent=self) + self.label_5.setGeometry(QtCore.QRect(40, 150, 31, 16)) + self.label_5.setFont(font) + self.label_5.setStyleSheet("color:white") + self.label_5.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.label_5.setObjectName("label_5") + + self.layoutWidget = QtWidgets.QWidget(parent=self) + self.layoutWidget.setGeometry(QtCore.QRect(10, 30, 691, 81)) + self.layoutWidget.setObjectName("layoutWidget") + + self.leds_slider_header_layout = QtWidgets.QHBoxLayout(self.layoutWidget) + self.leds_slider_header_layout.setContentsMargins(0, 0, 0, 0) + self.leds_slider_header_layout.setObjectName("leds_slider_header_layout") + spacerItem19 = QtWidgets.QSpacerItem( + 60, + 20, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.leds_slider_header_layout.addItem(spacerItem19) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Preferred, + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.leds_slider_tittle_label = QtWidgets.QLabel(parent=self.layoutWidget) + self.leds_slider_tittle_label.setSizePolicy(sizePolicy) + self.leds_slider_tittle_label.setMinimumSize(QtCore.QSize(0, 60)) + self.leds_slider_tittle_label.setMaximumSize(QtCore.QSize(16777215, 60)) + self.leds_slider_tittle_label.setFont(font) + self.leds_slider_tittle_label.setStyleSheet( + "background: transparent; color: white;" + ) + self.leds_slider_tittle_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.leds_slider_tittle_label.setObjectName("leds_slider_tittle_label") + self.leds_slider_header_layout.addWidget(self.leds_slider_tittle_label) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(20) + font.setItalic(False) + font.setStyleStrategy(QtGui.QFont.StyleStrategy.PreferAntialias) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + QtWidgets.QSizePolicy.Policy.MinimumExpanding, + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.leds_slider_back_btn = IconButton(parent=self.layoutWidget) + self.leds_slider_back_btn.setSizePolicy(sizePolicy) + self.leds_slider_back_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.leds_slider_back_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.leds_slider_back_btn.setFont(font) + self.leds_slider_back_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") + ) + self.leds_slider_back_btn.setObjectName("leds_slider_back_btn") + self.leds_slider_header_layout.addWidget(self.leds_slider_back_btn) + + self.verticalLayout = QtWidgets.QVBoxLayout(self) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.leds_w_slider = BlocksSlider(parent=self) + self.leds_w_slider.setSizePolicy(sizePolicy) + self.leds_w_slider.setMinimumSize(QtCore.QSize(600, 100)) + self.leds_w_slider.setMaximumSize(QtCore.QSize(600, 100)) + self.leds_w_slider.setMaximum(100) + self.leds_w_slider.setProperty("value", 100) + self.leds_w_slider.setOrientation(QtCore.Qt.Orientation.Horizontal) + self.leds_w_slider.setObjectName("leds_w_slider") + self.verticalLayout.addWidget( + self.leds_w_slider, 0, QtCore.Qt.AlignmentFlag.AlignHCenter + ) + + widget.setLayout(self.verticalLayout) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.toggle_led_button.setText( + _translate("utilitiesStackedWidget", "PushButton") + ) + self.label_4.setText(_translate("utilitiesStackedWidget", "On")) + self.label_5.setText(_translate("utilitiesStackedWidget", "Off")) + self.leds_slider_tittle_label.setText( + _translate("utilitiesStackedWidget", "LED's") + ) + self.leds_slider_tittle_label.setProperty( + "class", _translate("utilitiesStackedWidget", "title_text") + ) + self.leds_slider_back_btn.setText(_translate("utilitiesStackedWidget", "Back")) + self.leds_slider_back_btn.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) + self.leds_slider_back_btn.setProperty( + "button_type", _translate("utilitiesStackedWidget", "icon") + ) diff --git a/BlocksScreen/lib/panels/widgets/UtilitiesTab/rc_page.py b/BlocksScreen/lib/panels/widgets/UtilitiesTab/rc_page.py new file mode 100644 index 00000000..ed450059 --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/UtilitiesTab/rc_page.py @@ -0,0 +1,162 @@ +import typing + +from PyQt6 import QtCore, QtGui, QtWidgets + +from lib.utils.blocks_button import BlocksCustomButton + + +class RoutineCheckAnswerPage(QtWidgets.QWidget): + request_back_button = QtCore.pyqtSignal(name="request-back-button") + + run_gcode_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="run-gcode" + ) + + on_rc_asnwer = QtCore.pyqtSignal(str, name="on-rc-asnwer") + + def __init__( + self, + parent: typing.Optional["QtWidgets.QWidget"], + ) -> None: + super(RoutineCheckAnswerPage, self).__init__(parent) + + self._setup_ui() + + self.rc_yes.clicked.connect(self.on_routine_answer) + self.rc_no.clicked.connect(self.on_routine_answer) + + def setTitle(self, title: str): + self.rc_title.setText(title) + + def setMessage(self, message: str): + self.rc_label.setText(message) + + def on_routine_answer(self): + if self.sender() == self.rc_yes: + self.on_rc_asnwer.emit("yes") + else: + self.on_rc_asnwer.emit("no") + self.request_back_button.emit() + + def _setup_ui(self) -> None: + self.setObjectName("fans_page") + widget = QtWidgets.QWidget(parent=self) + widget.setGeometry(QtCore.QRect(0, 0, 720, 420)) + + self.verticalLayout = QtWidgets.QVBoxLayout(self) + self.verticalLayout.setObjectName("verticalLayout") + spacerItem10 = QtWidgets.QSpacerItem( + 20, + 24, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem10) + self.rc_header_layout = QtWidgets.QHBoxLayout() + self.rc_header_layout.setObjectName("rc_header_layout") + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.rc_title = QtWidgets.QLabel(parent=self) + self.rc_title.setSizePolicy(sizePolicy) + self.rc_title.setMinimumSize(QtCore.QSize(0, 60)) + self.rc_title.setFont(font) + self.rc_title.setStyleSheet("background: transparent; color: white;") + self.rc_title.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.rc_title.setObjectName("rc_title") + + self.rc_header_layout.addWidget(self.rc_title) + self.verticalLayout.addLayout(self.rc_header_layout) + self.rc_content_layout = QtWidgets.QGridLayout() + self.rc_content_layout.setVerticalSpacing(0) + self.rc_content_layout.setObjectName("rc_content_layout") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Preferred, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + font = QtGui.QFont() + font.setPointSize(15) + + self.rc_label = QtWidgets.QLabel(parent=self) + + self.rc_label.setSizePolicy(sizePolicy) + self.rc_label.setFont(font) + self.rc_label.setStyleSheet("color:white") + self.rc_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.rc_label.setObjectName("rc_label") + + self.rc_content_layout.addWidget(self.rc_label, 0, 0, 1, 1) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Fixed + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(19) + font.setStyleStrategy(QtGui.QFont.StyleStrategy.PreferAntialias) + + self.rc_yes = BlocksCustomButton(parent=self) + self.rc_yes.setSizePolicy(sizePolicy) + self.rc_yes.setMinimumSize(QtCore.QSize(250, 80)) + self.rc_yes.setMaximumSize(QtCore.QSize(250, 80)) + self.rc_yes.setFont(font) + self.rc_yes.setProperty( + "icon_pixmap", QtGui.QPixmap(":/dialog/media/btn_icons/yes.svg") + ) + self.rc_yes.setObjectName("rc_yes") + self.horizontalLayout_3.addWidget(self.rc_yes) + spacerItem11 = QtWidgets.QSpacerItem( + 40, + 20, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.horizontalLayout_3.addItem(spacerItem11) + + self.rc_no = BlocksCustomButton(parent=self) + self.rc_no.setSizePolicy(sizePolicy) + self.rc_no.setMinimumSize(QtCore.QSize(250, 80)) + self.rc_no.setMaximumSize(QtCore.QSize(250, 80)) + self.rc_no.setFont(font) + self.rc_no.setProperty( + "icon_pixmap", QtGui.QPixmap(":/dialog/media/btn_icons/no.svg") + ) + self.rc_no.setObjectName("rc_no") + self.horizontalLayout_3.addWidget(self.rc_no) + self.rc_content_layout.addLayout(self.horizontalLayout_3, 1, 0, 1, 1) + self.verticalLayout.addLayout(self.rc_content_layout) + + widget.setLayout(self.verticalLayout) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.rc_title.setText(_translate("utilitiesStackedWidget", "label")) + self.rc_title.setProperty( + "class", _translate("utilitiesStackedWidget", "title_text") + ) + self.rc_label.setText(_translate("utilitiesStackedWidget", "TextLabel")) + self.rc_yes.setText(_translate("utilitiesStackedWidget", "Yes")) + self.rc_yes.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) + self.rc_no.setText(_translate("utilitiesStackedWidget", "No")) + self.rc_no.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) diff --git a/BlocksScreen/lib/panels/widgets/UtilitiesTab/routineCheckPage.py b/BlocksScreen/lib/panels/widgets/UtilitiesTab/routineCheckPage.py new file mode 100644 index 00000000..77ef11e3 --- /dev/null +++ b/BlocksScreen/lib/panels/widgets/UtilitiesTab/routineCheckPage.py @@ -0,0 +1,364 @@ +import typing +from enum import Enum, auto +from lib.utils.icon_button import IconButton + +from PyQt6 import QtCore, QtGui, QtWidgets + +from lib.utils.blocks_button import BlocksCustomButton + + +class Process(Enum): + FAN = auto() + AXIS = auto() + BED_HEATER = auto() + EXTRUDER = auto() + AXIS_MAINTENANCE = auto() + + +class RoutineCheckPage(QtWidgets.QWidget): + request_troubleshoot_page = QtCore.pyqtSignal(name="request-troubleshoot-page") + + request_back_button = QtCore.pyqtSignal(name="request-back-button") + + run_gcode_signal: typing.ClassVar[QtCore.pyqtSignal] = QtCore.pyqtSignal( + str, name="run-gcode" + ) + show_waiting_page = QtCore.pyqtSignal(str, int, bool, name="show-waiting-page") + + set_rc_page = QtCore.pyqtSignal(str, str, name="set-rc-page") + + def __init__( + self, + parent: typing.Optional["QtWidgets.QWidget"], + ) -> None: + super(RoutineCheckPage, self).__init__(parent) + + self.objects: dict = { + "fans": {}, + "axis": {"x": "indf", "y": "indf", "z": "indf"}, + "bheat": {"Bed_Heater": "indf"}, + "extrude": {"extruder": "indf"}, + "leds": {}, + } + self.tb = False + + self._setup_ui() + + self.current_object: typing.Optional[str] = None + self.routine_check_back_btn.clicked.connect(self.request_back_button) + + self.rc_fans.clicked.connect(lambda: self.run_routine(Process.FAN)) + self.rc_bheat.clicked.connect(lambda: self.run_routine(Process.BED_HEATER)) + self.rc_ext.clicked.connect(lambda: self.run_routine(Process.EXTRUDER)) + self.rc_axis.clicked.connect(lambda: self.run_routine(Process.AXIS)) + + @QtCore.pyqtSlot(list, name="on_object_list") + def on_object_list(self, object_list: list) -> None: + """Handle receiving printer object list""" + self.cg = object_list + for obj in self.cg: + base_name = obj.split()[0] + # Only accept 'fan_generic' or 'fan' + if base_name == "fan_generic" or base_name == "fan": + self.objects["fans"][obj.split()[1]] = "indef" + + def run_routine(self, process: Process): + """Run check routine for available processes""" + self.current_process = process + routine_configs = { + Process.FAN: ("fans", "fan is spinning"), + Process.AXIS: ("axis", "axis is moving"), + Process.BED_HEATER: ("bheat", "bed is heating"), + Process.EXTRUDER: ("extrude", "extruder is being tested"), + } + if process not in routine_configs: + return + obj_key, message = routine_configs[process] + obj_list = list(self.objects.get(obj_key, {}).keys()) + if not self._advance_routine_object(obj_list): + if self.tb: + self.request_troubleshoot_page.emit() + self.tb = False + else: + self.request_back_button.emit + + if process == Process.FAN: + self.run_gcode_signal.emit("M107") + return + + message = f"Please check if the {self.current_object} is functioning correctly." + if process == Process.AXIS: + message = f"Please ensure the {self.current_object} axis moves correctly." + elif process in [Process.BED_HEATER, Process.EXTRUDER]: + message = "Please check if the temperature reaches 60°C. \n you may need to wait a few moments." + + self.set_rc_page.emit(f"Running routine for: {self.current_object}", message) + self.show_waiting_page.emit( + f"Please check if the {message}", + 10000 if process == Process.AXIS else 0, + False, + ) + self._send_routine_gcode() + + @QtCore.pyqtSlot(str, name="on_rc_asnwer") + def on_routine_answer(self, answer: str) -> None: + """Handle routine ongoing process""" + if self.current_process is None or self.current_object is None: + return + if answer == "no": + self.tb = True + + process_map = { + Process.FAN: ("fans", self.current_object), + Process.AXIS: ("axis", self.current_object), + Process.BED_HEATER: ("bheat", "Bed_Heater"), + Process.EXTRUDER: ("extrude", "extruder"), + } + if self.current_process in process_map: + obj_key, item_key = process_map[self.current_process] + self.objects[obj_key][item_key] = answer + if self.current_process in [Process.BED_HEATER, Process.EXTRUDER]: + self.run_gcode_signal.emit("TURN_OFF_HEATERS") + + if self.current_process is Process.FAN: + for i in self.objects["fans"]: + self.run_gcode_signal.emit(f"SET_FAN_SPEED FAN={i} SPEED=0\nM400") + + self.run_routine(self.current_process) + + def _advance_routine_object(self, obj_list: list) -> bool: + if not obj_list: + is_first_run = self.current_object is None + self.current_object = obj_list[0] if is_first_run and obj_list else "done" + return is_first_run + if self.current_object not in obj_list: + if self.current_process == Process.AXIS: + self.run_gcode_signal.emit("G28") + self.run_gcode_signal.emit("G91\nG1 X60 F700") + self.current_object = obj_list[0] + return True + try: + current_index = obj_list.index(self.current_object) + if current_index + 1 < len(obj_list): + self.current_object = obj_list[current_index + 1] + return True + else: + self.current_object = None + return False + except ValueError: + self.current_object = obj_list[0] + return True + + def _send_routine_gcode(self): + """Send the correct G-code for the current process and object.""" + if self.current_process == Process.FAN: + fan_name = self.current_object or next(iter(self.objects["fans"]), None) + if fan_name: + if fan_name == "fan": + self.run_gcode_signal.emit("M106 S255\nM400") + else: + self.run_gcode_signal.emit( + f"SET_FAN_SPEED FAN={fan_name} SPEED=0.8\nM400" + ) + + return + + gcode_map = { + Process.BED_HEATER: "SET_HEATER_TEMPERATURE HEATER=heater_bed TARGET=60", + Process.EXTRUDER: "SET_HEATER_TEMPERATURE HEATER=extruder TARGET=60", + (Process.AXIS, "x"): "G91\nG1 X50 F700\nG1 X-50 F700", + (Process.AXIS, "y"): "G91\nG1 Y-50 F700\nG1 Y50 F700", + (Process.AXIS, "z"): "G91\nG1 Z50 F600\nG1 Z-50 F600", + } + + key = ( + (self.current_process, self.current_object) + if self.current_process == Process.AXIS + else self.current_process + ) + + if gcode := gcode_map.get(key): + self.run_gcode_signal.emit(f"{gcode}\nM400") + + def _setup_ui(self) -> None: + self.setObjectName("fans_page") + widget = QtWidgets.QWidget(parent=self) + widget.setGeometry(QtCore.QRect(0, 0, 720, 420)) + + self.routines_page = QtWidgets.QWidget() + self.routines_page.setObjectName("routines_page") + self.verticalLayout = QtWidgets.QVBoxLayout(self.routines_page) + self.verticalLayout.setObjectName("verticalLayout") + spacerItem6 = QtWidgets.QSpacerItem( + 20, + 24, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem6) + self.routines_header_layout = QtWidgets.QHBoxLayout() + self.routines_header_layout.setSizeConstraint( + QtWidgets.QLayout.SizeConstraint.SetMinimumSize + ) + self.routines_header_layout.setObjectName("routines_header_layout") + spacerItem7 = QtWidgets.QSpacerItem( + 60, + 20, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.routines_header_layout.addItem(spacerItem7) + self.routines_page_title = QtWidgets.QLabel(parent=self.routines_page) + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth( + self.routines_page_title.sizePolicy().hasHeightForWidth() + ) + self.routines_page_title.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(24) + self.routines_page_title.setFont(font) + self.routines_page_title.setStyleSheet("background: transparent; color: white;") + self.routines_page_title.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.routines_page_title.setObjectName("routines_page_title") + self.routines_header_layout.addWidget(self.routines_page_title) + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + self.routine_check_back_btn = IconButton(parent=self.routines_page) + self.routine_check_back_btn.setSizePolicy(sizePolicy) + self.routine_check_back_btn.setMinimumSize(QtCore.QSize(60, 60)) + self.routine_check_back_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.routine_check_back_btn.setProperty( + "icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg") + ) + self.routine_check_back_btn.setObjectName("routine_check_back_btn") + self.routines_header_layout.addWidget(self.routine_check_back_btn) + self.verticalLayout.addLayout(self.routines_header_layout) + + spacerItem8 = QtWidgets.QSpacerItem( + 20, + 60, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + self.verticalLayout.addItem(spacerItem8) + self.routines_content_layout = QtWidgets.QGridLayout() + self.routines_content_layout.setVerticalSpacing(20) + self.routines_content_layout.setObjectName("routines_content_layout") + + sizePolicy = QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + + font = QtGui.QFont() + font.setFamily("Momcake") + font.setPointSize(19) + font.setItalic(False) + font.setStyleStrategy(QtGui.QFont.StyleStrategy.PreferAntialias) + + self.rc_bheat = BlocksCustomButton(parent=self.routines_page) + self.rc_bheat.setSizePolicy(sizePolicy) + self.rc_bheat.setFont(font) + self.rc_bheat.setMinimumSize(QtCore.QSize(250, 80)) + self.rc_bheat.setMaximumSize(QtCore.QSize(250, 80)) + self.rc_bheat.setProperty( + "icon_pixmap", + QtGui.QPixmap( + ":/temperature_related/media/btn_icons/temperature_plate.svg" + ), + ) + self.rc_bheat.setObjectName("rc_bheat") + self.routines_content_layout.addWidget(self.rc_bheat, 0, 1, 1, 1) + + self.rc_fans = BlocksCustomButton(parent=self.routines_page) + self.rc_fans.setSizePolicy(sizePolicy) + self.rc_fans.setFont(font) + self.rc_fans.setMinimumSize(QtCore.QSize(250, 80)) + self.rc_fans.setMaximumSize(QtCore.QSize(250, 80)) + self.rc_fans.setProperty( + "icon_pixmap", QtGui.QPixmap(":/fan_related/media/btn_icons/fan_cage.svg") + ) + self.rc_fans.setObjectName("rc_fans") + self.routines_content_layout.addWidget(self.rc_fans, 0, 0, 1, 1) + + self.rc_axis = BlocksCustomButton(parent=self.routines_page) + self.rc_axis.setSizePolicy(sizePolicy) + self.rc_axis.setFont(font) + self.rc_axis.setMinimumSize(QtCore.QSize(250, 80)) + self.rc_axis.setMaximumSize(QtCore.QSize(250, 80)) + self.rc_axis.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/motion/media/btn_icons/axis_maintenance.svg"), + ) + self.rc_axis.setObjectName("rc_axis") + self.routines_content_layout.addWidget(self.rc_axis, 1, 1, 1, 1) + + self.rc_ext = BlocksCustomButton(parent=self.routines_page) + self.rc_ext.setSizePolicy(sizePolicy) + self.rc_ext.setFont(font) + self.rc_ext.setMinimumSize(QtCore.QSize(250, 80)) + self.rc_ext.setMaximumSize(QtCore.QSize(250, 80)) + self.rc_ext.setProperty( + "icon_pixmap", + QtGui.QPixmap(":/extruder_related/media/btn_icons/nozzle.svg"), + ) + self.rc_ext.setObjectName("rc_ext") + self.routines_content_layout.addWidget(self.rc_ext, 1, 0, 1, 1) + self.verticalLayout.addLayout(self.routines_content_layout) + spacerItem9 = QtWidgets.QSpacerItem( + 20, + 40, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Expanding, + ) + self.verticalLayout.addItem(spacerItem9) + + widget.setLayout(self.verticalLayout) + + self.retranslateUi() + + def retranslateUi(self): + _translate = QtCore.QCoreApplication.translate + self.routines_page_title.setText( + _translate("utilitiesStackedWidget", "Routine Check") + ) + self.routines_page_title.setProperty( + "class", _translate("utilitiesStackedWidget", "title_text") + ) + self.routine_check_back_btn.setText( + _translate("utilitiesStackedWidget", "Back") + ) + self.routine_check_back_btn.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) + self.routine_check_back_btn.setProperty( + "button_type", _translate("utilitiesStackedWidget", "icon") + ) + self.rc_bheat.setText(_translate("utilitiesStackedWidget", "Bed Heater")) + self.rc_bheat.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) + self.rc_fans.setText(_translate("utilitiesStackedWidget", "Fans")) + self.rc_fans.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) + self.rc_axis.setText(_translate("utilitiesStackedWidget", "Axis")) + self.rc_axis.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) + self.rc_ext.setText(_translate("utilitiesStackedWidget", "Extruder")) + self.rc_ext.setProperty( + "class", _translate("utilitiesStackedWidget", "menu_btn") + ) diff --git a/BlocksScreen/lib/panels/widgets/troubleshootPage.py b/BlocksScreen/lib/panels/widgets/UtilitiesTab/troubleshootPage.py similarity index 98% rename from BlocksScreen/lib/panels/widgets/troubleshootPage.py rename to BlocksScreen/lib/panels/widgets/UtilitiesTab/troubleshootPage.py index 0c327ac7..48cdefc7 100644 --- a/BlocksScreen/lib/panels/widgets/troubleshootPage.py +++ b/BlocksScreen/lib/panels/widgets/UtilitiesTab/troubleshootPage.py @@ -24,6 +24,7 @@ def __init__( self.label_4.setText( "For more information check our website \n www.blockstec.com \n or \nsupport@blockstec.com" ) + self.tb_back_btn.clicked.connect(lambda: self.hide()) self.repaint() def _geometry_calc(self) -> None: diff --git a/BlocksScreen/lib/panels/widgets/basePopup.py b/BlocksScreen/lib/panels/widgets/basePopup.py index a9a4d188..daea968b 100644 --- a/BlocksScreen/lib/panels/widgets/basePopup.py +++ b/BlocksScreen/lib/panels/widgets/basePopup.py @@ -105,37 +105,74 @@ def _update_button_style(self) -> None: ) def set_message(self, message: str) -> None: + """Sets Main Message + + Args: + message (str): a message + """ self.label.setText(message) def cancel_button_text(self, text: str) -> None: + """Sets Cancel button text + + Args: + text (str): a string + """ + if not self.dialog: return self.cancel_button.setText(text) def confirm_button_text(self, text: str) -> None: + """Sets Confirm button text + + Args: + text (str): a string + """ if not self.dialog: return self.confirm_button.setText(text) def cancel_background_color(self, color: str) -> None: + """Sets Cancel button color + + Args: + color (str): a string containing a hex color + """ + if not self.dialog: return self.cancel_bk_color = color self._update_button_style() def confirm_background_color(self, color: str) -> None: + """Sets Confirm button color + + Args: + color (str): a string containing a hex color + """ if not self.dialog: return self.confirm_bk_color = color self._update_button_style() def cancel_font_color(self, color: str) -> None: + """Sets cancel font color + + Args: + color (str): a string containing a hex color + """ if not self.dialog: return self.cancel_ft_color = color self._update_button_style() def confirm_font_color(self, color: str) -> None: + """Sets confirm font color + + Args: + color (str): a string containing a hex color + """ if not self.dialog: return self.confirm_ft_color = color diff --git a/BlocksScreen/lib/panels/widgets/fansPage.py b/BlocksScreen/lib/panels/widgets/fansPage.py deleted file mode 100644 index 925c0230..00000000 --- a/BlocksScreen/lib/panels/widgets/fansPage.py +++ /dev/null @@ -1,15 +0,0 @@ -from PyQt6 import QtCore, QtWidgets -import typing - - -class FansPage(QtWidgets.QWidget): - def __init__( - self, - parent: typing.Optional["QtWidgets.QWidget"], - flags: typing.Optional["QtCore.Qt.WindowType"], - ) -> None: - if parent is not None and flags is not None: - super(FansPage, self).__init__(parent, flags) - - else: - super(FansPage, self).__init__() diff --git a/BlocksScreen/lib/ui/controlStackedWidget.ui b/BlocksScreen/lib/ui/controlStackedWidget.ui index 92475345..e51206d2 100644 --- a/BlocksScreen/lib/ui/controlStackedWidget.ui +++ b/BlocksScreen/lib/ui/controlStackedWidget.ui @@ -32,7 +32,7 @@ StackedWidget - 7 + 3 @@ -2583,1729 +2583,1639 @@ Home 420 - - - true - - - - 160 - 350 - 51 - 41 - - - - - Montserrat - 14 - - - - background: transparent; color: white; - - - X: - - - - - true - - - - 340 - 350 - 51 - 41 - - - - - Montserrat - 14 - - - - background: transparent; color: white; - - - Y: - - - - - true - - - - 500 - 350 - 51 - 41 - - - - - Montserrat - 14 - - - - background: transparent; color: white; - - - Z: - - - - - true - - - - 550 - 350 - 91 - 41 - - - - - Montserrat - 14 - - - - background: transparent; color: white; - - - 0 - - - - - true - - - - 370 - 350 - 91 - 41 - - - - - Montserrat - 14 - - - - background: transparent; color: white; - - - 0 - - - - - true - - - - 190 - 350 - 81 - 41 - - - - - Montserrat - 14 - - - - background: transparent; color: white; - - - 0 - - - - - - 10 - 23 - 691 - 81 - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 60 - 20 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 60 - - - - - Momcake - 24 - - - - background: transparent; color: white; - - - Move Axis - - - Qt::AlignCenter - - - title_text - - - - - - - - 0 - 0 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - Momcake - 20 - false - PreferAntialias - - - - false - - - true - - - Qt::NoContextMenu - - - Qt::LeftToRight - - - - - - Back - - - false - - - true - - - menu_btn - - - icon - - - :/ui/media/btn_icons/back.svg - - - - - - - - - 630 - 130 - 71 - 201 - - - - - - - true - - - - 1 - 1 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - - - - - - - 16 - 16 - - - - false - - - false - - - true - - - icon - - - :/arrow_icons/media/btn_icons/up_arrow.svg - - - - - - - true - - - - 1 - 1 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - - - - - - - 16 - 16 - - - - false - - - false - - - true - - - icon - - - :/arrow_icons/media/btn_icons/down_arrow.svg - - - - - - - - - 10 - 90 - 81 - 301 - - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - true - - - - 1 - 1 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - - - - - - - 16 - 16 - - - - false - - - false - - - true - - - icon - - - :/motion/media/btn_icons/home_x.svg - - - - - - - true - - - - 1 - 1 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - - - - - - - 16 - 16 - - - - false - - - false - - - true - - - icon - - - :/motion/media/btn_icons/home_y.svg - - - - - - - true - - - - 1 - 1 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - - - - - - - 16 - 16 - - - - false - - - false - - - true - - - icon - - - :/motion/media/btn_icons/home_z.svg - - - - - - - true - - - - 1 - 1 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - - - - - - - 16 - 16 - - - - false - - - false - - - true - - - icon - - - :/motion/media/btn_icons/home_all.svg - - - - - - - - - 96 - 240 - 100 - 100 - - - - - 60 - 60 - - - - - 100 - 100 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - - - 14 - - - - 25 - - - true - - - true - - - true - - - axis_select_speed_group - - - - - - 205 - 240 - 100 - 100 - - - - - 60 - 60 - - - - - 100 - 100 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - - - 14 - - - - 50 - - - true - - - false - - - axis_select_speed_group - - - - - - 315 - 240 - 100 - 100 - - - - - 60 - 60 - - - - - 100 - 100 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - - - 14 - - - - 100 - - - true - - - false - - - axis_select_speed_group - - - - - - 109 - 216 - 261 - 21 - - - - - 14 - - - - color:white - - - Move Speed mm/s - - - - - - 96 - 110 - 100 - 100 - - - - - 60 - 60 - - - - - 100 - 100 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - - - 14 - - - - 1 - - - true - - - true - - - true - - - axis_select_length_group - - - - - - 204 - 110 - 100 - 100 - - - - - 60 - 60 - - - - - 100 - 100 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - - - 14 - - - - 10 - - - true - - - false - - - axis_select_length_group - - - - - - 315 - 110 - 100 - 100 - - - - - 60 - 60 - - - - - 100 - 100 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - - - 14 - - - - 100 - - - true - - - false - - - axis_select_length_group - - - - - - 109 - 85 - 261 - 21 - - - - - 14 - - - - color:white - - - Move Length mm - - - - - - 440 - 128 - 196 - 204 - - - - - 0 - - - 5 - - - 0 - - - 5 - - - - - true - - - - 1 - 1 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - - - - - - - 16 - 16 - - - - false - - - false - - - true - - - icon - - - :/arrow_icons/media/btn_icons/left_arrow.svg - - - - - - - true - - - - 1 - 1 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - - - - - - - 16 - 16 - - - - false - - - false - - - true - - - icon - - - :/arrow_icons/media/btn_icons/right_arrow.svg - - - - - - - true - - - - 1 - 1 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - - - - - - - 60 - 60 - - - - false - - - false - - - true - - - icon - - - :/arrow_icons/media/btn_icons/down_arrow.svg - - - - - - - true - - - - 1 - 1 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - - - - - - - 60 - 60 - - - - false - - - false - - - true - - - icon - - - :/arrow_icons/media/btn_icons/up_arrow.svg - - - - - - - - 0 - 0 - - - - - 60 - 60 - - - - - 60 - 60 - - - - - - - true - - - icon - - - :/ui/media/btn_icons/center_arrows.svg - - - - - + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 60 + 20 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 60 + + + + + Momcake + 24 + + + + background: transparent; color: white; + + + Move Axis + + + Qt::AlignCenter + + + title_text + + + + + + + + 0 + 0 + + + + + 60 + 60 + + + + + 60 + 60 + + + + + Momcake + 20 + false + PreferAntialias + + + + false + + + true + + + Qt::NoContextMenu + + + Qt::LeftToRight + + + + + + Back + + + false + + + true + + + menu_btn + + + icon + + + :/ui/media/btn_icons/back.svg + + + + + + + + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + true + + + + 1 + 1 + + + + + 80 + 80 + + + + + 80 + 80 + + + + + + + + + + + 16 + 16 + + + + false + + + false + + + true + + + icon + + + :/motion/media/btn_icons/home_x.svg + + + + + + + true + + + + 1 + 1 + + + + + 80 + 80 + + + + + 80 + 80 + + + + + + + + + + + 16 + 16 + + + + false + + + false + + + true + + + icon + + + :/motion/media/btn_icons/home_y.svg + + + + + + + true + + + + 1 + 1 + + + + + 80 + 80 + + + + + 80 + 80 + + + + + + + + + + + 16 + 16 + + + + false + + + false + + + true + + + icon + + + :/motion/media/btn_icons/home_z.svg + + + + + + + true + + + + 1 + 1 + + + + + 80 + 80 + + + + + 80 + 80 + + + + + + + + + + + 16 + 16 + + + + false + + + false + + + true + + + icon + + + :/motion/media/btn_icons/home_all.svg + + + + + + + + + + + + 16777215 + 20 + + + + + 14 + + + + color:white + + + Move Length mm + + + + + + + + + + 90 + 90 + + + + + 90 + 90 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + + + 14 + + + + 1 + + + true + + + true + + + true + + + + + + + + 90 + 90 + + + + + 90 + 90 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + + + 14 + + + + 10 + + + true + + + false + + + + + + + + 90 + 90 + + + + + 90 + 90 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + + + 14 + + + + 100 + + + true + + + false + + + + + + + + + + 0 + 0 + + + + + 16777215 + 20 + + + + + 14 + + + + color:white + + + Move Speed mm/s + + + + + + + + + + 90 + 90 + + + + + 90 + 90 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + + + 14 + + + + 25 + + + true + + + true + + + true + + + + + + + + 90 + 90 + + + + + 90 + 90 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + + + 14 + + + + 50 + + + true + + + false + + + + + + + + 90 + 90 + + + + + 90 + 90 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + + + 14 + + + + 100 + + + true + + + false + + + + + + + + + + + + + 0 + + + 5 + + + 0 + + + 5 + + + + + true + + + + 1 + 1 + + + + + 60 + 60 + + + + + 60 + 60 + + + + + + + + + + + 16 + 16 + + + + false + + + false + + + true + + + icon + + + :/arrow_icons/media/btn_icons/left_arrow.svg + + + + + + + true + + + + 1 + 1 + + + + + 60 + 60 + + + + + 60 + 60 + + + + + + + + + + + 16 + 16 + + + + false + + + false + + + true + + + icon + + + :/arrow_icons/media/btn_icons/right_arrow.svg + + + + + + + true + + + + 1 + 1 + + + + + 60 + 60 + + + + + 60 + 60 + + + + + + + + + + + 60 + 60 + + + + false + + + false + + + true + + + icon + + + :/arrow_icons/media/btn_icons/down_arrow.svg + + + + + + + true + + + + 1 + 1 + + + + + 60 + 60 + + + + + 60 + 60 + + + + + + + + + + + 60 + 60 + + + + false + + + false + + + true + + + icon + + + :/arrow_icons/media/btn_icons/up_arrow.svg + + + + + + + + 0 + 0 + + + + + 60 + 60 + + + + + 60 + 60 + + + + + + + true + + + icon + + + :/ui/media/btn_icons/center_arrows.svg + + + + + + + + + + + true + + + + 1 + 1 + + + + + 60 + 60 + + + + + 60 + 60 + + + + + + + + + + + 16 + 16 + + + + false + + + false + + + true + + + icon + + + :/arrow_icons/media/btn_icons/up_arrow.svg + + + + + + + true + + + + 1 + 1 + + + + + 60 + 60 + + + + + 60 + 60 + + + + + + + + + + + 16 + 16 + + + + false + + + false + + + true + + + icon + + + :/arrow_icons/media/btn_icons/down_arrow.svg + + + + + + + + + + + + + + + true + + + + Montserrat + 14 + + + + background: transparent; color: white; + + + X: + + + + + + + true + + + + Montserrat + 14 + + + + background: transparent; color: white; + + + 0 + + + + + + + true + + + + Montserrat + 14 + + + + background: transparent; color: white; + + + Y: + + + + + + + true + + + + Montserrat + 14 + + + + background: transparent; color: white; + + + 0 + + + + + + + true + + + + Montserrat + 14 + + + + background: transparent; color: white; + + + Z: + + + + + + + true + + + + Montserrat + 14 + + + + background: transparent; color: white; + + + 0 + + + + + + @@ -5781,9 +5691,9 @@ Home + - diff --git a/BlocksScreen/lib/ui/controlStackedWidget_ui.py b/BlocksScreen/lib/ui/controlStackedWidget_ui.py index d76bb627..e6bff9c3 100644 --- a/BlocksScreen/lib/ui/controlStackedWidget_ui.py +++ b/BlocksScreen/lib/ui/controlStackedWidget_ui.py @@ -1,6 +1,6 @@ # Form implementation generated from reading ui file '/home/levi/BlocksScreen/BlocksScreen/lib/ui/controlStackedWidget.ui' # -# Created by: PyQt6 UI code generator 6.7.1 +# Created by: PyQt6 UI code generator 6.4.2 # # WARNING: Any manual changes made to this file will be lost when pyuic6 is # run again. Do not edit this file unless you know what you are doing. @@ -453,7 +453,7 @@ def setupUi(self, controlStackedWidget): self.exp_length_content_layout.setContentsMargins(5, 5, 5, 5) self.exp_length_content_layout.setSpacing(5) self.exp_length_content_layout.setObjectName("exp_length_content_layout") - self.extrude_select_length_10_btn = BlocksCustomCheckButton(parent=self.layoutWidget) + self.extrude_select_length_10_btn = GroupButton(parent=self.layoutWidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -521,7 +521,7 @@ def setupUi(self, controlStackedWidget): self.extrude_select_length_group.setObjectName("extrude_select_length_group") self.extrude_select_length_group.addButton(self.extrude_select_length_10_btn) self.exp_length_content_layout.addWidget(self.extrude_select_length_10_btn) - self.extrude_select_length_50_btn = BlocksCustomCheckButton(parent=self.layoutWidget) + self.extrude_select_length_50_btn = GroupButton(parent=self.layoutWidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -586,7 +586,7 @@ def setupUi(self, controlStackedWidget): self.extrude_select_length_50_btn.setObjectName("extrude_select_length_50_btn") self.extrude_select_length_group.addButton(self.extrude_select_length_50_btn) self.exp_length_content_layout.addWidget(self.extrude_select_length_50_btn) - self.extrude_select_length_100_btn = BlocksCustomCheckButton(parent=self.layoutWidget) + self.extrude_select_length_100_btn = GroupButton(parent=self.layoutWidget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -677,7 +677,7 @@ def setupUi(self, controlStackedWidget): self.exp_feedrate_content_layout.setContentsMargins(5, 5, 5, 5) self.exp_feedrate_content_layout.setSpacing(5) self.exp_feedrate_content_layout.setObjectName("exp_feedrate_content_layout") - self.extrude_select_feedrate_2_btn = BlocksCustomCheckButton(parent=self.layoutWidget1) + self.extrude_select_feedrate_2_btn = GroupButton(parent=self.layoutWidget1) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -745,7 +745,7 @@ def setupUi(self, controlStackedWidget): self.extrude_select_feedrate_group.setObjectName("extrude_select_feedrate_group") self.extrude_select_feedrate_group.addButton(self.extrude_select_feedrate_2_btn) self.exp_feedrate_content_layout.addWidget(self.extrude_select_feedrate_2_btn) - self.extrude_select_feedrate_5_btn = BlocksCustomCheckButton(parent=self.layoutWidget1) + self.extrude_select_feedrate_5_btn = GroupButton(parent=self.layoutWidget1) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -810,7 +810,7 @@ def setupUi(self, controlStackedWidget): self.extrude_select_feedrate_5_btn.setObjectName("extrude_select_feedrate_5_btn") self.extrude_select_feedrate_group.addButton(self.extrude_select_feedrate_5_btn) self.exp_feedrate_content_layout.addWidget(self.extrude_select_feedrate_5_btn) - self.extrude_select_feedrate_10_btn = BlocksCustomCheckButton(parent=self.layoutWidget1) + self.extrude_select_feedrate_10_btn = GroupButton(parent=self.layoutWidget1) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -974,69 +974,13 @@ def setupUi(self, controlStackedWidget): self.move_axis_page.setMinimumSize(QtCore.QSize(710, 400)) self.move_axis_page.setMaximumSize(QtCore.QSize(720, 420)) self.move_axis_page.setObjectName("move_axis_page") - self.mva_x_label = QtWidgets.QLabel(parent=self.move_axis_page) - self.mva_x_label.setEnabled(True) - self.mva_x_label.setGeometry(QtCore.QRect(160, 350, 51, 41)) - font = QtGui.QFont() - font.setFamily("Montserrat") - font.setPointSize(14) - self.mva_x_label.setFont(font) - self.mva_x_label.setStyleSheet("background: transparent; color: white;") - self.mva_x_label.setObjectName("mva_x_label") - self.mva_y_label = QtWidgets.QLabel(parent=self.move_axis_page) - self.mva_y_label.setEnabled(True) - self.mva_y_label.setGeometry(QtCore.QRect(340, 350, 51, 41)) - font = QtGui.QFont() - font.setFamily("Montserrat") - font.setPointSize(14) - self.mva_y_label.setFont(font) - self.mva_y_label.setStyleSheet("background: transparent; color: white;") - self.mva_y_label.setObjectName("mva_y_label") - self.mva_z_label = QtWidgets.QLabel(parent=self.move_axis_page) - self.mva_z_label.setEnabled(True) - self.mva_z_label.setGeometry(QtCore.QRect(500, 350, 51, 41)) - font = QtGui.QFont() - font.setFamily("Montserrat") - font.setPointSize(14) - self.mva_z_label.setFont(font) - self.mva_z_label.setStyleSheet("background: transparent; color: white;") - self.mva_z_label.setObjectName("mva_z_label") - self.mva_z_value_label = QtWidgets.QLabel(parent=self.move_axis_page) - self.mva_z_value_label.setEnabled(True) - self.mva_z_value_label.setGeometry(QtCore.QRect(550, 350, 91, 41)) - font = QtGui.QFont() - font.setFamily("Montserrat") - font.setPointSize(14) - self.mva_z_value_label.setFont(font) - self.mva_z_value_label.setStyleSheet("background: transparent; color: white;") - self.mva_z_value_label.setObjectName("mva_z_value_label") - self.mva_y_value_label = QtWidgets.QLabel(parent=self.move_axis_page) - self.mva_y_value_label.setEnabled(True) - self.mva_y_value_label.setGeometry(QtCore.QRect(370, 350, 91, 41)) - font = QtGui.QFont() - font.setFamily("Montserrat") - font.setPointSize(14) - self.mva_y_value_label.setFont(font) - self.mva_y_value_label.setStyleSheet("background: transparent; color: white;") - self.mva_y_value_label.setObjectName("mva_y_value_label") - self.mva_x_value_label = QtWidgets.QLabel(parent=self.move_axis_page) - self.mva_x_value_label.setEnabled(True) - self.mva_x_value_label.setGeometry(QtCore.QRect(190, 350, 81, 41)) - font = QtGui.QFont() - font.setFamily("Montserrat") - font.setPointSize(14) - self.mva_x_value_label.setFont(font) - self.mva_x_value_label.setStyleSheet("background: transparent; color: white;") - self.mva_x_value_label.setObjectName("mva_x_value_label") - self.horizontalLayoutWidget_3 = QtWidgets.QWidget(parent=self.move_axis_page) - self.horizontalLayoutWidget_3.setGeometry(QtCore.QRect(10, 23, 691, 81)) - self.horizontalLayoutWidget_3.setObjectName("horizontalLayoutWidget_3") - self.mva_header_layout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget_3) - self.mva_header_layout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.move_axis_page) + self.verticalLayout_7.setObjectName("verticalLayout_7") + self.mva_header_layout = QtWidgets.QHBoxLayout() self.mva_header_layout.setObjectName("mva_header_layout") spacerItem2 = QtWidgets.QSpacerItem(60, 20, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum) self.mva_header_layout.addItem(spacerItem2) - self.mva_title_label = QtWidgets.QLabel(parent=self.horizontalLayoutWidget_3) + self.mva_title_label = QtWidgets.QLabel(parent=self.move_axis_page) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -1052,7 +996,7 @@ def setupUi(self, controlStackedWidget): self.mva_title_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) self.mva_title_label.setObjectName("mva_title_label") self.mva_header_layout.addWidget(self.mva_title_label) - self.mva_back_btn = IconButton(parent=self.horizontalLayoutWidget_3) + self.mva_back_btn = IconButton(parent=self.move_axis_page) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -1076,63 +1020,21 @@ def setupUi(self, controlStackedWidget): self.mva_back_btn.setProperty("icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/back.svg")) self.mva_back_btn.setObjectName("mva_back_btn") self.mva_header_layout.addWidget(self.mva_back_btn, 0, QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignVCenter) - self.verticalLayoutWidget_2 = QtWidgets.QWidget(parent=self.move_axis_page) - self.verticalLayoutWidget_2.setGeometry(QtCore.QRect(630, 130, 71, 201)) - self.verticalLayoutWidget_2.setObjectName("verticalLayoutWidget_2") - self.mva_z_layout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_2) - self.mva_z_layout.setContentsMargins(0, 0, 0, 0) - self.mva_z_layout.setObjectName("mva_z_layout") - self.mva_z_up = IconButton(parent=self.verticalLayoutWidget_2) - self.mva_z_up.setEnabled(True) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.MinimumExpanding) - sizePolicy.setHorizontalStretch(1) - sizePolicy.setVerticalStretch(1) - sizePolicy.setHeightForWidth(self.mva_z_up.sizePolicy().hasHeightForWidth()) - self.mva_z_up.setSizePolicy(sizePolicy) - self.mva_z_up.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_z_up.setMaximumSize(QtCore.QSize(60, 60)) - self.mva_z_up.setStyleSheet("") - self.mva_z_up.setText("") - self.mva_z_up.setIconSize(QtCore.QSize(16, 16)) - self.mva_z_up.setCheckable(False) - self.mva_z_up.setChecked(False) - self.mva_z_up.setFlat(True) - self.mva_z_up.setProperty("icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/up_arrow.svg")) - self.mva_z_up.setObjectName("mva_z_up") - self.mva_z_layout.addWidget(self.mva_z_up, 0, QtCore.Qt.AlignmentFlag.AlignHCenter) - self.mva_z_down = IconButton(parent=self.verticalLayoutWidget_2) - self.mva_z_down.setEnabled(True) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.MinimumExpanding) - sizePolicy.setHorizontalStretch(1) - sizePolicy.setVerticalStretch(1) - sizePolicy.setHeightForWidth(self.mva_z_down.sizePolicy().hasHeightForWidth()) - self.mva_z_down.setSizePolicy(sizePolicy) - self.mva_z_down.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_z_down.setMaximumSize(QtCore.QSize(60, 60)) - self.mva_z_down.setStyleSheet("") - self.mva_z_down.setText("") - self.mva_z_down.setIconSize(QtCore.QSize(16, 16)) - self.mva_z_down.setCheckable(False) - self.mva_z_down.setChecked(False) - self.mva_z_down.setFlat(True) - self.mva_z_down.setProperty("icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/down_arrow.svg")) - self.mva_z_down.setObjectName("mva_z_down") - self.mva_z_layout.addWidget(self.mva_z_down, 0, QtCore.Qt.AlignmentFlag.AlignHCenter) - self.verticalLayoutWidget_3 = QtWidgets.QWidget(parent=self.move_axis_page) - self.verticalLayoutWidget_3.setGeometry(QtCore.QRect(10, 90, 81, 301)) - self.verticalLayoutWidget_3.setObjectName("verticalLayoutWidget_3") - self.mva_home_axis_layout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_3) + self.verticalLayout_7.addLayout(self.mva_header_layout) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.mva_home_axis_layout = QtWidgets.QVBoxLayout() self.mva_home_axis_layout.setContentsMargins(5, 5, 5, 5) self.mva_home_axis_layout.setObjectName("mva_home_axis_layout") - self.mva_home_x_btn = IconButton(parent=self.verticalLayoutWidget_3) + self.mva_home_x_btn = IconButton(parent=self.move_axis_page) self.mva_home_x_btn.setEnabled(True) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.MinimumExpanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth(self.mva_home_x_btn.sizePolicy().hasHeightForWidth()) self.mva_home_x_btn.setSizePolicy(sizePolicy) - self.mva_home_x_btn.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_home_x_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_home_x_btn.setMinimumSize(QtCore.QSize(80, 80)) + self.mva_home_x_btn.setMaximumSize(QtCore.QSize(80, 80)) self.mva_home_x_btn.setStyleSheet("") self.mva_home_x_btn.setText("") self.mva_home_x_btn.setIconSize(QtCore.QSize(16, 16)) @@ -1142,15 +1044,15 @@ def setupUi(self, controlStackedWidget): self.mva_home_x_btn.setProperty("icon_pixmap", QtGui.QPixmap(":/motion/media/btn_icons/home_x.svg")) self.mva_home_x_btn.setObjectName("mva_home_x_btn") self.mva_home_axis_layout.addWidget(self.mva_home_x_btn, 0, QtCore.Qt.AlignmentFlag.AlignHCenter) - self.mva_home_y_btn = IconButton(parent=self.verticalLayoutWidget_3) + self.mva_home_y_btn = IconButton(parent=self.move_axis_page) self.mva_home_y_btn.setEnabled(True) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.MinimumExpanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth(self.mva_home_y_btn.sizePolicy().hasHeightForWidth()) self.mva_home_y_btn.setSizePolicy(sizePolicy) - self.mva_home_y_btn.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_home_y_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_home_y_btn.setMinimumSize(QtCore.QSize(80, 80)) + self.mva_home_y_btn.setMaximumSize(QtCore.QSize(80, 80)) self.mva_home_y_btn.setStyleSheet("") self.mva_home_y_btn.setText("") self.mva_home_y_btn.setIconSize(QtCore.QSize(16, 16)) @@ -1160,15 +1062,15 @@ def setupUi(self, controlStackedWidget): self.mva_home_y_btn.setProperty("icon_pixmap", QtGui.QPixmap(":/motion/media/btn_icons/home_y.svg")) self.mva_home_y_btn.setObjectName("mva_home_y_btn") self.mva_home_axis_layout.addWidget(self.mva_home_y_btn, 0, QtCore.Qt.AlignmentFlag.AlignHCenter) - self.mva_home_z_btn = IconButton(parent=self.verticalLayoutWidget_3) + self.mva_home_z_btn = IconButton(parent=self.move_axis_page) self.mva_home_z_btn.setEnabled(True) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.MinimumExpanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth(self.mva_home_z_btn.sizePolicy().hasHeightForWidth()) self.mva_home_z_btn.setSizePolicy(sizePolicy) - self.mva_home_z_btn.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_home_z_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_home_z_btn.setMinimumSize(QtCore.QSize(80, 80)) + self.mva_home_z_btn.setMaximumSize(QtCore.QSize(80, 80)) self.mva_home_z_btn.setStyleSheet("") self.mva_home_z_btn.setText("") self.mva_home_z_btn.setIconSize(QtCore.QSize(16, 16)) @@ -1178,15 +1080,15 @@ def setupUi(self, controlStackedWidget): self.mva_home_z_btn.setProperty("icon_pixmap", QtGui.QPixmap(":/motion/media/btn_icons/home_z.svg")) self.mva_home_z_btn.setObjectName("mva_home_z_btn") self.mva_home_axis_layout.addWidget(self.mva_home_z_btn, 0, QtCore.Qt.AlignmentFlag.AlignHCenter) - self.mva_home_all_btn = IconButton(parent=self.verticalLayoutWidget_3) + self.mva_home_all_btn = IconButton(parent=self.move_axis_page) self.mva_home_all_btn.setEnabled(True) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.MinimumExpanding) sizePolicy.setHorizontalStretch(1) sizePolicy.setVerticalStretch(1) sizePolicy.setHeightForWidth(self.mva_home_all_btn.sizePolicy().hasHeightForWidth()) self.mva_home_all_btn.setSizePolicy(sizePolicy) - self.mva_home_all_btn.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_home_all_btn.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_home_all_btn.setMinimumSize(QtCore.QSize(80, 80)) + self.mva_home_all_btn.setMaximumSize(QtCore.QSize(80, 80)) self.mva_home_all_btn.setStyleSheet("") self.mva_home_all_btn.setText("") self.mva_home_all_btn.setIconSize(QtCore.QSize(16, 16)) @@ -1196,10 +1098,22 @@ def setupUi(self, controlStackedWidget): self.mva_home_all_btn.setProperty("icon_pixmap", QtGui.QPixmap(":/motion/media/btn_icons/home_all.svg")) self.mva_home_all_btn.setObjectName("mva_home_all_btn") self.mva_home_axis_layout.addWidget(self.mva_home_all_btn, 0, QtCore.Qt.AlignmentFlag.AlignHCenter) - self.mva_select_speed_25_btn = BlocksCustomCheckButton(parent=self.move_axis_page) - self.mva_select_speed_25_btn.setGeometry(QtCore.QRect(96, 240, 100, 100)) - self.mva_select_speed_25_btn.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_select_speed_25_btn.setMaximumSize(QtCore.QSize(100, 100)) + self.horizontalLayout_2.addLayout(self.mva_home_axis_layout) + self.verticalLayout_6 = QtWidgets.QVBoxLayout() + self.verticalLayout_6.setObjectName("verticalLayout_6") + self.label_2 = QtWidgets.QLabel(parent=self.move_axis_page) + self.label_2.setMaximumSize(QtCore.QSize(16777215, 20)) + font = QtGui.QFont() + font.setPointSize(14) + self.label_2.setFont(font) + self.label_2.setStyleSheet("color:white") + self.label_2.setObjectName("label_2") + self.verticalLayout_6.addWidget(self.label_2) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.mva_select_length_1_btn = GroupButton(parent=self.move_axis_page) + self.mva_select_length_1_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_length_1_btn.setMaximumSize(QtCore.QSize(90, 90)) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) @@ -1228,21 +1142,18 @@ def setupUi(self, controlStackedWidget): brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ButtonText, brush) - self.mva_select_speed_25_btn.setPalette(palette) + self.mva_select_length_1_btn.setPalette(palette) font = QtGui.QFont() font.setPointSize(14) - self.mva_select_speed_25_btn.setFont(font) - self.mva_select_speed_25_btn.setCheckable(True) - self.mva_select_speed_25_btn.setChecked(True) - self.mva_select_speed_25_btn.setFlat(True) - self.mva_select_speed_25_btn.setObjectName("mva_select_speed_25_btn") - self.axis_select_speed_group = QtWidgets.QButtonGroup(controlStackedWidget) - self.axis_select_speed_group.setObjectName("axis_select_speed_group") - self.axis_select_speed_group.addButton(self.mva_select_speed_25_btn) - self.mva_select_speed_50_btn = BlocksCustomCheckButton(parent=self.move_axis_page) - self.mva_select_speed_50_btn.setGeometry(QtCore.QRect(205, 240, 100, 100)) - self.mva_select_speed_50_btn.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_select_speed_50_btn.setMaximumSize(QtCore.QSize(100, 100)) + self.mva_select_length_1_btn.setFont(font) + self.mva_select_length_1_btn.setCheckable(True) + self.mva_select_length_1_btn.setChecked(True) + self.mva_select_length_1_btn.setFlat(True) + self.mva_select_length_1_btn.setObjectName("mva_select_length_1_btn") + self.horizontalLayout_3.addWidget(self.mva_select_length_1_btn) + self.mva_select_length_10_btn = GroupButton(parent=self.move_axis_page) + self.mva_select_length_10_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_length_10_btn.setMaximumSize(QtCore.QSize(90, 90)) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) @@ -1271,18 +1182,17 @@ def setupUi(self, controlStackedWidget): brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ButtonText, brush) - self.mva_select_speed_50_btn.setPalette(palette) + self.mva_select_length_10_btn.setPalette(palette) font = QtGui.QFont() font.setPointSize(14) - self.mva_select_speed_50_btn.setFont(font) - self.mva_select_speed_50_btn.setCheckable(True) - self.mva_select_speed_50_btn.setFlat(False) - self.mva_select_speed_50_btn.setObjectName("mva_select_speed_50_btn") - self.axis_select_speed_group.addButton(self.mva_select_speed_50_btn) - self.mva_select_speed_100_btn = BlocksCustomCheckButton(parent=self.move_axis_page) - self.mva_select_speed_100_btn.setGeometry(QtCore.QRect(315, 240, 100, 100)) - self.mva_select_speed_100_btn.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_select_speed_100_btn.setMaximumSize(QtCore.QSize(100, 100)) + self.mva_select_length_10_btn.setFont(font) + self.mva_select_length_10_btn.setCheckable(True) + self.mva_select_length_10_btn.setFlat(False) + self.mva_select_length_10_btn.setObjectName("mva_select_length_10_btn") + self.horizontalLayout_3.addWidget(self.mva_select_length_10_btn) + self.mva_select_length_100_btn = GroupButton(parent=self.move_axis_page) + self.mva_select_length_100_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_length_100_btn.setMaximumSize(QtCore.QSize(90, 90)) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) @@ -1311,25 +1221,33 @@ def setupUi(self, controlStackedWidget): brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ButtonText, brush) - self.mva_select_speed_100_btn.setPalette(palette) + self.mva_select_length_100_btn.setPalette(palette) font = QtGui.QFont() font.setPointSize(14) - self.mva_select_speed_100_btn.setFont(font) - self.mva_select_speed_100_btn.setCheckable(True) - self.mva_select_speed_100_btn.setFlat(False) - self.mva_select_speed_100_btn.setObjectName("mva_select_speed_100_btn") - self.axis_select_speed_group.addButton(self.mva_select_speed_100_btn) + self.mva_select_length_100_btn.setFont(font) + self.mva_select_length_100_btn.setCheckable(True) + self.mva_select_length_100_btn.setFlat(False) + self.mva_select_length_100_btn.setObjectName("mva_select_length_100_btn") + self.horizontalLayout_3.addWidget(self.mva_select_length_100_btn) + self.verticalLayout_6.addLayout(self.horizontalLayout_3) self.label = QtWidgets.QLabel(parent=self.move_axis_page) - self.label.setGeometry(QtCore.QRect(109, 216, 261, 21)) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) + self.label.setSizePolicy(sizePolicy) + self.label.setMaximumSize(QtCore.QSize(16777215, 20)) font = QtGui.QFont() font.setPointSize(14) self.label.setFont(font) self.label.setStyleSheet("color:white") self.label.setObjectName("label") - self.mva_select_length_1_btn = BlocksCustomCheckButton(parent=self.move_axis_page) - self.mva_select_length_1_btn.setGeometry(QtCore.QRect(96, 110, 100, 100)) - self.mva_select_length_1_btn.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_select_length_1_btn.setMaximumSize(QtCore.QSize(100, 100)) + self.verticalLayout_6.addWidget(self.label) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + self.mva_select_speed_25_btn = GroupButton(parent=self.move_axis_page) + self.mva_select_speed_25_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_speed_25_btn.setMaximumSize(QtCore.QSize(90, 90)) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) @@ -1358,21 +1276,18 @@ def setupUi(self, controlStackedWidget): brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ButtonText, brush) - self.mva_select_length_1_btn.setPalette(palette) + self.mva_select_speed_25_btn.setPalette(palette) font = QtGui.QFont() font.setPointSize(14) - self.mva_select_length_1_btn.setFont(font) - self.mva_select_length_1_btn.setCheckable(True) - self.mva_select_length_1_btn.setChecked(True) - self.mva_select_length_1_btn.setFlat(True) - self.mva_select_length_1_btn.setObjectName("mva_select_length_1_btn") - self.axis_select_length_group = QtWidgets.QButtonGroup(controlStackedWidget) - self.axis_select_length_group.setObjectName("axis_select_length_group") - self.axis_select_length_group.addButton(self.mva_select_length_1_btn) - self.mva_select_length_10_btn = BlocksCustomCheckButton(parent=self.move_axis_page) - self.mva_select_length_10_btn.setGeometry(QtCore.QRect(204, 110, 100, 100)) - self.mva_select_length_10_btn.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_select_length_10_btn.setMaximumSize(QtCore.QSize(100, 100)) + self.mva_select_speed_25_btn.setFont(font) + self.mva_select_speed_25_btn.setCheckable(True) + self.mva_select_speed_25_btn.setChecked(True) + self.mva_select_speed_25_btn.setFlat(True) + self.mva_select_speed_25_btn.setObjectName("mva_select_speed_25_btn") + self.horizontalLayout_4.addWidget(self.mva_select_speed_25_btn) + self.mva_select_speed_50_btn = GroupButton(parent=self.move_axis_page) + self.mva_select_speed_50_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_speed_50_btn.setMaximumSize(QtCore.QSize(90, 90)) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) @@ -1401,18 +1316,17 @@ def setupUi(self, controlStackedWidget): brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ButtonText, brush) - self.mva_select_length_10_btn.setPalette(palette) + self.mva_select_speed_50_btn.setPalette(palette) font = QtGui.QFont() font.setPointSize(14) - self.mva_select_length_10_btn.setFont(font) - self.mva_select_length_10_btn.setCheckable(True) - self.mva_select_length_10_btn.setFlat(False) - self.mva_select_length_10_btn.setObjectName("mva_select_length_10_btn") - self.axis_select_length_group.addButton(self.mva_select_length_10_btn) - self.mva_select_length_100_btn = BlocksCustomCheckButton(parent=self.move_axis_page) - self.mva_select_length_100_btn.setGeometry(QtCore.QRect(315, 110, 100, 100)) - self.mva_select_length_100_btn.setMinimumSize(QtCore.QSize(60, 60)) - self.mva_select_length_100_btn.setMaximumSize(QtCore.QSize(100, 100)) + self.mva_select_speed_50_btn.setFont(font) + self.mva_select_speed_50_btn.setCheckable(True) + self.mva_select_speed_50_btn.setFlat(False) + self.mva_select_speed_50_btn.setObjectName("mva_select_speed_50_btn") + self.horizontalLayout_4.addWidget(self.mva_select_speed_50_btn) + self.mva_select_speed_100_btn = GroupButton(parent=self.move_axis_page) + self.mva_select_speed_100_btn.setMinimumSize(QtCore.QSize(90, 90)) + self.mva_select_speed_100_btn.setMaximumSize(QtCore.QSize(90, 90)) palette = QtGui.QPalette() brush = QtGui.QBrush(QtGui.QColor(255, 255, 255)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) @@ -1441,28 +1355,22 @@ def setupUi(self, controlStackedWidget): brush = QtGui.QBrush(QtGui.QColor(120, 120, 120)) brush.setStyle(QtCore.Qt.BrushStyle.SolidPattern) palette.setBrush(QtGui.QPalette.ColorGroup.Disabled, QtGui.QPalette.ColorRole.ButtonText, brush) - self.mva_select_length_100_btn.setPalette(palette) - font = QtGui.QFont() - font.setPointSize(14) - self.mva_select_length_100_btn.setFont(font) - self.mva_select_length_100_btn.setCheckable(True) - self.mva_select_length_100_btn.setFlat(False) - self.mva_select_length_100_btn.setObjectName("mva_select_length_100_btn") - self.axis_select_length_group.addButton(self.mva_select_length_100_btn) - self.label_2 = QtWidgets.QLabel(parent=self.move_axis_page) - self.label_2.setGeometry(QtCore.QRect(109, 85, 261, 21)) + self.mva_select_speed_100_btn.setPalette(palette) font = QtGui.QFont() font.setPointSize(14) - self.label_2.setFont(font) - self.label_2.setStyleSheet("color:white") - self.label_2.setObjectName("label_2") - self.verticalLayoutWidget = QtWidgets.QWidget(parent=self.move_axis_page) - self.verticalLayoutWidget.setGeometry(QtCore.QRect(440, 128, 196, 204)) - self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") - self.gridLayout_2 = QtWidgets.QGridLayout(self.verticalLayoutWidget) + self.mva_select_speed_100_btn.setFont(font) + self.mva_select_speed_100_btn.setCheckable(True) + self.mva_select_speed_100_btn.setFlat(False) + self.mva_select_speed_100_btn.setObjectName("mva_select_speed_100_btn") + self.horizontalLayout_4.addWidget(self.mva_select_speed_100_btn) + self.verticalLayout_6.addLayout(self.horizontalLayout_4) + self.horizontalLayout_2.addLayout(self.verticalLayout_6) + self.horizontalLayout_5 = QtWidgets.QHBoxLayout() + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.gridLayout_2 = QtWidgets.QGridLayout() self.gridLayout_2.setContentsMargins(0, 5, 0, 5) self.gridLayout_2.setObjectName("gridLayout_2") - self.mva_left_btn = IconButton(parent=self.verticalLayoutWidget) + self.mva_left_btn = IconButton(parent=self.move_axis_page) self.mva_left_btn.setEnabled(True) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum) sizePolicy.setHorizontalStretch(1) @@ -1479,8 +1387,8 @@ def setupUi(self, controlStackedWidget): self.mva_left_btn.setFlat(True) self.mva_left_btn.setProperty("icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/left_arrow.svg")) self.mva_left_btn.setObjectName("mva_left_btn") - self.gridLayout_2.addWidget(self.mva_left_btn, 1, 0, 1, 1) - self.mva_right_btn = IconButton(parent=self.verticalLayoutWidget) + self.gridLayout_2.addWidget(self.mva_left_btn, 1, 0, 1, 1, QtCore.Qt.AlignmentFlag.AlignRight) + self.mva_right_btn = IconButton(parent=self.move_axis_page) self.mva_right_btn.setEnabled(True) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum) sizePolicy.setHorizontalStretch(1) @@ -1497,8 +1405,8 @@ def setupUi(self, controlStackedWidget): self.mva_right_btn.setFlat(True) self.mva_right_btn.setProperty("icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/right_arrow.svg")) self.mva_right_btn.setObjectName("mva_right_btn") - self.gridLayout_2.addWidget(self.mva_right_btn, 1, 2, 1, 1) - self.mva_down_btn = IconButton(parent=self.verticalLayoutWidget) + self.gridLayout_2.addWidget(self.mva_right_btn, 1, 2, 1, 1, QtCore.Qt.AlignmentFlag.AlignLeft) + self.mva_down_btn = IconButton(parent=self.move_axis_page) self.mva_down_btn.setEnabled(True) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum) sizePolicy.setHorizontalStretch(1) @@ -1515,8 +1423,8 @@ def setupUi(self, controlStackedWidget): self.mva_down_btn.setFlat(True) self.mva_down_btn.setProperty("icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/down_arrow.svg")) self.mva_down_btn.setObjectName("mva_down_btn") - self.gridLayout_2.addWidget(self.mva_down_btn, 2, 1, 1, 1) - self.mva_up_btn = IconButton(parent=self.verticalLayoutWidget) + self.gridLayout_2.addWidget(self.mva_down_btn, 2, 1, 1, 1, QtCore.Qt.AlignmentFlag.AlignTop) + self.mva_up_btn = IconButton(parent=self.move_axis_page) self.mva_up_btn.setEnabled(True) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum) sizePolicy.setHorizontalStretch(1) @@ -1533,8 +1441,8 @@ def setupUi(self, controlStackedWidget): self.mva_up_btn.setFlat(True) self.mva_up_btn.setProperty("icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/up_arrow.svg")) self.mva_up_btn.setObjectName("mva_up_btn") - self.gridLayout_2.addWidget(self.mva_up_btn, 0, 1, 1, 1) - self.mva_middle = IconButton(parent=self.verticalLayoutWidget) + self.gridLayout_2.addWidget(self.mva_up_btn, 0, 1, 1, 1, QtCore.Qt.AlignmentFlag.AlignBottom) + self.mva_middle = IconButton(parent=self.move_axis_page) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -1547,6 +1455,105 @@ def setupUi(self, controlStackedWidget): self.mva_middle.setProperty("icon_pixmap", QtGui.QPixmap(":/ui/media/btn_icons/center_arrows.svg")) self.mva_middle.setObjectName("mva_middle") self.gridLayout_2.addWidget(self.mva_middle, 1, 1, 1, 1) + self.horizontalLayout_5.addLayout(self.gridLayout_2) + self.mva_z_layout = QtWidgets.QVBoxLayout() + self.mva_z_layout.setObjectName("mva_z_layout") + self.mva_z_up = IconButton(parent=self.move_axis_page) + self.mva_z_up.setEnabled(True) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.MinimumExpanding) + sizePolicy.setHorizontalStretch(1) + sizePolicy.setVerticalStretch(1) + sizePolicy.setHeightForWidth(self.mva_z_up.sizePolicy().hasHeightForWidth()) + self.mva_z_up.setSizePolicy(sizePolicy) + self.mva_z_up.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_z_up.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_z_up.setStyleSheet("") + self.mva_z_up.setText("") + self.mva_z_up.setIconSize(QtCore.QSize(16, 16)) + self.mva_z_up.setCheckable(False) + self.mva_z_up.setChecked(False) + self.mva_z_up.setFlat(True) + self.mva_z_up.setProperty("icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/up_arrow.svg")) + self.mva_z_up.setObjectName("mva_z_up") + self.mva_z_layout.addWidget(self.mva_z_up, 0, QtCore.Qt.AlignmentFlag.AlignHCenter) + self.mva_z_down = IconButton(parent=self.move_axis_page) + self.mva_z_down.setEnabled(True) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.MinimumExpanding) + sizePolicy.setHorizontalStretch(1) + sizePolicy.setVerticalStretch(1) + sizePolicy.setHeightForWidth(self.mva_z_down.sizePolicy().hasHeightForWidth()) + self.mva_z_down.setSizePolicy(sizePolicy) + self.mva_z_down.setMinimumSize(QtCore.QSize(60, 60)) + self.mva_z_down.setMaximumSize(QtCore.QSize(60, 60)) + self.mva_z_down.setStyleSheet("") + self.mva_z_down.setText("") + self.mva_z_down.setIconSize(QtCore.QSize(16, 16)) + self.mva_z_down.setCheckable(False) + self.mva_z_down.setChecked(False) + self.mva_z_down.setFlat(True) + self.mva_z_down.setProperty("icon_pixmap", QtGui.QPixmap(":/arrow_icons/media/btn_icons/down_arrow.svg")) + self.mva_z_down.setObjectName("mva_z_down") + self.mva_z_layout.addWidget(self.mva_z_down, 0, QtCore.Qt.AlignmentFlag.AlignHCenter) + self.horizontalLayout_5.addLayout(self.mva_z_layout) + self.horizontalLayout_2.addLayout(self.horizontalLayout_5) + self.verticalLayout_7.addLayout(self.horizontalLayout_2) + self.horizontalLayout_6 = QtWidgets.QHBoxLayout() + self.horizontalLayout_6.setObjectName("horizontalLayout_6") + self.mva_x_label = QtWidgets.QLabel(parent=self.move_axis_page) + self.mva_x_label.setEnabled(True) + font = QtGui.QFont() + font.setFamily("Montserrat") + font.setPointSize(14) + self.mva_x_label.setFont(font) + self.mva_x_label.setStyleSheet("background: transparent; color: white;") + self.mva_x_label.setObjectName("mva_x_label") + self.horizontalLayout_6.addWidget(self.mva_x_label, 0, QtCore.Qt.AlignmentFlag.AlignRight) + self.mva_x_value_label = QtWidgets.QLabel(parent=self.move_axis_page) + self.mva_x_value_label.setEnabled(True) + font = QtGui.QFont() + font.setFamily("Montserrat") + font.setPointSize(14) + self.mva_x_value_label.setFont(font) + self.mva_x_value_label.setStyleSheet("background: transparent; color: white;") + self.mva_x_value_label.setObjectName("mva_x_value_label") + self.horizontalLayout_6.addWidget(self.mva_x_value_label) + self.mva_y_label = QtWidgets.QLabel(parent=self.move_axis_page) + self.mva_y_label.setEnabled(True) + font = QtGui.QFont() + font.setFamily("Montserrat") + font.setPointSize(14) + self.mva_y_label.setFont(font) + self.mva_y_label.setStyleSheet("background: transparent; color: white;") + self.mva_y_label.setObjectName("mva_y_label") + self.horizontalLayout_6.addWidget(self.mva_y_label, 0, QtCore.Qt.AlignmentFlag.AlignRight) + self.mva_y_value_label = QtWidgets.QLabel(parent=self.move_axis_page) + self.mva_y_value_label.setEnabled(True) + font = QtGui.QFont() + font.setFamily("Montserrat") + font.setPointSize(14) + self.mva_y_value_label.setFont(font) + self.mva_y_value_label.setStyleSheet("background: transparent; color: white;") + self.mva_y_value_label.setObjectName("mva_y_value_label") + self.horizontalLayout_6.addWidget(self.mva_y_value_label) + self.mva_z_label = QtWidgets.QLabel(parent=self.move_axis_page) + self.mva_z_label.setEnabled(True) + font = QtGui.QFont() + font.setFamily("Montserrat") + font.setPointSize(14) + self.mva_z_label.setFont(font) + self.mva_z_label.setStyleSheet("background: transparent; color: white;") + self.mva_z_label.setObjectName("mva_z_label") + self.horizontalLayout_6.addWidget(self.mva_z_label, 0, QtCore.Qt.AlignmentFlag.AlignRight) + self.mva_z_value_label = QtWidgets.QLabel(parent=self.move_axis_page) + self.mva_z_value_label.setEnabled(True) + font = QtGui.QFont() + font.setFamily("Montserrat") + font.setPointSize(14) + self.mva_z_value_label.setFont(font) + self.mva_z_value_label.setStyleSheet("background: transparent; color: white;") + self.mva_z_value_label.setObjectName("mva_z_value_label") + self.horizontalLayout_6.addWidget(self.mva_z_value_label) + self.verticalLayout_7.addLayout(self.horizontalLayout_6) controlStackedWidget.addWidget(self.move_axis_page) self.temperature_page = QtWidgets.QWidget() self.temperature_page.setMinimumSize(QtCore.QSize(710, 400)) @@ -2054,7 +2061,7 @@ def setupUi(self, controlStackedWidget): controlStackedWidget.addWidget(self.fans_page) self.retranslateUi(controlStackedWidget) - controlStackedWidget.setCurrentIndex(7) + controlStackedWidget.setCurrentIndex(3) QtCore.QMetaObject.connectSlotsByName(controlStackedWidget) def retranslateUi(self, controlStackedWidget): @@ -2117,36 +2124,36 @@ def retranslateUi(self, controlStackedWidget): self.exp_extrude_btn.setText(_translate("controlStackedWidget", "Extrude")) self.exp_extrude_btn.setProperty("class", _translate("controlStackedWidget", "menu_btn")) self.exp_info_label.setText(_translate("controlStackedWidget", "Nozzle heating to extrude")) - self.mva_x_label.setText(_translate("controlStackedWidget", "X:")) - self.mva_y_label.setText(_translate("controlStackedWidget", "Y:")) - self.mva_z_label.setText(_translate("controlStackedWidget", "Z:")) - self.mva_z_value_label.setText(_translate("controlStackedWidget", "0")) - self.mva_y_value_label.setText(_translate("controlStackedWidget", "0")) - self.mva_x_value_label.setText(_translate("controlStackedWidget", "0")) self.mva_title_label.setText(_translate("controlStackedWidget", "Move Axis")) self.mva_title_label.setProperty("class", _translate("controlStackedWidget", "title_text")) self.mva_back_btn.setText(_translate("controlStackedWidget", "Back")) self.mva_back_btn.setProperty("class", _translate("controlStackedWidget", "menu_btn")) self.mva_back_btn.setProperty("button_type", _translate("controlStackedWidget", "icon")) - self.mva_z_up.setProperty("button_type", _translate("controlStackedWidget", "icon")) - self.mva_z_down.setProperty("button_type", _translate("controlStackedWidget", "icon")) self.mva_home_x_btn.setProperty("button_type", _translate("controlStackedWidget", "icon")) self.mva_home_y_btn.setProperty("button_type", _translate("controlStackedWidget", "icon")) self.mva_home_z_btn.setProperty("button_type", _translate("controlStackedWidget", "icon")) self.mva_home_all_btn.setProperty("button_type", _translate("controlStackedWidget", "icon")) - self.mva_select_speed_25_btn.setText(_translate("controlStackedWidget", "25")) - self.mva_select_speed_50_btn.setText(_translate("controlStackedWidget", "50")) - self.mva_select_speed_100_btn.setText(_translate("controlStackedWidget", "100")) - self.label.setText(_translate("controlStackedWidget", "Move Speed mm/s")) + self.label_2.setText(_translate("controlStackedWidget", "Move Length mm")) self.mva_select_length_1_btn.setText(_translate("controlStackedWidget", "1")) self.mva_select_length_10_btn.setText(_translate("controlStackedWidget", "10")) self.mva_select_length_100_btn.setText(_translate("controlStackedWidget", "100")) - self.label_2.setText(_translate("controlStackedWidget", "Move Length mm")) + self.label.setText(_translate("controlStackedWidget", "Move Speed mm/s")) + self.mva_select_speed_25_btn.setText(_translate("controlStackedWidget", "25")) + self.mva_select_speed_50_btn.setText(_translate("controlStackedWidget", "50")) + self.mva_select_speed_100_btn.setText(_translate("controlStackedWidget", "100")) self.mva_left_btn.setProperty("button_type", _translate("controlStackedWidget", "icon")) self.mva_right_btn.setProperty("button_type", _translate("controlStackedWidget", "icon")) self.mva_down_btn.setProperty("button_type", _translate("controlStackedWidget", "icon")) self.mva_up_btn.setProperty("button_type", _translate("controlStackedWidget", "icon")) self.mva_middle.setProperty("button_type", _translate("controlStackedWidget", "icon")) + self.mva_z_up.setProperty("button_type", _translate("controlStackedWidget", "icon")) + self.mva_z_down.setProperty("button_type", _translate("controlStackedWidget", "icon")) + self.mva_x_label.setText(_translate("controlStackedWidget", "X:")) + self.mva_x_value_label.setText(_translate("controlStackedWidget", "0")) + self.mva_y_label.setText(_translate("controlStackedWidget", "Y:")) + self.mva_y_value_label.setText(_translate("controlStackedWidget", "0")) + self.mva_z_label.setText(_translate("controlStackedWidget", "Z:")) + self.mva_z_value_label.setText(_translate("controlStackedWidget", "0")) self.temp_header_title.setText(_translate("controlStackedWidget", "Temperature")) self.temp_header_title.setProperty("class", _translate("controlStackedWidget", "title_text")) self.temp_back_button.setText(_translate("controlStackedWidget", "Back")) @@ -2190,5 +2197,5 @@ def retranslateUi(self, controlStackedWidget): from lib.utils.blocks_button import BlocksCustomButton from lib.utils.blocks_label import BlocksLabel from lib.utils.display_button import DisplayButton -from lib.utils.check_button import BlocksCustomCheckButton +from lib.utils.group_button import GroupButton from lib.utils.icon_button import IconButton