IntentModel.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. # Copyright (c) 2019 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from typing import Optional, List, Dict, Any
  4. from PyQt5.QtCore import Qt, QObject, pyqtProperty, pyqtSignal
  5. from UM.Qt.ListModel import ListModel
  6. from UM.Settings.ContainerRegistry import ContainerRegistry
  7. from UM.Settings.SettingFunction import SettingFunction
  8. from cura.Machines.ContainerTree import ContainerTree
  9. from cura.Settings.ExtruderManager import ExtruderManager
  10. from cura.Settings.IntentManager import IntentManager
  11. import cura.CuraApplication
  12. class IntentModel(ListModel):
  13. NameRole = Qt.UserRole + 1
  14. QualityTypeRole = Qt.UserRole + 2
  15. LayerHeightRole = Qt.UserRole + 3
  16. AvailableRole = Qt.UserRole + 4
  17. IntentRole = Qt.UserRole + 5
  18. def __init__(self, parent: Optional[QObject] = None) -> None:
  19. super().__init__(parent)
  20. self.addRoleName(self.NameRole, "name")
  21. self.addRoleName(self.QualityTypeRole, "quality_type")
  22. self.addRoleName(self.LayerHeightRole, "layer_height")
  23. self.addRoleName(self.AvailableRole, "available")
  24. self.addRoleName(self.IntentRole, "intent_category")
  25. self._intent_category = "engineering"
  26. machine_manager = cura.CuraApplication.CuraApplication.getInstance().getMachineManager()
  27. machine_manager.globalContainerChanged.connect(self._update)
  28. ContainerRegistry.getInstance().containerAdded.connect(self._onChanged)
  29. ContainerRegistry.getInstance().containerRemoved.connect(self._onChanged)
  30. self._layer_height_unit = "" # This is cached
  31. self._update()
  32. intentCategoryChanged = pyqtSignal()
  33. def setIntentCategory(self, new_category: str) -> None:
  34. if self._intent_category != new_category:
  35. self._intent_category = new_category
  36. self.intentCategoryChanged.emit()
  37. self._update()
  38. @pyqtProperty(str, fset = setIntentCategory, notify = intentCategoryChanged)
  39. def intentCategory(self) -> str:
  40. return self._intent_category
  41. def _onChanged(self, container):
  42. if container.getMetaDataEntry("type") == "intent":
  43. self._update()
  44. def _update(self) -> None:
  45. new_items = [] # type: List[Dict[str, Any]]
  46. global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
  47. if not global_stack:
  48. self.setItems(new_items)
  49. return
  50. quality_groups = ContainerTree.getInstance().getCurrentQualityGroups()
  51. container_tree = ContainerTree.getInstance()
  52. machine_node = container_tree.machines[global_stack.definition.getId()]
  53. active_extruder = ExtruderManager.getInstance().getActiveExtruderStack()
  54. if not active_extruder:
  55. return
  56. active_variant_name = active_extruder.variant.getMetaDataEntry("name")
  57. active_variant_node = machine_node.variants[active_variant_name]
  58. active_material_node = active_variant_node.materials[active_extruder.material.getMetaDataEntry("base_file")]
  59. layer_heights_added = []
  60. for quality_id, quality_node in active_material_node.qualities.items():
  61. quality_group = quality_groups[quality_node.quality_type]
  62. layer_height = self._fetchLayerHeight(quality_group)
  63. for intent_id, intent_node in quality_node.intents.items():
  64. if intent_node.intent_category != self._intent_category:
  65. continue
  66. layer_heights_added.append(layer_height)
  67. new_items.append({"name": quality_group.name,
  68. "quality_type": quality_group.quality_type,
  69. "layer_height": layer_height,
  70. "available": quality_group.is_available,
  71. "intent_category": self._intent_category
  72. })
  73. # Now that we added all intents that we found something for, ensure that we set add ticks (and layer_heights)
  74. # for all groups that we don't have anything for (and set it to not available)
  75. for quality_tuple, quality_group in quality_groups.items():
  76. # Add the intents that are of the correct category
  77. if quality_tuple[0] != self._intent_category:
  78. layer_height = self._fetchLayerHeight(quality_group)
  79. if layer_height not in layer_heights_added:
  80. new_items.append({"name": "Unavailable",
  81. "quality_type": "",
  82. "layer_height": layer_height,
  83. "intent_category": self._intent_category,
  84. "available": False})
  85. layer_heights_added.append(layer_height)
  86. new_items = sorted(new_items, key=lambda x: x["layer_height"])
  87. self.setItems(new_items)
  88. #TODO: Copied this from QualityProfilesDropdownMenuModel for the moment. This code duplication should be fixed.
  89. def _fetchLayerHeight(self, quality_group) -> float:
  90. global_stack = cura.CuraApplication.CuraApplication.getInstance().getMachineManager().activeMachine
  91. if not self._layer_height_unit:
  92. unit = global_stack.definition.getProperty("layer_height", "unit")
  93. if not unit:
  94. unit = ""
  95. self._layer_height_unit = unit
  96. default_layer_height = global_stack.definition.getProperty("layer_height", "value")
  97. # Get layer_height from the quality profile for the GlobalStack
  98. if quality_group.node_for_global is None:
  99. return float(default_layer_height)
  100. container = quality_group.node_for_global.getContainer()
  101. layer_height = default_layer_height
  102. if container and container.hasProperty("layer_height", "value"):
  103. layer_height = container.getProperty("layer_height", "value")
  104. else:
  105. # Look for layer_height in the GlobalStack from material -> definition
  106. container = global_stack.definition
  107. if container and container.hasProperty("layer_height", "value"):
  108. layer_height = container.getProperty("layer_height", "value")
  109. if isinstance(layer_height, SettingFunction):
  110. layer_height = layer_height(global_stack)
  111. return float(layer_height)
  112. def __repr__(self):
  113. return str(self.items)