ExtruderStack.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # Copyright (c) 2017 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from typing import Any, TYPE_CHECKING, Optional
  4. from UM.Decorators import override
  5. from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
  6. from UM.Settings.ContainerStack import ContainerStack
  7. from UM.Settings.ContainerRegistry import ContainerRegistry
  8. from UM.Settings.Interfaces import ContainerInterface, PropertyEvaluationContext
  9. from . import Exceptions
  10. from .CuraContainerStack import CuraContainerStack
  11. from .ExtruderManager import ExtruderManager
  12. if TYPE_CHECKING:
  13. from cura.Settings.GlobalStack import GlobalStack
  14. ## Represents an Extruder and its related containers.
  15. #
  16. #
  17. class ExtruderStack(CuraContainerStack):
  18. def __init__(self, container_id: str, *args, **kwargs):
  19. super().__init__(container_id, *args, **kwargs)
  20. self.addMetaDataEntry("type", "extruder_train") # For backward compatibility
  21. self.propertiesChanged.connect(self._onPropertiesChanged)
  22. ## Overridden from ContainerStack
  23. #
  24. # This will set the next stack and ensure that we register this stack as an extruder.
  25. @override(ContainerStack)
  26. def setNextStack(self, stack: ContainerStack) -> None:
  27. super().setNextStack(stack)
  28. stack.addExtruder(self)
  29. self.addMetaDataEntry("machine", stack.id)
  30. # For backward compatibility: Register the extruder with the Extruder Manager
  31. ExtruderManager.getInstance().registerExtruder(self, stack.id)
  32. @override(ContainerStack)
  33. def getNextStack(self) -> Optional["GlobalStack"]:
  34. return super().getNextStack()
  35. @classmethod
  36. def getLoadingPriority(cls) -> int:
  37. return 3
  38. ## Overridden from ContainerStack
  39. #
  40. # It will perform a few extra checks when trying to get properties.
  41. #
  42. # The two extra checks it currently does is to ensure a next stack is set and to bypass
  43. # the extruder when the property is not settable per extruder.
  44. #
  45. # \throws Exceptions.NoGlobalStackError Raised when trying to get a property from an extruder without
  46. # having a next stack set.
  47. @override(ContainerStack)
  48. def getProperty(self, key: str, property_name: str, context: Optional[PropertyEvaluationContext] = None) -> Any:
  49. if not self._next_stack:
  50. raise Exceptions.NoGlobalStackError("Extruder {id} is missing the next stack!".format(id = self.id))
  51. if context is None:
  52. context = PropertyEvaluationContext()
  53. context.pushContainer(self)
  54. if not super().getProperty(key, "settable_per_extruder", context):
  55. result = self.getNextStack().getProperty(key, property_name, context)
  56. context.popContainer()
  57. return result
  58. limit_to_extruder = super().getProperty(key, "limit_to_extruder", context)
  59. if limit_to_extruder is not None:
  60. limit_to_extruder = str(limit_to_extruder)
  61. if (limit_to_extruder is not None and limit_to_extruder != "-1") and self.getMetaDataEntry("position") != str(limit_to_extruder):
  62. if str(limit_to_extruder) in self.getNextStack().extruders:
  63. result = self.getNextStack().extruders[str(limit_to_extruder)].getProperty(key, property_name, context)
  64. if result is not None:
  65. context.popContainer()
  66. return result
  67. result = super().getProperty(key, property_name, context)
  68. context.popContainer()
  69. return result
  70. @override(CuraContainerStack)
  71. def _getMachineDefinition(self) -> ContainerInterface:
  72. if not self.getNextStack():
  73. raise Exceptions.NoGlobalStackError("Extruder {id} is missing the next stack!".format(id = self.id))
  74. return self.getNextStack()._getMachineDefinition()
  75. @override(CuraContainerStack)
  76. def deserialize(self, contents: str) -> None:
  77. super().deserialize(contents)
  78. stacks = ContainerRegistry.getInstance().findContainerStacks(id=self.getMetaDataEntry("machine", ""))
  79. if stacks:
  80. self.setNextStack(stacks[0])
  81. def _onPropertiesChanged(self, key, properties):
  82. # When there is a setting that is not settable per extruder that depends on a value from a setting that is,
  83. # we do not always get properly informed that we should re-evaluate the setting. So make sure to indicate
  84. # something changed for those settings.
  85. if not self.getNextStack():
  86. return #There are no global settings to depend on.
  87. definitions = self.getNextStack().definition.findDefinitions(key = key)
  88. if definitions:
  89. has_global_dependencies = False
  90. for relation in definitions[0].relations:
  91. if not getattr(relation.target, "settable_per_extruder", True):
  92. has_global_dependencies = True
  93. break
  94. if has_global_dependencies:
  95. self.getNextStack().propertiesChanged.emit(key, properties)
  96. extruder_stack_mime = MimeType(
  97. name = "application/x-cura-extruderstack",
  98. comment = "Cura Extruder Stack",
  99. suffixes = ["extruder.cfg"]
  100. )
  101. MimeTypeDatabase.addMimeType(extruder_stack_mime)
  102. ContainerRegistry.addContainerTypeByName(ExtruderStack, "extruder_stack", extruder_stack_mime.name)