QualitySettingsModel.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. # Copyright (c) 2016 Ultimaker B.V.
  2. # Cura is released under the terms of the AGPLv3 or higher.
  3. import collections
  4. from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt
  5. import UM.Application
  6. import UM.Logger
  7. import UM.Qt
  8. import UM.Settings
  9. from UM.i18n import i18nCatalog
  10. from UM.Settings.ContainerRegistry import ContainerRegistry
  11. import os
  12. class QualitySettingsModel(UM.Qt.ListModel.ListModel):
  13. KeyRole = Qt.UserRole + 1
  14. LabelRole = Qt.UserRole + 2
  15. UnitRole = Qt.UserRole + 3
  16. ProfileValueRole = Qt.UserRole + 4
  17. ProfileValueSourceRole = Qt.UserRole + 5
  18. UserValueRole = Qt.UserRole + 6
  19. CategoryRole = Qt.UserRole + 7
  20. def __init__(self, parent = None):
  21. super().__init__(parent = parent)
  22. self._container_registry = UM.Settings.ContainerRegistry.getInstance()
  23. self._extruder_id = None
  24. self._extruder_definition_id = None
  25. self._quality_id = None
  26. self._material_id = None
  27. self._i18n_catalog = None
  28. self.addRoleName(self.KeyRole, "key")
  29. self.addRoleName(self.LabelRole, "label")
  30. self.addRoleName(self.UnitRole, "unit")
  31. self.addRoleName(self.ProfileValueRole, "profile_value")
  32. self.addRoleName(self.ProfileValueSourceRole, "profile_value_source")
  33. self.addRoleName(self.UserValueRole, "user_value")
  34. self.addRoleName(self.CategoryRole, "category")
  35. def setExtruderId(self, extruder_id):
  36. if extruder_id != self._extruder_id:
  37. self._extruder_id = extruder_id
  38. self._update()
  39. self.extruderIdChanged.emit()
  40. extruderIdChanged = pyqtSignal()
  41. @pyqtProperty(str, fset = setExtruderId, notify = extruderIdChanged)
  42. def extruderId(self):
  43. return self._extruder_id
  44. def setExtruderDefinition(self, extruder_definition):
  45. if extruder_definition != self._extruder_definition_id:
  46. self._extruder_definition_id = extruder_definition
  47. self._update()
  48. self.extruderDefinitionChanged.emit()
  49. extruderDefinitionChanged = pyqtSignal()
  50. @pyqtProperty(str, fset = setExtruderDefinition, notify = extruderDefinitionChanged)
  51. def extruderDefinition(self):
  52. return self._extruder_definition_id
  53. def setQuality(self, quality):
  54. if quality != self._quality_id:
  55. self._quality_id = quality
  56. self._update()
  57. self.qualityChanged.emit()
  58. qualityChanged = pyqtSignal()
  59. @pyqtProperty(str, fset = setQuality, notify = qualityChanged)
  60. def quality(self):
  61. return self._quality_id
  62. def setMaterial(self, material):
  63. if material != self._material_id:
  64. self._material_id = material
  65. self._update()
  66. self.materialChanged.emit()
  67. materialChanged = pyqtSignal()
  68. @pyqtProperty(str, fset = setMaterial, notify = materialChanged)
  69. def material(self):
  70. return self._material_id
  71. def _update(self):
  72. if not self._quality_id:
  73. return
  74. items = []
  75. settings = collections.OrderedDict()
  76. definition_container = UM.Application.getInstance().getGlobalContainerStack().getBottom()
  77. containers = self._container_registry.findInstanceContainers(id = self._quality_id)
  78. if not containers:
  79. UM.Logger.log("w", "Could not find a quality container with id %s", self._quality_id)
  80. return
  81. quality_container = None
  82. quality_changes_container = None
  83. if containers[0].getMetaDataEntry("type") == "quality":
  84. quality_container = containers[0]
  85. else:
  86. quality_changes_container = containers[0]
  87. criteria = {
  88. "type": "quality",
  89. "quality_type": quality_changes_container.getMetaDataEntry("quality_type"),
  90. "definition": quality_changes_container.getDefinition().getId()
  91. }
  92. quality_container = self._container_registry.findInstanceContainers(**criteria)
  93. if not quality_container:
  94. UM.Logger.log("w", "Could not find a quality container matching quality changes %s", quality_changes_container.getId())
  95. return
  96. quality_container = quality_container[0]
  97. quality_type = quality_container.getMetaDataEntry("quality_type")
  98. definition_id = UM.Application.getInstance().getMachineManager().getQualityDefinitionId(quality_container.getDefinition())
  99. definition = quality_container.getDefinition()
  100. # Check if the definition container has a translation file.
  101. definition_suffix = ContainerRegistry.getMimeTypeForContainer(type(definition)).preferredSuffix
  102. catalog = i18nCatalog(os.path.basename(definition_id + "." + definition_suffix))
  103. if catalog.hasTranslationLoaded():
  104. self._i18n_catalog = catalog
  105. for file_name in quality_container.getDefinition().getInheritedFiles():
  106. catalog = i18nCatalog(os.path.basename(file_name))
  107. if catalog.hasTranslationLoaded():
  108. self._i18n_catalog = catalog
  109. criteria = {"type": "quality", "quality_type": quality_type, "definition": definition_id}
  110. if self._material_id and self._material_id != "empty_material":
  111. criteria["material"] = self._material_id
  112. criteria["extruder"] = self._extruder_id
  113. containers = self._container_registry.findInstanceContainers(**criteria)
  114. if not containers:
  115. # Try again, this time without extruder
  116. new_criteria = criteria.copy()
  117. new_criteria.pop("extruder")
  118. containers = self._container_registry.findInstanceContainers(**new_criteria)
  119. if not containers and "material" in criteria:
  120. # Try again, this time without material
  121. criteria.pop("material", None)
  122. containers = self._container_registry.findInstanceContainers(**criteria)
  123. if not containers:
  124. # Try again, this time without material or extruder
  125. criteria.pop("extruder") # "material" has already been popped
  126. containers = self._container_registry.findInstanceContainers(**criteria)
  127. if not containers:
  128. UM.Logger.log("w", "Could not find any quality containers matching the search criteria %s" % str(criteria))
  129. return
  130. if quality_changes_container:
  131. criteria = {"type": "quality_changes", "quality_type": quality_type, "definition": definition_id, "name": quality_changes_container.getName()}
  132. if self._extruder_definition_id != "":
  133. extruder_definitions = self._container_registry.findDefinitionContainers(id = self._extruder_definition_id)
  134. if extruder_definitions:
  135. criteria["extruder"] = UM.Application.getInstance().getMachineManager().getQualityDefinitionId(extruder_definitions[0])
  136. criteria["name"] = quality_changes_container.getName()
  137. else:
  138. criteria["extruder"] = None
  139. changes = self._container_registry.findInstanceContainers(**criteria)
  140. if changes:
  141. containers.extend(changes)
  142. global_container_stack = UM.Application.getInstance().getGlobalContainerStack()
  143. is_multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1
  144. current_category = ""
  145. for definition in definition_container.findDefinitions():
  146. if definition.type == "category":
  147. current_category = definition.label
  148. if self._i18n_catalog:
  149. current_category = self._i18n_catalog.i18nc(definition.key + " label", definition.label)
  150. continue
  151. profile_value = None
  152. profile_value_source = ""
  153. for container in containers:
  154. new_value = container.getProperty(definition.key, "value")
  155. if new_value is not None:
  156. profile_value_source = container.getMetaDataEntry("type")
  157. profile_value = new_value
  158. # Global tab should use resolve (if there is one)
  159. if not self._extruder_id:
  160. resolve_value = global_container_stack.getProperty(definition.key, "resolve")
  161. if resolve_value is not None and profile_value is not None and profile_value_source != "quality_changes":
  162. profile_value = resolve_value
  163. user_value = None
  164. if not self._extruder_id:
  165. user_value = global_container_stack.getTop().getProperty(definition.key, "value")
  166. else:
  167. extruder_stack = self._container_registry.findContainerStacks(id = self._extruder_id)
  168. if extruder_stack:
  169. user_value = extruder_stack[0].getTop().getProperty(definition.key, "value")
  170. if profile_value is None and user_value is None:
  171. continue
  172. if is_multi_extrusion:
  173. settable_per_extruder = global_container_stack.getProperty(definition.key, "settable_per_extruder")
  174. # If a setting is not settable per extruder (global) and we're looking at an extruder tab, don't show this value.
  175. if self._extruder_id != "" and not settable_per_extruder:
  176. continue
  177. # If a setting is settable per extruder (not global) and we're looking at global tab, don't show this value.
  178. if self._extruder_id == "" and settable_per_extruder:
  179. continue
  180. label = definition.label
  181. if self._i18n_catalog:
  182. label = self._i18n_catalog.i18nc(definition.key + " label", label)
  183. items.append({
  184. "key": definition.key,
  185. "label": label,
  186. "unit": definition.unit,
  187. "profile_value": "" if profile_value is None else str(profile_value), # it is for display only
  188. "profile_value_source": profile_value_source,
  189. "user_value": "" if user_value is None else str(user_value),
  190. "category": current_category
  191. })
  192. self.setItems(items)