QualitySettingsModel.py 11 KB

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