diff --git a/cura/GlobalStacksModel.py b/cura/GlobalStacksModel.py index 289a03d1c4..406e7b6bb3 100644 --- a/cura/GlobalStacksModel.py +++ b/cura/GlobalStacksModel.py @@ -5,10 +5,8 @@ from UM.Qt.ListModel import ListModel from PyQt5.QtCore import pyqtProperty, Qt, pyqtSignal -from UM.Settings.ContainerRegistry import ContainerRegistry -from UM.Settings.ContainerStack import ContainerStack - from cura.PrinterOutputDevice import ConnectionType +from cura.Settings.CuraContainerRegistry import CuraContainerRegistry from cura.Settings.GlobalStack import GlobalStack @@ -25,14 +23,13 @@ class GlobalStacksModel(ListModel): self.addRoleName(self.NameRole, "name") self.addRoleName(self.IdRole, "id") self.addRoleName(self.HasRemoteConnectionRole, "hasRemoteConnection") - self.addRoleName(self.ConnectionTypeRole, "connectionType") self.addRoleName(self.MetaDataRole, "metadata") self._container_stacks = [] # Listen to changes - ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged) - ContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged) - ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged) + CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged) + CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged) + CuraContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged) self._filter_dict = {} self._update() @@ -45,11 +42,14 @@ class GlobalStacksModel(ListModel): def _update(self) -> None: items = [] - container_stacks = ContainerRegistry.getInstance().findContainerStacks(type = "machine") + container_stacks = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine") for container_stack in container_stacks: - connection_type = int(container_stack.getMetaDataEntry("connection_type", ConnectionType.NotConnected.value)) - has_remote_connection = connection_type in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value] + has_remote_connection = False + + for connection_type in container_stack.configuredConnectionTypes: + has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value] + if container_stack.getMetaDataEntry("hidden", False) in ["True", True]: continue @@ -57,7 +57,6 @@ class GlobalStacksModel(ListModel): items.append({"name": container_stack.getMetaDataEntry("connect_group_name", container_stack.getName()), "id": container_stack.getId(), "hasRemoteConnection": has_remote_connection, - "connectionType": connection_type, "metadata": container_stack.getMetaData().copy()}) items.sort(key=lambda i: not i["hasRemoteConnection"]) self.setItems(items) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index 44ceee9511..b65b0fcbf4 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -42,7 +42,12 @@ class GlobalStack(CuraContainerStack): # Per thread we have our own resolving_settings, or strange things sometimes occur. self._resolving_settings = defaultdict(set) #type: Dict[str, Set[str]] # keys are thread names + # Since the metadatachanged is defined in container stack, we can't use it here as a notifier for pyqt + # properties. So we need to tie them together like this. + self.metaDataChanged.connect(self.configuredConnectionTypesChanged) + extrudersChanged = pyqtSignal() + configuredConnectionTypesChanged = pyqtSignal() ## Get the list of extruders of this stack. # @@ -63,6 +68,27 @@ class GlobalStack(CuraContainerStack): def getLoadingPriority(cls) -> int: return 2 + @pyqtProperty("QVariantList", notify=configuredConnectionTypesChanged) + def configuredConnectionTypes(self): + # Requesting it from the metadata actually gets them as strings (as that's what you get from serializing). + # But we do want them returned as a list of ints (so the rest of the code can directly compare) + connection_types = self.getMetaDataEntry("connection_type", "").split(",") + return [int(connection_type) for connection_type in connection_types if connection_type != ""] + + def addConfiguredConnectionType(self, connection_type): + configured_connection_types = self.configuredConnectionTypes + if connection_type not in configured_connection_types: + # Store the values as a string. + configured_connection_types.append(str(connection_type)) + self.setMetaDataEntry("connection_type", ",".join(configured_connection_types)) + + def removeConfiguredConnectionType(self, connection_type): + configured_connection_types = self.configuredConnectionTypes + if connection_type in self.configured_connection_types: + # Store the values as a string. + configured_connection_types.remove(str(connection_type)) + self.setMetaDataEntry("connection_type", ",".join(configured_connection_types)) + @classmethod def getConfigurationTypeFromSerialized(cls, serialized: str) -> Optional[str]: configuration_type = super().getConfigurationTypeFromSerialized(serialized) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 5f33be1c54..ae74d76734 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -528,8 +528,12 @@ class MachineManager(QObject): @pyqtProperty(bool, notify = printerConnectedStatusChanged) def activeMachineHasRemoteConnection(self) -> bool: if self._global_container_stack: - connection_type = int(self._global_container_stack.getMetaDataEntry("connection_type", ConnectionType.NotConnected.value)) - return connection_type in [ConnectionType.NetworkConnection.value, ConnectionType.CloudConnection.value] + has_remote_connection = False + + for connection_type in self._global_container_stack.configuredConnectionTypes: + has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value, + ConnectionType.CloudConnection.value] + return has_remote_connection return False @pyqtProperty(bool, notify = printerConnectedStatusChanged) diff --git a/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py b/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py index b688ee9d7d..7072aef4cc 100644 --- a/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py +++ b/plugins/UM3NetworkPrinting/src/DiscoverUM3Action.py @@ -13,6 +13,7 @@ from UM.i18n import i18nCatalog from cura.CuraApplication import CuraApplication from cura.MachineAction import MachineAction +from cura.Settings.CuraContainerRegistry import CuraContainerRegistry from .UM3OutputDevicePlugin import UM3OutputDevicePlugin @@ -133,23 +134,29 @@ class DiscoverUM3Action(MachineAction): return meta_data = global_container_stack.getMetaData() - if "um_network_key" in meta_data: - previous_network_key = meta_data["um_network_key"] - global_container_stack.setMetaDataEntry("um_network_key", printer_device.key) - # Delete old authentication data. - Logger.log("d", "Removing old authentication id %s for device %s", - global_container_stack.getMetaDataEntry("network_authentication_id", None), printer_device.key) - global_container_stack.removeMetaDataEntry("network_authentication_id") - global_container_stack.removeMetaDataEntry("network_authentication_key") - CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "um_network_key", value = previous_network_key, new_value = printer_device.key) - if "connection_type" in meta_data: - previous_connection_type = meta_data["connection_type"] - global_container_stack.setMetaDataEntry("connection_type", printer_device.connectionType.value) - CuraApplication.getInstance().getMachineManager().replaceContainersMetadata(key = "connection_type", value = previous_connection_type, new_value = printer_device.connectionType.value) - else: + if "um_network_key" in meta_data: # Global stack already had a connection, but it's changed. + old_network_key = meta_data["um_network_key"] + # Since we might have a bunch of hidden stacks, we also need to change it there. + metadata_filter = {"um_network_key": old_network_key} + containers = CuraContainerRegistry.getInstance().findContainerStacks(type="machine", **metadata_filter) + + for container in containers: + container.setMetaDataEntry("um_network_key", printer_device.key) + + # Delete old authentication data. + Logger.log("d", "Removing old authentication id %s for device %s", + global_container_stack.getMetaDataEntry("network_authentication_id", None), printer_device.key) + + container.removeMetaDataEntry("network_authentication_id") + container.removeMetaDataEntry("network_authentication_key") + + # Ensure that these containers do know that they are configured for network connection + container.addConfiguredConnectionType(printer_device.connectionType.value) + + else: # Global stack didn't have a connection yet, configure it. global_container_stack.setMetaDataEntry("um_network_key", printer_device.key) - global_container_stack.setMetaDataEntry("connection_type", printer_device.connectionType.value) + global_container_stack.addConfiguredConnectionType(printer_device.connectionType.value) if self._network_plugin: # Ensure that the connection states are refreshed. diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index 4a510903dd..74d2d87b3b 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -9,7 +9,7 @@ from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange, ServiceInfo from PyQt5.QtNetwork import QNetworkRequest, QNetworkAccessManager from PyQt5.QtCore import QUrl -from UM.Application import Application +from cura.CuraApplication import CuraApplication from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin from UM.Logger import Logger from UM.Signal import Signal, signalemitter @@ -41,7 +41,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self.addDeviceSignal.connect(self._onAddDevice) self.removeDeviceSignal.connect(self._onRemoveDevice) - Application.getInstance().globalContainerStackChanged.connect(self.reCheckConnections) + CuraApplication.getInstance().globalContainerStackChanged.connect(self.reCheckConnections) self._discovered_devices = {} @@ -56,7 +56,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._cluster_api_prefix = "/cluster-api/v" + self._cluster_api_version + "/" # Get list of manual instances from preferences - self._preferences = Application.getInstance().getPreferences() + self._preferences = CuraApplication.getInstance().getPreferences() self._preferences.addPreference("um3networkprinting/manual_instances", "") # A comma-separated list of ip adresses or hostnames @@ -108,7 +108,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self.resetLastManualDevice() def reCheckConnections(self): - active_machine = Application.getInstance().getGlobalContainerStack() + active_machine = CuraApplication.getInstance().getGlobalContainerStack() if not active_machine: return @@ -118,7 +118,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): if key == um_network_key: if not self._discovered_devices[key].isConnected(): Logger.log("d", "Attempting to connect with [%s]" % key) - active_machine.setMetaDataEntry("connection_type", self._discovered_devices[key].connectionType.value) + # It should already be set, but if it actually connects we know for sure it's supported! + active_machine.addConfiguredConnectionType(self._discovered_devices[key].connectionType.value) self._discovered_devices[key].connect() self._discovered_devices[key].connectionStateChanged.connect(self._onDeviceConnectionStateChanged) else: @@ -134,7 +135,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): return if self._discovered_devices[key].isConnected(): # Sometimes the status changes after changing the global container and maybe the device doesn't belong to this machine - um_network_key = Application.getInstance().getGlobalContainerStack().getMetaDataEntry("um_network_key") + um_network_key = CuraApplication.getInstance().getGlobalContainerStack().getMetaDataEntry("um_network_key") if key == um_network_key: self.getOutputDeviceManager().addOutputDevice(self._discovered_devices[key]) else: @@ -287,9 +288,10 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._discovered_devices[device.getId()] = device self.discoveredDevicesChanged.emit() - global_container_stack = Application.getInstance().getGlobalContainerStack() + global_container_stack = CuraApplication.getInstance().getGlobalContainerStack() if global_container_stack and device.getId() == global_container_stack.getMetaDataEntry("um_network_key"): - global_container_stack.setMetaDataEntry("connection_type", device.connectionType.value) + # Ensure that the configured connection type is set. + global_container_stack.addConfiguredConnectionType(device.connectionType.value) device.connect() device.connectionStateChanged.connect(self._onDeviceConnectionStateChanged) @@ -306,7 +308,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._service_changed_request_event.wait(timeout = 5.0) # Stop if the application is shutting down - if Application.getInstance().isShuttingDown(): + if CuraApplication.getInstance().isShuttingDown(): return self._service_changed_request_event.clear()