Browse Source

Merge pull request #13089 from Ultimaker/CURA-9277_cloud_printer_types

Cura 9277 cloud printer types
Jelle Spijker 2 years ago
parent
commit
d262d71b5d

+ 5 - 0
cura/CuraApplication.py

@@ -145,6 +145,8 @@ class CuraApplication(QtApplication):
         DefinitionChangesContainer = Resources.UserType + 10
         SettingVisibilityPreset = Resources.UserType + 11
         IntentInstanceContainer = Resources.UserType + 12
+        AbstractMachineStack = Resources.UserType + 13
+
 
     pyqtEnum(ResourceTypes)
 
@@ -423,6 +425,7 @@ class CuraApplication(QtApplication):
         Resources.addStorageType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes")
         Resources.addStorageType(self.ResourceTypes.SettingVisibilityPreset, "setting_visibility")
         Resources.addStorageType(self.ResourceTypes.IntentInstanceContainer, "intent")
+        Resources.addStorageType(self.ResourceTypes.AbstractMachineStack, "abstract_machine_instances")
 
         self._container_registry.addResourceType(self.ResourceTypes.QualityInstanceContainer, "quality")
         self._container_registry.addResourceType(self.ResourceTypes.QualityChangesInstanceContainer, "quality_changes")
@@ -433,6 +436,7 @@ class CuraApplication(QtApplication):
         self._container_registry.addResourceType(self.ResourceTypes.MachineStack, "machine")
         self._container_registry.addResourceType(self.ResourceTypes.DefinitionChangesContainer, "definition_changes")
         self._container_registry.addResourceType(self.ResourceTypes.IntentInstanceContainer, "intent")
+        self._container_registry.addResourceType(self.ResourceTypes.AbstractMachineStack, "abstract_machine")
 
         Resources.addType(self.ResourceTypes.QmlFiles, "qml")
         Resources.addType(self.ResourceTypes.Firmware, "firmware")
@@ -481,6 +485,7 @@ class CuraApplication(QtApplication):
                 ("variant", InstanceContainer.Version * 1000000 + self.SettingVersion):                         (self.ResourceTypes.VariantInstanceContainer, "application/x-uranium-instancecontainer"),
                 ("setting_visibility", SettingVisibilityPresetsModel.Version * 1000000 + self.SettingVersion):  (self.ResourceTypes.SettingVisibilityPreset, "application/x-uranium-preferences"),
                 ("machine", 2):                                                                                 (Resources.DefinitionContainers, "application/x-uranium-definitioncontainer"),
+                ("abstract_machine", 1):                                                                        (Resources.DefinitionContainers, "application/x-uranium-definitioncontainer"),
                 ("extruder", 2):                                                                                    (Resources.DefinitionContainers, "application/x-uranium-definitioncontainer")
             }
         )

+ 35 - 0
cura/Settings/AbstractMachine.py

@@ -0,0 +1,35 @@
+from typing import List
+
+from UM.Settings.ContainerStack import ContainerStack
+from cura.PrinterOutput.PrinterOutputDevice import ConnectionType
+from cura.Settings.GlobalStack import GlobalStack
+from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
+from UM.Settings.ContainerRegistry import ContainerRegistry
+
+
+class AbstractMachine(GlobalStack):
+    """ Represents a group of machines of the same type. This allows the user to select settings before selecting a printer. """
+
+    def __init__(self, container_id: str) -> None:
+        super().__init__(container_id)
+        self.setMetaDataEntry("type", "abstract_machine")
+
+    def getMachines(self) -> List[ContainerStack]:
+        from cura.CuraApplication import CuraApplication
+
+        application = CuraApplication.getInstance()
+        registry = application.getContainerRegistry()
+
+        printer_type = self.definition.getId()
+        return [machine for machine in registry.findContainerStacks(type="machine") if machine.definition.id == printer_type and ConnectionType.CloudConnection in machine.configuredConnectionTypes]
+
+
+## private:
+_abstract_machine_mime = MimeType(
+    name = "application/x-cura-abstract-machine",
+    comment = "Cura Abstract Machine",
+    suffixes = ["global.cfg"]
+)
+
+MimeTypeDatabase.addMimeType(_abstract_machine_mime)
+ContainerRegistry.addContainerTypeByName(AbstractMachine, "abstract_machine", _abstract_machine_mime.name)

+ 1 - 1
cura/Settings/CuraContainerRegistry.py

@@ -108,7 +108,7 @@ class CuraContainerRegistry(ContainerRegistry):
         :param container_type: :type{string} Type of the container (machine, quality, ...)
         :param container_name: :type{string} Name to check
         """
-        container_class = ContainerStack if container_type == "machine" else InstanceContainer
+        container_class = ContainerStack if "machine" in container_type else InstanceContainer
 
         return self.findContainersMetadata(container_type = container_class, id = container_name, type = container_type, ignore_case = True) or \
                 self.findContainersMetadata(container_type = container_class, name = container_name, type = container_type)

+ 60 - 7
cura/Settings/CuraStackBuilder.py

@@ -9,6 +9,7 @@ from UM.Settings.Interfaces import DefinitionContainerInterface
 from UM.Settings.InstanceContainer import InstanceContainer
 
 from cura.Machines.ContainerTree import ContainerTree
+from .AbstractMachine import AbstractMachine
 from .GlobalStack import GlobalStack
 from .ExtruderStack import ExtruderStack
 
@@ -27,7 +28,7 @@ class CuraStackBuilder:
         :return: The new global stack or None if an error occurred.
         """
 
-        from cura.CuraApplication import CuraApplication
+        from cura.CuraApplication import CuraApplication  # inline import needed due to circular import
         application = CuraApplication.getInstance()
         registry = application.getContainerRegistry()
         container_tree = ContainerTree.getInstance()
@@ -91,7 +92,7 @@ class CuraStackBuilder:
         :param extruder_position: The position of the current extruder.
         """
 
-        from cura.CuraApplication import CuraApplication
+        from cura.CuraApplication import CuraApplication  # inline import needed due to circular import
         application = CuraApplication.getInstance()
         registry = application.getContainerRegistry()
 
@@ -199,13 +200,21 @@ class CuraStackBuilder:
 
         :return: A new Global stack instance with the specified parameters.
         """
+        stack = GlobalStack(new_stack_id)
+        stack.setDefinition(definition)
+        cls.createUserContainer(new_stack_id, definition, stack, variant_container, material_container, quality_container)
+        return stack
 
+    @classmethod
+    def createUserContainer(cls, new_stack_id: str, definition: DefinitionContainerInterface,
+                            stack: GlobalStack,
+                            variant_container: "InstanceContainer",
+                            material_container: "InstanceContainer",
+                            quality_container: "InstanceContainer") -> None:
         from cura.CuraApplication import CuraApplication
         application = CuraApplication.getInstance()
-        registry = application.getContainerRegistry()
 
-        stack = GlobalStack(new_stack_id)
-        stack.setDefinition(definition)
+        registry = application.getContainerRegistry()
 
         # Create user container
         user_container = cls.createUserChangesContainer(new_stack_id + "_user", definition.getId(), new_stack_id,
@@ -221,8 +230,6 @@ class CuraStackBuilder:
 
         registry.addContainer(user_container)
 
-        return stack
-
     @classmethod
     def createUserChangesContainer(cls, container_name: str, definition_id: str, stack_id: str,
                                    is_global_stack: bool) -> "InstanceContainer":
@@ -259,3 +266,49 @@ class CuraStackBuilder:
         container_stack.definitionChanges = definition_changes_container
 
         return definition_changes_container
+
+    @classmethod
+    def createAbstractMachine(cls, definition_id: str) -> Optional[AbstractMachine]:
+        """Create a new instance of an abstract machine.
+
+        :param definition_id: The ID of the machine definition to use.
+
+        :return: The new Abstract Machine or None if an error occurred.
+        """
+        abstract_machine_id = definition_id + "_abstract_machine"
+
+        from cura.CuraApplication import CuraApplication
+        application = CuraApplication.getInstance()
+        registry = application.getContainerRegistry()
+        container_tree = ContainerTree.getInstance()
+
+        if registry.findContainerStacks(type = "abstract_machine", id = abstract_machine_id):
+            # This abstract machine already exists
+            return None
+
+        match registry.findDefinitionContainers(type = "machine", id = definition_id):
+            case []:
+                # It should not be possible for the definition to be missing since an abstract machine will only
+                # be created as a result of a machine with definition_id being created.
+                Logger.error(f"Definition {definition_id} was not found!")
+                return None
+            case [machine_definition, *_definitions]:
+                machine_node = container_tree.machines[machine_definition.getId()]
+                name = machine_definition.getName()
+
+                stack = AbstractMachine(abstract_machine_id)
+                stack.setDefinition(machine_definition)
+                cls.createUserContainer(
+                    name,
+                    machine_definition,
+                    stack,
+                    application.empty_variant_container,
+                    application.empty_material_container,
+                    machine_node.preferredGlobalQuality().container,
+                )
+
+                stack.setName(name)
+
+                registry.addContainer(stack)
+
+                return stack

+ 3 - 1
plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py

@@ -400,11 +400,13 @@ class CloudOutputDeviceManager:
         # We do not use use MachineManager.addMachine here because we need to set the cluster ID before activating it.
         new_machine = CuraStackBuilder.createMachine(device.name, device.printerType, show_warning_message=False)
         if not new_machine:
-            Logger.log("e", "Failed creating a new machine")
+            Logger.error(f"Failed creating a new machine for {device.name}")
             return False
 
         self._setOutputDeviceMetadata(device, new_machine)
 
+        _abstract_machine = CuraStackBuilder.createAbstractMachine(device.printerType)
+
         if activate:
             CuraApplication.getInstance().getMachineManager().setActiveMachine(new_machine.getId())