IntentSelectionModel.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # Copyright (c) 2023 UltiMaker
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. import collections
  4. from typing import Optional
  5. from PyQt6.QtCore import Qt, QTimer, QObject, QUrl
  6. import cura
  7. from UM import i18nCatalog
  8. from UM.Logger import Logger
  9. from UM.Qt.ListModel import ListModel
  10. from UM.Resources import Resources
  11. from UM.Settings.ContainerRegistry import ContainerRegistry
  12. from UM.Settings.Interfaces import ContainerInterface
  13. from cura.Machines.Models.IntentCategoryModel import IntentCategoryModel
  14. from cura.Settings.IntentManager import IntentManager
  15. catalog = i18nCatalog("cura")
  16. class IntentSelectionModel(ListModel):
  17. NameRole = Qt.ItemDataRole.UserRole + 1
  18. IntentCategoryRole = Qt.ItemDataRole.UserRole + 2
  19. WeightRole = Qt.ItemDataRole.UserRole + 3
  20. DescriptionRole = Qt.ItemDataRole.UserRole + 4
  21. IconRole = Qt.ItemDataRole.UserRole + 5
  22. CustomIconRole = Qt.ItemDataRole.UserRole + 6
  23. def __init__(self, parent: Optional[QObject] = None) -> None:
  24. super().__init__(parent)
  25. self.addRoleName(self.NameRole, "name")
  26. self.addRoleName(self.IntentCategoryRole, "intent_category")
  27. self.addRoleName(self.WeightRole, "weight")
  28. self.addRoleName(self.DescriptionRole, "description")
  29. self.addRoleName(self.IconRole, "icon")
  30. self.addRoleName(self.CustomIconRole, "custom_icon")
  31. application = cura.CuraApplication.CuraApplication.getInstance()
  32. ContainerRegistry.getInstance().containerAdded.connect(self._onContainerChange)
  33. ContainerRegistry.getInstance().containerRemoved.connect(self._onContainerChange)
  34. machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager()
  35. machine_manager.activeMaterialChanged.connect(self._update)
  36. machine_manager.activeVariantChanged.connect(self._update)
  37. machine_manager.extruderChanged.connect(self._update)
  38. extruder_manager = application.getExtruderManager()
  39. extruder_manager.extrudersChanged.connect(self._update)
  40. self._update_timer: QTimer = QTimer()
  41. self._update_timer.setInterval(100)
  42. self._update_timer.setSingleShot(True)
  43. self._update_timer.timeout.connect(self._update)
  44. self._onChange()
  45. _default_intent_categories = ["default", "visual", "engineering", "quick", "annealing"]
  46. _icons = {"default": "GearCheck", "visual": "Visual", "engineering": "Nut", "quick": "SpeedOMeter", "annealing": "Anneal"}
  47. def _onContainerChange(self, container: ContainerInterface) -> None:
  48. """Updates the list of intents if an intent profile was added or removed."""
  49. if container.getMetaDataEntry("type") == "intent":
  50. self._update()
  51. def _onChange(self) -> None:
  52. self._update_timer.start()
  53. def _update(self) -> None:
  54. Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
  55. cura_application = cura.CuraApplication.CuraApplication.getInstance()
  56. global_stack = cura_application.getGlobalContainerStack()
  57. if global_stack is None:
  58. self.setItems([])
  59. Logger.log("d", "No active GlobalStack, set quality profile model as empty.")
  60. return
  61. # Check for material compatibility
  62. if not cura_application.getMachineManager().activeMaterialsCompatible():
  63. Logger.log("d", "No active material compatibility, set quality profile model as empty.")
  64. self.setItems([])
  65. return
  66. available_categories = IntentManager.getInstance().currentAvailableIntentCategories()
  67. result = []
  68. for category in available_categories:
  69. if category in self._default_intent_categories:
  70. result.append({
  71. "name": IntentCategoryModel.translation(category, "name", category.title()),
  72. "description": IntentCategoryModel.translation(category, "description", None),
  73. "icon": self._icons[category],
  74. "custom_icon": None,
  75. "intent_category": category,
  76. "weight": self._default_intent_categories.index(category),
  77. })
  78. else:
  79. # There can be multiple intents with the same category, use one of these
  80. # intent-metadata's for the icon/description defintions for the intent
  81. intent_metadata = cura_application.getContainerRegistry().findContainersMetadata(type="intent",
  82. definition=global_stack.findInstanceContainerDefinitionId(global_stack.definition),
  83. intent_category=category)[0]
  84. intent_name = intent_metadata.get("name", category.title())
  85. icon = intent_metadata.get("icon", None)
  86. description = intent_metadata.get("description", None)
  87. if icon is not None and icon != '':
  88. try:
  89. icon = QUrl.fromLocalFile(
  90. Resources.getPath(cura.CuraApplication.CuraApplication.ResourceTypes.ImageFiles, icon))
  91. except (FileNotFoundError, NotADirectoryError, PermissionError):
  92. Logger.log("e", f"Icon file for intent {intent_name} not found.")
  93. icon = None
  94. result.append({
  95. "name": intent_name,
  96. "description": description,
  97. "custom_icon": icon,
  98. "icon": None,
  99. "intent_category": category,
  100. "weight": 5,
  101. })
  102. result.sort(key=lambda k: k["weight"])
  103. self.setItems(result)