From 3774fdbd0209e5bfca735160ba7fc05a9324670d Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 28 Jan 2019 14:29:41 +0100 Subject: [PATCH] Refactored the "connection_type" metadata entry so it can support multiple types. After a lot of discussion and finding out what the hell was going on, we figured out we made a pretty big derp by only setting a single connection_type in the metadata of the machine. What it's actually doing is describing what connection types have been configured (and not just randomly displaying whatever output device set the value last) --- cura/GlobalStacksModel.py | 21 +++++------ cura/Settings/GlobalStack.py | 26 +++++++++++++ cura/Settings/MachineManager.py | 8 +++- .../src/DiscoverUM3Action.py | 37 +++++++++++-------- .../src/UM3OutputDevicePlugin.py | 20 +++++----- 5 files changed, 75 insertions(+), 37 deletions(-) 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()