QualitySettingsModel.py 10.0 KB

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