예제 #1
0
    def canMaterialBeRemoved(self, material_node: "MaterialNode"):
        # Check if the material is active in any extruder train. In that case, the material shouldn't be removed!
        # In the future we might enable this again, but right now, it's causing a ton of issues if we do (since it
        # corrupts the configuration)
        root_material_id = material_node.base_file
        ids_to_remove = {
            metadata.get("id", "")
            for metadata in CuraContainerRegistry.getInstance().
            findInstanceContainersMetadata(base_file=root_material_id)
        }

        for extruder_stack in CuraContainerRegistry.getInstance(
        ).findContainerStacks(type="extruder_train"):
            if extruder_stack.material.getId() in ids_to_remove:
                return False
        return True
예제 #2
0
    def _update(self) -> None:
        items = []

        container_stacks = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine")
        for container_stack in container_stacks:
            has_remote_connection = False

            for connection_type in container_stack.configuredConnectionTypes:
                has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value,
                                                             ConnectionType.CloudConnection.value]

            if parseBool(container_stack.getMetaDataEntry("hidden", False)):
                continue

            device_name = container_stack.getMetaDataEntry("group_name", container_stack.getName())
            section_name = "Connected printers" if has_remote_connection else "Preset printers"
            section_name = self._catalog.i18nc("@info:title", section_name)

            default_removal_warning = self._catalog.i18nc(
                "@label {0} is the name of a printer that's about to be deleted.",
                "Are you sure you wish to remove {0}? This cannot be undone!", device_name
            )
            removal_warning = container_stack.getMetaDataEntry("removal_warning", default_removal_warning)

            items.append({"name": device_name,
                          "id": container_stack.getId(),
                          "hasRemoteConnection": has_remote_connection,
                          "metadata": container_stack.getMetaData().copy(),
                          "discoverySource": section_name,
                          "removalWarning": removal_warning})
        items.sort(key=lambda i: (not i["hasRemoteConnection"], i["name"]))
        self.setItems(items)
예제 #3
0
    def createMaterial(self) -> str:
        """Create a new material by cloning the preferred material for the current material diameter and generate a new
        GUID.

        The material type is explicitly left to be the one from the preferred material, since this allows the user to
        still have SOME profiles to work with.

        :return: The ID of the newly created material.
        """

        # Ensure all settings are saved.
        application = cura.CuraApplication.CuraApplication.getInstance()
        application.saveSettings()

        # Find the preferred material.
        extruder_stack = application.getMachineManager().activeStack
        active_variant_name = extruder_stack.variant.getName()
        approximate_diameter = int(extruder_stack.approximateMaterialDiameter)
        global_container_stack = application.getGlobalContainerStack()
        if not global_container_stack:
            return ""
        machine_node = ContainerTree.getInstance().machines[global_container_stack.definition.getId()]
        preferred_material_node = machine_node.variants[active_variant_name].preferredMaterial(approximate_diameter)

        # Create a new ID & new metadata for the new material.
        new_id = CuraContainerRegistry.getInstance().uniqueName("custom_material")
        new_metadata = {"name": catalog.i18nc("@label", "Custom Material"),
                        "brand": catalog.i18nc("@label", "Custom"),
                        "GUID": str(uuid.uuid4()),
                        }

        self.duplicateMaterial(preferred_material_node, new_base_id = new_id, new_metadata = new_metadata)
        return new_id
예제 #4
0
    def removeMaterial(self, material_node: "MaterialNode") -> None:
        """Deletes a material from Cura.

        This function does not do any safety checking any more. Please call this function only if:
            - The material is not read-only.
            - The material is not used in any stacks.

        If the material was not lazy-loaded yet, this will fully load the container. When removing this material
        node, all other materials with the same base fill will also be removed.

        :param material_node: The material to remove.
        """

        container_registry = CuraContainerRegistry.getInstance()
        materials_this_base_file = container_registry.findContainersMetadata(
            base_file=material_node.base_file)

        # The material containers belonging to the same material file are supposed to work together. This postponeSignals()
        # does two things:
        #   - optimizing the signal emitting.
        #   - making sure that the signals will only be emitted after all the material containers have been removed.
        with postponeSignals(
                container_registry.containerRemoved,
                compress=CompressTechnique.CompressPerParameterValue):
            # CURA-6886: Some containers may not have been loaded. If remove one material container, its material file
            # will be removed. If later we remove a sub-material container which hasn't been loaded previously, it will
            # crash because removeContainer() requires to load the container first, but the material file was already
            # gone.
            for material_metadata in materials_this_base_file:
                container_registry.findInstanceContainers(
                    id=material_metadata["id"])
            for material_metadata in materials_this_base_file:
                container_registry.removeContainer(material_metadata["id"])
예제 #5
0
    def _update(self) -> None:
        items = []

        container_stacks = CuraContainerRegistry.getInstance(
        ).findContainerStacks(type="machine")

        for container_stack in container_stacks:
            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

            # TODO: Remove reference to connect group name.
            items.append({
                "name":
                container_stack.getMetaDataEntry("connect_group_name",
                                                 container_stack.getName()),
                "id":
                container_stack.getId(),
                "hasRemoteConnection":
                has_remote_connection,
                "metadata":
                container_stack.getMetaData().copy()
            })
        items.sort(key=lambda i: not i["hasRemoteConnection"])
        self.setItems(items)
예제 #6
0
    def _update(self) -> None:
        items = []

        container_stacks = CuraContainerRegistry.getInstance(
        ).findContainerStacks(type="machine")
        for container_stack in container_stacks:
            has_remote_connection = False

            for connection_type in container_stack.configuredConnectionTypes:
                has_remote_connection |= connection_type in [
                    ConnectionType.NetworkConnection.value,
                    ConnectionType.CloudConnection.value
                ]

            if parseBool(container_stack.getMetaDataEntry("hidden", False)):
                continue

            section_name = "Network enabled printers" if has_remote_connection else "Local printers"
            section_name = self._catalog.i18nc("@info:title", section_name)

            items.append({
                "name":
                container_stack.getMetaDataEntry("group_name",
                                                 container_stack.getName()),
                "id":
                container_stack.getId(),
                "hasRemoteConnection":
                has_remote_connection,
                "metadata":
                container_stack.getMetaData().copy(),
                "discoverySource":
                section_name
            })
        items.sort(key=lambda i: (not i["hasRemoteConnection"], i["name"]))
        self.setItems(items)
예제 #7
0
 def _createMaterialItem(self, root_material_id, container_node):
     metadata_list = CuraContainerRegistry.getInstance().findContainersMetadata(id = container_node.container_id)
     if not metadata_list:
         return None
     metadata = metadata_list[0]
     item = {
         "root_material_id":     root_material_id,
         "id":                   metadata["id"],
         "container_id":         metadata["id"], # TODO: Remove duplicate in material manager qml
         "GUID":                 metadata["GUID"],
         "name":                 metadata["name"],
         "brand":                metadata["brand"],
         "description":          metadata["description"],
         "material":             metadata["material"],
         "color_name":           metadata["color_name"],
         "color_code":           metadata.get("color_code", ""),
         "density":              metadata.get("properties", {}).get("density", ""),
         "diameter":             metadata.get("properties", {}).get("diameter", ""),
         "approximate_diameter": metadata["approximate_diameter"],
         "adhesion_info":        metadata["adhesion_info"],
         "is_read_only":         self._container_registry.isReadOnly(metadata["id"]),
         "container_node":       container_node,
         "is_favorite":          root_material_id in self._favorite_ids
     }
     return item
예제 #8
0
    def exportAll(self, file_path: QUrl) -> None:
        """
        Export all materials to a certain file path.
        :param file_path: The path to export the materials to.
        """
        registry = CuraContainerRegistry.getInstance()

        try:
            archive = zipfile.ZipFile(file_path.toLocalFile(), "w", compression = zipfile.ZIP_DEFLATED)
        except OSError as e:
            Logger.log("e", f"Can't write to destination {file_path.toLocalFile()}: {type(e)} - {str(e)}")
            error_message = Message(
                text = catalog.i18nc("@error:text Followed by an error message of why it could not save", "Could not save material archive to {filename}:").format(filename = file_path.toLocalFile()) + " " + str(e),
                title = catalog.i18nc("@error:title", "Failed to save material archive"),
                message_type = Message.MessageType.ERROR
            )
            error_message.show()
            return
        for metadata in registry.findInstanceContainersMetadata(type = "material"):
            if metadata["base_file"] != metadata["id"]:  # Only process base files.
                continue
            if metadata["id"] == "empty_material":  # Don't export the empty material.
                continue
            material = registry.findContainers(id = metadata["id"])[0]
            suffix = registry.getMimeTypeForContainer(type(material)).preferredSuffix
            filename = metadata["id"] + "." + suffix
            try:
                archive.writestr(filename, material.serialize())
            except OSError as e:
                Logger.log("e", f"An error has occurred while writing the material \'{metadata['id']}\' in the file \'{filename}\': {e}.")
예제 #9
0
    def _getCompatibleSupportMaterials(self, subdata: Dict[str,
                                                           Any]) -> List[str]:
        """
        Gets the list of support materials that the materials in this package are compatible with.

        Since the materials are individually encoded as keys in the API response, only PVA and Breakaway are currently
        supported.
        :param subdata: The "data" element in the package data, which should contain this compatibility information.
        :return: A list of support materials that the materials in this package are compatible with.
        """
        result = set()

        container_registry = CuraContainerRegistry.getInstance()
        try:
            pva_name = container_registry.findContainersMetadata(
                id="ultimaker_pva")[0].get("name", "Ultimaker PVA")
        except IndexError:
            pva_name = "Ultimaker PVA"
        try:
            breakaway_name = container_registry.findContainersMetadata(
                id="ultimaker_bam")[0].get("name", "Ultimaker Breakaway")
        except IndexError:
            breakaway_name = "Ultimaker Breakaway"

        for material in subdata.get("materials", []):
            if material.get("pva_compatible", False):
                result.add(pva_name)
            if material.get("breakaway_compatible", False):
                result.add(breakaway_name)

        return list(sorted(result))
예제 #10
0
 def setMaterialName(self, material_node: "MaterialNode", name: str) -> None:
     container_registry = CuraContainerRegistry.getInstance()
     root_material_id = material_node.base_file
     if container_registry.isReadOnly(root_material_id):
         Logger.log("w", "Cannot set name of read-only container %s.", root_material_id)
         return
     return container_registry.findContainers(id = root_material_id)[0].setName(name)
예제 #11
0
 def canMaterialBeRemoved(self, material_node: "MaterialNode") -> bool:
     container_registry = CuraContainerRegistry.getInstance()
     ids_to_remove = {metadata.get("id", "") for metadata in container_registry.findInstanceContainersMetadata(base_file = material_node.base_file)}
     for extruder_stack in container_registry.findContainerStacks(type = "extruder_train"):
         if extruder_stack.material.getId() in ids_to_remove:
             return False
     return True
예제 #12
0
    def removeMaterialByRootId(self, root_material_id: str):
        container_registry = CuraContainerRegistry.getInstance()
        results = container_registry.findContainers(id=root_material_id)
        if not results:
            container_registry.addWrongContainerId(root_material_id)

        for result in results:
            container_registry.removeContainer(
                result.getMetaDataEntry("id", ""))
예제 #13
0
    def getRootMaterialIDForDiameter(self, root_material_id: str,
                                     approximate_diameter: str) -> str:
        original_material = CuraContainerRegistry.getInstance(
        ).findInstanceContainersMetadata(id=root_material_id)[0]
        if original_material["approximate_diameter"] == approximate_diameter:
            return root_material_id

        matching_materials = CuraContainerRegistry.getInstance(
        ).findInstanceContainersMetadata(
            type="material",
            brand=original_material["brand"],
            definition=original_material["definition"],
            material=original_material["material"],
            color_name=original_material["color_name"])
        for material in matching_materials:
            if material["approximate_diameter"] == approximate_diameter:
                return material["id"]
        return root_material_id
예제 #14
0
 def _updateOnlinePrinters(self, printer_responses: Dict[str, CloudClusterResponse]) -> None:
     """
     Update the metadata of the printers to store whether they are online or not.
     :param printer_responses: The responses received from the API about the printer statuses.
     """
     for container_stack in CuraContainerRegistry.getInstance().findContainerStacks(type = "machine"):
         cluster_id = container_stack.getMetaDataEntry("um_cloud_cluster_id", "")
         if cluster_id in printer_responses:
             container_stack.setMetaDataEntry("is_online", printer_responses[cluster_id].is_online)
예제 #15
0
    def _update(self) -> None:
        items = []

        container_stacks = CuraContainerRegistry.getInstance(
        ).findContainerStacks(type="machine")
        for container_stack in container_stacks:
            if self._filter_connection_type is not None:  # We want to filter on connection types.
                if not any((connection_type == self._filter_connection_type
                            for connection_type in
                            container_stack.configuredConnectionTypes)):
                    continue  # No connection type on this printer matches the filter.

            has_remote_connection = False

            for connection_type in container_stack.configuredConnectionTypes:
                has_remote_connection |= connection_type in [
                    ConnectionType.NetworkConnection.value,
                    ConnectionType.CloudConnection.value
                ]

            if parseBool(container_stack.getMetaDataEntry("hidden", False)):
                continue

            is_online = container_stack.getMetaDataEntry("is_online", False)
            if self._filter_online_only and not is_online:
                continue

            capabilities = set(
                container_stack.getMetaDataEntry(META_CAPABILITIES,
                                                 "").split(","))
            if set(self._filter_capabilities
                   ) - capabilities:  # Not all required capabilities are met.
                continue

            device_name = container_stack.getMetaDataEntry(
                "group_name", container_stack.getName())
            section_name = "Connected printers" if has_remote_connection else "Preset printers"
            section_name = self._catalog.i18nc("@info:title", section_name)

            default_removal_warning = self._catalog.i18nc(
                "@label {0} is the name of a printer that's about to be deleted.",
                "Are you sure you wish to remove {0}? This cannot be undone!",
                device_name)
            removal_warning = container_stack.getMetaDataEntry(
                "removal_warning", default_removal_warning)

            items.append({
                "name": device_name,
                "id": container_stack.getId(),
                "hasRemoteConnection": has_remote_connection,
                "metadata": container_stack.getMetaData().copy(),
                "discoverySource": section_name,
                "removalWarning": removal_warning,
                "isOnline": is_online
            })
        items.sort(key=lambda i: (not i["hasRemoteConnection"], i["name"]))
        self.setItems(items)
예제 #16
0
    def duplicateMaterialByBaseFile(self, base_file: str, new_base_id: Optional[str] = None,
                                    new_metadata: Optional[Dict[str, Any]] = None) -> Optional[str]:
        container_registry = CuraContainerRegistry.getInstance()

        root_materials = container_registry.findContainers(id = base_file)
        if not root_materials:
            Logger.log("i", "Unable to duplicate the root material with ID {root_id}, because it doesn't exist.".format(root_id = base_file))
            return None
        root_material = root_materials[0]

        # Ensure that all settings are saved.
        application = cura.CuraApplication.CuraApplication.getInstance()
        application.saveSettings()

        # Create a new ID and container to hold the data.
        if new_base_id is None:
            new_base_id = container_registry.uniqueName(root_material.getId())
        new_root_material = copy.deepcopy(root_material)
        new_root_material.getMetaData()["id"] = new_base_id
        new_root_material.getMetaData()["base_file"] = new_base_id
        if new_metadata is not None:
            new_root_material.getMetaData().update(new_metadata)
        new_containers = [new_root_material]

        # Clone all submaterials.
        for container_to_copy in container_registry.findInstanceContainers(base_file = base_file):
            if container_to_copy.getId() == base_file:
                continue  # We already have that one. Skip it.
            new_id = new_base_id
            definition = container_to_copy.getMetaDataEntry("definition")
            if definition != "fdmprinter":
                new_id += "_" + definition
                variant_name = container_to_copy.getMetaDataEntry("variant_name")
                if variant_name:
                    new_id += "_" + variant_name.replace(" ", "_")

            new_container = copy.deepcopy(container_to_copy)
            new_container.getMetaData()["id"] = new_id
            new_container.getMetaData()["base_file"] = new_base_id
            if new_metadata is not None:
                new_container.getMetaData().update(new_metadata)
            new_containers.append(new_container)

        for container_to_add in new_containers:
            container_to_add.setDirty(True)
            container_registry.addContainer(container_to_add)

        # If the duplicated material was favorite then the new material should also be added to the favorites.
        favorites_set = set(application.getPreferences().getValue("cura/favorite_materials").split(";"))
        if base_file in favorites_set:
            favorites_set.add(new_base_id)
            application.getPreferences().setValue("cura/favorite_materials", ";".join(favorites_set))

        return new_base_id
예제 #17
0
 def _checkCorrectGroupName(self, device_id: str, group_name: str) -> None:
     global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
     active_machine_network_name = CuraApplication.getInstance().getMachineManager().activeMachineNetworkKey()
     if global_container_stack and device_id == active_machine_network_name:
         # Check if the group_name is correct. If not, update all the containers connected to the same printer
         if CuraApplication.getInstance().getMachineManager().activeMachineNetworkGroupName != group_name:
             metadata_filter = {"um_network_key": active_machine_network_name}
             containers = CuraContainerRegistry.getInstance().findContainerStacks(type="machine",
                                                                                  **metadata_filter)
             for container in containers:
                 container.setMetaDataEntry("group_name", group_name)
예제 #18
0
 def _checkCorrectGroupName(self, device_id: str, group_name: str) -> None:
     global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
     active_machine_network_name = CuraApplication.getInstance().getMachineManager().activeMachineNetworkKey()
     if global_container_stack and device_id == active_machine_network_name:
         # Check if the group_name is correct. If not, update all the containers connected to the same printer
         if CuraApplication.getInstance().getMachineManager().activeMachineNetworkGroupName != group_name:
             metadata_filter = {"um_network_key": active_machine_network_name}
             containers = CuraContainerRegistry.getInstance().findContainerStacks(type="machine",
                                                                                  **metadata_filter)
             for container in containers:
                 container.setMetaDataEntry("group_name", group_name)
예제 #19
0
    def __init__(self, parent=None) -> None:
        super().__init__(parent)

        self._catalog = i18nCatalog("cura")

        self.addRoleName(self.NameRole, "name")
        self.addRoleName(self.IdRole, "id")
        self.addRoleName(self.HasRemoteConnectionRole, "hasRemoteConnection")
        self.addRoleName(self.MetaDataRole, "metadata")
        self.addRoleName(self.DiscoverySourceRole, "discoverySource")
        self.addRoleName(self.IsOnlineRole, "isOnline")

        self._change_timer = QTimer()
        self._change_timer.setInterval(200)
        self._change_timer.setSingleShot(True)
        self._change_timer.timeout.connect(self._update)

        self._filter_connection_type = None  # type: Optional[ConnectionType]
        self._filter_online_only = False
        self._filter_capabilities: List[str] = [
        ]  # Required capabilities that all listed printers must have.

        # Listen to changes
        CuraContainerRegistry.getInstance().containerAdded.connect(
            self._onContainerChanged)
        CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(
            self._onContainerChanged)
        CuraContainerRegistry.getInstance().containerRemoved.connect(
            self._onContainerChanged)
        self._updateDelayed()
예제 #20
0
    def setMaterialName(self, material_node: "MaterialNode", name: str) -> None:
        """Change the user-visible name of a material.

        :param material_node: The ContainerTree node of the material to rename.
        :param name: The new name for the material.
        """

        container_registry = CuraContainerRegistry.getInstance()
        root_material_id = material_node.base_file
        if container_registry.isReadOnly(root_material_id):
            Logger.log("w", "Cannot set name of read-only container %s.", root_material_id)
            return
        return container_registry.findContainers(id = root_material_id)[0].setName(name)
예제 #21
0
    def associateActiveMachineWithPrinterDevice(
            self, printer_device: Optional["PrinterOutputDevice"]) -> None:
        if not printer_device:
            return

        Logger.log(
            "d",
            "Attempting to set the network key of the active machine to %s",
            printer_device.key)

        global_container_stack = CuraApplication.getInstance(
        ).getGlobalContainerStack()
        if not global_container_stack:
            return

        meta_data = global_container_stack.getMetaData()

        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.addConfiguredConnectionType(
                printer_device.connectionType.value)

        if self._network_plugin:
            # Ensure that the connection states are refreshed.
            self._network_plugin.reCheckConnections()
예제 #22
0
    def _checkCorrectGroupName(self, device_id: str, group_name: str) -> None:
        """This method checks if the name of the group stored in the definition container is correct.

        After updating from 3.2 to 3.3 some group names may be temporary. If there is a mismatch in the name of the group
        then all the container stacks are updated, both the current and the hidden ones.
        """

        global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
        active_machine_network_name = CuraApplication.getInstance().getMachineManager().activeMachineNetworkKey()
        if global_container_stack and device_id == active_machine_network_name:
            # Check if the group_name is correct. If not, update all the containers connected to the same printer
            if CuraApplication.getInstance().getMachineManager().activeMachineNetworkGroupName != group_name:
                metadata_filter = {"um_network_key": active_machine_network_name}
                containers = CuraContainerRegistry.getInstance().findContainerStacks(type="machine",
                                                                                     **metadata_filter)
                for container in containers:
                    container.setMetaDataEntry("group_name", group_name)
예제 #23
0
    def exportAll(self, file_path: QUrl) -> None:
        """
        Export all materials to a certain file path.
        :param file_path: The path to export the materials to.
        """
        registry = CuraContainerRegistry.getInstance()

        archive = zipfile.ZipFile(file_path.toLocalFile(), "w", compression = zipfile.ZIP_DEFLATED)
        for metadata in registry.findInstanceContainersMetadata(type = "material"):
            if metadata["base_file"] != metadata["id"]:  # Only process base files.
                continue
            if metadata["id"] == "empty_material":  # Don't export the empty material.
                continue
            material = registry.findContainers(id = metadata["id"])[0]
            suffix = registry.getMimeTypeForContainer(type(material)).preferredSuffix
            filename = metadata["id"] + "." + suffix
            archive.writestr(filename, material.serialize())
예제 #24
0
    def removeMaterial(self, material_node: "MaterialNode") -> None:
        container_registry = CuraContainerRegistry.getInstance()
        materials_this_base_file = container_registry.findContainersMetadata(base_file = material_node.base_file)

        # The material containers belonging to the same material file are supposed to work together. This postponeSignals()
        # does two things:
        #   - optimizing the signal emitting.
        #   - making sure that the signals will only be emitted after all the material containers have been removed.
        with postponeSignals(container_registry.containerRemoved, compress = CompressTechnique.CompressPerParameterValue):
            # CURA-6886: Some containers may not have been loaded. If remove one material container, its material file
            # will be removed. If later we remove a sub-material container which hasn't been loaded previously, it will
            # crash because removeContainer() requires to load the container first, but the material file was already
            # gone.
            for material_metadata in materials_this_base_file:
                container_registry.findInstanceContainers(id = material_metadata["id"])
            for material_metadata in materials_this_base_file:
                container_registry.removeContainer(material_metadata["id"])
예제 #25
0
    def canMaterialBeRemoved(self, material_node: "MaterialNode") -> bool:
        """Can a certain material be deleted, or is it still in use in one of the container stacks anywhere?

        We forbid the user from deleting a material if it's in use in any stack. Deleting it while it's in use can
        lead to corrupted stacks. In the future we might enable this functionality again (deleting the material from
        those stacks) but for now it is easier to prevent the user from doing this.

        :param material_node: The ContainerTree node of the material to check.

        :return: Whether or not the material can be removed.
        """

        container_registry = CuraContainerRegistry.getInstance()
        ids_to_remove = {metadata.get("id", "") for metadata in container_registry.findInstanceContainersMetadata(base_file = material_node.base_file)}
        for extruder_stack in container_registry.findContainerStacks(type = "extruder_train"):
            if extruder_stack.material.getId() in ids_to_remove:
                return False
        return True
예제 #26
0
    def _check_unmapped_settings(self):
        Logger.log("d", "called")
        try:
            instances = json.loads(
                self._application.getPreferences().getValue(DUETRRF_SETTINGS))

            stacks = CuraContainerRegistry.getInstance().findContainerStacks(
                type='machine')
            stacks = [stack.getId() for stack in stacks]

            for printer_id, data in instances.items():
                if printer_id not in stacks:
                    self._found_unmapped[printer_id] = data
        except Exception as e:
            Logger.log("d", str(e))

        if self._found_unmapped:
            Logger.log("d", "Unmapped settings found!")
            self._showUnmappedSettingsMessage()
        else:
            Logger.log("d", "No unmapped settings found.")
예제 #27
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self.addRoleName(self.NameRole, "name")
        self.addRoleName(self.IdRole, "id")
        self.addRoleName(self.HasRemoteConnectionRole, "hasRemoteConnection")
        self.addRoleName(self.MetaDataRole, "metadata")
        self._container_stacks = []

        # Listen to changes
        CuraContainerRegistry.getInstance().containerAdded.connect(
            self._onContainerChanged)
        CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(
            self._onContainerChanged)
        CuraContainerRegistry.getInstance().containerRemoved.connect(
            self._onContainerChanged)
        self._filter_dict = {}
        self._update()
예제 #28
0
    def associateActiveMachineWithPrinterDevice(self, printer_device: Optional["PrinterOutputDevice"]) -> None:
        if not printer_device:
            return

        Logger.log("d", "Attempting to set the network key of the active machine to %s", printer_device.key)

        global_container_stack = CuraApplication.getInstance().getGlobalContainerStack()
        if not global_container_stack:
            return

        meta_data = global_container_stack.getMetaData()

        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.addConfiguredConnectionType(printer_device.connectionType.value)

        if self._network_plugin:
            # Ensure that the connection states are refreshed.
            self._network_plugin.reCheckConnections()
예제 #29
0
    def _update(self) -> None:
        items = []

        container_stacks = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine")
        for container_stack in container_stacks:
            has_remote_connection = False

            for connection_type in container_stack.configuredConnectionTypes:
                has_remote_connection |= connection_type in [ConnectionType.NetworkConnection.value,
                                                             ConnectionType.CloudConnection.value]

            if parseBool(container_stack.getMetaDataEntry("hidden", False)):
                continue

            section_name = "Network enabled printers" if has_remote_connection else "Local printers"
            section_name = self._catalog.i18nc("@info:title", section_name)

            items.append({"name": container_stack.getMetaDataEntry("group_name", container_stack.getName()),
                          "id": container_stack.getId(),
                          "hasRemoteConnection": has_remote_connection,
                          "metadata": container_stack.getMetaData().copy(),
                          "discoverySource": section_name})
        items.sort(key = lambda i: (not i["hasRemoteConnection"], i["name"]))
        self.setItems(items)
예제 #30
0
    def createMaterial(self) -> str:
        # Ensure all settings are saved.
        application = cura.CuraApplication.CuraApplication.getInstance()
        application.saveSettings()

        # Find the preferred material.
        extruder_stack = application.getMachineManager().activeStack
        active_variant_name = extruder_stack.variant.getName()
        approximate_diameter = int(extruder_stack.approximateMaterialDiameter)
        global_container_stack = application.getGlobalContainerStack()
        if not global_container_stack:
            return ""
        machine_node = ContainerTree.getInstance().machines[global_container_stack.definition.getId()]
        preferred_material_node = machine_node.variants[active_variant_name].preferredMaterial(approximate_diameter)

        # Create a new ID & new metadata for the new material.
        new_id = CuraContainerRegistry.getInstance().uniqueName("custom_material")
        new_metadata = {"name": catalog.i18nc("@label", "Custom Material"),
                        "brand": catalog.i18nc("@label", "Custom"),
                        "GUID": str(uuid.uuid4()),
                        }

        self.duplicateMaterial(preferred_material_node, new_base_id = new_id, new_metadata = new_metadata)
        return new_id
예제 #31
0
    def __init__(self, parent = None) -> None:
        super().__init__(parent)

        self._catalog = i18nCatalog("cura")

        self.addRoleName(self.NameRole, "name")
        self.addRoleName(self.IdRole, "id")
        self.addRoleName(self.HasRemoteConnectionRole, "hasRemoteConnection")
        self.addRoleName(self.MetaDataRole, "metadata")
        self.addRoleName(self.DiscoverySourceRole, "discoverySource")

        self._change_timer = QTimer()
        self._change_timer.setInterval(200)
        self._change_timer.setSingleShot(True)
        self._change_timer.timeout.connect(self._update)

        # Listen to changes
        CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
        CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
        CuraContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
        self._updateDelayed()
예제 #32
0
    def __init__(self, parent = None) -> None:
        super().__init__(parent)

        self._catalog = i18nCatalog("cura")

        self.addRoleName(self.NameRole, "name")
        self.addRoleName(self.IdRole, "id")
        self.addRoleName(self.HasRemoteConnectionRole, "hasRemoteConnection")
        self.addRoleName(self.MetaDataRole, "metadata")
        self.addRoleName(self.DiscoverySourceRole, "discoverySource")

        self._change_timer = QTimer()
        self._change_timer.setInterval(200)
        self._change_timer.setSingleShot(True)
        self._change_timer.timeout.connect(self._update)

        # Listen to changes
        CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerChanged)
        CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(self._onContainerChanged)
        CuraContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChanged)
        self._updateDelayed()
예제 #33
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self.addRoleName(self.NameRole, "name")
        self.addRoleName(self.IdRole, "id")
        self.addRoleName(self.HasRemoteConnectionRole, "hasRemoteConnection")
        self.addRoleName(self.MetaDataRole, "metadata")
        self._container_stacks = []

        self._change_timer = QTimer()
        self._change_timer.setInterval(200)
        self._change_timer.setSingleShot(True)
        self._change_timer.timeout.connect(self._update)

        # Listen to changes
        CuraContainerRegistry.getInstance().containerAdded.connect(
            self._onContainerChanged)
        CuraContainerRegistry.getInstance().containerMetaDataChanged.connect(
            self._onContainerChanged)
        CuraContainerRegistry.getInstance().containerRemoved.connect(
            self._onContainerChanged)
        self._filter_dict = {}
        self._updateDelayed()
예제 #34
0
 def existsKey(self, key: str) -> bool:
     metadata_filter = {"um_network_key": key}
     containers = CuraContainerRegistry.getInstance().findContainerStacks(type="machine", **metadata_filter)
     return bool(containers)
예제 #35
0
 def existsKey(self, key: str) -> bool:
     metadata_filter = {"um_network_key": key}
     containers = CuraContainerRegistry.getInstance().findContainerStacks(
         type="machine", **metadata_filter)
     return bool(containers)