ContainerTree.py 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. # Copyright (c) 2019 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from UM.Logger import Logger
  4. from UM.Settings.ContainerRegistry import ContainerRegistry # To listen to containers being added.
  5. from UM.Settings.DefinitionContainer import DefinitionContainer
  6. from UM.Settings.Interfaces import ContainerInterface
  7. import cura.CuraApplication # Imported like this to prevent circular dependencies.
  8. from UM.Signal import Signal
  9. from cura.Machines.MachineNode import MachineNode
  10. from typing import Dict, List, TYPE_CHECKING
  11. import time
  12. if TYPE_CHECKING:
  13. from cura.Machines.QualityGroup import QualityGroup
  14. ## This class contains a look-up tree for which containers are available at
  15. # which stages of configuration.
  16. #
  17. # The tree starts at the machine definitions. For every distinct definition
  18. # there will be one machine node here.
  19. #
  20. # All of the fallbacks for material choices, quality choices, etc. should be
  21. # encoded in this tree. There must always be at least one child node (for
  22. # nodes that have children) but that child node may be a node representing the
  23. # empty instance container.
  24. class ContainerTree:
  25. __instance = None
  26. @classmethod
  27. def getInstance(cls):
  28. if cls.__instance is None:
  29. cls.__instance = ContainerTree()
  30. return cls.__instance
  31. def __init__(self) -> None:
  32. self.machines = {} # type: Dict[str, MachineNode] # Mapping from definition ID to machine nodes.
  33. self.materialsChanged = Signal() # Emitted when any of the material nodes in the tree got changed.
  34. container_registry = ContainerRegistry.getInstance()
  35. container_registry.containerAdded.connect(self._machineAdded)
  36. self._loadAll()
  37. ## Get the quality groups available for the currently activated printer.
  38. #
  39. # This contains all quality groups, enabled or disabled. To check whether
  40. # the quality group can be activated, test for the
  41. # ``QualityGroup.is_available`` property.
  42. # \return For every quality type, one quality group.
  43. def getCurrentQualityGroups(self) -> Dict[str, "QualityGroup"]:
  44. global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
  45. if global_stack is None:
  46. return {}
  47. variant_names = [extruder.variant.getName() for extruder in global_stack.extruders.values()]
  48. material_bases = [extruder.material.getMetaDataEntry("base_file") for extruder in global_stack.extruders.values()]
  49. extruder_enabled = [extruder.isEnabled for extruder in global_stack.extruders.values()]
  50. return self.machines[global_stack.definition.getId()].getQualityGroups(variant_names, material_bases, extruder_enabled)
  51. ## Builds the initial container tree.
  52. def _loadAll(self):
  53. Logger.log("i", "Building container tree.")
  54. start_time = time.time()
  55. all_stacks = ContainerRegistry.getInstance().findContainerStacks()
  56. for stack in all_stacks:
  57. definition_id = stack.definition.getId()
  58. if definition_id not in self.machines:
  59. self.machines[definition_id] = MachineNode(definition_id)
  60. self.machines[definition_id].materialsChanged.connect(self.materialsChanged)
  61. Logger.log("d", "Building the container tree took %s seconds", time.time() - start_time)
  62. ## When a printer gets added, we need to build up the tree for that container.
  63. def _machineAdded(self, definition_container: ContainerInterface):
  64. if not isinstance(definition_container, DefinitionContainer):
  65. return # Not our concern.
  66. definition_id = definition_container.getId()
  67. if definition_id in self.machines:
  68. return # Already have this definition ID.
  69. self.machines[definition_id] = MachineNode(definition_id)
  70. self.machines[definition_id].materialsChanged.connect(self.materialsChanged)