# Copyright (c) 2023 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. import collections from typing import Optional from PyQt6.QtCore import Qt, QTimer, QObject, QUrl import cura from UM import i18nCatalog from UM.Logger import Logger from UM.Qt.ListModel import ListModel from UM.Resources import Resources from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.Interfaces import ContainerInterface from cura.Machines.Models.IntentCategoryModel import IntentCategoryModel from cura.Settings.IntentManager import IntentManager catalog = i18nCatalog("cura") class IntentSelectionModel(ListModel): NameRole = Qt.ItemDataRole.UserRole + 1 IntentCategoryRole = Qt.ItemDataRole.UserRole + 2 WeightRole = Qt.ItemDataRole.UserRole + 3 DescriptionRole = Qt.ItemDataRole.UserRole + 4 IconRole = Qt.ItemDataRole.UserRole + 5 CustomIconRole = Qt.ItemDataRole.UserRole + 6 def __init__(self, parent: Optional[QObject] = None) -> None: super().__init__(parent) self.addRoleName(self.NameRole, "name") self.addRoleName(self.IntentCategoryRole, "intent_category") self.addRoleName(self.WeightRole, "weight") self.addRoleName(self.DescriptionRole, "description") self.addRoleName(self.IconRole, "icon") self.addRoleName(self.CustomIconRole, "custom_icon") application = cura.CuraApplication.CuraApplication.getInstance() ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChange) ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChange) machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager() machine_manager.activeMaterialChanged.connect(self._update) machine_manager.activeVariantChanged.connect(self._update) machine_manager.extruderChanged.connect(self._update) extruder_manager = application.getExtruderManager() extruder_manager.extrudersChanged.connect(self._update) self._update_timer: QTimer = QTimer() self._update_timer.setInterval(100) self._update_timer.setSingleShot(True) self._update_timer.timeout.connect(self._update) self._onChange() _default_intent_categories = ["default", "visual", "engineering", "quick", "annealing"] _icons = {"default": "GearCheck", "visual": "Visual", "engineering": "Nut", "quick": "SpeedOMeter", "annealing": "Anneal"} def _onContainerChange(self, container: ContainerInterface) -> None: """Updates the list of intents if an intent profile was added or removed.""" if container.getMetaDataEntry("type") == "intent": self._update() def _onChange(self) -> None: self._update_timer.start() def _update(self) -> None: Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) cura_application = cura.CuraApplication.CuraApplication.getInstance() global_stack = cura_application.getGlobalContainerStack() if global_stack is None: self.setItems([]) Logger.log("d", "No active GlobalStack, set quality profile model as empty.") return # Check for material compatibility if not cura_application.getMachineManager().activeMaterialsCompatible(): Logger.log("d", "No active material compatibility, set quality profile model as empty.") self.setItems([]) return available_categories = IntentManager.getInstance().currentAvailableIntentCategories() result = [] for category in available_categories: if category in self._default_intent_categories: result.append({ "name": IntentCategoryModel.translation(category, "name", category.title()), "description": IntentCategoryModel.translation(category, "description", None), "icon": self._icons[category], "custom_icon": None, "intent_category": category, "weight": self._default_intent_categories.index(category), }) else: # There can be multiple intents with the same category, use one of these # intent-metadata's for the icon/description defintions for the intent intent_metadata = cura_application.getContainerRegistry().findContainersMetadata(type="intent", definition=global_stack.findInstanceContainerDefinitionId(global_stack.definition), intent_category=category)[0] intent_name = intent_metadata.get("name", category.title()) icon = intent_metadata.get("icon", None) description = intent_metadata.get("description", None) if icon is not None and icon != '': try: icon = QUrl.fromLocalFile( Resources.getPath(cura.CuraApplication.CuraApplication.ResourceTypes.ImageFiles, icon)) except (FileNotFoundError, NotADirectoryError, PermissionError): Logger.log("e", f"Icon file for intent {intent_name} not found.") icon = None result.append({ "name": intent_name, "description": description, "custom_icon": icon, "icon": None, "intent_category": category, "weight": 5, }) result.sort(key=lambda k: k["weight"]) self.setItems(result)