def createQualityChanges(self, base_name: str) -> None: machine_manager = self._application.getMachineManager() global_stack = machine_manager.activeMachine if not global_stack: return active_quality_name = machine_manager.activeQualityOrQualityChangesName if active_quality_name == "": Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) return machine_manager.blurSettings.emit() if base_name is None or base_name == "": base_name = active_quality_name unique_name = self._container_registry.uniqueName(base_name) # Go through the active stacks and create quality_changes containers from the user containers. stack_list = [global_stack] + list(global_stack.extruders.values()) for stack in stack_list: user_container = stack.userChanges quality_container = stack.quality quality_changes_container = stack.qualityChanges if not quality_container or not quality_changes_container: Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId()) continue quality_type = quality_container.getMetaDataEntry("quality_type") extruder_stack = None if isinstance(stack, ExtruderStack): extruder_stack = stack new_changes = self._createQualityChanges(quality_type, unique_name, global_stack, extruder_stack) from cura.Settings.ContainerManager import ContainerManager ContainerManager.getInstance()._performMerge(new_changes, quality_changes_container, clear_settings = False) ContainerManager.getInstance()._performMerge(new_changes, user_container) self._container_registry.addContainer(new_changes)
def _materialWarningMessageAction(self, message, button): if button == "Undo": container_manager = ContainerManager.getInstance() container_manager.setContainerMetaDataEntry(self._material_diameter_warning_message.material_id, "properties/diameter", self._material_diameter_warning_message.previous_diameter) message.hide() else: Logger.log("w", "Unknown button action for material diameter warning message: {action}".format(action = button))
def setUp(self): self._application = MagicMock() self._container_registry = MagicMock() self._machine_manager = MagicMock() self._mocked_mime = MagicMock() self._mocked_mime.preferredSuffix = "omg" self._mocked_mime.suffixes = ["omg"] self._mocked_mime.comment = "UnitTest!" self._mocked_container = MagicMock() self._mocked_container_data = "SOME DATA :D" self._mocked_container.serialize = MagicMock(return_value = self._mocked_container_data) self._containers_meta_data = [{"id": "test", "test_data": "omg"}] self._container_registry.findContainersMetadata = MagicMock(return_value = self._containers_meta_data) self._container_registry.getMimeTypeForContainer = MagicMock(return_value = self._mocked_mime) self._container_registry.findContainers = MagicMock(return_value = [self._mocked_container]) self._application.getContainerRegistry = MagicMock(return_value = self._container_registry) self._application.getMachineManager = MagicMock(return_value = self._machine_manager) # Destroy the previous instance of the container manager if ContainerManager.getInstance() is not None: ContainerManager._ContainerManager__instance = None self._container_manager = ContainerManager(self._application) MimeTypeDatabase.addMimeType(self._mocked_mime)
def setUp(self): self._application = MagicMock() self._container_registry = MagicMock() self._machine_manager = MagicMock() self._mocked_mime = MagicMock() self._mocked_mime.preferredSuffix = "omg" self._mocked_mime.suffixes = ["omg"] self._mocked_mime.comment = "UnitTest!" self._mocked_container = MagicMock() self._mocked_container_data = "SOME DATA :D" self._mocked_container.serialize = MagicMock( return_value=self._mocked_container_data) self._containers_meta_data = [{"id": "test", "test_data": "omg"}] self._container_registry.findContainersMetadata = MagicMock( return_value=self._containers_meta_data) self._container_registry.getMimeTypeForContainer = MagicMock( return_value=self._mocked_mime) self._container_registry.findContainers = MagicMock( return_value=[self._mocked_container]) self._application.getContainerRegistry = MagicMock( return_value=self._container_registry) self._application.getMachineManager = MagicMock( return_value=self._machine_manager) # Destroy the previous instance of the container manager if ContainerManager.getInstance() is not None: ContainerManager._ContainerManager__instance = None self._container_manager = ContainerManager(self._application) MimeTypeDatabase.addMimeType(self._mocked_mime)
def _sendMaterialProfiles(self): Logger.log("i", "Sending material profiles to printer") # TODO: Might want to move this to a job... for container in ContainerRegistry.getInstance( ).findInstanceContainers(type="material"): try: xml_data = container.serialize() if xml_data == "" or xml_data is None: continue names = ContainerManager.getInstance().getLinkedMaterials( container.getId()) if names: # There are other materials that share this GUID. if not container.isReadOnly(): continue # If it's not readonly, it's created by user, so skip it. file_name = "none.xml" self.postForm("materials", "form-data; name=\"file\";filename=\"%s\"" % file_name, xml_data.encode(), on_finished=None) except NotImplementedError: # If the material container is not the most "generic" one it can't be serialized an will raise a # NotImplementedError. We can simply ignore these. pass
def duplicateMaterial(self, message: QDBusMessage): from cura.Settings.ContainerManager import ContainerManager container_manager = ContainerManager.getInstance() base_material_id = message.arguments()[0] # material to duplicate from new_id = message.arguments()[1] # (preferred) duplicated material ID container_manager.duplicateMaterial(base_material_id, new_id)
def createMaterial(self, message: QDBusMessage): from cura.Settings.ContainerManager import ContainerManager container_manager = ContainerManager.getInstance() new_id = message.arguments()[0] new_name = message.arguments()[1] container_manager.createMaterial(new_id=new_id, new_name=new_name)
def _materialWarningMessageAction(self, message, button): if button == "Undo": container_manager = ContainerManager.getInstance() container_manager.setContainerMetaDataEntry(self._material_diameter_warning_message.material_id, "properties/diameter", self._material_diameter_warning_message.previous_diameter) approximate_previous_diameter = str(round(float(self._material_diameter_warning_message.previous_diameter))) container_manager.setContainerMetaDataEntry(self._material_diameter_warning_message.material_id, "approximate_diameter", approximate_previous_diameter) message.hide() else: Logger.log("w", "Unknown button action for material diameter warning message: {action}".format(action = button))
def exportMaterial(self, message: QDBusMessage): material_id = message.arguments()[0] material_file_path = message.arguments()[1] from cura.Settings.ContainerManager import ContainerManager container_manager = ContainerManager.getInstance() container_manager.exportContainer( material_id, container_manager.getContainerNameFilters("material")[0], material_file_path)
def createQualityChanges(self, base_name: str) -> None: machine_manager = cura.CuraApplication.CuraApplication.getInstance( ).getMachineManager() global_stack = machine_manager.activeMachine if not global_stack: return active_quality_name = machine_manager.activeQualityOrQualityChangesName if active_quality_name == "": Logger.log( "w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) return machine_manager.blurSettings.emit() if base_name is None or base_name == "": base_name = active_quality_name container_registry = cura.CuraApplication.CuraApplication.getInstance( ).getContainerRegistry() unique_name = container_registry.uniqueName(base_name) # Go through the active stacks and create quality_changes containers from the user containers. container_manager = ContainerManager.getInstance() stack_list = [global_stack] + list(global_stack.extruders.values()) for stack in stack_list: quality_container = stack.quality quality_changes_container = stack.qualityChanges if not quality_container or not quality_changes_container: Logger.log( "w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId()) continue extruder_stack = None intent_category = None if stack.getMetaDataEntry("position") is not None: extruder_stack = stack intent_category = stack.intent.getMetaDataEntry( "intent_category") new_changes = self._createQualityChanges( quality_container.getMetaDataEntry("quality_type"), intent_category, unique_name, global_stack, extruder_stack) container_manager._performMerge(new_changes, quality_changes_container, clear_settings=False) container_manager._performMerge(new_changes, stack.userChanges) container_registry.addContainer(new_changes)
def createQualityChanges(self, base_name: str) -> None: """Create quality changes containers from the user containers in the active stacks. This will go through the global and extruder stacks and create quality_changes containers from the user containers in each stack. These then replace the quality_changes containers in the stack and clear the user settings. :param base_name: The new name for the quality changes profile. The final name of the profile might be different from this, because it needs to be made unique. """ machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager() global_stack = machine_manager.activeMachine if not global_stack: return active_quality_name = machine_manager.activeQualityOrQualityChangesName if active_quality_name == "": Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) return machine_manager.blurSettings.emit() if base_name is None or base_name == "": base_name = active_quality_name container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry() unique_name = container_registry.uniqueName(base_name) # Go through the active stacks and create quality_changes containers from the user containers. container_manager = ContainerManager.getInstance() stack_list = [global_stack] + global_stack.extruderList for stack in stack_list: quality_container = stack.quality quality_changes_container = stack.qualityChanges if not quality_container or not quality_changes_container: Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId()) continue extruder_stack = None intent_category = None if stack.getMetaDataEntry("position") is not None: extruder_stack = stack intent_category = stack.intent.getMetaDataEntry("intent_category") new_changes = self._createQualityChanges(quality_container.getMetaDataEntry("quality_type"), intent_category, unique_name, global_stack, extruder_stack) container_manager._performMerge(new_changes, quality_changes_container, clear_settings = False) container_manager._performMerge(new_changes, stack.userChanges) container_registry.addContainer(new_changes)
def _sendMaterialProfiles(self): Logger.log("i", "Sending material profiles to printer") # TODO: Might want to move this to a job... for container in ContainerRegistry.getInstance().findInstanceContainers(type="material"): try: xml_data = container.serialize() if xml_data == "" or xml_data is None: continue names = ContainerManager.getInstance().getLinkedMaterials(container.getId()) if names: # There are other materials that share this GUID. if not container.isReadOnly(): continue # If it's not readonly, it's created by user, so skip it. file_name = "none.xml" self.postForm("materials", "form-data; name=\"file\";filename=\"%s\"" % file_name, xml_data.encode(), on_finished=None) except NotImplementedError: # If the material container is not the most "generic" one it can't be serialized an will raise a # NotImplementedError. We can simply ignore these. pass
def importProfile(self, file_name): Logger.log("d", "Attempting to import profile %s", file_name) if not file_name: return { "status": "error", "message": catalog.i18nc( "@info:status", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, "Invalid path", ), } plugin_registry = PluginRegistry.getInstance() extension = file_name.split(".")[-1] global_container_stack = Application.getInstance().getGlobalContainerStack() if not global_container_stack: return machine_extruders = list(ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId())) machine_extruders.sort(key=lambda k: k.getMetaDataEntry("position")) for plugin_id, meta_data in self._getIOPlugins("profile_reader"): if meta_data["profile_reader"][0]["extension"] != extension: continue profile_reader = plugin_registry.getPluginObject(plugin_id) try: profile_or_list = profile_reader.read(file_name) # Try to open the file with the profile reader. except Exception as e: # Note that this will fail quickly. That is, if any profile reader throws an exception, it will stop reading. It will only continue reading if the reader returned None. Logger.log( "e", "Failed to import profile from %s: %s while using profile reader. Got exception %s", file_name, profile_reader.getPluginId(), str(e), ) return { "status": "error", "message": catalog.i18nc( "@info:status", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, str(e), ), } if profile_or_list: # Success! name_seed = os.path.splitext(os.path.basename(file_name))[0] new_name = self.uniqueName(name_seed) if type(profile_or_list) is not list: profile = profile_or_list self._configureProfile(profile, name_seed, new_name) return { "status": "ok", "message": catalog.i18nc( "@info:status", "Successfully imported profile {0}", profile.getName() ), } else: profile_index = -1 global_profile = None for profile in profile_or_list: if profile_index >= 0: if len(machine_extruders) > profile_index: extruder_id = ( Application.getInstance() .getMachineManager() .getQualityDefinitionId(machine_extruders[profile_index].getBottom()) ) # Ensure the extruder profiles get non-conflicting names # NB: these are not user-facing if "extruder" in profile.getMetaData(): profile.setMetaDataEntry("extruder", extruder_id) else: profile.addMetaDataEntry("extruder", extruder_id) profile_id = (extruder_id + "_" + name_seed).lower().replace(" ", "_") elif profile_index == 0: # Importing a multiextrusion profile into a single extrusion machine; merge 1st extruder profile into global profile profile._id = self.uniqueName("temporary_profile") self.addContainer(profile) ContainerManager.getInstance().mergeContainers(global_profile.getId(), profile.getId()) self.removeContainer(profile.getId()) break else: # The imported composite profile has a profile for an extruder that this machine does not have. Ignore this extruder-profile break else: global_profile = profile profile_id = ( (global_container_stack.getBottom().getId() + "_" + name_seed).lower().replace(" ", "_") ) self._configureProfile(profile, profile_id, new_name) profile_index += 1 return { "status": "ok", "message": catalog.i18nc( "@info:status", "Successfully imported profile {0}", profile_or_list[0].getName() ), } # If it hasn't returned by now, none of the plugins loaded the profile successfully. return { "status": "error", "message": catalog.i18nc( "@info:status", "Profile {0} has an unknown file type or is corrupted.", file_name ), }
def importMaterial(self, message: QDBusMessage): material_file_path = message.arguments()[0] from cura.Settings.ContainerManager import ContainerManager container_manager = ContainerManager.getInstance() container_manager.importContainer(material_file_path)
def importProfile(self, file_name): Logger.log("d", "Attempting to import profile %s", file_name) if not file_name: return { "status": "error", "message": catalog.i18nc( "@info:status", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, "Invalid path") } plugin_registry = PluginRegistry.getInstance() extension = file_name.split(".")[-1] global_container_stack = Application.getInstance( ).getGlobalContainerStack() if not global_container_stack: return machine_extruders = list( ExtruderManager.getInstance().getMachineExtruders( global_container_stack.getId())) machine_extruders.sort(key=lambda k: k.getMetaDataEntry("position")) for plugin_id, meta_data in self._getIOPlugins("profile_reader"): if meta_data["profile_reader"][0]["extension"] != extension: continue profile_reader = plugin_registry.getPluginObject(plugin_id) try: profile_or_list = profile_reader.read( file_name) # Try to open the file with the profile reader. except Exception as e: # Note that this will fail quickly. That is, if any profile reader throws an exception, it will stop reading. It will only continue reading if the reader returned None. Logger.log( "e", "Failed to import profile from %s: %s while using profile reader. Got exception %s", file_name, profile_reader.getPluginId(), str(e)) return { "status": "error", "message": catalog.i18nc( "@info:status", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, str(e)) } if profile_or_list: # Success! name_seed = os.path.splitext(os.path.basename(file_name))[0] new_name = self.uniqueName(name_seed) if type(profile_or_list) is not list: profile = profile_or_list self._configureProfile(profile, name_seed, new_name) return { "status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profile {0}", profile.getName()) } else: profile_index = -1 global_profile = None for profile in profile_or_list: if profile_index >= 0: if len(machine_extruders) > profile_index: extruder_id = Application.getInstance( ).getMachineManager().getQualityDefinitionId( machine_extruders[profile_index].getBottom( )) # Ensure the extruder profiles get non-conflicting names # NB: these are not user-facing if "extruder" in profile.getMetaData(): profile.setMetaDataEntry( "extruder", extruder_id) else: profile.addMetaDataEntry( "extruder", extruder_id) profile_id = (extruder_id + "_" + name_seed).lower().replace( " ", "_") elif profile_index == 0: # Importing a multiextrusion profile into a single extrusion machine; merge 1st extruder profile into global profile profile._id = self.uniqueName( "temporary_profile") self.addContainer(profile) ContainerManager.getInstance().mergeContainers( global_profile.getId(), profile.getId()) self.removeContainer(profile.getId()) break else: # The imported composite profile has a profile for an extruder that this machine does not have. Ignore this extruder-profile break else: global_profile = profile profile_id = ( global_container_stack.getBottom().getId() + "_" + name_seed).lower().replace(" ", "_") self._configureProfile(profile, profile_id, new_name) profile_index += 1 return { "status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profile {0}", profile_or_list[0].getName()) } # If it hasn't returned by now, none of the plugins loaded the profile successfully. return { "status": "error", "message": catalog.i18nc( "@info:status", "Profile {0} has an unknown file type or is corrupted.", file_name) }