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