Display the printer activation status

CURA-12557
This commit is contained in:
Erwan MATHIEU 2025-06-11 13:51:45 +02:00
parent 65b0e4f080
commit 2e9999ed2d
6 changed files with 69 additions and 7 deletions

View file

@ -183,10 +183,16 @@ class MachineManager(QObject):
self.setActiveMachine(active_machine_id)
def _onOutputDevicesChanged(self) -> None:
for printer_output_device in self._printer_output_devices:
if hasattr(printer_output_device, "cloudActiveChanged"):
printer_output_device.cloudActiveChanged.disconnect(self.printerConnectedStatusChanged)
self._printer_output_devices = []
for printer_output_device in self._application.getOutputDeviceManager().getOutputDevices():
if isinstance(printer_output_device, PrinterOutputDevice):
self._printer_output_devices.append(printer_output_device)
if hasattr(printer_output_device, "cloudActiveChanged"):
printer_output_device.cloudActiveChanged.connect(self.printerConnectedStatusChanged)
self.outputDevicesChanged.emit()
@ -569,6 +575,14 @@ class MachineManager(QObject):
def activeMachineIsUsingCloudConnection(self) -> bool:
return self.activeMachineHasCloudConnection and not self.activeMachineHasNetworkConnection
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
def activeMachineIsCloudActive(self) -> bool:
if not self._printer_output_devices:
return True
first_printer = self._printer_output_devices[0]
return True if not hasattr(first_printer, 'cloudActive') else first_printer.cloudActive
def activeMachineNetworkKey(self) -> str:
if self._global_container_stack:
return self._global_container_stack.getMetaDataEntry("um_network_key", "")

View file

@ -65,6 +65,8 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
# Therefore, we create a private signal used to trigger the printersChanged signal.
_cloudClusterPrintersChanged = pyqtSignal()
cloudActiveChanged = pyqtSignal()
def __init__(self, api_client: CloudApiClient, cluster: CloudClusterResponse, parent: QObject = None) -> None:
"""Creates a new cloud output device
@ -113,6 +115,9 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
self._pre_upload_print_job = None # type: Optional[CloudPrintJobResponse]
self._uploaded_print_job = None # type: Optional[CloudPrintJobResponse]
# Whether the printer is active, i.e. authorized for use i.r.t to workspace limitations
self._active = cluster.display_status != "inactive"
CuraApplication.getInstance().getBackend().backendDone.connect(self._resetPrintJob)
CuraApplication.getInstance().getController().getScene().sceneChanged.connect(self._onSceneChanged)
@ -192,6 +197,10 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
self._received_print_jobs = status.print_jobs
self._updatePrintJobs(status.print_jobs)
if status.active != self._active:
self._active = status.active
self.cloudActiveChanged.emit()
def requestWrite(self, nodes: List[SceneNode], file_name: Optional[str] = None, limit_mimetypes: bool = False,
file_handler: Optional[FileHandler] = None, filter_by_machine: bool = False, **kwargs) -> None:
@ -436,6 +445,10 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
root_url_prefix = "-staging" if self._account.is_staging else ""
return f"https://digitalfactory{root_url_prefix}.ultimaker.com/app/jobs/{self.clusterData.cluster_id}"
@pyqtProperty(bool, notify = cloudActiveChanged)
def cloudActive(self) -> bool:
return self._active
def __del__(self):
CuraApplication.getInstance().getBackend().backendDone.disconnect(self._resetPrintJob)
CuraApplication.getInstance().getController().getScene().sceneChanged.disconnect(self._onSceneChanged)

View file

@ -10,7 +10,7 @@ class CloudClusterResponse(BaseModel):
"""Class representing a cloud connected cluster."""
def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str,
host_internal_ip: Optional[str] = None, host_version: Optional[str] = None,
display_status: str, host_internal_ip: Optional[str] = None, host_version: Optional[str] = None,
friendly_name: Optional[str] = None, printer_type: str = "ultimaker3", printer_count: int = 1,
capabilities: Optional[List[str]] = None, **kwargs) -> None:
"""Creates a new cluster response object.
@ -20,6 +20,7 @@ class CloudClusterResponse(BaseModel):
:param host_name: The name of the printer as configured during the Wi-Fi setup. Used as identifier for end users.
:param is_online: Whether this cluster is currently connected to the cloud.
:param status: The status of the cluster authentication (active or inactive).
:param display_status: The display status of the cluster.
:param host_version: The firmware version of the cluster host. This is where the Stardust client is running on.
:param host_internal_ip: The internal IP address of the host printer.
:param friendly_name: The human readable name of the host printer.
@ -31,6 +32,7 @@ class CloudClusterResponse(BaseModel):
self.host_guid = host_guid
self.host_name = host_name
self.status = status
self.display_status = display_status
self.is_online = is_online
self.host_version = host_version
self.host_internal_ip = host_internal_ip
@ -51,5 +53,5 @@ class CloudClusterResponse(BaseModel):
Convenience function for printing when debugging.
:return: A human-readable representation of the data in this object.
"""
return str({k: v for k, v in self.__dict__.items() if k in {"cluster_id", "host_guid", "host_name", "status", "is_online", "host_version", "host_internal_ip", "friendly_name", "printer_type", "printer_count", "capabilities"}})
return str({k: v for k, v in self.__dict__.items() if k in {"cluster_id", "host_guid", "host_name", "status", "display_status", "is_online", "host_version", "host_internal_ip", "friendly_name", "printer_type", "printer_count", "capabilities"}})

View file

@ -14,6 +14,7 @@ class CloudClusterStatus(BaseModel):
def __init__(self, printers: List[Union[ClusterPrinterStatus, Dict[str, Any]]],
print_jobs: List[Union[ClusterPrintJobStatus, Dict[str, Any]]],
generated_time: Union[str, datetime],
unavailable: bool = False,
**kwargs) -> None:
"""Creates a new cluster status model object.
@ -23,6 +24,7 @@ class CloudClusterStatus(BaseModel):
"""
self.generated_time = self.parseDate(generated_time)
self.active = not unavailable
self.printers = self.parseModels(ClusterPrinterStatus, printers)
self.print_jobs = self.parseModels(ClusterPrintJobStatus, print_jobs)
super().__init__(**kwargs)

View file

@ -16,6 +16,7 @@ Cura.ExpandablePopup
property bool isConnectedCloudPrinter: machineManager.activeMachineHasCloudConnection
property bool isCloudRegistered: machineManager.activeMachineHasCloudRegistration
property bool isGroup: machineManager.activeMachineIsGroup
property bool isCloudActive: machineManager.activeMachineIsCloudActive
property string machineName: {
if (isNetworkPrinter && machineManager.activeMachineNetworkGroupName != "")
{
@ -39,9 +40,16 @@ Cura.ExpandablePopup
return "printer_connected"
}
else if (isConnectedCloudPrinter && Cura.API.connectionStatus.isInternetReachable)
{
if (isCloudActive)
{
return "printer_cloud_connected"
}
else
{
return "printer_cloud_inactive"
}
}
else if (isCloudRegistered)
{
return "printer_cloud_not_available"
@ -53,7 +61,7 @@ Cura.ExpandablePopup
}
function getConnectionStatusMessage() {
if (connectionStatus == "printer_cloud_not_available")
if (connectionStatus === "printer_cloud_not_available")
{
if(Cura.API.connectionStatus.isInternetReachable)
{
@ -78,6 +86,10 @@ Cura.ExpandablePopup
return catalog.i18nc("@status", "The cloud connection is currently unavailable. Please check your internet connection.")
}
}
else if(connectionStatus === "printer_cloud_inactive")
{
return catalog.i18nc("@status", "This printer is deactivated and can not accept commands or jobs.")
}
else
{
return ""
@ -130,14 +142,18 @@ Cura.ExpandablePopup
source:
{
if (connectionStatus == "printer_connected")
if (connectionStatus === "printer_connected")
{
return UM.Theme.getIcon("CheckBlueBG", "low")
}
else if (connectionStatus == "printer_cloud_connected" || connectionStatus == "printer_cloud_not_available")
else if (connectionStatus === "printer_cloud_connected" || connectionStatus === "printer_cloud_not_available")
{
return UM.Theme.getIcon("CloudBadge", "low")
}
else if (connectionStatus === "printer_cloud_inactive")
{
return UM.Theme.getIcon("WarningBadge", "low")
}
else
{
return ""
@ -147,7 +163,21 @@ Cura.ExpandablePopup
width: UM.Theme.getSize("printer_status_icon").width
height: UM.Theme.getSize("printer_status_icon").height
color: connectionStatus == "printer_cloud_not_available" ? UM.Theme.getColor("cloud_unavailable") : UM.Theme.getColor("primary")
color:
{
if (connectionStatus === "printer_cloud_not_available")
{
return UM.Theme.getColor("cloud_unavailable")
}
else if(connectionStatus === "printer_cloud_inactive")
{
return UM.Theme.getColor("cloud_inactive")
}
else
{
return UM.Theme.getColor("primary")
}
}
visible: (isNetworkPrinter || isCloudRegistered) && source != ""

View file

@ -496,6 +496,7 @@
"monitor_carousel_dot_current": [119, 119, 119, 255],
"cloud_unavailable": [153, 153, 153, 255],
"cloud_inactive": "warning",
"connection_badge_background": [255, 255, 255, 255],
"warning_badge_background": [0, 0, 0, 255],
"error_badge_background": [255, 255, 255, 255],