MachineActionManager.py 7.0 KB

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