MachineManagerModel.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. # Copyright (c) 2016 Ultimaker B.V.
  2. # Cura is released under the terms of the AGPLv3 or higher.
  3. from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
  4. from UM.Application import Application
  5. from UM.Preferences import Preferences
  6. import UM.Settings
  7. from UM.Settings.Validator import ValidatorState
  8. from UM.Settings.InstanceContainer import InstanceContainer
  9. from cura.PrinterOutputDevice import PrinterOutputDevice
  10. from UM.Settings.ContainerStack import ContainerStack
  11. from . import ExtruderManager
  12. from UM.i18n import i18nCatalog
  13. catalog = i18nCatalog("cura")
  14. class MachineManagerModel(QObject):
  15. def __init__(self, parent = None):
  16. super().__init__(parent)
  17. self._active_container_stack = None
  18. self._global_container_stack = None
  19. Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
  20. self._global_stack_valid = None
  21. self._onGlobalContainerChanged()
  22. ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
  23. self.globalContainerChanged.connect(self._onActiveExtruderStackChanged)
  24. self._onActiveExtruderStackChanged()
  25. ## When the global container is changed, active material probably needs to be updated.
  26. self.globalContainerChanged.connect(self.activeMaterialChanged)
  27. self.globalContainerChanged.connect(self.activeVariantChanged)
  28. self.globalContainerChanged.connect(self.activeQualityChanged)
  29. ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeMaterialChanged)
  30. ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeVariantChanged)
  31. ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeQualityChanged)
  32. self.globalContainerChanged.connect(self.activeStackChanged)
  33. self.globalValueChanged.connect(self.activeStackChanged)
  34. ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeStackChanged)
  35. self._empty_variant_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_variant")[0]
  36. self._empty_material_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_material")[0]
  37. self._empty_quality_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality")[0]
  38. Preferences.getInstance().addPreference("cura/active_machine", "")
  39. active_machine_id = Preferences.getInstance().getValue("cura/active_machine")
  40. Application.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
  41. if active_machine_id != "":
  42. # An active machine was saved, so restore it.
  43. self.setActiveMachine(active_machine_id)
  44. pass
  45. globalContainerChanged = pyqtSignal()
  46. activeMaterialChanged = pyqtSignal()
  47. activeVariantChanged = pyqtSignal()
  48. activeQualityChanged = pyqtSignal()
  49. activeStackChanged = pyqtSignal()
  50. globalValueChanged = pyqtSignal() # Emitted whenever a value inside global container is changed.
  51. globalValidationChanged = pyqtSignal() # Emitted whenever a validation inside global container is changed
  52. blurSettings = pyqtSignal() # Emitted to force fields in the advanced sidebar to un-focus, so they update properly
  53. outputDevicesChanged = pyqtSignal()
  54. def _onOutputDevicesChanged(self):
  55. self.outputDevicesChanged.emit()
  56. def _onGlobalPropertyChanged(self, key, property_name):
  57. if property_name == "value":
  58. self.globalValueChanged.emit()
  59. if property_name == "validationState":
  60. if self._global_stack_valid:
  61. changed_validation_state = self._active_container_stack.getProperty(key, property_name)
  62. if changed_validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
  63. self._global_stack_valid = False
  64. self.globalValidationChanged.emit()
  65. else:
  66. has_errors = self._checkStackForErrors(self._active_container_stack)
  67. if not has_errors:
  68. self._global_stack_valid = True
  69. self.globalValidationChanged.emit()
  70. def _onGlobalContainerChanged(self):
  71. if self._global_container_stack:
  72. self._global_container_stack.containersChanged.disconnect(self._onInstanceContainersChanged)
  73. self._global_container_stack.propertyChanged.disconnect(self._onGlobalPropertyChanged)
  74. self._global_container_stack = Application.getInstance().getGlobalContainerStack()
  75. self.globalContainerChanged.emit()
  76. if self._global_container_stack:
  77. Preferences.getInstance().setValue("cura/active_machine", self._global_container_stack.getId())
  78. self._global_container_stack.containersChanged.connect(self._onInstanceContainersChanged)
  79. self._global_container_stack.propertyChanged.connect(self._onGlobalPropertyChanged)
  80. self._global_stack_valid = not self._checkStackForErrors(self._global_container_stack)
  81. def _onActiveExtruderStackChanged(self):
  82. self.blurSettings.emit() # Ensure no-one has focus.
  83. if self._active_container_stack and self._active_container_stack != self._global_container_stack:
  84. self._active_container_stack.containersChanged.disconnect(self._onInstanceContainersChanged)
  85. self._active_container_stack.propertyChanged.disconnect(self._onGlobalPropertyChanged)
  86. self._active_container_stack = ExtruderManager.ExtruderManager.getInstance().getActiveExtruderStack()
  87. if self._active_container_stack:
  88. self._active_container_stack.containersChanged.connect(self._onInstanceContainersChanged)
  89. self._active_container_stack.propertyChanged.connect(self._onGlobalPropertyChanged)
  90. else:
  91. self._active_container_stack = self._global_container_stack
  92. def _onInstanceContainersChanged(self, container):
  93. container_type = container.getMetaDataEntry("type")
  94. if container_type == "material":
  95. self.activeMaterialChanged.emit()
  96. elif container_type == "variant":
  97. self.activeVariantChanged.emit()
  98. elif container_type == "quality":
  99. self.activeQualityChanged.emit()
  100. @pyqtSlot(str)
  101. def setActiveMachine(self, stack_id):
  102. containers = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = stack_id)
  103. if containers:
  104. Application.getInstance().setGlobalContainerStack(containers[0])
  105. @pyqtSlot(str, str)
  106. def addMachine(self, name, definition_id):
  107. definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id = definition_id)
  108. if definitions:
  109. definition = definitions[0]
  110. name = self._createUniqueName("machine", "", name, definition.getName())
  111. new_global_stack = UM.Settings.ContainerStack(name)
  112. new_global_stack.addMetaDataEntry("type", "machine")
  113. UM.Settings.ContainerRegistry.getInstance().addContainer(new_global_stack)
  114. variant_instance_container = self._updateVariantContainer(definition)
  115. material_instance_container = self._updateMaterialContainer(definition, variant_instance_container)
  116. quality_instance_container = self._updateQualityContainer(definition, material_instance_container)
  117. current_settings_instance_container = UM.Settings.InstanceContainer(name + "_current_settings")
  118. current_settings_instance_container.addMetaDataEntry("machine", name)
  119. current_settings_instance_container.addMetaDataEntry("type", "user")
  120. current_settings_instance_container.setDefinition(definitions[0])
  121. UM.Settings.ContainerRegistry.getInstance().addContainer(current_settings_instance_container)
  122. # If a definition is found, its a list. Should only have one item.
  123. new_global_stack.addContainer(definition)
  124. if variant_instance_container:
  125. new_global_stack.addContainer(variant_instance_container)
  126. if material_instance_container:
  127. new_global_stack.addContainer(material_instance_container)
  128. if quality_instance_container:
  129. new_global_stack.addContainer(quality_instance_container)
  130. new_global_stack.addContainer(current_settings_instance_container)
  131. ExtruderManager.ExtruderManager.getInstance().addMachineExtruders(definition)
  132. Application.getInstance().setGlobalContainerStack(new_global_stack)
  133. @pyqtProperty("QVariantList", notify = outputDevicesChanged)
  134. def printerOutputDevices(self):
  135. return [printer_output_device for printer_output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices() if isinstance(printer_output_device, PrinterOutputDevice)]
  136. ## Create a name that is not empty and unique
  137. # \param container_type \type{string} Type of the container (machine, quality, ...)
  138. # \param current_name \type{} Current name of the container, which may be an acceptable option
  139. # \param new_name \type{string} Base name, which may not be unique
  140. # \param fallback_name \type{string} Name to use when (stripped) new_name is empty
  141. # \return \type{string} Name that is unique for the specified type and name/id
  142. def _createUniqueName(self, container_type, current_name, new_name, fallback_name):
  143. return UM.Settings.ContainerRegistry.getInstance().createUniqueName(container_type, current_name, new_name, fallback_name)
  144. ## Convenience function to check if a stack has errors.
  145. def _checkStackForErrors(self, stack):
  146. if stack is None:
  147. return False
  148. for key in stack.getAllKeys():
  149. validation_state = stack.getProperty(key, "validationState")
  150. if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError):
  151. return True
  152. return False
  153. ## Remove all instances from the top instanceContainer (effectively removing all user-changed settings)
  154. @pyqtSlot()
  155. def clearUserSettings(self):
  156. if not self._active_container_stack:
  157. return
  158. self.blurSettings.emit()
  159. user_settings = self._active_container_stack.getTop()
  160. user_settings.clear()
  161. ## Check if the global_container has instances in the user container
  162. @pyqtProperty(bool, notify = activeStackChanged)
  163. def hasUserSettings(self):
  164. if not self._active_container_stack:
  165. return False
  166. user_settings = self._active_container_stack.getTop().findInstances(**{})
  167. return len(user_settings) != 0
  168. ## Check if the global profile does not contain error states
  169. # Note that the _global_stack_valid is cached due to performance issues
  170. # Calling _checkStackForErrors on every change is simply too expensive
  171. @pyqtProperty(bool, notify = globalValidationChanged)
  172. def isGlobalStackValid(self):
  173. return self._global_stack_valid
  174. @pyqtProperty(str, notify = activeStackChanged)
  175. def activeUserProfileId(self):
  176. if self._active_container_stack:
  177. return self._active_container_stack.getTop().getId()
  178. return ""
  179. @pyqtProperty(str, notify = globalContainerChanged)
  180. def activeMachineName(self):
  181. if self._global_container_stack:
  182. return self._global_container_stack.getName()
  183. return ""
  184. @pyqtProperty(str, notify = globalContainerChanged)
  185. def activeMachineId(self):
  186. if self._global_container_stack:
  187. return self._global_container_stack.getId()
  188. return ""
  189. @pyqtProperty(str, notify = activeMaterialChanged)
  190. def activeMaterialName(self):
  191. if self._active_container_stack:
  192. material = self._active_container_stack.findContainer({"type":"material"})
  193. if material:
  194. return material.getName()
  195. return ""
  196. @pyqtProperty(str, notify=activeMaterialChanged)
  197. def activeMaterialId(self):
  198. if self._active_container_stack:
  199. material = self._active_container_stack.findContainer({"type": "material"})
  200. if material:
  201. return material.getId()
  202. return ""
  203. @pyqtProperty(str, notify=activeQualityChanged)
  204. def activeQualityName(self):
  205. if self._active_container_stack:
  206. quality = self._active_container_stack.findContainer({"type": "quality"})
  207. if quality:
  208. return quality.getName()
  209. return ""
  210. @pyqtProperty(str, notify=activeQualityChanged)
  211. def activeQualityId(self):
  212. if self._active_container_stack:
  213. quality = self._active_container_stack.findContainer({"type": "quality"})
  214. if quality:
  215. return quality.getId()
  216. return ""
  217. ## Check if a container is read_only
  218. @pyqtSlot(str, result = bool)
  219. def isReadOnly(self, container_id):
  220. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = container_id)
  221. if not containers or not self._active_container_stack:
  222. return True
  223. return containers[0].isReadOnly()
  224. @pyqtSlot(result = str)
  225. def newQualityContainerFromQualityAndUser(self):
  226. new_container_id = self.duplicateContainer(self.activeQualityId)
  227. if new_container_id == "":
  228. return
  229. self.blurSettings.emit()
  230. self.setActiveQuality(new_container_id)
  231. self.updateQualityContainerFromUserContainer()
  232. return new_container_id
  233. @pyqtSlot(str, result=str)
  234. def duplicateContainer(self, container_id):
  235. if not self._active_container_stack:
  236. return ""
  237. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = container_id)
  238. if containers:
  239. new_name = self._createUniqueName("quality", "", containers[0].getName(), catalog.i18nc("@label", "Custom profile"))
  240. new_container = InstanceContainer("")
  241. ## Copy all values
  242. new_container.deserialize(containers[0].serialize())
  243. new_container.setReadOnly(False)
  244. new_container.setName(new_name)
  245. new_container._id = new_name
  246. UM.Settings.ContainerRegistry.getInstance().addContainer(new_container)
  247. return new_name
  248. return ""
  249. @pyqtSlot(str, str)
  250. def renameQualityContainer(self, container_id, new_name):
  251. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = container_id, type = "quality")
  252. if containers:
  253. new_name = self._createUniqueName("quality", containers[0].getName(), new_name,
  254. catalog.i18nc("@label", "Custom profile"))
  255. if containers[0].getName() == new_name:
  256. # Nothing to do.
  257. return
  258. # As we also want the id of the container to be changed (so that profile name is the name of the file
  259. # on disk. We need to create a new instance and remove it (so the old file of the container is removed)
  260. # If we don't do that, we might get duplicates & other weird issues.
  261. new_container = InstanceContainer("")
  262. new_container.deserialize(containers[0].serialize())
  263. # Actually set the name
  264. new_container.setName(new_name)
  265. new_container._id = new_name # Todo: Fix proper id change function for this.
  266. # Add the "new" container.
  267. UM.Settings.ContainerRegistry.getInstance().addContainer(new_container)
  268. # Ensure that the renamed profile is saved -before- we remove the old profile.
  269. Application.getInstance().saveSettings()
  270. # Actually set & remove new / old quality.
  271. self.setActiveQuality(new_name)
  272. self.removeQualityContainer(containers[0].getId())
  273. @pyqtSlot(str)
  274. def removeQualityContainer(self, container_id):
  275. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = container_id)
  276. if not containers or not self._active_container_stack:
  277. return
  278. # If the container that is being removed is the currently active container, set another machine as the active container
  279. activate_new_container = container_id == self.activeQualityId
  280. UM.Settings.ContainerRegistry.getInstance().removeContainer(container_id)
  281. if activate_new_container:
  282. definition_id = "fdmprinter" if not self.filterQualityByMachine else self.activeDefinitionId
  283. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "quality", definition = definition_id)
  284. if containers:
  285. self.setActiveQuality(containers[0].getId())
  286. self.activeQualityChanged.emit()
  287. @pyqtSlot()
  288. def updateQualityContainerFromUserContainer(self):
  289. if not self._active_container_stack:
  290. return
  291. user_settings = self._active_container_stack.getTop()
  292. quality = self._active_container_stack.findContainer({"type": "quality"})
  293. for key in user_settings.getAllKeys():
  294. quality.setProperty(key, "value", user_settings.getProperty(key, "value"))
  295. self.clearUserSettings() # As all users settings are noq a quality, remove them.
  296. @pyqtSlot(str)
  297. def setActiveMaterial(self, material_id):
  298. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = material_id)
  299. if not containers or not self._active_container_stack:
  300. return
  301. old_material = self._active_container_stack.findContainer({"type":"material"})
  302. old_quality = self._active_container_stack.findContainer({"type": "quality"})
  303. if old_material:
  304. material_index = self._active_container_stack.getContainerIndex(old_material)
  305. self._active_container_stack.replaceContainer(material_index, containers[0])
  306. preferred_quality_name = None
  307. if old_quality:
  308. preferred_quality_name = old_quality.getName()
  309. self.setActiveQuality(self._updateQualityContainer(self._global_container_stack.getBottom(), containers[0], preferred_quality_name).id)
  310. @pyqtSlot(str)
  311. def setActiveVariant(self, variant_id):
  312. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = variant_id)
  313. if not containers or not self._active_container_stack:
  314. return
  315. old_variant = self._active_container_stack.findContainer({"type": "variant"})
  316. old_material = self._active_container_stack.findContainer({"type": "material"})
  317. if old_variant:
  318. variant_index = self._active_container_stack.getContainerIndex(old_variant)
  319. self._active_container_stack.replaceContainer(variant_index, containers[0])
  320. preferred_material = None
  321. if old_material:
  322. preferred_material = old_material.getId()
  323. self.setActiveMaterial(self._updateMaterialContainer(self._global_container_stack.getBottom(), containers[0], preferred_material).id)
  324. @pyqtSlot(str)
  325. def setActiveQuality(self, quality_id):
  326. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = quality_id)
  327. if not containers or not self._active_container_stack:
  328. return
  329. old_quality = self._active_container_stack.findContainer({"type": "quality"})
  330. if old_quality:
  331. quality_index = self._active_container_stack.getContainerIndex(old_quality)
  332. self._active_container_stack.replaceContainer(quality_index, containers[0])
  333. @pyqtProperty(str, notify = activeVariantChanged)
  334. def activeVariantName(self):
  335. if self._active_container_stack:
  336. variant = self._active_container_stack.findContainer({"type": "variant"})
  337. if variant:
  338. return variant.getName()
  339. return ""
  340. @pyqtProperty(str, notify = activeVariantChanged)
  341. def activeVariantId(self):
  342. if self._active_container_stack:
  343. variant = self._active_container_stack.findContainer({"type": "variant"})
  344. if variant:
  345. return variant.getId()
  346. return ""
  347. @pyqtProperty(str, notify = globalContainerChanged)
  348. def activeDefinitionId(self):
  349. if self._global_container_stack:
  350. definition = self._global_container_stack.getBottom()
  351. if definition:
  352. return definition.id
  353. return ""
  354. @pyqtSlot(str, str)
  355. def renameMachine(self, machine_id, new_name):
  356. containers = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = machine_id)
  357. if containers:
  358. new_name = self._createUniqueName("machine", containers[0].getName(), new_name, containers[0].getBottom().getName())
  359. containers[0].setName(new_name)
  360. self.globalContainerChanged.emit()
  361. @pyqtSlot(str)
  362. def removeMachine(self, machine_id):
  363. # If the machine that is being removed is the currently active machine, set another machine as the active machine
  364. activate_new_machine = (self._global_container_stack and self._global_container_stack.getId() == machine_id)
  365. current_settings_id = machine_id + "_current_settings"
  366. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = current_settings_id)
  367. for container in containers:
  368. UM.Settings.ContainerRegistry.getInstance().removeContainer(container.getId())
  369. UM.Settings.ContainerRegistry.getInstance().removeContainer(machine_id)
  370. if activate_new_machine:
  371. stacks = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(type = "machine")
  372. if stacks:
  373. Application.getInstance().setGlobalContainerStack(stacks[0])
  374. @pyqtProperty(bool, notify = globalContainerChanged)
  375. def hasMaterials(self):
  376. if self._global_container_stack:
  377. return bool(self._global_container_stack.getMetaDataEntry("has_materials", False))
  378. return False
  379. @pyqtProperty(bool, notify = globalContainerChanged)
  380. def hasVariants(self):
  381. if self._global_container_stack:
  382. return bool(self._global_container_stack.getMetaDataEntry("has_variants", False))
  383. return False
  384. @pyqtProperty(bool, notify = globalContainerChanged)
  385. def filterMaterialsByMachine(self):
  386. if self._global_container_stack:
  387. return bool(self._global_container_stack.getMetaDataEntry("has_machine_materials", False))
  388. return False
  389. @pyqtProperty(bool, notify = globalContainerChanged)
  390. def filterQualityByMachine(self):
  391. if self._global_container_stack:
  392. return bool(self._global_container_stack.getMetaDataEntry("has_machine_quality", False))
  393. return False
  394. @pyqtSlot(str, result = str)
  395. def getDefinitionByMachineId(self, machine_id):
  396. containers = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id=machine_id)
  397. if containers:
  398. return containers[0].getBottom().getId()
  399. def _updateVariantContainer(self, definition):
  400. if not definition.getMetaDataEntry("has_variants"):
  401. return self._empty_variant_container
  402. containers = []
  403. preferred_variant = definition.getMetaDataEntry("preferred_variant")
  404. if preferred_variant:
  405. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = definition.id, id = preferred_variant)
  406. if not containers:
  407. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = definition.id)
  408. if containers:
  409. return containers[0]
  410. return self._empty_variant_container
  411. def _updateMaterialContainer(self, definition, variant_container = None, preferred_material = None):
  412. if not definition.getMetaDataEntry("has_materials"):
  413. return self._empty_material_container
  414. search_criteria = { "type": "material" }
  415. if definition.getMetaDataEntry("has_machine_materials"):
  416. search_criteria["definition"] = definition.id
  417. if definition.getMetaDataEntry("has_variants") and variant_container:
  418. search_criteria["variant"] = variant_container.id
  419. else:
  420. search_criteria["definition"] = "fdmprinter"
  421. if not preferred_material:
  422. preferred_material = definition.getMetaDataEntry("preferred_material")
  423. if preferred_material:
  424. search_criteria["id"] = preferred_material
  425. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria)
  426. if containers:
  427. return containers[0]
  428. return self._empty_material_container
  429. def _updateQualityContainer(self, definition, material_container = None, preferred_quality_name = None):
  430. search_criteria = { "type": "quality" }
  431. if definition.getMetaDataEntry("has_machine_quality"):
  432. search_criteria["definition"] = definition.id
  433. if definition.getMetaDataEntry("has_materials") and material_container:
  434. search_criteria["material"] = material_container.id
  435. else:
  436. search_criteria["definition"] = "fdmprinter"
  437. if preferred_quality_name:
  438. search_criteria["name"] = preferred_quality_name
  439. else:
  440. preferred_quality = definition.getMetaDataEntry("preferred_quality")
  441. if preferred_quality:
  442. search_criteria["id"] = preferred_quality
  443. containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria)
  444. if containers:
  445. return containers[0]
  446. return self._empty_quality_container
  447. def createMachineManagerModel(engine, script_engine):
  448. return MachineManagerModel()