MachineActionManager.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from typing import TYPE_CHECKING, Optional, List, Set, Dict
  4. from PyQt5.QtCore import QObject
  5. from UM.FlameProfiler import pyqtSlot
  6. from UM.Logger import Logger
  7. from UM.PluginRegistry import PluginRegistry # So MachineAction can be added as plugin type
  8. if TYPE_CHECKING:
  9. from cura.CuraApplication import CuraApplication
  10. from cura.Settings.GlobalStack import GlobalStack
  11. from cura.MachineAction import MachineAction
  12. ## Raised when trying to add an unknown machine action as a required action
  13. class UnknownMachineActionError(Exception):
  14. pass
  15. ## Raised when trying to add a machine action that does not have an unique key.
  16. class NotUniqueMachineActionError(Exception):
  17. pass
  18. class MachineActionManager(QObject):
  19. def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
  20. super().__init__(parent = parent)
  21. self._application = application
  22. self._container_registry = self._application.getContainerRegistry()
  23. # Keeps track of which machines have already been processed so we don't do that again.
  24. self._definition_ids_with_default_actions_added = set() # type: Set[str]
  25. # Dict of all known machine actions
  26. self._machine_actions = {} # type: Dict[str, MachineAction]
  27. # Dict of all required actions by definition ID
  28. self._required_actions = {} # type: Dict[str, List[MachineAction]]
  29. # Dict of all supported actions by definition ID
  30. self._supported_actions = {} # type: Dict[str, List[MachineAction]]
  31. # Dict of all actions that need to be done when first added by definition ID
  32. self._first_start_actions = {} # type: Dict[str, List[MachineAction]]
  33. def initialize(self) -> None:
  34. # Add machine_action as plugin type
  35. PluginRegistry.addType("machine_action", self.addMachineAction)
  36. # Adds all default machine actions that are defined in the machine definition for the given machine.
  37. def addDefaultMachineActions(self, global_stack: "GlobalStack") -> None:
  38. definition_id = global_stack.definition.getId()
  39. if definition_id in self._definition_ids_with_default_actions_added:
  40. Logger.log("i", "Default machine actions have been added for machine definition [%s], do nothing.",
  41. definition_id)
  42. return
  43. supported_actions = global_stack.getMetaDataEntry("supported_actions", [])
  44. for action_key in supported_actions:
  45. self.addSupportedAction(definition_id, action_key)
  46. required_actions = global_stack.getMetaDataEntry("required_actions", [])
  47. for action_key in required_actions:
  48. self.addRequiredAction(definition_id, action_key)
  49. first_start_actions = global_stack.getMetaDataEntry("first_start_actions", [])
  50. for action_key in first_start_actions:
  51. self.addFirstStartAction(definition_id, action_key)
  52. self._definition_ids_with_default_actions_added.add(definition_id)
  53. Logger.log("i", "Default machine actions added for machine definition [%s]", definition_id)
  54. ## Add a required action to a machine
  55. # Raises an exception when the action is not recognised.
  56. def addRequiredAction(self, definition_id: str, action_key: str) -> None:
  57. if action_key in self._machine_actions:
  58. if definition_id in self._required_actions:
  59. if self._machine_actions[action_key] not in self._required_actions[definition_id]:
  60. self._required_actions[definition_id].append(self._machine_actions[action_key])
  61. else:
  62. self._required_actions[definition_id] = [self._machine_actions[action_key]]
  63. else:
  64. raise UnknownMachineActionError("Action %s, which is required for %s is not known." % (action_key, definition_id))
  65. ## Add a supported action to a machine.
  66. def addSupportedAction(self, definition_id: str, action_key: str) -> None:
  67. if action_key in self._machine_actions:
  68. if definition_id in self._supported_actions:
  69. if self._machine_actions[action_key] not in self._supported_actions[definition_id]:
  70. self._supported_actions[definition_id].append(self._machine_actions[action_key])
  71. else:
  72. self._supported_actions[definition_id] = [self._machine_actions[action_key]]
  73. else:
  74. Logger.log("w", "Unable to add %s to %s, as the action is not recognised", action_key, definition_id)
  75. ## Add an action to the first start list of a machine.
  76. def addFirstStartAction(self, definition_id: str, action_key: str) -> None:
  77. if action_key in self._machine_actions:
  78. if definition_id in self._first_start_actions:
  79. self._first_start_actions[definition_id].append(self._machine_actions[action_key])
  80. else:
  81. self._first_start_actions[definition_id] = [self._machine_actions[action_key]]
  82. else:
  83. Logger.log("w", "Unable to add %s to %s, as the action is not recognised", action_key, definition_id)
  84. ## Add a (unique) MachineAction
  85. # if the Key of the action is not unique, an exception is raised.
  86. def addMachineAction(self, action: "MachineAction") -> None:
  87. if action.getKey() not in self._machine_actions:
  88. self._machine_actions[action.getKey()] = action
  89. else:
  90. raise NotUniqueMachineActionError("MachineAction with key %s was already added. Actions must have unique keys.", action.getKey())
  91. ## Get all actions supported by given machine
  92. # \param definition_id The ID of the definition you want the supported actions of
  93. # \returns set of supported actions.
  94. @pyqtSlot(str, result = "QVariantList")
  95. def getSupportedActions(self, definition_id: str) -> List["MachineAction"]:
  96. if definition_id in self._supported_actions:
  97. return list(self._supported_actions[definition_id])
  98. else:
  99. return list()
  100. ## Get all actions required by given machine
  101. # \param definition_id The ID of the definition you want the required actions of
  102. # \returns set of required actions.
  103. def getRequiredActions(self, definition_id: str) -> List["MachineAction"]:
  104. if definition_id in self._required_actions:
  105. return self._required_actions[definition_id]
  106. else:
  107. return list()
  108. ## Get all actions that need to be performed upon first start of a given machine.
  109. # Note that contrary to required / supported actions a list is returned (as it could be required to run the same
  110. # action multiple times).
  111. # \param definition_id The ID of the definition that you want to get the "on added" actions for.
  112. # \returns List of actions.
  113. @pyqtSlot(str, result = "QVariantList")
  114. def getFirstStartActions(self, definition_id: str) -> List["MachineAction"]:
  115. if definition_id in self._first_start_actions:
  116. return self._first_start_actions[definition_id]
  117. else:
  118. return []
  119. ## Remove Machine action from manager
  120. # \param action to remove
  121. def removeMachineAction(self, action: "MachineAction") -> None:
  122. try:
  123. del self._machine_actions[action.getKey()]
  124. except KeyError:
  125. Logger.log("w", "Trying to remove MachineAction (%s) that was already removed", action.getKey())
  126. ## Get MachineAction by key
  127. # \param key String of key to select
  128. # \return Machine action if found, None otherwise
  129. def getMachineAction(self, key: str) -> Optional["MachineAction"]:
  130. if key in self._machine_actions:
  131. return self._machine_actions[key]
  132. else:
  133. return None