diff --git a/BlocksScreen/lib/panels/filamentTab.py b/BlocksScreen/lib/panels/filamentTab.py index 015e7915..f3e22949 100644 --- a/BlocksScreen/lib/panels/filamentTab.py +++ b/BlocksScreen/lib/panels/filamentTab.py @@ -382,6 +382,16 @@ def _build_spool_page(self) -> QtWidgets.QWidget: frame_lay.addWidget(self._spool_load_widget, 1) self._spool_list_view.hide() + self._no_spools_label = QtWidgets.QLabel("", frame) + self._no_spools_label.setWordWrap(True) + self._no_spools_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self._no_spools_label.setStyleSheet("color: gray;") + no_spools_font = QtGui.QFont() + no_spools_font.setPointSize(13) + self._no_spools_label.setFont(no_spools_font) + self._no_spools_label.hide() + frame_lay.addWidget(self._no_spools_label) + self._add_spool_page = AddSpoolPage(self) self._add_filament_page = AddFilamentPage(self) @@ -617,6 +627,7 @@ def on_spools_received(self, result: dict) -> None: """Handles the result from the API call to get spools for the spoolman page.""" self._spool_load_widget.hide() self._spool_list_view.show() + self._no_spools_label.hide() self.reset_spool_info() @@ -660,6 +671,16 @@ def on_spools_received(self, result: dict) -> None: self._spool_id_map[name] = spool self.update() + if self._spool_id_map: + self._no_spools_label.hide() + else: + self._no_spools_label.setText( + f'No spools found for "{self._material_filter}"' + if self._material_filter + else "No spools found" + ) + self._no_spools_label.show() + def _on_spool_selected(self) -> None: item = self._spool_model.get_selected_item() if item is None: diff --git a/BlocksScreen/lib/panels/widgets/addFilamentPage.py b/BlocksScreen/lib/panels/widgets/addFilamentPage.py index 08e4b09a..2332f6f3 100644 --- a/BlocksScreen/lib/panels/widgets/addFilamentPage.py +++ b/BlocksScreen/lib/panels/widgets/addFilamentPage.py @@ -29,6 +29,7 @@ class AddFilamentPage(QtWidgets.QWidget): def __init__(self, parent=None) -> None: super().__init__(parent) self._keyboard_field: QtWidgets.QLineEdit | None = None + self._color_hex = "ffffff" self._build_ui() @@ -66,7 +67,7 @@ def setData(self, material: str, extruder_temp: int): def reset(self): self._name_field.setText("") self._material_field.setText("---") - self._color_field.setText("ffffff") + self._set_color("ffffff") self._ext_temp_field.setText("---") self._bed_temp_field.setText("---") self._density_field.setText("---") @@ -135,30 +136,37 @@ def _on_bed_temp_change(self, _name: str, value: int) -> None: self._bed_temp_field.setText(str(value)) def _open_color_wheel(self) -> None: - self.color_whell.set_color_hex( - self._color_field.text().strip().lstrip("#") or "ffffff" - ) + self.color_whell.set_color_hex(self._color_hex or "ffffff") self._color_whell_popup.show() @QtCore.pyqtSlot(str, name="on-color-selected") def _on_color_selected(self, hex_str: str) -> None: - self._color_field.setText(hex_str) - - def _update_swatch(self) -> None: - hex_text = self._color_field.text().strip("#").strip() - if len(hex_text) == 6: - color = QtGui.QColor(f"#{hex_text}") - self._color_swatch.setStyleSheet( - f"border-radius: 8px;" - f"background: rgb({color.red()},{color.green()},{color.blue()});" - f"border: 2px solid rgba(255,255,255,80);" - ) + self._set_color(hex_str) + + def _set_color(self, hex_str: str) -> None: + """Stores *hex_str* (what the Spoolman API needs) and updates the + RGB text label + swatch preview shown to the user.""" + hex_text = hex_str.strip().lstrip("#") + if len(hex_text) != 6: + return + self._color_hex = hex_text + color = QtGui.QColor(f"#{hex_text}") + self._color_field.setText( + f"R:{color.red()} " + f"G:{color.green()} " + f"B:{color.blue()}" + ) + self._color_swatch.setStyleSheet( + f"border-radius: 8px;" + f"background: rgb({color.red()},{color.green()},{color.blue()});" + f"border: 2px solid rgba(255,255,255,80);" + ) def _on_submit(self) -> None: body: dict = {} name = self._name_field.text().strip() material = self._material_field.text().strip() - color_hex = self._color_field.text().strip().strip("#") + color_hex = self._color_hex ext_temp = self._ext_temp_field.text().strip() bed_temp = self._bed_temp_field.text().strip() density_text = self._density_field.text().strip() @@ -184,7 +192,7 @@ def _on_submit(self) -> None: body["density"] = 1.24 body["diameter"] = 1.75 # Default diameter, can be modified later if needed - if not vendor_text == "---": + if vendor_text != "---": self.request_add_manufacturer.emit({"name": vendor_text}) self.request_filament_body = body return @@ -232,7 +240,7 @@ def _make_field(parent: QtWidgets.QWidget) -> BlocksCustomLinEdit: blank.setFixedSize(60, 60) hdr.addWidget(blank) - title_lbl = QtWidgets.QLabel("Add Filament", self) + title_lbl = QtWidgets.QLabel("New Filament", self) title_lbl.setFont(_f(22)) title_lbl.setFixedHeight(60) title_lbl.setStyleSheet("color: white; background: transparent;") @@ -257,13 +265,19 @@ def _make_field(parent: QtWidgets.QWidget) -> BlocksCustomLinEdit: self._name_field = _make_field(left_frame) self._material_field = _make_field(left_frame) - self._color_field = _make_field(left_frame) + + self._color_field = QtWidgets.QLabel(left_frame) + self._color_field.setFont(_f(14)) + self._color_field.setFixedHeight(46) + self._color_field.setStyleSheet("color: rgb(255, 255, 255);") self._color_swatch = QtWidgets.QLabel(left_frame) self._color_swatch.setFixedSize(70, 70) self._color_swatch.setStyleSheet( "border-radius: 8px; background: #ffffff; border: 2px solid rgba(255,255,255,80);" ) + self._color_swatch.setCursor(QtCore.Qt.CursorShape.PointingHandCursor) + self._color_swatch.mousePressEvent = lambda event: self._open_color_wheel() left_lay.addWidget(_key_lbl("Name:", left_frame)) left_lay.addWidget(self._name_field) @@ -271,13 +285,13 @@ def _make_field(parent: QtWidgets.QWidget) -> BlocksCustomLinEdit: left_lay.addWidget(_key_lbl("Material:", left_frame)) left_lay.addWidget(self._material_field) - left_lay.addWidget(_key_lbl("Color (hex):", left_frame)) + left_lay.addWidget(_key_lbl("Color:", left_frame)) color_row = QtWidgets.QHBoxLayout() color_row.setSpacing(30) color_row.setContentsMargins(0, 0, 0, 0) - self._color_field.setMaximumWidth(100) - color_row.addWidget(self._color_field) + self._color_field.setMaximumWidth(220) color_row.addWidget(self._color_swatch) + color_row.addWidget(self._color_field) color_row.addStretch(1) left_lay.addLayout(color_row) @@ -324,7 +338,7 @@ def _make_field(parent: QtWidgets.QWidget) -> BlocksCustomLinEdit: self._name_field.setPlaceholderText("e.g. PLA Generic") self._material_field.setText("PLA") - self._color_field.setText("ffffff") + self._set_color("ffffff") self._ext_temp_field.setText("220") self._bed_temp_field.setText("60") self._density_field.setText("1.24") @@ -334,7 +348,6 @@ def _make_field(parent: QtWidgets.QWidget) -> BlocksCustomLinEdit: self._material_field.clicked.connect( lambda: self._show_keyboard(self._material_field) ) - self._color_field.clicked.connect(self._open_color_wheel) self._ext_temp_field.clicked.connect( lambda: self.request_numpad[str, int, "PyQt_PyObject", int, int].emit( "Extruder Temp", @@ -360,13 +373,18 @@ def _make_field(parent: QtWidgets.QWidget) -> BlocksCustomLinEdit: lambda: self._show_keyboard(self._vendor_field, max_char=65) ) - self._color_field.textChanged.connect(self._update_swatch) - + spacer = QtWidgets.QSpacerItem( + 5, + 5, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + root.addItem(spacer) # Submit submit_btn = BlocksCustomButton(self) - submit_btn.setFixedSize(220, 80) + submit_btn.setFixedSize(400, 80) submit_btn.setFont(_f(16)) - submit_btn.setText("Add\nFilament") + submit_btn.setText("New Filament") submit_btn.setPixmap( QtGui.QPixmap(":/filament_related/media/btn_icons/add filament.svg") ) diff --git a/BlocksScreen/lib/panels/widgets/addSpoolPage.py b/BlocksScreen/lib/panels/widgets/addSpoolPage.py index 9c082991..6ee4147d 100644 --- a/BlocksScreen/lib/panels/widgets/addSpoolPage.py +++ b/BlocksScreen/lib/panels/widgets/addSpoolPage.py @@ -59,11 +59,15 @@ def reset(self) -> None: """Clear state and trigger a fresh filament fetch. Call before showing.""" self._selected_filament_id = None self._submit_btn.setEnabled(False) + self._lot_field.setEnabled(False) + self._weight_field.setEnabled(False) + self._location_field.setEnabled(False) self._location_field.clear() self._lot_field.clear() self._weight_field.clear() self._fil_list_view.hide() self._fil_load_widget.show() + self._no_filaments_label.hide() self._fil_model.clear() self._fil_delegate.clear() self.request_filaments.emit() @@ -87,7 +91,7 @@ def on_filaments_received(self, result: dict) -> None: self._fil_delegate.clear() self._fil_model.add_item( ListItem( - text="+ Add Filament", + text=" New Filament", left_icon=self._make_add_pixmap(), _lfontsize=14, height=60, @@ -116,6 +120,16 @@ def on_filaments_received(self, result: dict) -> None: self._filament_id_map[name] = fil self.update() + if self._filament_id_map: + self._no_filaments_label.hide() + else: + self._no_filaments_label.setText( + f'No filaments found for "{self._material_filter}"' + if self._material_filter + else "No filaments found" + ) + self._no_filaments_label.show() + @staticmethod def _make_add_pixmap() -> QtGui.QPixmap: pixmap = QtGui.QPixmap(32, 32) @@ -142,12 +156,15 @@ def on_add_spool_result(self, result: dict) -> None: def _on_filament_selected(self, item: ListItem) -> None: if not item: return - if item.text == "+ Add Filament": + if item.text == " New Filament": self.open_add_filament.emit() return filament = self._filament_id_map.get(item.text) if filament: self._selected_filament_id = filament.get("id") + self._lot_field.setEnabled(True) + self._weight_field.setEnabled(True) + self._location_field.setEnabled(True) self._submit_btn.setEnabled(True) def _show_keyboard( @@ -341,6 +358,16 @@ def _key_lbl(text: str) -> QtWidgets.QLabel: left_lay.addWidget(self._fil_load_widget, 1) self._fil_list_view.hide() + self._no_filaments_label = QtWidgets.QLabel("", left_frame) + self._no_filaments_label.setWordWrap(True) + self._no_filaments_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self._no_filaments_label.setStyleSheet("color: gray;") + no_fil_font = QtGui.QFont() + no_fil_font.setPointSize(13) + self._no_filaments_label.setFont(no_fil_font) + self._no_filaments_label.hide() + left_lay.addWidget(self._no_filaments_label) + body.addWidget(left_frame, 1) # Right: optional spool fields diff --git a/BlocksScreen/lib/panels/widgets/spoolmanPage.py b/BlocksScreen/lib/panels/widgets/spoolmanPage.py index 0bb774bc..4b061c77 100644 --- a/BlocksScreen/lib/panels/widgets/spoolmanPage.py +++ b/BlocksScreen/lib/panels/widgets/spoolmanPage.py @@ -192,7 +192,7 @@ def _build_model_list(self) -> None: self.model.add_item( ListItem( - text="+ Add Spool", + text=" Add Spool", left_icon=self._make_add_pixmap(), _lfontsize=14, height=60, @@ -234,12 +234,17 @@ def _build_model_list(self) -> None: self.spool_list_widget.blockSignals(False) + if self._display_name_to_spool: + self._no_spools_label.hide() + else: + self._no_spools_label.show() + @QtCore.pyqtSlot(ListItem, name="on-item-clicked") def on_item_clicked(self, item: ListItem) -> None: """Handle when a spool item is clicked in the list.""" if not item: return - if item.text == "+ Add Spool": + if item.text == " Add Spool": self._on_add_spool_clicked() return self._selected_spool = self._display_name_to_spool.get(item.text) @@ -398,9 +403,19 @@ def _icon_btn(icon_path: str) -> IconButton: QtWidgets.QScroller.ScrollerGestureType.LeftMouseButtonGesture, ) + self._no_spools_label = QtWidgets.QLabel("No spools found", list_frame) + self._no_spools_label.setWordWrap(True) + self._no_spools_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self._no_spools_label.setStyleSheet("color: gray;") + no_spools_font = QtGui.QFont() + no_spools_font.setPointSize(13) + self._no_spools_label.setFont(no_spools_font) + self._no_spools_label.hide() + list_layout = QtWidgets.QVBoxLayout() list_layout.setContentsMargins(4, 4, 4, 4) list_layout.addWidget(self.spool_list_widget, 1) + list_layout.addWidget(self._no_spools_label) list_frame.setLayout(list_layout) main_layout.addWidget(list_frame, 3) @@ -421,6 +436,14 @@ def _icon_btn(icon_path: str) -> IconButton: white_palette.ColorRole.WindowText, QtGui.QColor("#FFFFFF") ) + spacer = QtWidgets.QSpacerItem( + 30, + 30, + QtWidgets.QSizePolicy.Policy.Minimum, + QtWidgets.QSizePolicy.Policy.Minimum, + ) + info_layout.addItem(spacer) + def _add_row(title_text: str) -> QtWidgets.QLabel: row = QtWidgets.QHBoxLayout() row.setSpacing(4)