예제 #1
0
    def _materialRemoved(self, container: ContainerInterface) -> None:
        if container.getMetaDataEntry("type") != "material":
            return  # Only interested in materials.
        base_file = container.getMetaDataEntry("base_file")
        if base_file not in self.materials:
            return  # We don't track this material anyway. No need to remove it.

        original_node = self.materials[base_file]
        del self.materials[base_file]
        self.materialsChanged.emit(original_node)

        # Now a different material from the same base file may have been hidden because it was not as specific as the one we deleted.
        # Search for any submaterials from that base file that are still left.
        materials_same_base_file = ContainerRegistry.getInstance().findContainersMetadata(base_file = base_file)
        if materials_same_base_file:
            most_specific_submaterial = None
            for submaterial in materials_same_base_file:
                if submaterial["definition"] == self.machine.container_id:
                    if submaterial.get("variant_name", "empty") == self.variant_name:
                        most_specific_submaterial = submaterial
                        break  # most specific match possible
                    if submaterial.get("variant_name", "empty") == "empty":
                        most_specific_submaterial = submaterial

            if most_specific_submaterial is None:
                Logger.log("w", "Material %s removed, but no suitable replacement found", base_file)
            else:
                Logger.log("i", "Material %s (%s) overridden by %s", base_file, self.variant_name, most_specific_submaterial.get("id"))
                self.materials[base_file] = MaterialNode(most_specific_submaterial["id"], variant = self)
                self.materialsChanged.emit(self.materials[base_file])

        if not self.materials:  # The last available material just got deleted and there is nothing with the same base file to replace it.
            self.materials["empty_material"] = MaterialNode("empty_material", variant = self)
            self.materialsChanged.emit(self.materials["empty_material"])
예제 #2
0
    def replaceContainer(self,
                         index: int,
                         container: ContainerInterface,
                         postpone_emit: bool = False) -> None:
        """Overridden from ContainerStack

        Replaces the container at the specified index with another container.
        This version performs checks to make sure the new container has the expected metadata and type.

        :throws Exception.InvalidContainerError Raised when trying to replace a container with a container that has an incorrect type.
        """

        expected_type = _ContainerIndexes.IndexTypeMap[index]
        if expected_type == "definition":
            if not isinstance(container, DefinitionContainer):
                raise Exceptions.InvalidContainerError(
                    "Cannot replace container at index {index} with a container that is not a DefinitionContainer"
                    .format(index=index))
        elif container != self._empty_instance_container and container.getMetaDataEntry(
                "type") != expected_type:
            raise Exceptions.InvalidContainerError(
                "Cannot replace container at index {index} with a container that is not of {type} type, but {actual_type} type."
                .format(index=index,
                        type=expected_type,
                        actual_type=container.getMetaDataEntry("type")))

        current_container = self._containers[index]
        if current_container.getId() == container.getId():
            return

        super().replaceContainer(index, container, postpone_emit)
예제 #3
0
    def _onContainerAdded(self, container: ContainerInterface) -> None:
        # We don't have all the machines loaded in the beginning, so in order to add the missing extruder stack
        # for single extrusion machines, we subscribe to the containerAdded signal, and whenever a global stack
        # is added, we check to see if an extruder stack needs to be added.
        if not isinstance(container, ContainerStack) or container.getMetaDataEntry("type") != "machine":
            return

        machine_extruder_trains = container.getMetaDataEntry("machine_extruder_trains")
        if machine_extruder_trains is not None and machine_extruder_trains != {"0": "fdmextruder"}:
            return

        extruder_stacks = self.findContainerStacks(type = "extruder_train", machine = container.getId())
        if not extruder_stacks:
            self.addExtruderStackForSingleExtrusionMachine(container, "fdmextruder")
예제 #4
0
    def replaceContainer(self, index: int, container: ContainerInterface, postpone_emit: bool = False) -> None:
        expected_type = _ContainerIndexes.IndexTypeMap[index]
        if expected_type == "definition":
            if not isinstance(container, DefinitionContainer):
                raise Exceptions.InvalidContainerError("Cannot replace container at index {index} with a container that is not a DefinitionContainer".format(index = index))
        elif container != self._empty_instance_container and container.getMetaDataEntry("type") != expected_type:
            raise Exceptions.InvalidContainerError("Cannot replace container at index {index} with a container that is not of {type} type, but {actual_type} type.".format(index = index, type = expected_type, actual_type = container.getMetaDataEntry("type")))

        super().replaceContainer(index, container, postpone_emit)
예제 #5
0
  def _on_printer_container_removed(self,
                                    container: ContainerInterface) -> None:
    """Removes device if it is managed by this plugin.

    Called when the user deletes a printer.

    Args:
      container: deleted container.
    """
    device_id = container.getMetaDataEntry(_METADATA_MPSM2_KEY)
    self.remove_device(device_id, _get_address(device_id))
예제 #6
0
    def _printerRemoved(self, container: ContainerInterface) -> None:
        """
        Callback connected to the containerRemoved signal. Invoked when a cloud printer is removed from Cura to remove
        the printer's reference from the _remote_clusters.

        :param container: The ContainerInterface passed to this function whenever the ContainerRemoved signal is emitted
        :return: None
        """
        if isinstance(container, GlobalStack):
            container_cluster_id = container.getMetaDataEntry(self.META_CLUSTER_ID, None)
            if container_cluster_id in self._remote_clusters.keys():
                del self._remote_clusters[container_cluster_id]
예제 #7
0
    def _materialAdded(self, container: ContainerInterface) -> None:
        if container.getMetaDataEntry("type") != "material":
            return  # Not interested.
        if not self.machine.has_materials:
            return  # We won't add any materials.
        material_definition = container.getMetaDataEntry("definition")

        base_file = container.getMetaDataEntry("base_file")
        if base_file in self.machine.exclude_materials:
            return  # Material is forbidden for this printer.
        if base_file not in self.materials:  # Completely new base file. Always better than not having a file as long as it matches our set-up.
            if material_definition != "fdmprinter" and material_definition != self.machine.container_id:
                return
            material_variant = container.getMetaDataEntry("variant_name", "empty")
            if material_variant != "empty" and material_variant != self.variant_name:
                return
        else:  # We already have this base profile. Replace the base profile if the new one is more specific.
            new_definition = container.getMetaDataEntry("definition")
            if new_definition == "fdmprinter":
                return  # Just as unspecific or worse.
            if new_definition != self.machine.container_id:
                return  # Doesn't match this set-up.
            original_metadata = ContainerRegistry.getInstance().findContainersMetadata(id = self.materials[base_file].container_id)[0]
            original_variant = original_metadata.get("variant_name", "empty")
            if original_variant != "empty" or container.getMetaDataEntry("variant_name", "empty") == "empty":
                return  # Original was already specific or just as unspecific as the new one.

        if "empty_material" in self.materials:
            del self.materials["empty_material"]
        self.materials[base_file] = MaterialNode(container.getId(), variant = self)
        self.materials[base_file].materialChanged.connect(self.materialsChanged)
        self.materialsChanged.emit(self.materials[base_file])
예제 #8
0
    def addContainer(self, container: ContainerInterface) -> None:
        # Note: Intentional check with type() because we want to ignore subclasses
        if type(container) == ContainerStack:
            container = self._convertContainerStack(cast(ContainerStack, container))

        if isinstance(container, InstanceContainer) and type(container) != type(self.getEmptyInstanceContainer()):
            # Check against setting version of the definition.
            required_setting_version = cura.CuraApplication.CuraApplication.SettingVersion
            actual_setting_version = int(container.getMetaDataEntry("setting_version", default = 0))
            if required_setting_version != actual_setting_version:
                Logger.log("w", "Instance container {container_id} is outdated. Its setting version is {actual_setting_version} but it should be {required_setting_version}.".format(container_id = container.getId(), actual_setting_version = actual_setting_version, required_setting_version = required_setting_version))
                return  # Don't add.

        super().addContainer(container)
예제 #9
0
    def setProperty(self,
                    name: str,
                    value: Any,
                    container: ContainerInterface = None):
        if SettingDefinition.hasProperty(name):
            if SettingDefinition.isReadOnlyProperty(name):
                Logger.log(
                    "e",
                    "Tried to set property %s which is a read-only property",
                    name)
                return

            if name not in self.__property_values or value != self.__property_values[
                    name]:
                if isinstance(value, str) and value.strip().startswith("="):
                    value = SettingFunction.SettingFunction(value[1:])

                self.__property_values[name] = value
                if name == "value":
                    if not container:
                        container = self._container
                    ## If state changed, emit the signal
                    if self._state != InstanceState.User and container.getMetaDataEntry(
                            "type") == "user":
                        self._state = InstanceState.User
                        self.propertyChanged.emit(self._definition.key,
                                                  "state")

                    self.updateRelations(container)

                if self._validator:
                    self.propertyChanged.emit(self._definition.key,
                                              "validationState")

                self.propertyChanged.emit(self._definition.key, name)
                for property_name in self._definition.getPropertyNames():
                    if self._definition.dependsOnProperty(
                            property_name) == name:
                        self.propertyChanged.emit(self._definition.key,
                                                  property_name)
        else:
            if name == "state":
                if value == "InstanceState.Calculated":
                    if self._state != InstanceState.Calculated:
                        self._state = InstanceState.Calculated
                        self.propertyChanged.emit(self._definition.key,
                                                  "state")
            else:
                raise AttributeError("No property {0} defined".format(name))
예제 #10
0
    def _materialAdded(self, container: ContainerInterface) -> None:
        if container.getMetaDataEntry("type") != "material":
            return  # Not interested.
        if not ContainerRegistry.getInstance().findContainersMetadata(
                id=container.getId()):
            # CURA-6889
            # containerAdded and removed signals may be triggered in the next event cycle. If a container gets added
            # and removed in the same event cycle, in the next cycle, the connections should just ignore the signals.
            # The check here makes sure that the container in the signal still exists.
            Logger.log(
                "d",
                "Got container added signal for container [%s] but it no longer exists, do nothing.",
                container.getId())
            return
        if not self.machine.has_materials:
            return  # We won't add any materials.
        material_definition = container.getMetaDataEntry("definition")

        base_file = container.getMetaDataEntry("base_file")
        if base_file in self.machine.exclude_materials:
            return  # Material is forbidden for this printer.
        if base_file not in self.materials:  # Completely new base file. Always better than not having a file as long as it matches our set-up.
            if material_definition != "fdmprinter" and material_definition != self.machine.container_id:
                return
            material_variant = container.getMetaDataEntry("variant_name")
            if material_variant is not None and material_variant != self.variant_name:
                return
        else:  # We already have this base profile. Replace the base profile if the new one is more specific.
            new_definition = container.getMetaDataEntry("definition")
            if new_definition == "fdmprinter":
                return  # Just as unspecific or worse.
            material_variant = container.getMetaDataEntry("variant_name")
            if new_definition != self.machine.container_id or material_variant != self.variant_name:
                return  # Doesn't match this set-up.
            original_metadata = ContainerRegistry.getInstance(
            ).findContainersMetadata(
                id=self.materials[base_file].container_id)[0]
            if "variant_name" in original_metadata or material_variant is None:
                return  # Original was already specific or just as unspecific as the new one.

        if "empty_material" in self.materials:
            del self.materials["empty_material"]
        self.materials[base_file] = MaterialNode(container.getId(),
                                                 variant=self)
        self.materials[base_file].materialChanged.connect(
            self.materialsChanged)
        self.materialsChanged.emit(self.materials[base_file])