mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-06-26 01:15:28 -06:00
Remove trailing whitespace from Python files
This commit is contained in:
parent
1e33360c35
commit
89f0970a88
157 changed files with 562 additions and 562 deletions
|
@ -13,7 +13,7 @@ import sys
|
|||
|
||||
def find_json_files(work_dir: str) -> list:
|
||||
"""Finds all JSON files in the given directory recursively and returns a list of those files in absolute paths.
|
||||
|
||||
|
||||
:param work_dir: The directory to look for JSON files recursively.
|
||||
:return: A list of JSON files in absolute paths that are found in the given directory.
|
||||
"""
|
||||
|
@ -28,7 +28,7 @@ def find_json_files(work_dir: str) -> list:
|
|||
|
||||
def remove_entries_from_json_file(file_path: str, entries: list) -> None:
|
||||
"""Removes the given entries from the given JSON file. The file will modified in-place.
|
||||
|
||||
|
||||
:param file_path: The JSON file to modify.
|
||||
:param entries: A list of strings as entries to remove.
|
||||
:return: None
|
||||
|
|
|
@ -10,9 +10,9 @@ if TYPE_CHECKING:
|
|||
|
||||
class Backups:
|
||||
"""The back-ups API provides a version-proof bridge between Cura's
|
||||
|
||||
|
||||
BackupManager and plug-ins that hook into it.
|
||||
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: python
|
||||
|
@ -28,7 +28,7 @@ class Backups:
|
|||
|
||||
def createBackup(self) -> Tuple[Optional[bytes], Optional[Dict[str, Any]]]:
|
||||
"""Create a new back-up using the BackupsManager.
|
||||
|
||||
|
||||
:return: Tuple containing a ZIP file with the back-up data and a dict with metadata about the back-up.
|
||||
"""
|
||||
|
||||
|
@ -36,7 +36,7 @@ class Backups:
|
|||
|
||||
def restoreBackup(self, zip_file: bytes, meta_data: Dict[str, Any]) -> None:
|
||||
"""Restore a back-up using the BackupsManager.
|
||||
|
||||
|
||||
:param zip_file: A ZIP file containing the actual back-up data.
|
||||
:param meta_data: Some metadata needed for restoring a back-up, like the Cura version number.
|
||||
"""
|
||||
|
|
|
@ -10,9 +10,9 @@ if TYPE_CHECKING:
|
|||
class Settings:
|
||||
"""The Interface.Settings API provides a version-proof bridge
|
||||
between Cura's
|
||||
|
||||
|
||||
(currently) sidebar UI and plug-ins that hook into it.
|
||||
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: python
|
||||
|
@ -34,7 +34,7 @@ class Settings:
|
|||
|
||||
def addContextMenuItem(self, menu_item: dict) -> None:
|
||||
"""Add items to the sidebar context menu.
|
||||
|
||||
|
||||
:param menu_item: dict containing the menu item to add.
|
||||
"""
|
||||
|
||||
|
@ -42,7 +42,7 @@ class Settings:
|
|||
|
||||
def getContextMenuItems(self) -> list:
|
||||
"""Get all custom items currently added to the sidebar context menu.
|
||||
|
||||
|
||||
:return: List containing all custom context menu items.
|
||||
"""
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@ if TYPE_CHECKING:
|
|||
|
||||
class Interface:
|
||||
"""The Interface class serves as a common root for the specific API
|
||||
|
||||
|
||||
methods for each interface element.
|
||||
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: python
|
||||
|
|
|
@ -23,7 +23,7 @@ class ShapeArray:
|
|||
@classmethod
|
||||
def fromPolygon(cls, vertices: numpy.array, scale: float = 1) -> "ShapeArray":
|
||||
"""Instantiate from a bunch of vertices
|
||||
|
||||
|
||||
:param vertices:
|
||||
:param scale: scale the coordinates
|
||||
:return: a shape array instantiated from a bunch of vertices
|
||||
|
@ -52,7 +52,7 @@ class ShapeArray:
|
|||
@classmethod
|
||||
def fromNode(cls, node: "SceneNode", min_offset: float, scale: float = 0.5, include_children: bool = False) -> Tuple[Optional["ShapeArray"], Optional["ShapeArray"]]:
|
||||
"""Instantiate an offset and hull ShapeArray from a scene node.
|
||||
|
||||
|
||||
:param node: source node where the convex hull must be present
|
||||
:param min_offset: offset for the offset ShapeArray
|
||||
:param scale: scale the coordinates
|
||||
|
@ -100,7 +100,7 @@ class ShapeArray:
|
|||
@classmethod
|
||||
def arrayFromPolygon(cls, shape: Tuple[int, int], vertices: numpy.array) -> numpy.array:
|
||||
"""Create :py:class:`numpy.ndarray` with dimensions defined by shape
|
||||
|
||||
|
||||
Fills polygon defined by vertices with ones, all other values zero
|
||||
Only works correctly for convex hull vertices
|
||||
Originally from: `Stackoverflow - generating a filled polygon inside a numpy array <https://stackoverflow.com/questions/37117878/generating-a-filled-polygon-inside-a-numpy-array>`_
|
||||
|
@ -128,7 +128,7 @@ class ShapeArray:
|
|||
@classmethod
|
||||
def _check(cls, p1: numpy.array, p2: numpy.array, base_array: numpy.array) -> Optional[numpy.array]:
|
||||
"""Return indices that mark one side of the line, used by arrayFromPolygon
|
||||
|
||||
|
||||
Uses the line defined by p1 and p2 to check array of
|
||||
input indices against interpolated value
|
||||
Returns boolean array, with True inside and False outside of shape
|
||||
|
|
|
@ -20,7 +20,7 @@ if TYPE_CHECKING:
|
|||
|
||||
class Backup:
|
||||
"""The back-up class holds all data about a back-up.
|
||||
|
||||
|
||||
It is also responsible for reading and writing the zip file to the user data folder.
|
||||
"""
|
||||
|
||||
|
@ -68,7 +68,7 @@ class Backup:
|
|||
material_count = len([s for s in files if "materials/" in s]) - 1
|
||||
profile_count = len([s for s in files if "quality_changes/" in s]) - 1
|
||||
plugin_count = len([s for s in files if "plugin.json" in s])
|
||||
|
||||
|
||||
# Store the archive and metadata so the BackupManager can fetch them when needed.
|
||||
self.zip_file = buffer.getvalue()
|
||||
self.meta_data = {
|
||||
|
@ -81,7 +81,7 @@ class Backup:
|
|||
|
||||
def _makeArchive(self, buffer: "io.BytesIO", root_path: str) -> Optional[ZipFile]:
|
||||
"""Make a full archive from the given root path with the given name.
|
||||
|
||||
|
||||
:param root_path: The root directory to archive recursively.
|
||||
:return: The archive as bytes.
|
||||
"""
|
||||
|
@ -111,7 +111,7 @@ class Backup:
|
|||
|
||||
def restore(self) -> bool:
|
||||
"""Restore this back-up.
|
||||
|
||||
|
||||
:return: Whether we had success or not.
|
||||
"""
|
||||
|
||||
|
@ -151,7 +151,7 @@ class Backup:
|
|||
@staticmethod
|
||||
def _extractArchive(archive: "ZipFile", target_path: str) -> bool:
|
||||
"""Extract the whole archive to the given target path.
|
||||
|
||||
|
||||
:param archive: The archive as ZipFile.
|
||||
:param target_path: The target path.
|
||||
:return: Whether we had success or not.
|
||||
|
|
|
@ -166,7 +166,7 @@ class BuildVolume(SceneNode):
|
|||
|
||||
def _updateNodeListeners(self, node: SceneNode):
|
||||
"""Updates the listeners that listen for changes in per-mesh stacks.
|
||||
|
||||
|
||||
:param node: The node for which the decorators changed.
|
||||
"""
|
||||
|
||||
|
@ -587,7 +587,7 @@ class BuildVolume(SceneNode):
|
|||
def _calculateExtraZClearance(self, extruders: List["ContainerStack"]) -> float:
|
||||
if not self._global_container_stack:
|
||||
return 0
|
||||
|
||||
|
||||
extra_z = 0.0
|
||||
for extruder in extruders:
|
||||
if extruder.getProperty("retraction_hop_enabled", "value"):
|
||||
|
@ -728,7 +728,7 @@ class BuildVolume(SceneNode):
|
|||
|
||||
def _updateDisallowedAreasAndRebuild(self):
|
||||
"""Calls :py:meth:`cura.BuildVolume._updateDisallowedAreas` and makes sure the changes appear in the scene.
|
||||
|
||||
|
||||
This is required for a signal to trigger the update in one go. The
|
||||
:py:meth:`cura.BuildVolume._updateDisallowedAreas` method itself shouldn't call
|
||||
:py:meth:`cura.BuildVolume.rebuild`, since there may be other changes before it needs to be rebuilt,
|
||||
|
@ -798,9 +798,9 @@ class BuildVolume(SceneNode):
|
|||
|
||||
def _computeDisallowedAreasPrinted(self, used_extruders):
|
||||
"""Computes the disallowed areas for objects that are printed with print features.
|
||||
|
||||
|
||||
This means that the brim, travel avoidance and such will be applied to these features.
|
||||
|
||||
|
||||
:return: A dictionary with for each used extruder ID the disallowed areas where that extruder may not print.
|
||||
"""
|
||||
|
||||
|
@ -843,10 +843,10 @@ class BuildVolume(SceneNode):
|
|||
|
||||
def _computeDisallowedAreasPrimeBlob(self, border_size: float, used_extruders: List["ExtruderStack"]) -> Dict[str, List[Polygon]]:
|
||||
"""Computes the disallowed areas for the prime blobs.
|
||||
|
||||
|
||||
These are special because they are not subject to things like brim or travel avoidance. They do get a dilute
|
||||
with the border size though because they may not intersect with brims and such of other objects.
|
||||
|
||||
|
||||
:param border_size: The size with which to offset the disallowed areas due to skirt, brim, travel avoid distance
|
||||
, etc.
|
||||
:param used_extruders: The extruder stacks to generate disallowed areas for.
|
||||
|
@ -882,7 +882,7 @@ class BuildVolume(SceneNode):
|
|||
|
||||
def _computeDisallowedAreasStatic(self, border_size:float, used_extruders: List["ExtruderStack"]) -> Dict[str, List[Polygon]]:
|
||||
"""Computes the disallowed areas that are statically placed in the machine.
|
||||
|
||||
|
||||
It computes different disallowed areas depending on the offset of the extruder. The resulting dictionary will
|
||||
therefore have an entry for each extruder that is used.
|
||||
|
||||
|
@ -1024,9 +1024,9 @@ class BuildVolume(SceneNode):
|
|||
|
||||
def _getSettingFromAllExtruders(self, setting_key: str) -> List[Any]:
|
||||
"""Private convenience function to get a setting from every extruder.
|
||||
|
||||
|
||||
For single extrusion machines, this gets the setting from the global stack.
|
||||
|
||||
|
||||
:return: A sequence of setting values, one for each extruder.
|
||||
"""
|
||||
|
||||
|
@ -1116,7 +1116,7 @@ class BuildVolume(SceneNode):
|
|||
|
||||
def getEdgeDisallowedSize(self):
|
||||
"""Calculate the disallowed radius around the edge.
|
||||
|
||||
|
||||
This disallowed radius is to allow for space around the models that is not part of the collision radius,
|
||||
such as bed adhesion (skirt/brim/raft) and travel avoid distance.
|
||||
"""
|
||||
|
|
|
@ -237,7 +237,7 @@ class CrashHandler:
|
|||
scope.set_tag("locale_os", self.data["locale_os"])
|
||||
scope.set_tag("locale_cura", self.cura_locale)
|
||||
scope.set_tag("is_enterprise", ApplicationMetadata.IsEnterpriseVersion)
|
||||
|
||||
|
||||
scope.set_user({"id": str(uuid.getnode())})
|
||||
|
||||
return group
|
||||
|
|
|
@ -78,7 +78,7 @@ class CuraActions(QObject):
|
|||
@pyqtSlot(int)
|
||||
def multiplySelection(self, count: int) -> None:
|
||||
"""Multiply all objects in the selection
|
||||
|
||||
|
||||
:param count: The number of times to multiply the selection.
|
||||
"""
|
||||
|
||||
|
@ -114,7 +114,7 @@ class CuraActions(QObject):
|
|||
@pyqtSlot(str)
|
||||
def setExtruderForSelection(self, extruder_id: str) -> None:
|
||||
"""Set the extruder that should be used to print the selection.
|
||||
|
||||
|
||||
:param extruder_id: The ID of the extruder stack to use for the selected objects.
|
||||
"""
|
||||
|
||||
|
|
|
@ -730,7 +730,7 @@ class CuraApplication(QtApplication):
|
|||
|
||||
def _loadPlugins(self) -> None:
|
||||
"""Handle loading of all plugin types (and the backend explicitly)
|
||||
|
||||
|
||||
:py:class:`Uranium.UM.PluginRegistry`
|
||||
"""
|
||||
|
||||
|
@ -759,7 +759,7 @@ class CuraApplication(QtApplication):
|
|||
|
||||
def _setLoadingHint(self, hint: str):
|
||||
"""Set a short, user-friendly hint about current loading status.
|
||||
|
||||
|
||||
The way this message is displayed depends on application state
|
||||
"""
|
||||
|
||||
|
@ -1010,7 +1010,7 @@ class CuraApplication(QtApplication):
|
|||
|
||||
def getMachineActionManager(self, *args: Any) -> MachineActionManager.MachineActionManager:
|
||||
"""Get the machine action manager
|
||||
|
||||
|
||||
We ignore any *args given to this, as we also register the machine manager as qml singleton.
|
||||
It wants to give this function an engine and script engine, but we don't care about that.
|
||||
"""
|
||||
|
@ -1068,7 +1068,7 @@ class CuraApplication(QtApplication):
|
|||
|
||||
def registerObjects(self, engine):
|
||||
"""Registers objects for the QML engine to use.
|
||||
|
||||
|
||||
:param engine: The QML engine.
|
||||
"""
|
||||
|
||||
|
@ -1391,7 +1391,7 @@ class CuraApplication(QtApplication):
|
|||
|
||||
def arrange(self, nodes: List[SceneNode], fixed_nodes: List[SceneNode]) -> None:
|
||||
"""Arrange a set of nodes given a set of fixed nodes
|
||||
|
||||
|
||||
:param nodes: nodes that we have to place
|
||||
:param fixed_nodes: nodes that are placed in the arranger before finding spots for nodes
|
||||
"""
|
||||
|
@ -1685,7 +1685,7 @@ class CuraApplication(QtApplication):
|
|||
@pyqtSlot(str, "QVariant")
|
||||
def addAdditionalComponent(self, area_id: str, component):
|
||||
"""Add a component to a list of components to be reparented to another area in the GUI.
|
||||
|
||||
|
||||
The actual reparenting is done by the area itself.
|
||||
:param area_id: dentifying name of the area to which the component should be reparented
|
||||
:param (QQuickComponent) component: The component that should be reparented
|
||||
|
@ -1707,7 +1707,7 @@ class CuraApplication(QtApplication):
|
|||
@pyqtSlot(QUrl)
|
||||
def readLocalFile(self, file: QUrl, project_mode: Optional[str] = None):
|
||||
"""Open a local file
|
||||
|
||||
|
||||
:param project_mode: How to handle project files. Either None(default): Follow user preference, "open_as_model"
|
||||
or "open_as_project". This parameter is only considered if the file is a project file.
|
||||
"""
|
||||
|
|
|
@ -76,7 +76,7 @@ class Layer:
|
|||
|
||||
def createMeshOrJumps(self, make_mesh: bool) -> MeshData:
|
||||
builder = MeshBuilder()
|
||||
|
||||
|
||||
line_count = 0
|
||||
if make_mesh:
|
||||
for polygon in self._polygons:
|
||||
|
@ -87,7 +87,7 @@ class Layer:
|
|||
|
||||
# Reserve the necessary space for the data upfront
|
||||
builder.reserveFaceAndVertexCount(2 * line_count, 4 * line_count)
|
||||
|
||||
|
||||
for polygon in self._polygons:
|
||||
# Filter out the types of lines we are not interested in depending on whether we are drawing the mesh or the jumps.
|
||||
index_mask = numpy.logical_not(polygon.jumpMask) if make_mesh else polygon.jumpMask
|
||||
|
@ -96,7 +96,7 @@ class Layer:
|
|||
points = numpy.concatenate((polygon.data[:-1], polygon.data[1:]), 1)[index_mask.ravel()]
|
||||
# Line types of the points we want to draw
|
||||
line_types = polygon.types[index_mask]
|
||||
|
||||
|
||||
# Shift the z-axis according to previous implementation.
|
||||
if make_mesh:
|
||||
points[polygon.isInfillOrSkinType(line_types), 1::3] -= 0.01
|
||||
|
@ -118,5 +118,5 @@ class Layer:
|
|||
f_colors = numpy.repeat(polygon.mapLineTypeToColor(line_types), 4, 0)
|
||||
|
||||
builder.addFacesWithColor(f_points, f_indices, f_colors)
|
||||
|
||||
|
||||
return builder.build()
|
|
@ -5,7 +5,7 @@ from UM.Mesh.MeshData import MeshData
|
|||
|
||||
class LayerData(MeshData):
|
||||
"""Class to holds the layer mesh and information about the layers.
|
||||
|
||||
|
||||
Immutable, use :py:class:`cura.LayerDataBuilder.LayerDataBuilder` to create one of these.
|
||||
"""
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class LayerDataBuilder(MeshBuilder):
|
|||
|
||||
def build(self, material_color_map, line_type_brightness = 1.0):
|
||||
"""Return the layer data as :py:class:`cura.LayerData.LayerData`.
|
||||
|
||||
|
||||
:param material_color_map: [r, g, b, a] for each extruder row.
|
||||
:param line_type_brightness: compatibility layer view uses line type brightness of 0.5
|
||||
"""
|
||||
|
|
|
@ -62,21 +62,21 @@ class LayerPolygon:
|
|||
# re-used and can save alot of memory usage.
|
||||
self._color_map = LayerPolygon.getColorMap()
|
||||
self._colors = self._color_map[self._types] # type: numpy.ndarray
|
||||
|
||||
|
||||
# When type is used as index returns true if type == LayerPolygon.InfillType or type == LayerPolygon.SkinType or type == LayerPolygon.SupportInfillType
|
||||
# Should be generated in better way, not hardcoded.
|
||||
self._is_infill_or_skin_type_map = numpy.array([0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0], dtype = numpy.bool)
|
||||
|
||||
|
||||
self._build_cache_line_mesh_mask = None # type: Optional[numpy.ndarray]
|
||||
self._build_cache_needed_points = None # type: Optional[numpy.ndarray]
|
||||
|
||||
|
||||
def buildCache(self) -> None:
|
||||
# For the line mesh we do not draw Infill or Jumps. Therefore those lines are filtered out.
|
||||
self._build_cache_line_mesh_mask = numpy.ones(self._jump_mask.shape, dtype = bool)
|
||||
mesh_line_count = numpy.sum(self._build_cache_line_mesh_mask)
|
||||
self._index_begin = 0
|
||||
self._index_end = mesh_line_count
|
||||
|
||||
|
||||
self._build_cache_needed_points = numpy.ones((len(self._types), 2), dtype = numpy.bool)
|
||||
# Only if the type of line segment changes do we need to add an extra vertex to change colors
|
||||
self._build_cache_needed_points[1:, 0][:, numpy.newaxis] = self._types[1:] != self._types[:-1]
|
||||
|
@ -88,9 +88,9 @@ class LayerPolygon:
|
|||
|
||||
def build(self, vertex_offset: int, index_offset: int, vertices: numpy.ndarray, colors: numpy.ndarray, line_dimensions: numpy.ndarray, feedrates: numpy.ndarray, extruders: numpy.ndarray, line_types: numpy.ndarray, indices: numpy.ndarray) -> None:
|
||||
"""Set all the arrays provided by the function caller, representing the LayerPolygon
|
||||
|
||||
|
||||
The arrays are either by vertex or by indices.
|
||||
|
||||
|
||||
:param vertex_offset: determines where to start and end filling the arrays
|
||||
:param index_offset: determines where to start and end filling the arrays
|
||||
:param vertices: vertex numpy array to be filled
|
||||
|
@ -111,16 +111,16 @@ class LayerPolygon:
|
|||
|
||||
line_mesh_mask = self._build_cache_line_mesh_mask
|
||||
needed_points_list = self._build_cache_needed_points
|
||||
|
||||
|
||||
# Index to the points we need to represent the line mesh. This is constructed by generating simple
|
||||
# start and end points for each line. For line segment n these are points n and n+1. Row n reads [n n+1]
|
||||
# Then then the indices for the points we don't need are thrown away based on the pre-calculated list.
|
||||
index_list = ( numpy.arange(len(self._types)).reshape((-1, 1)) + numpy.array([[0, 1]]) ).reshape((-1, 1))[needed_points_list.reshape((-1, 1))]
|
||||
|
||||
|
||||
# The relative values of begin and end indices have already been set in buildCache, so we only need to offset them to the parents offset.
|
||||
self._vertex_begin += vertex_offset
|
||||
self._vertex_end += vertex_offset
|
||||
|
||||
|
||||
# Points are picked based on the index list to get the vertices needed.
|
||||
vertices[self._vertex_begin:self._vertex_end, :] = self._data[index_list, :]
|
||||
|
||||
|
@ -142,14 +142,14 @@ class LayerPolygon:
|
|||
# The relative values of begin and end indices have already been set in buildCache, so we only need to offset them to the parents offset.
|
||||
self._index_begin += index_offset
|
||||
self._index_end += index_offset
|
||||
|
||||
|
||||
indices[self._index_begin:self._index_end, :] = numpy.arange(self._index_end-self._index_begin, dtype = numpy.int32).reshape((-1, 1))
|
||||
# When the line type changes the index needs to be increased by 2.
|
||||
indices[self._index_begin:self._index_end, :] += numpy.cumsum(needed_points_list[line_mesh_mask.ravel(), 0], dtype = numpy.int32).reshape((-1, 1))
|
||||
# Each line segment goes from it's starting point p to p+1, offset by the vertex index.
|
||||
# The -1 is to compensate for the neccecarily True value of needed_points_list[0,0] which causes an unwanted +1 in cumsum above.
|
||||
indices[self._index_begin:self._index_end, :] += numpy.array([self._vertex_begin - 1, self._vertex_begin])
|
||||
|
||||
|
||||
self._build_cache_line_mesh_mask = None
|
||||
self._build_cache_needed_points = None
|
||||
|
||||
|
@ -195,7 +195,7 @@ class LayerPolygon:
|
|||
@property
|
||||
def lineFeedrates(self):
|
||||
return self._line_feedrates
|
||||
|
||||
|
||||
@property
|
||||
def jumpMask(self):
|
||||
return self._jump_mask
|
||||
|
|
|
@ -62,7 +62,7 @@ class MachineAction(QObject, PluginObject):
|
|||
@pyqtSlot()
|
||||
def reset(self) -> None:
|
||||
"""Reset the action to it's default state.
|
||||
|
||||
|
||||
This should not be re-implemented by child classes, instead re-implement _reset.
|
||||
|
||||
:py:meth:`cura.MachineAction.MachineAction._reset`
|
||||
|
@ -73,7 +73,7 @@ class MachineAction(QObject, PluginObject):
|
|||
|
||||
def _reset(self) -> None:
|
||||
"""Protected implementation of reset.
|
||||
|
||||
|
||||
See also :py:meth:`cura.MachineAction.MachineAction.reset`
|
||||
"""
|
||||
|
||||
|
|
|
@ -11,14 +11,14 @@ from UM.Settings.InstanceContainer import InstanceContainer
|
|||
|
||||
class ContainerNode:
|
||||
"""A node in the container tree. It represents one container.
|
||||
|
||||
|
||||
The container it represents is referenced by its container_id. During normal use of the tree, this container is
|
||||
not constructed. Only when parts of the tree need to get loaded in the container stack should it get constructed.
|
||||
"""
|
||||
|
||||
def __init__(self, container_id: str) -> None:
|
||||
"""Creates a new node for the container tree.
|
||||
|
||||
|
||||
:param container_id: The ID of the container that this node should represent.
|
||||
"""
|
||||
|
||||
|
@ -28,7 +28,7 @@ class ContainerNode:
|
|||
|
||||
def getMetadata(self) -> Dict[str, Any]:
|
||||
"""Gets the metadata of the container that this node represents.
|
||||
|
||||
|
||||
Getting the metadata from the container directly is about 10x as fast.
|
||||
|
||||
:return: The metadata of the container in this node.
|
||||
|
@ -38,7 +38,7 @@ class ContainerNode:
|
|||
|
||||
def getMetaDataEntry(self, entry: str, default: Any = None) -> Any:
|
||||
"""Get an entry from the metadata of the container that this node contains.
|
||||
|
||||
|
||||
This is just a convenience function.
|
||||
|
||||
:param entry: The metadata entry key to return.
|
||||
|
@ -56,7 +56,7 @@ class ContainerNode:
|
|||
@property
|
||||
def container(self) -> Optional[InstanceContainer]:
|
||||
"""The container that this node's container ID refers to.
|
||||
|
||||
|
||||
This can be used to finally instantiate the container in order to put it in the container stack.
|
||||
|
||||
:return: A container.
|
||||
|
|
|
@ -21,9 +21,9 @@ if TYPE_CHECKING:
|
|||
|
||||
class ContainerTree:
|
||||
"""This class contains a look-up tree for which containers are available at which stages of configuration.
|
||||
|
||||
|
||||
The tree starts at the machine definitions. For every distinct definition there will be one machine node here.
|
||||
|
||||
|
||||
All of the fallbacks for material choices, quality choices, etc. should be encoded in this tree. There must
|
||||
always be at least one child node (for nodes that have children) but that child node may be a node representing
|
||||
the empty instance container.
|
||||
|
@ -44,7 +44,7 @@ class ContainerTree:
|
|||
|
||||
def getCurrentQualityGroups(self) -> Dict[str, "QualityGroup"]:
|
||||
"""Get the quality groups available for the currently activated printer.
|
||||
|
||||
|
||||
This contains all quality groups, enabled or disabled. To check whether the quality group can be activated,
|
||||
test for the ``QualityGroup.is_available`` property.
|
||||
|
||||
|
@ -61,7 +61,7 @@ class ContainerTree:
|
|||
|
||||
def getCurrentQualityChangesGroups(self) -> List["QualityChangesGroup"]:
|
||||
"""Get the quality changes groups available for the currently activated printer.
|
||||
|
||||
|
||||
This contains all quality changes groups, enabled or disabled. To check whether the quality changes group can
|
||||
be activated, test for the ``QualityChangesGroup.is_available`` property.
|
||||
|
||||
|
@ -84,7 +84,7 @@ class ContainerTree:
|
|||
|
||||
class _MachineNodeMap:
|
||||
"""Dictionary-like object that contains the machines.
|
||||
|
||||
|
||||
This handles the lazy loading of MachineNodes.
|
||||
"""
|
||||
|
||||
|
@ -105,7 +105,7 @@ class ContainerTree:
|
|||
|
||||
def __getitem__(self, definition_id: str) -> MachineNode:
|
||||
"""Returns a machine node for the specified definition ID.
|
||||
|
||||
|
||||
If the machine node wasn't loaded yet, this will load it lazily.
|
||||
|
||||
:param definition_id: The definition to look for.
|
||||
|
@ -122,7 +122,7 @@ class ContainerTree:
|
|||
|
||||
def get(self, definition_id: str, default: Optional[MachineNode] = None) -> Optional[MachineNode]:
|
||||
"""Gets a machine node for the specified definition ID, with default.
|
||||
|
||||
|
||||
The default is returned if there is no definition with the specified ID. If the machine node wasn't
|
||||
loaded yet, this will load it lazily.
|
||||
|
||||
|
@ -140,7 +140,7 @@ class ContainerTree:
|
|||
|
||||
def is_loaded(self, definition_id: str) -> bool:
|
||||
"""Returns whether we've already cached this definition's node.
|
||||
|
||||
|
||||
:param definition_id: The definition that we may have cached.
|
||||
|
||||
:return: ``True`` if it's cached.
|
||||
|
@ -155,7 +155,7 @@ class ContainerTree:
|
|||
|
||||
def __init__(self, tree_root: "ContainerTree", container_stacks: List["ContainerStack"]) -> None:
|
||||
"""Creates a new background task.
|
||||
|
||||
|
||||
:param tree_root: The container tree instance. This cannot be obtained through the singleton static
|
||||
function since the instance may not yet be constructed completely.
|
||||
:param container_stacks: All of the stacks to pre-load the container trees for. This needs to be provided
|
||||
|
@ -168,7 +168,7 @@ class ContainerTree:
|
|||
|
||||
def run(self) -> None:
|
||||
"""Starts the background task.
|
||||
|
||||
|
||||
The ``JobQueue`` will schedule this on a different thread.
|
||||
"""
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ if TYPE_CHECKING:
|
|||
|
||||
class IntentNode(ContainerNode):
|
||||
"""This class represents an intent profile in the container tree.
|
||||
|
||||
|
||||
This class has no more subnodes.
|
||||
"""
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import UM.FlameProfiler
|
|||
|
||||
class MachineNode(ContainerNode):
|
||||
"""This class represents a machine in the container tree.
|
||||
|
||||
|
||||
The subnodes of these nodes are variants.
|
||||
"""
|
||||
|
||||
|
@ -51,7 +51,7 @@ class MachineNode(ContainerNode):
|
|||
|
||||
def getQualityGroups(self, variant_names: List[str], material_bases: List[str], extruder_enabled: List[bool]) -> Dict[str, QualityGroup]:
|
||||
"""Get the available quality groups for this machine.
|
||||
|
||||
|
||||
This returns all quality groups, regardless of whether they are available to the combination of extruders or
|
||||
not. On the resulting quality groups, the is_available property is set to indicate whether the quality group
|
||||
can be selected according to the combination of extruders in the parameters.
|
||||
|
@ -103,13 +103,13 @@ class MachineNode(ContainerNode):
|
|||
|
||||
def getQualityChangesGroups(self, variant_names: List[str], material_bases: List[str], extruder_enabled: List[bool]) -> List[QualityChangesGroup]:
|
||||
"""Returns all of the quality changes groups available to this printer.
|
||||
|
||||
|
||||
The quality changes groups store which quality type and intent category they were made for, but not which
|
||||
material and nozzle. Instead for the quality type and intent category, the quality changes will always be
|
||||
available but change the quality type and intent category when activated.
|
||||
|
||||
|
||||
The quality changes group does depend on the printer: Which quality definition is used.
|
||||
|
||||
|
||||
The quality changes groups that are available do depend on the quality types that are available, so it must
|
||||
still be known which extruders are enabled and which materials and variants are loaded in them. This allows
|
||||
setting the correct is_available flag.
|
||||
|
@ -150,7 +150,7 @@ class MachineNode(ContainerNode):
|
|||
|
||||
def preferredGlobalQuality(self) -> "QualityNode":
|
||||
"""Gets the preferred global quality node, going by the preferred quality type.
|
||||
|
||||
|
||||
If the preferred global quality is not in there, an arbitrary global quality is taken. If there are no global
|
||||
qualities, an empty quality is returned.
|
||||
"""
|
||||
|
|
|
@ -9,17 +9,17 @@ if TYPE_CHECKING:
|
|||
|
||||
class MaterialGroup:
|
||||
"""A MaterialGroup represents a group of material InstanceContainers that are derived from a single material profile.
|
||||
|
||||
|
||||
The main InstanceContainer which has the ID of the material profile file name is called the "root_material". For
|
||||
example: "generic_abs" is the root material (ID) of "generic_abs_ultimaker3" and "generic_abs_ultimaker3_AA_0.4",
|
||||
and "generic_abs_ultimaker3" and "generic_abs_ultimaker3_AA_0.4" are derived materials of "generic_abs".
|
||||
|
||||
|
||||
Using "generic_abs" as an example, the MaterialGroup for "generic_abs" will contain the following information:
|
||||
- name: "generic_abs", root_material_id
|
||||
- root_material_node: MaterialNode of "generic_abs"
|
||||
- derived_material_node_list: A list of MaterialNodes that are derived from "generic_abs", so
|
||||
"generic_abs_ultimaker3", "generic_abs_ultimaker3_AA_0.4", etc.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
__slots__ = ("name", "is_read_only", "root_material_node", "derived_material_node_list")
|
||||
|
|
|
@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|||
|
||||
class MaterialNode(ContainerNode):
|
||||
"""Represents a material in the container tree.
|
||||
|
||||
|
||||
Its subcontainers are quality profiles.
|
||||
"""
|
||||
|
||||
|
@ -38,7 +38,7 @@ class MaterialNode(ContainerNode):
|
|||
|
||||
def preferredQuality(self) -> QualityNode:
|
||||
"""Finds the preferred quality for this printer with this material and this variant loaded.
|
||||
|
||||
|
||||
If the preferred quality is not available, an arbitrary quality is returned. If there is a configuration
|
||||
mistake (like a typo in the preferred quality) this returns a random available quality. If there are no
|
||||
available qualities, this will return the empty quality node.
|
||||
|
|
|
@ -15,7 +15,7 @@ from cura.Settings.CuraContainerRegistry import CuraContainerRegistry
|
|||
|
||||
class BaseMaterialsModel(ListModel):
|
||||
"""This is the base model class for GenericMaterialsModel and MaterialBrandsModel.
|
||||
|
||||
|
||||
Those 2 models are used by the material drop down menu to show generic materials and branded materials
|
||||
separately. The extruder position defined here is being used to bound a menu to the correct extruder. This is
|
||||
used in the top bar menu "Settings" -> "Extruder nr" -> "Material" -> this menu
|
||||
|
@ -125,7 +125,7 @@ class BaseMaterialsModel(ListModel):
|
|||
|
||||
def _materialsListChanged(self, material: MaterialNode) -> None:
|
||||
"""Triggered when a list of materials changed somewhere in the container
|
||||
|
||||
|
||||
tree. This change may trigger an _update() call when the materials changed for the configuration that this
|
||||
model is looking for.
|
||||
"""
|
||||
|
|
|
@ -212,7 +212,7 @@ class DiscoveredPrintersModel(QObject):
|
|||
@pyqtProperty("QVariantMap", notify = discoveredPrintersChanged)
|
||||
def discoveredPrintersByAddress(self) -> Dict[str, DiscoveredPrinter]:
|
||||
return self._discovered_printer_by_ip_dict
|
||||
|
||||
|
||||
@pyqtProperty("QVariantList", notify = discoveredPrintersChanged)
|
||||
def discoveredPrinters(self) -> List["DiscoveredPrinter"]:
|
||||
item_list = list(
|
||||
|
|
|
@ -17,7 +17,7 @@ catalog = i18nCatalog("cura")
|
|||
|
||||
class ExtrudersModel(ListModel):
|
||||
"""Model that holds extruders.
|
||||
|
||||
|
||||
This model is designed for use by any list of extruders, but specifically intended for drop-down lists of the
|
||||
current machine's extruders in place of settings.
|
||||
"""
|
||||
|
@ -33,7 +33,7 @@ class ExtrudersModel(ListModel):
|
|||
|
||||
IndexRole = Qt.UserRole + 4
|
||||
"""Index of the extruder, which is also the value of the setting itself.
|
||||
|
||||
|
||||
An index of 0 indicates the first extruder, an index of 1 the second one, and so on. This is the value that will
|
||||
be saved in instance containers. """
|
||||
|
||||
|
@ -58,7 +58,7 @@ class ExtrudersModel(ListModel):
|
|||
|
||||
def __init__(self, parent = None):
|
||||
"""Initialises the extruders model, defining the roles and listening for changes in the data.
|
||||
|
||||
|
||||
:param parent: Parent QtObject of this list.
|
||||
"""
|
||||
|
||||
|
@ -104,7 +104,7 @@ class ExtrudersModel(ListModel):
|
|||
def _extrudersChanged(self, machine_id = None):
|
||||
"""Links to the stack-changed signal of the new extruders when an extruder is swapped out or added in the
|
||||
current machine.
|
||||
|
||||
|
||||
:param machine_id: The machine for which the extruders changed. This is filled by the
|
||||
ExtruderManager.extrudersChanged signal when coming from that signal. Application.globalContainerStackChanged
|
||||
doesn't fill this signal; it's assumed to be the current printer in that case.
|
||||
|
@ -150,7 +150,7 @@ class ExtrudersModel(ListModel):
|
|||
@UM.FlameProfiler.profile
|
||||
def __updateExtruders(self):
|
||||
"""Update the list of extruders.
|
||||
|
||||
|
||||
This should be called whenever the list of extruders changes.
|
||||
"""
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ class IntentCategoryModel(ListModel):
|
|||
|
||||
def __init__(self, intent_category: str) -> None:
|
||||
"""Creates a new model for a certain intent category.
|
||||
|
||||
|
||||
:param intent_category: category to list the intent profiles for.
|
||||
"""
|
||||
|
||||
|
|
|
@ -21,20 +21,20 @@ catalog = i18nCatalog("cura")
|
|||
|
||||
class MaterialManagementModel(QObject):
|
||||
"""Proxy class to the materials page in the preferences.
|
||||
|
||||
|
||||
This class handles the actions in that page, such as creating new materials, renaming them, etc.
|
||||
"""
|
||||
|
||||
favoritesChanged = pyqtSignal(str)
|
||||
"""Triggered when a favorite is added or removed.
|
||||
|
||||
|
||||
:param The base file of the material is provided as parameter when this emits
|
||||
"""
|
||||
|
||||
@pyqtSlot("QVariant", result = bool)
|
||||
def canMaterialBeRemoved(self, material_node: "MaterialNode") -> bool:
|
||||
"""Can a certain material be deleted, or is it still in use in one of the container stacks anywhere?
|
||||
|
||||
|
||||
We forbid the user from deleting a material if it's in use in any stack. Deleting it while it's in use can
|
||||
lead to corrupted stacks. In the future we might enable this functionality again (deleting the material from
|
||||
those stacks) but for now it is easier to prevent the user from doing this.
|
||||
|
@ -54,7 +54,7 @@ class MaterialManagementModel(QObject):
|
|||
@pyqtSlot("QVariant", str)
|
||||
def setMaterialName(self, material_node: "MaterialNode", name: str) -> None:
|
||||
"""Change the user-visible name of a material.
|
||||
|
||||
|
||||
:param material_node: The ContainerTree node of the material to rename.
|
||||
:param name: The new name for the material.
|
||||
"""
|
||||
|
@ -69,7 +69,7 @@ class MaterialManagementModel(QObject):
|
|||
@pyqtSlot("QVariant")
|
||||
def removeMaterial(self, material_node: "MaterialNode") -> None:
|
||||
"""Deletes a material from Cura.
|
||||
|
||||
|
||||
This function does not do any safety checking any more. Please call this function only if:
|
||||
- The material is not read-only.
|
||||
- The material is not used in any stacks.
|
||||
|
@ -200,7 +200,7 @@ class MaterialManagementModel(QObject):
|
|||
def createMaterial(self) -> str:
|
||||
"""Create a new material by cloning the preferred material for the current material diameter and generate a new
|
||||
GUID.
|
||||
|
||||
|
||||
The material type is explicitly left to be the one from the preferred material, since this allows the user to
|
||||
still have SOME profiles to work with.
|
||||
|
||||
|
@ -234,7 +234,7 @@ class MaterialManagementModel(QObject):
|
|||
@pyqtSlot(str)
|
||||
def addFavorite(self, material_base_file: str) -> None:
|
||||
"""Adds a certain material to the favorite materials.
|
||||
|
||||
|
||||
:param material_base_file: The base file of the material to add.
|
||||
"""
|
||||
|
||||
|
@ -249,7 +249,7 @@ class MaterialManagementModel(QObject):
|
|||
@pyqtSlot(str)
|
||||
def removeFavorite(self, material_base_file: str) -> None:
|
||||
"""Removes a certain material from the favorite materials.
|
||||
|
||||
|
||||
If the material was not in the favorite materials, nothing happens.
|
||||
"""
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ class QualityManagementModel(ListModel):
|
|||
@pyqtSlot(QObject)
|
||||
def removeQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup") -> None:
|
||||
"""Deletes a custom profile. It will be gone forever.
|
||||
|
||||
|
||||
:param quality_changes_group: The quality changes group representing the profile to delete.
|
||||
"""
|
||||
|
||||
|
@ -99,7 +99,7 @@ class QualityManagementModel(ListModel):
|
|||
@pyqtSlot(QObject, str, result = str)
|
||||
def renameQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup", new_name: str) -> str:
|
||||
"""Rename a custom profile.
|
||||
|
||||
|
||||
Because the names must be unique, the new name may not actually become the name that was given. The actual
|
||||
name is returned by this function.
|
||||
|
||||
|
@ -145,7 +145,7 @@ class QualityManagementModel(ListModel):
|
|||
@pyqtSlot(str, "QVariantMap")
|
||||
def duplicateQualityChanges(self, new_name: str, quality_model_item: Dict[str, Any]) -> None:
|
||||
"""Duplicates a given quality profile OR quality changes profile.
|
||||
|
||||
|
||||
:param new_name: The desired name of the new profile. This will be made unique, so it might end up with a
|
||||
different name.
|
||||
:param quality_model_item: The item of this model to duplicate, as dictionary. See the descriptions of the
|
||||
|
@ -180,7 +180,7 @@ class QualityManagementModel(ListModel):
|
|||
@pyqtSlot(str)
|
||||
def createQualityChanges(self, base_name: str) -> None:
|
||||
"""Create quality changes containers from the user containers in the active stacks.
|
||||
|
||||
|
||||
This will go through the global and extruder stacks and create quality_changes containers from the user
|
||||
containers in each stack. These then replace the quality_changes containers in the stack and clear the user
|
||||
settings.
|
||||
|
@ -229,7 +229,7 @@ class QualityManagementModel(ListModel):
|
|||
|
||||
def _createQualityChanges(self, quality_type: str, intent_category: Optional[str], new_name: str, machine: "GlobalStack", extruder_stack: Optional["ExtruderStack"]) -> "InstanceContainer":
|
||||
"""Create a quality changes container with the given set-up.
|
||||
|
||||
|
||||
:param quality_type: The quality type of the new container.
|
||||
:param intent_category: The intent category of the new container.
|
||||
:param new_name: The name of the container. This name must be unique.
|
||||
|
@ -264,7 +264,7 @@ class QualityManagementModel(ListModel):
|
|||
|
||||
def _qualityChangesListChanged(self, container: "ContainerInterface") -> None:
|
||||
"""Triggered when any container changed.
|
||||
|
||||
|
||||
This filters the updates to the container manager: When it applies to the list of quality changes, we need to
|
||||
update our list.
|
||||
"""
|
||||
|
@ -383,7 +383,7 @@ class QualityManagementModel(ListModel):
|
|||
|
||||
The convenience meta-filters "All Supported Types" and "All Files" are added when listing readers,
|
||||
but not when listing writers.
|
||||
|
||||
|
||||
:param io_type: name of the needed IO type
|
||||
:return: A list of strings indicating file name filters for a file dialog.
|
||||
|
||||
|
@ -408,7 +408,7 @@ class QualityManagementModel(ListModel):
|
|||
|
||||
def _getIOPlugins(self, io_type):
|
||||
"""Gets a list of profile reader or writer plugins
|
||||
|
||||
|
||||
:return: List of tuples of (plugin_id, meta_data).
|
||||
"""
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
|
|
|
@ -8,7 +8,7 @@ from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal
|
|||
|
||||
class QualityChangesGroup(QObject):
|
||||
"""Data struct to group several quality changes instance containers together.
|
||||
|
||||
|
||||
Each group represents one "custom profile" as the user sees it, which contains an instance container for the
|
||||
global stack and one instance container per extruder.
|
||||
"""
|
||||
|
|
|
@ -12,7 +12,7 @@ from cura.Machines.ContainerNode import ContainerNode
|
|||
class QualityGroup:
|
||||
"""A QualityGroup represents a group of quality containers that must be applied to each ContainerStack when it's
|
||||
used.
|
||||
|
||||
|
||||
A concrete example: When there are two extruders and the user selects the quality type "normal", this quality
|
||||
type must be applied to all stacks in a machine, although each stack can have different containers. So one global
|
||||
profile gets put on the global stack and one extruder profile gets put on each extruder stack. This quality group
|
||||
|
@ -24,7 +24,7 @@ class QualityGroup:
|
|||
- um3_global_normal
|
||||
- um3_aa04_pla_normal
|
||||
- um3_aa04_abs_normal
|
||||
|
||||
|
||||
The purpose of these quality groups is to group the containers that can be applied to a configuration,
|
||||
so that when a quality level is selected, the container can directly be applied to each stack instead of looking
|
||||
them up again.
|
||||
|
@ -32,7 +32,7 @@ class QualityGroup:
|
|||
|
||||
def __init__(self, name: str, quality_type: str) -> None:
|
||||
"""Constructs a new group.
|
||||
|
||||
|
||||
:param name: The user-visible name for the group.
|
||||
:param quality_type: The quality level that each profile in this group has.
|
||||
"""
|
||||
|
|
|
@ -15,9 +15,9 @@ if TYPE_CHECKING:
|
|||
|
||||
class QualityNode(ContainerNode):
|
||||
"""Represents a quality profile in the container tree.
|
||||
|
||||
|
||||
This may either be a normal quality profile or a global quality profile.
|
||||
|
||||
|
||||
Its subcontainers are intent profiles.
|
||||
"""
|
||||
|
||||
|
|
|
@ -19,9 +19,9 @@ if TYPE_CHECKING:
|
|||
|
||||
class VariantNode(ContainerNode):
|
||||
"""This class represents an extruder variant in the container tree.
|
||||
|
||||
|
||||
The subnodes of these nodes are materials.
|
||||
|
||||
|
||||
This node contains materials with ALL filament diameters underneath it. The tree of this variant is not specific
|
||||
to one global stack, so because the list of materials can be different per stack depending on the compatible
|
||||
material diameter setting, we cannot filter them here. Filtering must be done in the model.
|
||||
|
@ -72,7 +72,7 @@ class VariantNode(ContainerNode):
|
|||
|
||||
def preferredMaterial(self, approximate_diameter: int) -> MaterialNode:
|
||||
"""Finds the preferred material for this printer with this nozzle in one of the extruders.
|
||||
|
||||
|
||||
If the preferred material is not available, an arbitrary material is returned. If there is a configuration
|
||||
mistake (like a typo in the preferred material) this returns a random available material. If there are no
|
||||
available materials, this will return the empty material node.
|
||||
|
@ -85,14 +85,14 @@ class VariantNode(ContainerNode):
|
|||
for base_material, material_node in self.materials.items():
|
||||
if self.machine.preferred_material == base_material and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
|
||||
return material_node
|
||||
|
||||
|
||||
# First fallback: Check if we should be checking for the 175 variant.
|
||||
if approximate_diameter == 2:
|
||||
preferred_material = self.machine.preferred_material + "_175"
|
||||
for base_material, material_node in self.materials.items():
|
||||
if preferred_material == base_material and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
|
||||
return material_node
|
||||
|
||||
|
||||
# Second fallback: Choose any material with matching diameter.
|
||||
for material_node in self.materials.values():
|
||||
if material_node.getMetaDataEntry("approximate_diameter") and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
|
||||
|
|
|
@ -31,12 +31,12 @@ class AuthorizationHelpers:
|
|||
|
||||
def getAccessTokenUsingAuthorizationCode(self, authorization_code: str, verification_code: str) -> "AuthenticationResponse":
|
||||
"""Request the access token from the authorization server.
|
||||
|
||||
|
||||
:param authorization_code: The authorization code from the 1st step.
|
||||
:param verification_code: The verification code needed for the PKCE extension.
|
||||
:return: An AuthenticationResponse object.
|
||||
"""
|
||||
|
||||
|
||||
data = {
|
||||
"client_id": self._settings.CLIENT_ID if self._settings.CLIENT_ID is not None else "",
|
||||
"redirect_uri": self._settings.CALLBACK_URL if self._settings.CALLBACK_URL is not None else "",
|
||||
|
@ -52,11 +52,11 @@ class AuthorizationHelpers:
|
|||
|
||||
def getAccessTokenUsingRefreshToken(self, refresh_token: str) -> "AuthenticationResponse":
|
||||
"""Request the access token from the authorization server using a refresh token.
|
||||
|
||||
|
||||
:param refresh_token:
|
||||
:return: An AuthenticationResponse object.
|
||||
"""
|
||||
|
||||
|
||||
Logger.log("d", "Refreshing the access token.")
|
||||
data = {
|
||||
"client_id": self._settings.CLIENT_ID if self._settings.CLIENT_ID is not None else "",
|
||||
|
@ -73,11 +73,11 @@ class AuthorizationHelpers:
|
|||
@staticmethod
|
||||
def parseTokenResponse(token_response: requests.models.Response) -> "AuthenticationResponse":
|
||||
"""Parse the token response from the authorization server into an AuthenticationResponse object.
|
||||
|
||||
|
||||
:param token_response: The JSON string data response from the authorization server.
|
||||
:return: An AuthenticationResponse object.
|
||||
"""
|
||||
|
||||
|
||||
token_data = None
|
||||
|
||||
try:
|
||||
|
@ -101,11 +101,11 @@ class AuthorizationHelpers:
|
|||
|
||||
def parseJWT(self, access_token: str) -> Optional["UserProfile"]:
|
||||
"""Calls the authentication API endpoint to get the token data.
|
||||
|
||||
|
||||
:param access_token: The encoded JWT token.
|
||||
:return: Dict containing some profile data.
|
||||
"""
|
||||
|
||||
|
||||
try:
|
||||
token_request = requests.get("{}/check-token".format(self._settings.OAUTH_SERVER_URL), headers = {
|
||||
"Authorization": "Bearer {}".format(access_token)
|
||||
|
@ -130,20 +130,20 @@ class AuthorizationHelpers:
|
|||
@staticmethod
|
||||
def generateVerificationCode(code_length: int = 32) -> str:
|
||||
"""Generate a verification code of arbitrary length.
|
||||
|
||||
|
||||
:param code_length:: How long should the code be? This should never be lower than 16, but it's probably
|
||||
better to leave it at 32
|
||||
"""
|
||||
|
||||
|
||||
return "".join(random.choice("0123456789ABCDEF") for i in range(code_length))
|
||||
|
||||
@staticmethod
|
||||
def generateVerificationCodeChallenge(verification_code: str) -> str:
|
||||
"""Generates a base64 encoded sha512 encrypted version of a given string.
|
||||
|
||||
|
||||
:param verification_code:
|
||||
:return: The encrypted code in base64 format.
|
||||
"""
|
||||
|
||||
|
||||
encoded = sha512(verification_code.encode()).digest()
|
||||
return b64encode(encoded, altchars = b"_-").decode()
|
||||
|
|
|
@ -16,10 +16,10 @@ catalog = i18nCatalog("cura")
|
|||
|
||||
class AuthorizationRequestHandler(BaseHTTPRequestHandler):
|
||||
"""This handler handles all HTTP requests on the local web server.
|
||||
|
||||
|
||||
It also requests the access token for the 2nd stage of the OAuth flow.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, request, client_address, server) -> None:
|
||||
super().__init__(request, client_address, server)
|
||||
|
||||
|
@ -60,11 +60,11 @@ class AuthorizationRequestHandler(BaseHTTPRequestHandler):
|
|||
|
||||
def _handleCallback(self, query: Dict[Any, List]) -> Tuple[ResponseData, Optional[AuthenticationResponse]]:
|
||||
"""Handler for the callback URL redirect.
|
||||
|
||||
|
||||
:param query: Dict containing the HTTP query parameters.
|
||||
:return: HTTP ResponseData containing a success page to show to the user.
|
||||
"""
|
||||
|
||||
|
||||
code = self._queryGet(query, "code")
|
||||
state = self._queryGet(query, "state")
|
||||
if state != self.state:
|
||||
|
|
|
@ -11,11 +11,11 @@ if TYPE_CHECKING:
|
|||
|
||||
class AuthorizationRequestServer(HTTPServer):
|
||||
"""The authorization request callback handler server.
|
||||
|
||||
|
||||
This subclass is needed to be able to pass some data to the request handler. This cannot be done on the request
|
||||
handler directly as the HTTPServer creates an instance of the handler after init.
|
||||
"""
|
||||
|
||||
|
||||
def setAuthorizationHelpers(self, authorization_helpers: "AuthorizationHelpers") -> None:
|
||||
"""Set the authorization helpers instance on the request handler."""
|
||||
|
||||
|
|
|
@ -251,7 +251,7 @@ class AuthorizationService:
|
|||
if self._preferences is None:
|
||||
Logger.log("e", "Unable to save authentication data, since no preference has been set!")
|
||||
return
|
||||
|
||||
|
||||
self._auth_data = auth_data
|
||||
if auth_data:
|
||||
self._user_profile = self.getUserProfile()
|
||||
|
|
|
@ -24,19 +24,19 @@ class LocalAuthorizationServer:
|
|||
auth_state_changed_callback: Callable[["AuthenticationResponse"], Any],
|
||||
daemon: bool) -> None:
|
||||
"""The local LocalAuthorizationServer takes care of the oauth2 callbacks.
|
||||
|
||||
|
||||
Once the flow is completed, this server should be closed down again by calling
|
||||
:py:meth:`cura.OAuth2.LocalAuthorizationServer.LocalAuthorizationServer.stop()`
|
||||
|
||||
|
||||
:param auth_helpers: An instance of the authorization helpers class.
|
||||
:param auth_state_changed_callback: A callback function to be called when the authorization state changes.
|
||||
:param daemon: Whether the server thread should be run in daemon mode.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
Daemon threads are abruptly stopped at shutdown. Their resources (e.g. open files) may never be released.
|
||||
"""
|
||||
|
||||
|
||||
self._web_server = None # type: Optional[AuthorizationRequestServer]
|
||||
self._web_server_thread = None # type: Optional[threading.Thread]
|
||||
self._web_server_port = auth_helpers.settings.CALLBACK_PORT
|
||||
|
@ -46,11 +46,11 @@ class LocalAuthorizationServer:
|
|||
|
||||
def start(self, verification_code: str, state: str) -> None:
|
||||
"""Starts the local web server to handle the authorization callback.
|
||||
|
||||
|
||||
:param verification_code: The verification code part of the OAuth2 client identification.
|
||||
:param state: The unique state code (to ensure that the request we get back is really from the server.
|
||||
"""
|
||||
|
||||
|
||||
if self._web_server:
|
||||
# If the server is already running (because of a previously aborted auth flow), we don't have to start it.
|
||||
# We still inject the new verification code though.
|
||||
|
|
|
@ -9,7 +9,7 @@ from functools import cmp_to_key
|
|||
|
||||
class OneAtATimeIterator(Iterator.Iterator):
|
||||
"""Iterator that returns a list of nodes in the order that they need to be printed
|
||||
|
||||
|
||||
If there is no solution an empty list is returned.
|
||||
Take note that the list of nodes can have children (that may or may not contain mesh data)
|
||||
"""
|
||||
|
@ -80,7 +80,7 @@ class OneAtATimeIterator(Iterator.Iterator):
|
|||
|
||||
def _checkBlockMultiple(self, node: SceneNode, other_nodes: List[SceneNode]) -> bool:
|
||||
"""Check for a node whether it hits any of the other nodes.
|
||||
|
||||
|
||||
:param node: The node to check whether it collides with the other nodes.
|
||||
:param other_nodes: The nodes to check for collisions.
|
||||
:return: returns collision between nodes
|
||||
|
@ -140,7 +140,7 @@ class _ObjectOrder:
|
|||
|
||||
def __init__(self, order: List[SceneNode], todo: List[SceneNode]) -> None:
|
||||
"""Creates the _ObjectOrder instance.
|
||||
|
||||
|
||||
:param order: List of indices in which to print objects, ordered by printing order.
|
||||
:param todo: List of indices which are not yet inserted into the order list.
|
||||
"""
|
||||
|
|
|
@ -11,7 +11,7 @@ class SetParentOperation(Operation.Operation):
|
|||
|
||||
def __init__(self, node: SceneNode, parent_node: Optional[SceneNode]) -> None:
|
||||
"""Initialises this SetParentOperation.
|
||||
|
||||
|
||||
:param node: The node which will be reparented.
|
||||
:param parent_node: The node which will be the parent.
|
||||
"""
|
||||
|
@ -33,7 +33,7 @@ class SetParentOperation(Operation.Operation):
|
|||
|
||||
def _set_parent(self, new_parent: Optional[SceneNode]) -> None:
|
||||
"""Sets the parent of the node while applying transformations to the world-transform of the node stays the same.
|
||||
|
||||
|
||||
:param new_parent: The new parent. Note: this argument can be None, which would hide the node from the scene.
|
||||
"""
|
||||
|
||||
|
@ -64,7 +64,7 @@ class SetParentOperation(Operation.Operation):
|
|||
|
||||
def __repr__(self) -> str:
|
||||
"""Returns a programmer-readable representation of this operation.
|
||||
|
||||
|
||||
:return: A programmer-readable representation of this operation.
|
||||
"""
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@ if TYPE_CHECKING:
|
|||
class PickingPass(RenderPass):
|
||||
"""A :py:class:`Uranium.UM.View.RenderPass` subclass that renders a the distance of selectable objects from the
|
||||
active camera to a texture.
|
||||
|
||||
|
||||
The texture is used to map a 2d location (eg the mouse location) to a world space position
|
||||
|
||||
|
||||
.. note:: that in order to increase precision, the 24 bit depth value is encoded into all three of the R,G & B channels
|
||||
"""
|
||||
|
||||
|
|
|
@ -95,15 +95,15 @@ class PlatformPhysics:
|
|||
# Ignore root, ourselves and anything that is not a normal SceneNode.
|
||||
if other_node is root or not issubclass(type(other_node), SceneNode) or other_node is node or other_node.callDecoration("getBuildPlateNumber") != node.callDecoration("getBuildPlateNumber"):
|
||||
continue
|
||||
|
||||
|
||||
# Ignore collisions of a group with it's own children
|
||||
if other_node in node.getAllChildren() or node in other_node.getAllChildren():
|
||||
continue
|
||||
|
||||
|
||||
# Ignore collisions within a group
|
||||
if other_node.getParent() and node.getParent() and (other_node.getParent().callDecoration("isGroup") is not None or node.getParent().callDecoration("isGroup") is not None):
|
||||
continue
|
||||
|
||||
|
||||
# Ignore nodes that do not have the right properties set.
|
||||
if not other_node.callDecoration("getConvexHull") or not other_node.getBoundingBox():
|
||||
continue
|
||||
|
|
|
@ -39,9 +39,9 @@ def prettier_color(color_list: List[float]) -> List[float]:
|
|||
|
||||
class PreviewPass(RenderPass):
|
||||
"""A :py:class:`Uranium.UM.View.RenderPass` subclass that renders slicable objects with default parameters.
|
||||
|
||||
|
||||
It uses the active camera by default, but it can be overridden to use a different camera.
|
||||
|
||||
|
||||
This is useful to get a preview image of a scene taken from a different location as the active camera.
|
||||
"""
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class FirmwareUpdater(QObject):
|
|||
if self._firmware_file == "":
|
||||
self._setFirmwareUpdateState(FirmwareUpdateState.firmware_not_found_error)
|
||||
return
|
||||
|
||||
|
||||
self._setFirmwareUpdateState(FirmwareUpdateState.updating)
|
||||
|
||||
self._update_firmware_thread.start()
|
||||
|
|
|
@ -49,7 +49,7 @@ class ExtruderConfigurationModel(QObject):
|
|||
|
||||
def isValid(self) -> bool:
|
||||
"""This method is intended to indicate whether the configuration is valid or not.
|
||||
|
||||
|
||||
The method checks if the mandatory fields are or not set
|
||||
At this moment is always valid since we allow to have empty material and variants.
|
||||
"""
|
||||
|
|
|
@ -106,7 +106,7 @@ class ExtruderOutputModel(QObject):
|
|||
@pyqtSlot(float, float)
|
||||
def preheatHotend(self, temperature: float, duration: float) -> None:
|
||||
"""Pre-heats the extruder before printer.
|
||||
|
||||
|
||||
:param temperature: The temperature to heat the extruder to, in degrees
|
||||
Celsius.
|
||||
:param duration: How long the bed should stay warm, in seconds.
|
||||
|
|
|
@ -50,7 +50,7 @@ class PrinterConfigurationModel(QObject):
|
|||
|
||||
def isValid(self) -> bool:
|
||||
"""This method is intended to indicate whether the configuration is valid or not.
|
||||
|
||||
|
||||
The method checks if the mandatory fields are or not set
|
||||
"""
|
||||
if not self._extruder_configurations:
|
||||
|
@ -101,7 +101,7 @@ class PrinterConfigurationModel(QObject):
|
|||
|
||||
def __hash__(self):
|
||||
"""The hash function is used to compare and create unique sets. The configuration is unique if the configuration
|
||||
|
||||
|
||||
of the extruders is unique (the order of the extruders matters), and the type and buildplate is the same.
|
||||
"""
|
||||
extruder_hash = hash(0)
|
||||
|
|
|
@ -166,7 +166,7 @@ class PrinterOutputModel(QObject):
|
|||
@pyqtSlot(float, float)
|
||||
def preheatBed(self, temperature: float, duration: float) -> None:
|
||||
"""Pre-heats the heated bed of the printer.
|
||||
|
||||
|
||||
:param temperature: The temperature to heat the bed to, in degrees
|
||||
Celsius.
|
||||
:param duration: How long the bed should stay warm, in seconds.
|
||||
|
|
|
@ -147,7 +147,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
|||
|
||||
def createFormPart(self, content_header: str, data: bytes, content_type: Optional[str] = None) -> QHttpPart:
|
||||
"""This method was only available privately before, but it was actually called from SendMaterialJob.py.
|
||||
|
||||
|
||||
We now have a public equivalent as well. We did not remove the private one as plugins might be using that.
|
||||
"""
|
||||
return self._createFormPart(content_header, data, content_type)
|
||||
|
@ -194,7 +194,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
|||
on_finished: Optional[Callable[[QNetworkReply], None]] = None,
|
||||
on_progress: Optional[Callable[[int, int], None]] = None) -> None:
|
||||
"""Sends a put request to the given path.
|
||||
|
||||
|
||||
:param url: The path after the API prefix.
|
||||
:param data: The data to be sent in the body
|
||||
:param content_type: The content type of the body data.
|
||||
|
@ -219,7 +219,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
|||
|
||||
def delete(self, url: str, on_finished: Optional[Callable[[QNetworkReply], None]]) -> None:
|
||||
"""Sends a delete request to the given path.
|
||||
|
||||
|
||||
:param url: The path after the API prefix.
|
||||
:param on_finished: The function to be call when the response is received.
|
||||
"""
|
||||
|
@ -237,7 +237,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
|||
|
||||
def get(self, url: str, on_finished: Optional[Callable[[QNetworkReply], None]]) -> None:
|
||||
"""Sends a get request to the given path.
|
||||
|
||||
|
||||
:param url: The path after the API prefix.
|
||||
:param on_finished: The function to be call when the response is received.
|
||||
"""
|
||||
|
@ -258,7 +258,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
|||
on_progress: Optional[Callable[[int, int], None]] = None) -> None:
|
||||
|
||||
"""Sends a post request to the given path.
|
||||
|
||||
|
||||
:param url: The path after the API prefix.
|
||||
:param data: The data to be sent in the body
|
||||
:param on_finished: The function to call when the response is received.
|
||||
|
@ -333,7 +333,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
|||
|
||||
def _checkCorrectGroupName(self, device_id: str, group_name: str) -> None:
|
||||
"""This method checks if the name of the group stored in the definition container is correct.
|
||||
|
||||
|
||||
After updating from 3.2 to 3.3 some group names may be temporary. If there is a mismatch in the name of the group
|
||||
then all the container stacks are updated, both the current and the hidden ones.
|
||||
"""
|
||||
|
@ -385,7 +385,7 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
|
|||
@pyqtProperty(str, constant = True)
|
||||
def key(self) -> str:
|
||||
"""Get the unique key of this machine
|
||||
|
||||
|
||||
:return: key String containing the key of the machine.
|
||||
"""
|
||||
return self._id
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
class Peripheral:
|
||||
"""Data class that represents a peripheral for a printer.
|
||||
|
||||
|
||||
Output device plug-ins may specify that the printer has a certain set of
|
||||
peripherals. This set is then possibly shown in the interface of the monitor
|
||||
stage.
|
||||
|
@ -12,7 +12,7 @@ class Peripheral:
|
|||
|
||||
def __init__(self, peripheral_type: str, name: str) -> None:
|
||||
"""Constructs the peripheral.
|
||||
|
||||
|
||||
:param peripheral_type: A unique ID for the type of peripheral.
|
||||
:param name: A human-readable name for the peripheral.
|
||||
"""
|
||||
|
|
|
@ -44,13 +44,13 @@ class ConnectionType(IntEnum):
|
|||
@signalemitter
|
||||
class PrinterOutputDevice(QObject, OutputDevice):
|
||||
"""Printer output device adds extra interface options on top of output device.
|
||||
|
||||
|
||||
The assumption is made the printer is a FDM printer.
|
||||
|
||||
|
||||
Note that a number of settings are marked as "final". This is because decorators
|
||||
are not inherited by children. To fix this we use the private counter part of those
|
||||
functions to actually have the implementation.
|
||||
|
||||
|
||||
For all other uses it should be used in the same way as a "regular" OutputDevice.
|
||||
"""
|
||||
|
||||
|
@ -250,7 +250,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
|||
|
||||
def _setFirmwareName(self, name: str) -> None:
|
||||
"""Set the device firmware name
|
||||
|
||||
|
||||
:param name: The name of the firmware.
|
||||
"""
|
||||
|
||||
|
@ -258,7 +258,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
|
|||
|
||||
def getFirmwareName(self) -> Optional[str]:
|
||||
"""Get the name of device firmware
|
||||
|
||||
|
||||
This name can be used to define device type
|
||||
"""
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ class NoProfileException(Exception):
|
|||
|
||||
class ProfileReader(PluginObject):
|
||||
"""A type of plug-ins that reads profiles from a file.
|
||||
|
||||
|
||||
The profile is then stored as instance container of the type user profile.
|
||||
"""
|
||||
|
||||
|
@ -21,7 +21,7 @@ class ProfileReader(PluginObject):
|
|||
|
||||
def read(self, file_name):
|
||||
"""Read profile data from a file and return a filled profile.
|
||||
|
||||
|
||||
:return: :type{Profile|Profile[]} The profile that was obtained from the file or a list of Profiles.
|
||||
"""
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@ from UM.PluginObject import PluginObject
|
|||
|
||||
class ProfileWriter(PluginObject):
|
||||
"""Base class for profile writer plugins.
|
||||
|
||||
|
||||
This class defines a write() function to write profiles to files with.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialises the profile writer.
|
||||
|
||||
|
||||
This currently doesn't do anything since the writer is basically static.
|
||||
"""
|
||||
|
||||
|
@ -20,9 +20,9 @@ class ProfileWriter(PluginObject):
|
|||
|
||||
def write(self, path, profiles):
|
||||
"""Writes a profile to the specified file path.
|
||||
|
||||
|
||||
The profile writer may write its own file format to the specified file.
|
||||
|
||||
|
||||
:param path: :type{string} The file to output to.
|
||||
:param profiles: :type{Profile} or :type{List} The profile(s) to write to the file.
|
||||
:return: True if the writing was successful, or False if it wasn't.
|
||||
|
|
|
@ -25,7 +25,7 @@ if TYPE_CHECKING:
|
|||
|
||||
class ConvexHullDecorator(SceneNodeDecorator):
|
||||
"""The convex hull decorator is a scene node decorator that adds the convex hull functionality to a scene node.
|
||||
|
||||
|
||||
If a scene node has a convex hull decorator, it will have a shadow in which other objects can not be printed.
|
||||
"""
|
||||
|
||||
|
@ -84,7 +84,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
|
||||
def getAdhesionArea(self) -> Optional[Polygon]:
|
||||
"""The polygon representing the 2D adhesion area.
|
||||
|
||||
|
||||
If no adhesion is used, the regular convex hull is returned
|
||||
"""
|
||||
if self._node is None:
|
||||
|
@ -98,7 +98,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
|
||||
def getConvexHull(self) -> Optional[Polygon]:
|
||||
"""Get the unmodified 2D projected convex hull of the node (if any)
|
||||
|
||||
|
||||
In case of one-at-a-time, this includes adhesion and head+fans clearance
|
||||
"""
|
||||
if self._node is None:
|
||||
|
@ -118,7 +118,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
|
||||
def getConvexHullHeadFull(self) -> Optional[Polygon]:
|
||||
"""For one at the time this is the convex hull of the node with the full head size
|
||||
|
||||
|
||||
In case of printing all at once this is None.
|
||||
"""
|
||||
if self._node is None:
|
||||
|
@ -138,7 +138,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
|
||||
def getConvexHullHead(self) -> Optional[Polygon]:
|
||||
"""Get convex hull of the object + head size
|
||||
|
||||
|
||||
In case of printing all at once this is None.
|
||||
For one at the time this is area with intersection of mirrored head
|
||||
"""
|
||||
|
@ -156,7 +156,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
|
||||
def getConvexHullBoundary(self) -> Optional[Polygon]:
|
||||
"""Get convex hull of the node
|
||||
|
||||
|
||||
In case of printing all at once this None??
|
||||
For one at the time this is the area without the head.
|
||||
"""
|
||||
|
@ -173,7 +173,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
|
||||
def getPrintingArea(self) -> Optional[Polygon]:
|
||||
"""Get the buildplate polygon where will be printed
|
||||
|
||||
|
||||
In case of printing all at once this is the same as convex hull (no individual adhesion)
|
||||
For one at the time this includes the adhesion area
|
||||
"""
|
||||
|
@ -344,7 +344,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
|
||||
def _add2DAdhesionMargin(self, poly: Polygon) -> Polygon:
|
||||
"""Compensate given 2D polygon with adhesion margin
|
||||
|
||||
|
||||
:return: 2D polygon with added margin
|
||||
"""
|
||||
if not self._global_stack:
|
||||
|
@ -379,7 +379,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
|
||||
def _offsetHull(self, convex_hull: Polygon) -> Polygon:
|
||||
"""Offset the convex hull with settings that influence the collision area.
|
||||
|
||||
|
||||
:param convex_hull: Polygon of the original convex hull.
|
||||
:return: New Polygon instance that is offset with everything that
|
||||
influences the collision area.
|
||||
|
@ -476,6 +476,6 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
|
||||
_influencing_settings = {"xy_offset", "xy_offset_layer_0", "mold_enabled", "mold_width", "anti_overhang_mesh", "infill_mesh", "cutting_mesh"}
|
||||
"""Settings that change the convex hull.
|
||||
|
||||
|
||||
If these settings change, the convex hull should be recalculated.
|
||||
"""
|
||||
|
|
|
@ -20,7 +20,7 @@ class ConvexHullNode(SceneNode):
|
|||
|
||||
def __init__(self, node: SceneNode, hull: Optional[Polygon], thickness: float, parent: Optional[SceneNode] = None) -> None:
|
||||
"""Convex hull node is a special type of scene node that is used to display an area, to indicate the
|
||||
|
||||
|
||||
location an object uses on the buildplate. This area (or area's in case of one at a time printing) is
|
||||
then displayed as a transparent shadow. If the adhesion type is set to raft, the area is extruded
|
||||
to represent the raft as well.
|
||||
|
|
|
@ -17,7 +17,7 @@ from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator # F
|
|||
|
||||
class CuraSceneNode(SceneNode):
|
||||
"""Scene nodes that are models are only seen when selecting the corresponding build plate
|
||||
|
||||
|
||||
Note that many other nodes can just be UM SceneNode objects.
|
||||
"""
|
||||
def __init__(self, parent: Optional["SceneNode"] = None, visible: bool = True, name: str = "", no_setting_override: bool = False) -> None:
|
||||
|
@ -40,7 +40,7 @@ class CuraSceneNode(SceneNode):
|
|||
|
||||
def getPrintingExtruder(self) -> Optional[ExtruderStack]:
|
||||
"""Get the extruder used to print this node. If there is no active node, then the extruder in position zero is returned
|
||||
|
||||
|
||||
TODO The best way to do it is by adding the setActiveExtruder decorator to every node when is loaded
|
||||
"""
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
|
|
|
@ -4,7 +4,7 @@ from UM.Scene.SceneNodeDecorator import SceneNodeDecorator
|
|||
class SliceableObjectDecorator(SceneNodeDecorator):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
|
||||
def isSliceable(self) -> bool:
|
||||
return True
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ catalog = i18nCatalog("cura")
|
|||
|
||||
class ContainerManager(QObject):
|
||||
"""Manager class that contains common actions to deal with containers in Cura.
|
||||
|
||||
|
||||
This is primarily intended as a class to be able to perform certain actions
|
||||
from within QML. We want to be able to trigger things like removing a container
|
||||
when a certain action happens. This can be done through this class.
|
||||
|
@ -72,16 +72,16 @@ class ContainerManager(QObject):
|
|||
@pyqtSlot("QVariant", str, str)
|
||||
def setContainerMetaDataEntry(self, container_node: "ContainerNode", entry_name: str, entry_value: str) -> bool:
|
||||
"""Set a metadata entry of the specified container.
|
||||
|
||||
|
||||
This will set the specified entry of the container's metadata to the specified
|
||||
value. Note that entries containing dictionaries can have their entries changed
|
||||
by using "/" as a separator. For example, to change an entry "foo" in a
|
||||
dictionary entry "bar", you can specify "bar/foo" as entry name.
|
||||
|
||||
|
||||
:param container_node: :type{ContainerNode}
|
||||
:param entry_name: :type{str} The name of the metadata entry to change.
|
||||
:param entry_value: The new value of the entry.
|
||||
|
||||
|
||||
TODO: This is ONLY used by MaterialView for material containers. Maybe refactor this.
|
||||
Update: In order for QML to use objects and sub objects, those (sub) objects must all be QObject. Is that what we want?
|
||||
"""
|
||||
|
@ -131,14 +131,14 @@ class ContainerManager(QObject):
|
|||
@pyqtSlot(str, result = "QStringList")
|
||||
def getContainerNameFilters(self, type_name: str) -> List[str]:
|
||||
"""Get a list of string that can be used as name filters for a Qt File Dialog
|
||||
|
||||
|
||||
This will go through the list of available container types and generate a list of strings
|
||||
out of that. The strings are formatted as "description (*.extension)" and can be directly
|
||||
passed to a nameFilters property of a Qt File Dialog.
|
||||
|
||||
|
||||
:param type_name: Which types of containers to list. These types correspond to the "type"
|
||||
key of the plugin metadata.
|
||||
|
||||
|
||||
:return: A string list with name filters.
|
||||
"""
|
||||
|
||||
|
@ -156,11 +156,11 @@ class ContainerManager(QObject):
|
|||
@pyqtSlot(str, str, QUrl, result = "QVariantMap")
|
||||
def exportContainer(self, container_id: str, file_type: str, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
|
||||
"""Export a container to a file
|
||||
|
||||
|
||||
:param container_id: The ID of the container to export
|
||||
:param file_type: The type of file to save as. Should be in the form of "description (*.extension, *.ext)"
|
||||
:param file_url_or_string: The URL where to save the file.
|
||||
|
||||
|
||||
:return: A dictionary containing a key "status" with a status code and a key "message" with a message
|
||||
explaining the status. The status code can be one of "error", "cancelled", "success"
|
||||
"""
|
||||
|
@ -224,9 +224,9 @@ class ContainerManager(QObject):
|
|||
@pyqtSlot(QUrl, result = "QVariantMap")
|
||||
def importMaterialContainer(self, file_url_or_string: Union[QUrl, str]) -> Dict[str, str]:
|
||||
"""Imports a profile from a file
|
||||
|
||||
|
||||
:param file_url: A URL that points to the file to import.
|
||||
|
||||
|
||||
:return: :type{Dict} dict with a 'status' key containing the string 'success' or 'error', and a 'message' key
|
||||
containing a message for the user
|
||||
"""
|
||||
|
@ -278,10 +278,10 @@ class ContainerManager(QObject):
|
|||
@pyqtSlot(result = bool)
|
||||
def updateQualityChanges(self) -> bool:
|
||||
"""Update the current active quality changes container with the settings from the user container.
|
||||
|
||||
|
||||
This will go through the active global stack and all active extruder stacks and merge the changes from the user
|
||||
container into the quality_changes container. After that, the user container is cleared.
|
||||
|
||||
|
||||
:return: :type{bool} True if successful, False if not.
|
||||
"""
|
||||
|
||||
|
@ -350,7 +350,7 @@ class ContainerManager(QObject):
|
|||
@pyqtSlot("QVariant", bool, result = "QStringList")
|
||||
def getLinkedMaterials(self, material_node: "MaterialNode", exclude_self: bool = False) -> List[str]:
|
||||
"""Get a list of materials that have the same GUID as the reference material
|
||||
|
||||
|
||||
:param material_node: The node representing the material for which to get
|
||||
the same GUID.
|
||||
:param exclude_self: Whether to include the name of the material you provided.
|
||||
|
@ -366,7 +366,7 @@ class ContainerManager(QObject):
|
|||
@pyqtSlot("QVariant")
|
||||
def unlinkMaterial(self, material_node: "MaterialNode") -> None:
|
||||
"""Unlink a material from all other materials by creating a new GUID
|
||||
|
||||
|
||||
:param material_id: :type{str} the id of the material to create a new GUID for.
|
||||
"""
|
||||
# Get the material group
|
||||
|
|
|
@ -20,11 +20,11 @@ from . import Exceptions
|
|||
|
||||
class CuraContainerStack(ContainerStack):
|
||||
"""Base class for Cura related stacks that want to enforce certain containers are available.
|
||||
|
||||
|
||||
This class makes sure that the stack has the following containers set: user changes, quality
|
||||
changes, quality, material, variant, definition changes and finally definition. Initially,
|
||||
these will be equal to the empty instance container.
|
||||
|
||||
|
||||
The container types are determined based on the following criteria:
|
||||
- user: An InstanceContainer with the metadata entry "type" set to "user".
|
||||
- quality changes: An InstanceContainer with the metadata entry "type" set to "quality_changes".
|
||||
|
@ -33,7 +33,7 @@ class CuraContainerStack(ContainerStack):
|
|||
- variant: An InstanceContainer with the metadata entry "type" set to "variant".
|
||||
- definition changes: An InstanceContainer with the metadata entry "type" set to "definition_changes".
|
||||
- definition: A DefinitionContainer.
|
||||
|
||||
|
||||
Internally, this class ensures the mentioned containers are always there and kept in a specific order.
|
||||
This also means that operations on the stack that modifies the container ordering is prohibited and
|
||||
will raise an exception.
|
||||
|
@ -65,7 +65,7 @@ class CuraContainerStack(ContainerStack):
|
|||
|
||||
def setUserChanges(self, new_user_changes: InstanceContainer) -> None:
|
||||
"""Set the user changes container.
|
||||
|
||||
|
||||
:param new_user_changes: The new user changes container. It is expected to have a "type" metadata entry with the value "user".
|
||||
"""
|
||||
|
||||
|
@ -74,7 +74,7 @@ class CuraContainerStack(ContainerStack):
|
|||
@pyqtProperty(InstanceContainer, fset = setUserChanges, notify = pyqtContainersChanged)
|
||||
def userChanges(self) -> InstanceContainer:
|
||||
"""Get the user changes container.
|
||||
|
||||
|
||||
:return: The user changes container. Should always be a valid container, but can be equal to the empty InstanceContainer.
|
||||
"""
|
||||
|
||||
|
@ -82,7 +82,7 @@ class CuraContainerStack(ContainerStack):
|
|||
|
||||
def setQualityChanges(self, new_quality_changes: InstanceContainer, postpone_emit = False) -> None:
|
||||
"""Set the quality changes container.
|
||||
|
||||
|
||||
:param new_quality_changes: The new quality changes container. It is expected to have a "type" metadata entry with the value "quality_changes".
|
||||
"""
|
||||
|
||||
|
@ -91,7 +91,7 @@ class CuraContainerStack(ContainerStack):
|
|||
@pyqtProperty(InstanceContainer, fset = setQualityChanges, notify = pyqtContainersChanged)
|
||||
def qualityChanges(self) -> InstanceContainer:
|
||||
"""Get the quality changes container.
|
||||
|
||||
|
||||
:return: The quality changes container. Should always be a valid container, but can be equal to the empty InstanceContainer.
|
||||
"""
|
||||
|
||||
|
@ -99,7 +99,7 @@ class CuraContainerStack(ContainerStack):
|
|||
|
||||
def setIntent(self, new_intent: InstanceContainer, postpone_emit: bool = False) -> None:
|
||||
"""Set the intent container.
|
||||
|
||||
|
||||
:param new_intent: The new intent container. It is expected to have a "type" metadata entry with the value "intent".
|
||||
"""
|
||||
|
||||
|
@ -108,7 +108,7 @@ class CuraContainerStack(ContainerStack):
|
|||
@pyqtProperty(InstanceContainer, fset = setIntent, notify = pyqtContainersChanged)
|
||||
def intent(self) -> InstanceContainer:
|
||||
"""Get the quality container.
|
||||
|
||||
|
||||
:return: The intent container. Should always be a valid container, but can be equal to the empty InstanceContainer.
|
||||
"""
|
||||
|
||||
|
@ -116,7 +116,7 @@ class CuraContainerStack(ContainerStack):
|
|||
|
||||
def setQuality(self, new_quality: InstanceContainer, postpone_emit: bool = False) -> None:
|
||||
"""Set the quality container.
|
||||
|
||||
|
||||
:param new_quality: The new quality container. It is expected to have a "type" metadata entry with the value "quality".
|
||||
"""
|
||||
|
||||
|
@ -125,7 +125,7 @@ class CuraContainerStack(ContainerStack):
|
|||
@pyqtProperty(InstanceContainer, fset = setQuality, notify = pyqtContainersChanged)
|
||||
def quality(self) -> InstanceContainer:
|
||||
"""Get the quality container.
|
||||
|
||||
|
||||
:return: The quality container. Should always be a valid container, but can be equal to the empty InstanceContainer.
|
||||
"""
|
||||
|
||||
|
@ -133,7 +133,7 @@ class CuraContainerStack(ContainerStack):
|
|||
|
||||
def setMaterial(self, new_material: InstanceContainer, postpone_emit: bool = False) -> None:
|
||||
"""Set the material container.
|
||||
|
||||
|
||||
:param new_material: The new material container. It is expected to have a "type" metadata entry with the value "material".
|
||||
"""
|
||||
|
||||
|
@ -142,7 +142,7 @@ class CuraContainerStack(ContainerStack):
|
|||
@pyqtProperty(InstanceContainer, fset = setMaterial, notify = pyqtContainersChanged)
|
||||
def material(self) -> InstanceContainer:
|
||||
"""Get the material container.
|
||||
|
||||
|
||||
:return: The material container. Should always be a valid container, but can be equal to the empty InstanceContainer.
|
||||
"""
|
||||
|
||||
|
@ -150,7 +150,7 @@ class CuraContainerStack(ContainerStack):
|
|||
|
||||
def setVariant(self, new_variant: InstanceContainer) -> None:
|
||||
"""Set the variant container.
|
||||
|
||||
|
||||
:param new_variant: The new variant container. It is expected to have a "type" metadata entry with the value "variant".
|
||||
"""
|
||||
|
||||
|
@ -159,7 +159,7 @@ class CuraContainerStack(ContainerStack):
|
|||
@pyqtProperty(InstanceContainer, fset = setVariant, notify = pyqtContainersChanged)
|
||||
def variant(self) -> InstanceContainer:
|
||||
"""Get the variant container.
|
||||
|
||||
|
||||
:return: The variant container. Should always be a valid container, but can be equal to the empty InstanceContainer.
|
||||
"""
|
||||
|
||||
|
@ -167,7 +167,7 @@ class CuraContainerStack(ContainerStack):
|
|||
|
||||
def setDefinitionChanges(self, new_definition_changes: InstanceContainer) -> None:
|
||||
"""Set the definition changes container.
|
||||
|
||||
|
||||
:param new_definition_changes: The new definition changes container. It is expected to have a "type" metadata entry with the value "definition_changes".
|
||||
"""
|
||||
|
||||
|
@ -176,7 +176,7 @@ class CuraContainerStack(ContainerStack):
|
|||
@pyqtProperty(InstanceContainer, fset = setDefinitionChanges, notify = pyqtContainersChanged)
|
||||
def definitionChanges(self) -> InstanceContainer:
|
||||
"""Get the definition changes container.
|
||||
|
||||
|
||||
:return: The definition changes container. Should always be a valid container, but can be equal to the empty InstanceContainer.
|
||||
"""
|
||||
|
||||
|
@ -184,7 +184,7 @@ class CuraContainerStack(ContainerStack):
|
|||
|
||||
def setDefinition(self, new_definition: DefinitionContainerInterface) -> None:
|
||||
"""Set the definition container.
|
||||
|
||||
|
||||
:param new_definition: The new definition container. It is expected to have a "type" metadata entry with the value "definition".
|
||||
"""
|
||||
|
||||
|
@ -206,10 +206,10 @@ class CuraContainerStack(ContainerStack):
|
|||
@pyqtSlot(str, result = bool)
|
||||
def hasUserValue(self, key: str) -> bool:
|
||||
"""Check whether the specified setting has a 'user' value.
|
||||
|
||||
|
||||
A user value here is defined as the setting having a value in either
|
||||
the UserChanges or QualityChanges container.
|
||||
|
||||
|
||||
:return: True if the setting has a user value, False if not.
|
||||
"""
|
||||
|
||||
|
@ -223,11 +223,11 @@ class CuraContainerStack(ContainerStack):
|
|||
|
||||
def setProperty(self, key: str, property_name: str, property_value: Any, container: "ContainerInterface" = None, set_from_cache: bool = False) -> None:
|
||||
"""Set a property of a setting.
|
||||
|
||||
|
||||
This will set a property of a specified setting. Since the container stack does not contain
|
||||
any settings itself, it is required to specify a container to set the property on. The target
|
||||
container is matched by container type.
|
||||
|
||||
|
||||
:param key: The key of the setting to set.
|
||||
:param property_name: The name of the property to set.
|
||||
:param new_value: The new value to set the property to.
|
||||
|
@ -239,7 +239,7 @@ class CuraContainerStack(ContainerStack):
|
|||
@override(ContainerStack)
|
||||
def addContainer(self, container: ContainerInterface) -> None:
|
||||
"""Overridden from ContainerStack
|
||||
|
||||
|
||||
Since we have a fixed order of containers in the stack and this method would modify the container
|
||||
ordering, we disallow this operation.
|
||||
"""
|
||||
|
@ -249,7 +249,7 @@ class CuraContainerStack(ContainerStack):
|
|||
@override(ContainerStack)
|
||||
def insertContainer(self, index: int, container: ContainerInterface) -> None:
|
||||
"""Overridden from ContainerStack
|
||||
|
||||
|
||||
Since we have a fixed order of containers in the stack and this method would modify the container
|
||||
ordering, we disallow this operation.
|
||||
"""
|
||||
|
@ -259,7 +259,7 @@ class CuraContainerStack(ContainerStack):
|
|||
@override(ContainerStack)
|
||||
def removeContainer(self, index: int = 0) -> None:
|
||||
"""Overridden from ContainerStack
|
||||
|
||||
|
||||
Since we have a fixed order of containers in the stack and this method would modify the container
|
||||
ordering, we disallow this operation.
|
||||
"""
|
||||
|
@ -269,10 +269,10 @@ class CuraContainerStack(ContainerStack):
|
|||
@override(ContainerStack)
|
||||
def replaceContainer(self, index: int, container: ContainerInterface, postpone_emit: bool = False) -> None:
|
||||
"""Overridden from ContainerStack
|
||||
|
||||
|
||||
Replaces the container at the specified index with another container.
|
||||
This version performs checks to make sure the new container has the expected metadata and type.
|
||||
|
||||
|
||||
:throws Exception.InvalidContainerError Raised when trying to replace a container with a container that has an incorrect type.
|
||||
"""
|
||||
|
||||
|
@ -292,12 +292,12 @@ class CuraContainerStack(ContainerStack):
|
|||
@override(ContainerStack)
|
||||
def deserialize(self, serialized: str, file_name: Optional[str] = None) -> str:
|
||||
"""Overridden from ContainerStack
|
||||
|
||||
|
||||
This deserialize will make sure the internal list of containers matches with what we expect.
|
||||
It will first check to see if the container at a certain index already matches with what we
|
||||
expect. If it does not, it will search for a matching container with the correct type. Should
|
||||
no container with the correct type be found, it will use the empty container.
|
||||
|
||||
|
||||
:raise InvalidContainerStackError: Raised when no definition can be found for the stack.
|
||||
"""
|
||||
|
||||
|
@ -357,12 +357,12 @@ class CuraContainerStack(ContainerStack):
|
|||
@classmethod
|
||||
def _findInstanceContainerDefinitionId(cls, machine_definition: DefinitionContainerInterface) -> str:
|
||||
"""Find the ID that should be used when searching for instance containers for a specified definition.
|
||||
|
||||
|
||||
This handles the situation where the definition specifies we should use a different definition when
|
||||
searching for instance containers.
|
||||
|
||||
|
||||
:param machine_definition: The definition to find the "quality definition" for.
|
||||
|
||||
|
||||
:return: The ID of the definition container to use when searching for instance containers.
|
||||
"""
|
||||
|
||||
|
|
|
@ -20,10 +20,10 @@ class CuraStackBuilder:
|
|||
@classmethod
|
||||
def createMachine(cls, name: str, definition_id: str) -> Optional[GlobalStack]:
|
||||
"""Create a new instance of a machine.
|
||||
|
||||
|
||||
:param name: The name of the new machine.
|
||||
:param definition_id: The ID of the machine definition to use.
|
||||
|
||||
|
||||
:return: The new global stack or None if an error occurred.
|
||||
"""
|
||||
|
||||
|
@ -77,7 +77,7 @@ class CuraStackBuilder:
|
|||
@classmethod
|
||||
def createExtruderStackWithDefaultSetup(cls, global_stack: "GlobalStack", extruder_position: int) -> None:
|
||||
"""Create a default Extruder Stack
|
||||
|
||||
|
||||
:param global_stack: The global stack this extruder refers to.
|
||||
:param extruder_position: The position of the current extruder.
|
||||
"""
|
||||
|
@ -134,7 +134,7 @@ class CuraStackBuilder:
|
|||
quality_container: "InstanceContainer") -> ExtruderStack:
|
||||
|
||||
"""Create a new Extruder stack
|
||||
|
||||
|
||||
:param new_stack_id: The ID of the new stack.
|
||||
:param extruder_definition: The definition to base the new stack on.
|
||||
:param machine_definition_id: The ID of the machine definition to use for the user container.
|
||||
|
@ -142,7 +142,7 @@ class CuraStackBuilder:
|
|||
:param variant_container: The variant selected for the current extruder.
|
||||
:param material_container: The material selected for the current extruder.
|
||||
:param quality_container: The quality selected for the current extruder.
|
||||
|
||||
|
||||
:return: A new Extruder stack instance with the specified parameters.
|
||||
"""
|
||||
|
||||
|
@ -181,13 +181,13 @@ class CuraStackBuilder:
|
|||
quality_container: "InstanceContainer") -> GlobalStack:
|
||||
|
||||
"""Create a new Global stack
|
||||
|
||||
|
||||
:param new_stack_id: The ID of the new stack.
|
||||
:param definition: The definition to base the new stack on.
|
||||
:param variant_container: The variant selected for the current stack.
|
||||
:param material_container: The material selected for the current stack.
|
||||
:param quality_container: The quality selected for the current stack.
|
||||
|
||||
|
||||
:return: A new Global stack instance with the specified parameters.
|
||||
"""
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ class ExtruderStack(CuraContainerStack):
|
|||
@override(ContainerStack)
|
||||
def setNextStack(self, stack: CuraContainerStack, connect_signals: bool = True) -> None:
|
||||
"""Overridden from ContainerStack
|
||||
|
||||
|
||||
This will set the next stack and ensure that we register this stack as an extruder.
|
||||
"""
|
||||
|
||||
|
@ -71,7 +71,7 @@ class ExtruderStack(CuraContainerStack):
|
|||
|
||||
def getCompatibleMaterialDiameter(self) -> float:
|
||||
"""Return the filament diameter that the machine requires.
|
||||
|
||||
|
||||
If the machine has no requirement for the diameter, -1 is returned.
|
||||
:return: The filament diameter for the printer
|
||||
"""
|
||||
|
@ -99,12 +99,12 @@ class ExtruderStack(CuraContainerStack):
|
|||
|
||||
def getApproximateMaterialDiameter(self) -> float:
|
||||
"""Return the approximate filament diameter that the machine requires.
|
||||
|
||||
|
||||
The approximate material diameter is the material diameter rounded to
|
||||
the nearest millimetre.
|
||||
|
||||
|
||||
If the machine has no requirement for the diameter, -1 is returned.
|
||||
|
||||
|
||||
:return: The approximate filament diameter for the printer
|
||||
"""
|
||||
|
||||
|
@ -116,12 +116,12 @@ class ExtruderStack(CuraContainerStack):
|
|||
@override(ContainerStack)
|
||||
def getProperty(self, key: str, property_name: str, context: Optional[PropertyEvaluationContext] = None) -> Any:
|
||||
"""Overridden from ContainerStack
|
||||
|
||||
|
||||
It will perform a few extra checks when trying to get properties.
|
||||
|
||||
|
||||
The two extra checks it currently does is to ensure a next stack is set and to bypass
|
||||
the extruder when the property is not settable per extruder.
|
||||
|
||||
|
||||
:throws Exceptions.NoGlobalStackError Raised when trying to get a property from an extruder without
|
||||
having a next stack set.
|
||||
"""
|
||||
|
|
|
@ -62,7 +62,7 @@ class GlobalStack(CuraContainerStack):
|
|||
@deprecated("Please use extruderList instead.", "4.4")
|
||||
def extruders(self) -> Dict[str, "ExtruderStack"]:
|
||||
"""Get the list of extruders of this stack.
|
||||
|
||||
|
||||
:return: The extruders registered with this stack.
|
||||
"""
|
||||
|
||||
|
@ -91,11 +91,11 @@ class GlobalStack(CuraContainerStack):
|
|||
@pyqtProperty("QVariantList", notify=configuredConnectionTypesChanged)
|
||||
def configuredConnectionTypes(self) -> List[int]:
|
||||
"""The configured connection types can be used to find out if the global
|
||||
|
||||
|
||||
stack is configured to be connected with a printer, without having to
|
||||
know all the details as to how this is exactly done (and without
|
||||
actually setting the stack to be active).
|
||||
|
||||
|
||||
This data can then in turn also be used when the global stack is active;
|
||||
If we can't get a network connection, but it is configured to have one,
|
||||
we can display a different icon to indicate the difference.
|
||||
|
@ -171,9 +171,9 @@ class GlobalStack(CuraContainerStack):
|
|||
|
||||
def addExtruder(self, extruder: ContainerStack) -> None:
|
||||
"""Add an extruder to the list of extruders of this stack.
|
||||
|
||||
|
||||
:param extruder: The extruder to add.
|
||||
|
||||
|
||||
:raise Exceptions.TooManyExtrudersError: Raised when trying to add an extruder while we
|
||||
already have the maximum number of extruders.
|
||||
"""
|
||||
|
@ -194,15 +194,15 @@ class GlobalStack(CuraContainerStack):
|
|||
@override(ContainerStack)
|
||||
def getProperty(self, key: str, property_name: str, context: Optional[PropertyEvaluationContext] = None) -> Any:
|
||||
"""Overridden from ContainerStack
|
||||
|
||||
|
||||
This will return the value of the specified property for the specified setting,
|
||||
unless the property is "value" and that setting has a "resolve" function set.
|
||||
When a resolve is set, it will instead try and execute the resolve first and
|
||||
then fall back to the normal "value" property.
|
||||
|
||||
|
||||
:param key: The setting key to get the property of.
|
||||
:param property_name: The property to get the value of.
|
||||
|
||||
|
||||
:return: The value of the property for the specified setting, or None if not found.
|
||||
"""
|
||||
|
||||
|
@ -248,7 +248,7 @@ class GlobalStack(CuraContainerStack):
|
|||
@override(ContainerStack)
|
||||
def setNextStack(self, stack: CuraContainerStack, connect_signals: bool = True) -> None:
|
||||
"""Overridden from ContainerStack
|
||||
|
||||
|
||||
This will simply raise an exception since the Global stack cannot have a next stack.
|
||||
"""
|
||||
|
||||
|
@ -281,7 +281,7 @@ class GlobalStack(CuraContainerStack):
|
|||
|
||||
def isValid(self) -> bool:
|
||||
"""Perform some sanity checks on the global stack
|
||||
|
||||
|
||||
Sanity check for extruders; they must have positions 0 and up to machine_extruder_count - 1
|
||||
"""
|
||||
container_registry = ContainerRegistry.getInstance()
|
||||
|
|
|
@ -32,9 +32,9 @@ class IntentManager(QObject):
|
|||
|
||||
def intentMetadatas(self, definition_id: str, nozzle_name: str, material_base_file: str) -> List[Dict[str, Any]]:
|
||||
"""Gets the metadata dictionaries of all intent profiles for a given
|
||||
|
||||
|
||||
configuration.
|
||||
|
||||
|
||||
:param definition_id: ID of the printer.
|
||||
:param nozzle_name: Name of the nozzle.
|
||||
:param material_base_file: The base_file of the material.
|
||||
|
@ -58,9 +58,9 @@ class IntentManager(QObject):
|
|||
|
||||
def intentCategories(self, definition_id: str, nozzle_id: str, material_id: str) -> List[str]:
|
||||
"""Collects and returns all intent categories available for the given
|
||||
|
||||
|
||||
parameters. Note that the 'default' category is always available.
|
||||
|
||||
|
||||
:param definition_id: ID of the printer.
|
||||
:param nozzle_name: Name of the nozzle.
|
||||
:param material_id: ID of the material.
|
||||
|
@ -74,10 +74,10 @@ class IntentManager(QObject):
|
|||
|
||||
def getCurrentAvailableIntents(self) -> List[Tuple[str, str]]:
|
||||
"""List of intents to be displayed in the interface.
|
||||
|
||||
|
||||
For the interface this will have to be broken up into the different
|
||||
intent categories. That is up to the model there.
|
||||
|
||||
|
||||
:return: A list of tuples of intent_category and quality_type. The actual
|
||||
instance may vary per extruder.
|
||||
"""
|
||||
|
@ -109,7 +109,7 @@ class IntentManager(QObject):
|
|||
|
||||
def currentAvailableIntentCategories(self) -> List[str]:
|
||||
"""List of intent categories available in either of the extruders.
|
||||
|
||||
|
||||
This is purposefully inconsistent with the way that the quality types
|
||||
are listed. The quality types will show all quality types available in
|
||||
the printer using any configuration. This will only list the intent
|
||||
|
@ -134,7 +134,7 @@ class IntentManager(QObject):
|
|||
|
||||
def getDefaultIntent(self) -> "InstanceContainer":
|
||||
"""The intent that gets selected by default when no intent is available for
|
||||
|
||||
|
||||
the configuration, an extruder can't match the intent that the user
|
||||
selects, or just when creating a new printer.
|
||||
"""
|
||||
|
|
|
@ -342,7 +342,7 @@ class MachineManager(QObject):
|
|||
@staticmethod
|
||||
def getMachine(definition_id: str, metadata_filter: Optional[Dict[str, str]] = None) -> Optional["GlobalStack"]:
|
||||
"""Given a definition id, return the machine with this id.
|
||||
|
||||
|
||||
Optional: add a list of keys and values to filter the list of machines with the given definition id
|
||||
:param definition_id: :type{str} definition id that needs to look for
|
||||
:param metadata_filter: :type{dict} list of metadata keys and values used for filtering
|
||||
|
@ -430,7 +430,7 @@ class MachineManager(QObject):
|
|||
@pyqtSlot(str)
|
||||
def clearUserSettingAllCurrentStacks(self, key: str) -> None:
|
||||
"""Delete a user setting from the global stack and all extruder stacks.
|
||||
|
||||
|
||||
:param key: :type{str} the name of the key to delete
|
||||
"""
|
||||
Logger.log("i", "Clearing the setting [%s] from all stacks", key)
|
||||
|
@ -464,7 +464,7 @@ class MachineManager(QObject):
|
|||
@pyqtProperty(bool, notify = stacksValidationChanged)
|
||||
def stacksHaveErrors(self) -> bool:
|
||||
"""Check if none of the stacks contain error states
|
||||
|
||||
|
||||
Note that the _stacks_have_errors is cached due to performance issues
|
||||
Calling _checkStack(s)ForErrors on every change is simply too expensive
|
||||
"""
|
||||
|
@ -503,7 +503,7 @@ class MachineManager(QObject):
|
|||
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
|
||||
def activeMachineHasCloudRegistration(self) -> bool:
|
||||
return self.activeMachine is not None and ConnectionType.CloudConnection in self.activeMachine.configuredConnectionTypes
|
||||
|
||||
|
||||
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
|
||||
def activeMachineIsUsingCloudConnection(self) -> bool:
|
||||
return self.activeMachineHasCloudConnection and not self.activeMachineHasNetworkConnection
|
||||
|
@ -544,9 +544,9 @@ class MachineManager(QObject):
|
|||
@pyqtProperty(float, notify = activeQualityGroupChanged)
|
||||
def activeQualityLayerHeight(self) -> float:
|
||||
"""Gets the layer height of the currently active quality profile.
|
||||
|
||||
|
||||
This is indicated together with the name of the active quality profile.
|
||||
|
||||
|
||||
:return: The layer height of the currently active quality profile. If
|
||||
there is no quality profile, this returns the default layer height.
|
||||
"""
|
||||
|
@ -623,7 +623,7 @@ class MachineManager(QObject):
|
|||
@pyqtProperty(bool, notify = activeQualityChanged)
|
||||
def isCurrentSetupSupported(self) -> bool:
|
||||
"""Returns whether there is anything unsupported in the current set-up.
|
||||
|
||||
|
||||
The current set-up signifies the global stack and all extruder stacks,
|
||||
so this indicates whether there is any container in any of the container
|
||||
stacks that is not marked as supported.
|
||||
|
@ -670,7 +670,7 @@ class MachineManager(QObject):
|
|||
@pyqtProperty(str, notify = globalContainerChanged)
|
||||
def activeQualityDefinitionId(self) -> str:
|
||||
"""Get the Definition ID to use to select quality profiles for the currently active machine
|
||||
|
||||
|
||||
:returns: DefinitionID (string) if found, empty string otherwise
|
||||
"""
|
||||
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
|
||||
|
@ -681,7 +681,7 @@ class MachineManager(QObject):
|
|||
@pyqtProperty(str, notify = globalContainerChanged)
|
||||
def activeDefinitionVariantsName(self) -> str:
|
||||
"""Gets how the active definition calls variants
|
||||
|
||||
|
||||
Caveat: per-definition-variant-title is currently not translated (though the fallback is)
|
||||
"""
|
||||
fallback_title = catalog.i18nc("@label", "Nozzle")
|
||||
|
@ -754,7 +754,7 @@ class MachineManager(QObject):
|
|||
@pyqtProperty(bool, notify = activeMaterialChanged)
|
||||
def variantBuildplateUsable(self) -> bool:
|
||||
"""The selected buildplate is usable if it is usable for all materials OR it is compatible for one but not compatible
|
||||
|
||||
|
||||
for the other material but the buildplate is still usable
|
||||
"""
|
||||
if not self._global_container_stack:
|
||||
|
@ -780,7 +780,7 @@ class MachineManager(QObject):
|
|||
@pyqtSlot(str, result = str)
|
||||
def getDefinitionByMachineId(self, machine_id: str) -> Optional[str]:
|
||||
"""Get the Definition ID of a machine (specified by ID)
|
||||
|
||||
|
||||
:param machine_id: string machine id to get the definition ID of
|
||||
:returns: DefinitionID if found, None otherwise
|
||||
"""
|
||||
|
@ -834,7 +834,7 @@ class MachineManager(QObject):
|
|||
|
||||
def setActiveMachineExtruderCount(self, extruder_count: int) -> None:
|
||||
"""Set the amount of extruders on the active machine (global stack)
|
||||
|
||||
|
||||
:param extruder_count: int the number of extruders to set
|
||||
"""
|
||||
if self._global_container_stack is None:
|
||||
|
@ -979,7 +979,7 @@ class MachineManager(QObject):
|
|||
|
||||
def _getContainerChangedSignals(self) -> List[Signal]:
|
||||
"""Get the signals that signal that the containers changed for all stacks.
|
||||
|
||||
|
||||
This includes the global stack and all extruder stacks. So if any
|
||||
container changed anywhere.
|
||||
"""
|
||||
|
@ -999,7 +999,7 @@ class MachineManager(QObject):
|
|||
@pyqtSlot(str)
|
||||
def resetSettingForAllExtruders(self, setting_name: str) -> None:
|
||||
"""Reset all setting properties of a setting for all extruders.
|
||||
|
||||
|
||||
:param setting_name: The ID of the setting to reset.
|
||||
"""
|
||||
if self._global_container_stack is None:
|
||||
|
@ -1247,7 +1247,7 @@ class MachineManager(QObject):
|
|||
@pyqtSlot()
|
||||
def updateMaterialWithVariant(self, position: Optional[str] = None) -> None:
|
||||
"""Update the material profile in the current stacks when the variant is
|
||||
|
||||
|
||||
changed.
|
||||
:param position: The extruder stack to update. If provided with None, all
|
||||
extruder stacks will be updated.
|
||||
|
@ -1289,7 +1289,7 @@ class MachineManager(QObject):
|
|||
@pyqtSlot(str)
|
||||
def switchPrinterType(self, machine_name: str) -> None:
|
||||
"""Given a printer definition name, select the right machine instance. In case it doesn't exist, create a new
|
||||
|
||||
|
||||
instance with the same network key.
|
||||
"""
|
||||
# Don't switch if the user tries to change to the same type of printer
|
||||
|
@ -1311,7 +1311,7 @@ class MachineManager(QObject):
|
|||
if not new_machine:
|
||||
Logger.log("e", "Failed to create new machine when switching configuration.")
|
||||
return
|
||||
|
||||
|
||||
for metadata_key in self._global_container_stack.getMetaData():
|
||||
if metadata_key in new_machine.getMetaData():
|
||||
continue # Don't copy the already preset stuff.
|
||||
|
@ -1444,7 +1444,7 @@ class MachineManager(QObject):
|
|||
@pyqtSlot(str, "QVariant")
|
||||
def setMaterial(self, position: str, container_node, global_stack: Optional["GlobalStack"] = None) -> None:
|
||||
"""Global_stack: if you want to provide your own global_stack instead of the current active one
|
||||
|
||||
|
||||
if you update an active machine, special measures have to be taken.
|
||||
"""
|
||||
if global_stack is not None and global_stack != self._global_container_stack:
|
||||
|
@ -1495,7 +1495,7 @@ class MachineManager(QObject):
|
|||
@pyqtSlot(QObject)
|
||||
def setQualityGroup(self, quality_group: "QualityGroup", no_dialog: bool = False, global_stack: Optional["GlobalStack"] = None) -> None:
|
||||
"""Optionally provide global_stack if you want to use your own
|
||||
|
||||
|
||||
The active global_stack is treated differently.
|
||||
"""
|
||||
if global_stack is not None and global_stack != self._global_container_stack:
|
||||
|
@ -1562,7 +1562,7 @@ class MachineManager(QObject):
|
|||
@pyqtSlot(str)
|
||||
def setIntentByCategory(self, intent_category: str) -> None:
|
||||
"""Change the intent category of the current printer.
|
||||
|
||||
|
||||
All extruders can change their profiles. If an intent profile is
|
||||
available with the desired intent category, that one will get chosen.
|
||||
Otherwise the intent profile will be left to the empty profile, which
|
||||
|
@ -1603,7 +1603,7 @@ class MachineManager(QObject):
|
|||
|
||||
def activeQualityGroup(self) -> Optional["QualityGroup"]:
|
||||
"""Get the currently activated quality group.
|
||||
|
||||
|
||||
If no printer is added yet or the printer doesn't have quality profiles,
|
||||
this returns ``None``.
|
||||
:return: The currently active quality group.
|
||||
|
@ -1617,7 +1617,7 @@ class MachineManager(QObject):
|
|||
@pyqtProperty(str, notify = activeQualityGroupChanged)
|
||||
def activeQualityGroupName(self) -> str:
|
||||
"""Get the name of the active quality group.
|
||||
|
||||
|
||||
:return: The name of the active quality group.
|
||||
"""
|
||||
quality_group = self.activeQualityGroup()
|
||||
|
|
|
@ -13,7 +13,7 @@ from UM.Settings.InstanceContainer import InstanceContainer
|
|||
|
||||
class MachineNameValidator(QObject):
|
||||
"""Are machine names valid?
|
||||
|
||||
|
||||
Performs checks based on the length of the name.
|
||||
"""
|
||||
|
||||
|
@ -37,7 +37,7 @@ class MachineNameValidator(QObject):
|
|||
|
||||
def validate(self, name):
|
||||
"""Check if a specified machine name is allowed.
|
||||
|
||||
|
||||
:param name: The machine name to check.
|
||||
:return: ``QValidator.Invalid`` if it's disallowed, or ``QValidator.Acceptable`` if it's allowed.
|
||||
"""
|
||||
|
|
|
@ -18,7 +18,7 @@ from cura.Settings.ExtruderManager import ExtruderManager
|
|||
@signalemitter
|
||||
class SettingOverrideDecorator(SceneNodeDecorator):
|
||||
"""A decorator that adds a container stack to a Node. This stack should be queried for all settings regarding
|
||||
|
||||
|
||||
the linked node. The Stack in question will refer to the global stack (so that settings that are not defined by
|
||||
this stack still resolve.
|
||||
"""
|
||||
|
@ -27,7 +27,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
|
|||
|
||||
_non_printing_mesh_settings = {"anti_overhang_mesh", "infill_mesh", "cutting_mesh"}
|
||||
"""Non-printing meshes
|
||||
|
||||
|
||||
If these settings are True for any mesh, the mesh does not need a convex hull,
|
||||
and is sent to the slicer regardless of whether it fits inside the build volume.
|
||||
Note that Support Mesh is not in here because it actually generates
|
||||
|
@ -83,7 +83,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
|
|||
|
||||
def getActiveExtruder(self):
|
||||
"""Gets the currently active extruder to print this object with.
|
||||
|
||||
|
||||
:return: An extruder's container stack.
|
||||
"""
|
||||
|
||||
|
@ -91,7 +91,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
|
|||
|
||||
def getActiveExtruderChangedSignal(self):
|
||||
"""Gets the signal that emits if the active extruder changed.
|
||||
|
||||
|
||||
This can then be accessed via a decorator.
|
||||
"""
|
||||
|
||||
|
@ -99,7 +99,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
|
|||
|
||||
def getActiveExtruderPosition(self):
|
||||
"""Gets the currently active extruders position
|
||||
|
||||
|
||||
:return: An extruder's position, or None if no position info is available.
|
||||
"""
|
||||
|
||||
|
@ -137,7 +137,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
|
|||
|
||||
def _updateNextStack(self):
|
||||
"""Makes sure that the stack upon which the container stack is placed is
|
||||
|
||||
|
||||
kept up to date.
|
||||
"""
|
||||
if self._extruder_stack:
|
||||
|
@ -160,7 +160,7 @@ class SettingOverrideDecorator(SceneNodeDecorator):
|
|||
|
||||
def setActiveExtruder(self, extruder_stack_id):
|
||||
"""Changes the extruder with which to print this node.
|
||||
|
||||
|
||||
:param extruder_stack_id: The new extruder stack to print with.
|
||||
"""
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ class MachineActionManager(QObject):
|
|||
|
||||
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:
|
||||
|
@ -112,7 +112,7 @@ class MachineActionManager(QObject):
|
|||
|
||||
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:
|
||||
|
@ -123,7 +123,7 @@ class MachineActionManager(QObject):
|
|||
@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.
|
||||
"""
|
||||
|
@ -134,7 +134,7 @@ class MachineActionManager(QObject):
|
|||
|
||||
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.
|
||||
"""
|
||||
|
@ -146,7 +146,7 @@ class MachineActionManager(QObject):
|
|||
@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.
|
||||
|
@ -159,7 +159,7 @@ class MachineActionManager(QObject):
|
|||
|
||||
def removeMachineAction(self, action: "MachineAction") -> None:
|
||||
"""Remove Machine action from manager
|
||||
|
||||
|
||||
:param action: to remove
|
||||
"""
|
||||
try:
|
||||
|
@ -169,7 +169,7 @@ class MachineActionManager(QObject):
|
|||
|
||||
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
|
||||
"""
|
||||
|
|
|
@ -23,7 +23,7 @@ catalog = i18nCatalog("cura")
|
|||
|
||||
class PrintInformation(QObject):
|
||||
"""A class for processing and the print times per build plate as well as managing the job name
|
||||
|
||||
|
||||
This class also mangles the current machine name and the filename of the first loaded mesh into a job name.
|
||||
This job name is requested by the JobSpecs qml file.
|
||||
"""
|
||||
|
|
|
@ -13,9 +13,9 @@ SEMANTIC_VERSION_REGEX = re.compile(r"^[0-9]+\.[0-9]+(\.[0-9]+)?$")
|
|||
|
||||
def api(since_version: str) -> Callable:
|
||||
"""Decorator for functions that belong to a set of APIs. For now, this should only be used for officially supported
|
||||
|
||||
|
||||
APIs, meaning that those APIs should be versioned and maintained.
|
||||
|
||||
|
||||
:param since_version: The earliest version since when this API becomes supported. This means that since this version,
|
||||
this API function is supposed to behave the same. This parameter is not used. It's just a
|
||||
documentation.
|
||||
|
|
|
@ -59,11 +59,11 @@ class ThreeMFReader(MeshReader):
|
|||
temp_mat = Matrix()
|
||||
"""Transformation is saved as:
|
||||
M00 M01 M02 0.0
|
||||
|
||||
|
||||
M10 M11 M12 0.0
|
||||
|
||||
|
||||
M20 M21 M22 0.0
|
||||
|
||||
|
||||
M30 M31 M32 1.0
|
||||
We switch the row & cols as that is how everyone else uses matrices!
|
||||
"""
|
||||
|
@ -87,7 +87,7 @@ class ThreeMFReader(MeshReader):
|
|||
|
||||
def _convertSavitarNodeToUMNode(self, savitar_node: Savitar.SceneNode, file_name: str = "") -> Optional[SceneNode]:
|
||||
"""Convenience function that converts a SceneNode object (as obtained from libSavitar) to a scene node.
|
||||
|
||||
|
||||
:returns: Scene node.
|
||||
"""
|
||||
try:
|
||||
|
@ -252,7 +252,7 @@ class ThreeMFReader(MeshReader):
|
|||
|
||||
def _getScaleFromUnit(self, unit: Optional[str]) -> Vector:
|
||||
"""Create a scale vector based on a unit string.
|
||||
|
||||
|
||||
.. The core spec defines the following:
|
||||
* micron
|
||||
* millimeter (default)
|
||||
|
|
|
@ -133,7 +133,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
|
||||
def getNewId(self, old_id: str):
|
||||
"""Get a unique name based on the old_id. This is different from directly calling the registry in that it caches results.
|
||||
|
||||
|
||||
This has nothing to do with speed, but with getting consistent new naming for instances & objects.
|
||||
"""
|
||||
if old_id not in self._id_mapping:
|
||||
|
@ -142,7 +142,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
|
||||
def _determineGlobalAndExtruderStackFiles(self, project_file_name: str, file_list: List[str]) -> Tuple[str, List[str]]:
|
||||
"""Separates the given file list into a list of GlobalStack files and a list of ExtruderStack files.
|
||||
|
||||
|
||||
In old versions, extruder stack files have the same suffix as container stack files ".stack.cfg".
|
||||
"""
|
||||
|
||||
|
@ -187,7 +187,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
|
||||
def preRead(self, file_name, show_dialog=True, *args, **kwargs):
|
||||
"""Read some info so we can make decisions
|
||||
|
||||
|
||||
:param file_name:
|
||||
:param show_dialog: In case we use preRead() to check if a file is a valid project file,
|
||||
we don't want to show a dialog.
|
||||
|
@ -588,12 +588,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
@call_on_qt_thread
|
||||
def read(self, file_name):
|
||||
"""Read the project file
|
||||
|
||||
|
||||
Add all the definitions / materials / quality changes that do not exist yet. Then it loads
|
||||
all the stacks into the container registry. In some cases it will reuse the container for the global stack.
|
||||
It handles old style project files containing .stack.cfg as well as new style project files
|
||||
containing global.cfg / extruder.cfg
|
||||
|
||||
|
||||
:param file_name:
|
||||
"""
|
||||
application = CuraApplication.getInstance()
|
||||
|
@ -879,7 +879,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
|
||||
def _createNewQualityChanges(self, quality_type: str, intent_category: Optional[str], name: str, global_stack: GlobalStack, extruder_stack: Optional[ExtruderStack]) -> InstanceContainer:
|
||||
"""Helper class to create a new quality changes profile.
|
||||
|
||||
|
||||
This will then later be filled with the appropriate data.
|
||||
|
||||
:param quality_type: The quality type of the new profile.
|
||||
|
|
|
@ -33,7 +33,7 @@ def getMetaData() -> Dict:
|
|||
"description": catalog.i18nc("@item:inlistbox", "3MF File")
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
return metaData
|
||||
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
|||
@staticmethod
|
||||
def _writeContainerToArchive(container, archive):
|
||||
"""Helper function that writes ContainerStacks, InstanceContainers and DefinitionContainers to the archive.
|
||||
|
||||
|
||||
:param container: That follows the :type{ContainerInterface} to archive.
|
||||
:param archive: The archive to write to.
|
||||
"""
|
||||
|
|
|
@ -62,7 +62,7 @@ class ThreeMFWriter(MeshWriter):
|
|||
|
||||
def setStoreArchive(self, store_archive):
|
||||
"""Should we store the archive
|
||||
|
||||
|
||||
Note that if this is true, the archive will not be closed.
|
||||
The object that set this parameter is then responsible for closing it correctly!
|
||||
"""
|
||||
|
@ -70,7 +70,7 @@ class ThreeMFWriter(MeshWriter):
|
|||
|
||||
def _convertUMNodeToSavitarNode(self, um_node, transformation = Matrix()):
|
||||
"""Convenience function that converts an Uranium SceneNode object to a SavitarSceneNode
|
||||
|
||||
|
||||
:returns: Uranium Scene node.
|
||||
"""
|
||||
if not isinstance(um_node, SceneNode):
|
||||
|
|
|
@ -149,7 +149,7 @@ class AMFReader(MeshReader):
|
|||
|
||||
def _toMeshData(self, tri_node: trimesh.base.Trimesh, file_name: str = "") -> MeshData:
|
||||
"""Converts a Trimesh to Uranium's MeshData.
|
||||
|
||||
|
||||
:param tri_node: A Trimesh containing the contents of a file that was just read.
|
||||
:param file_name: The full original filename used to watch for changes
|
||||
:return: Mesh data from the Trimesh in a way that Uranium can understand it.
|
||||
|
|
|
@ -207,7 +207,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
|
||||
printDurationMessage = Signal()
|
||||
"""Emitted when we get a message containing print duration and material amount.
|
||||
|
||||
|
||||
This also implies the slicing has finished.
|
||||
:param time: The amount of time the print will take.
|
||||
:param material_amount: The amount of material the print will use.
|
||||
|
|
|
@ -30,7 +30,7 @@ catalog = i18nCatalog("cura")
|
|||
|
||||
def colorCodeToRGBA(color_code):
|
||||
"""Return a 4-tuple with floats 0-1 representing the html color code
|
||||
|
||||
|
||||
:param color_code: html color code, i.e. "#FF0000" -> red
|
||||
"""
|
||||
|
||||
|
@ -55,7 +55,7 @@ class ProcessSlicedLayersJob(Job):
|
|||
|
||||
def abort(self):
|
||||
"""Aborts the processing of layers.
|
||||
|
||||
|
||||
This abort is made on a best-effort basis, meaning that the actual
|
||||
job thread will check once in a while to see whether an abort is
|
||||
requested and then stop processing by itself. There is no guarantee
|
||||
|
|
|
@ -16,21 +16,21 @@ import zipfile
|
|||
|
||||
class CuraProfileReader(ProfileReader):
|
||||
"""A plugin that reads profile data from Cura profile files.
|
||||
|
||||
|
||||
It reads a profile from a .curaprofile file, and returns it as a profile
|
||||
instance.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialises the cura profile reader.
|
||||
|
||||
|
||||
This does nothing since the only other function is basically stateless.
|
||||
"""
|
||||
super().__init__()
|
||||
|
||||
def read(self, file_name: str) -> List[Optional[InstanceContainer]]:
|
||||
"""Reads a cura profile from a file and returns it.
|
||||
|
||||
|
||||
:param file_name: The file to read the cura profile from.
|
||||
:return: The cura profiles that were in the file, if any. If the file
|
||||
could not be read or didn't contain a valid profile, ``None`` is
|
||||
|
@ -59,7 +59,7 @@ class CuraProfileReader(ProfileReader):
|
|||
|
||||
def _upgradeProfile(self, serialized: str, profile_id: str) -> List[Tuple[str, str]]:
|
||||
"""Convert a profile from an old Cura to this Cura if needed.
|
||||
|
||||
|
||||
:param serialized: The profile data to convert in the serialized on-disk format.
|
||||
:param profile_id: The name of the profile.
|
||||
:return: List of serialized profile strings and matching profile names.
|
||||
|
@ -85,7 +85,7 @@ class CuraProfileReader(ProfileReader):
|
|||
|
||||
def _loadProfile(self, serialized: str, profile_id: str) -> Optional[InstanceContainer]:
|
||||
"""Load a profile from a serialized string.
|
||||
|
||||
|
||||
:param serialized: The profile data to read.
|
||||
:param profile_id: The name of the profile.
|
||||
:return: The profile that was stored in the string.
|
||||
|
@ -114,7 +114,7 @@ class CuraProfileReader(ProfileReader):
|
|||
|
||||
def _upgradeProfileVersion(self, serialized: str, profile_id: str, main_version: int, setting_version: int) -> List[Tuple[str, str]]:
|
||||
"""Upgrade a serialized profile to the current profile format.
|
||||
|
||||
|
||||
:param serialized: The profile data to convert.
|
||||
:param profile_id: The name of the profile.
|
||||
:param source_version: The profile version of 'serialized'.
|
||||
|
|
|
@ -11,7 +11,7 @@ class CuraProfileWriter(ProfileWriter):
|
|||
|
||||
def write(self, path, profiles):
|
||||
"""Writes a profile to the specified file path.
|
||||
|
||||
|
||||
:param path: :type{string} The file to output to.
|
||||
:param profiles: :type{Profile} :type{List} The profile(s) to write to that file.
|
||||
:return: True if the writing was successful, or
|
||||
|
|
|
@ -20,7 +20,7 @@ i18n_catalog = i18nCatalog("cura")
|
|||
|
||||
class FirmwareUpdateChecker(Extension):
|
||||
"""This Extension checks for new versions of the firmware based on the latest checked version number.
|
||||
|
||||
|
||||
The plugin is currently only usable for applications maintained by Ultimaker. But it should be relatively easy
|
||||
to change it to work for other applications.
|
||||
"""
|
||||
|
@ -62,10 +62,10 @@ class FirmwareUpdateChecker(Extension):
|
|||
|
||||
def checkFirmwareVersion(self, container = None, silent = False):
|
||||
"""Connect with software.ultimaker.com, load latest.version and check version info.
|
||||
|
||||
|
||||
If the version info is different from the current version, spawn a message to
|
||||
allow the user to download it.
|
||||
|
||||
|
||||
:param silent: type(boolean) Suppresses messages other than "new version found" messages.
|
||||
This is used when checking for a new firmware version at startup.
|
||||
"""
|
||||
|
|
|
@ -10,7 +10,7 @@ from UM.PluginRegistry import PluginRegistry
|
|||
|
||||
class GCodeGzReader(MeshReader):
|
||||
"""A file reader that reads gzipped g-code.
|
||||
|
||||
|
||||
If you're zipping g-code, you might as well use gzip!
|
||||
"""
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ catalog = i18nCatalog("cura")
|
|||
|
||||
class GCodeGzWriter(MeshWriter):
|
||||
"""A file writer that writes gzipped g-code.
|
||||
|
||||
|
||||
If you're zipping g-code, you might as well use gzip!
|
||||
"""
|
||||
|
||||
|
@ -26,11 +26,11 @@ class GCodeGzWriter(MeshWriter):
|
|||
|
||||
def write(self, stream: BufferedIOBase, nodes: List[SceneNode], mode = MeshWriter.OutputMode.BinaryMode) -> bool:
|
||||
"""Writes the gzipped g-code to a stream.
|
||||
|
||||
|
||||
Note that even though the function accepts a collection of nodes, the
|
||||
entire scene is always written to the file since it is not possible to
|
||||
separate the g-code for just specific nodes.
|
||||
|
||||
|
||||
:param stream: The stream to write the gzipped g-code to.
|
||||
:param nodes: This is ignored.
|
||||
:param mode: Additional information on what type of stream to use. This
|
||||
|
|
|
@ -15,14 +15,14 @@ from cura.ReaderWriters.ProfileReader import ProfileReader, NoProfileException
|
|||
|
||||
class GCodeProfileReader(ProfileReader):
|
||||
"""A class that reads profile data from g-code files.
|
||||
|
||||
|
||||
It reads the profile data from g-code files and stores it in a new profile.
|
||||
This class currently does not process the rest of the g-code in any way.
|
||||
"""
|
||||
|
||||
version = 3
|
||||
"""The file format version of the serialized g-code.
|
||||
|
||||
|
||||
It can only read settings with the same version as the version it was
|
||||
written with. If the file format is changed in a way that breaks reverse
|
||||
compatibility, increment this version number!
|
||||
|
@ -48,7 +48,7 @@ class GCodeProfileReader(ProfileReader):
|
|||
|
||||
def read(self, file_name):
|
||||
"""Reads a g-code file, loading the profile from it.
|
||||
|
||||
|
||||
:param file_name: The name of the file to read the profile from.
|
||||
:return: The profile that was in the specified file, if any. If the
|
||||
specified file was no g-code or contained no parsable profile,
|
||||
|
@ -106,7 +106,7 @@ class GCodeProfileReader(ProfileReader):
|
|||
|
||||
def unescapeGcodeComment(string: str) -> str:
|
||||
"""Unescape a string which has been escaped for use in a gcode comment.
|
||||
|
||||
|
||||
:param string: The string to unescape.
|
||||
:return: The unescaped string.
|
||||
"""
|
||||
|
@ -120,7 +120,7 @@ def unescapeGcodeComment(string: str) -> str:
|
|||
|
||||
def readQualityProfileFromString(profile_string) -> Optional[InstanceContainer]:
|
||||
"""Read in a profile from a serialized string.
|
||||
|
||||
|
||||
:param profile_string: The profile data in serialized form.
|
||||
:return: The resulting Profile object or None if it could not be read.
|
||||
"""
|
||||
|
|
|
@ -237,7 +237,7 @@ class FlavorParser:
|
|||
|
||||
def _gCode92(self, position: Position, params: PositionOptional, path: List[List[Union[float, int]]]) -> Position:
|
||||
"""Reset the current position to the values specified.
|
||||
|
||||
|
||||
For example: G92 X10 will set the X to 10 without any physical motion.
|
||||
"""
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class RepRapFlavorParser(FlavorParser.FlavorParser):
|
|||
|
||||
def _gCode90(self, position, params, path):
|
||||
"""Set the absolute positioning
|
||||
|
||||
|
||||
RepRapFlavor code G90 sets position of X, Y, Z to absolute
|
||||
For absolute E, M82 is used
|
||||
"""
|
||||
|
@ -30,7 +30,7 @@ class RepRapFlavorParser(FlavorParser.FlavorParser):
|
|||
|
||||
def _gCode91(self, position, params, path):
|
||||
"""Set the relative positioning
|
||||
|
||||
|
||||
RepRapFlavor code G91 sets position of X, Y, Z to relative
|
||||
For relative E, M83 is used
|
||||
"""
|
||||
|
|
|
@ -17,12 +17,12 @@ catalog = i18nCatalog("cura")
|
|||
|
||||
class GCodeWriter(MeshWriter):
|
||||
"""Writes g-code to a file.
|
||||
|
||||
|
||||
While this poses as a mesh writer, what this really does is take the g-code
|
||||
in the entire scene and write it to an output device. Since the g-code of a
|
||||
single mesh isn't separable from the rest what with rafts and travel moves
|
||||
and all, it doesn't make sense to write just a single mesh.
|
||||
|
||||
|
||||
So this plug-in takes the g-code that is stored in the root of the scene
|
||||
node tree, adds a bit of extra information about the profiles and writes
|
||||
that to the output device.
|
||||
|
@ -30,7 +30,7 @@ class GCodeWriter(MeshWriter):
|
|||
|
||||
version = 3
|
||||
"""The file format version of the serialised g-code.
|
||||
|
||||
|
||||
It can only read settings with the same version as the version it was
|
||||
written with. If the file format is changed in a way that breaks reverse
|
||||
compatibility, increment this version number!
|
||||
|
@ -42,9 +42,9 @@ class GCodeWriter(MeshWriter):
|
|||
re.escape("\r"): "\\r" # Carriage return. Windows users may need this for visualisation in their editors.
|
||||
}
|
||||
"""Dictionary that defines how characters are escaped when embedded in
|
||||
|
||||
|
||||
g-code.
|
||||
|
||||
|
||||
Note that the keys of this dictionary are regex strings. The values are
|
||||
not.
|
||||
"""
|
||||
|
@ -58,11 +58,11 @@ class GCodeWriter(MeshWriter):
|
|||
|
||||
def write(self, stream, nodes, mode = MeshWriter.OutputMode.TextMode):
|
||||
"""Writes the g-code for the entire scene to a stream.
|
||||
|
||||
|
||||
Note that even though the function accepts a collection of nodes, the
|
||||
entire scene is always written to the file since it is not possible to
|
||||
separate the g-code for just specific nodes.
|
||||
|
||||
|
||||
:param stream: The stream to write the g-code to.
|
||||
:param nodes: This is ignored.
|
||||
:param mode: Additional information on how to format the g-code in the
|
||||
|
@ -117,10 +117,10 @@ class GCodeWriter(MeshWriter):
|
|||
|
||||
def _serialiseSettings(self, stack):
|
||||
"""Serialises a container stack to prepare it for writing at the end of the g-code.
|
||||
|
||||
|
||||
The settings are serialised, and special characters (including newline)
|
||||
are escaped.
|
||||
|
||||
|
||||
:param stack: A container stack to serialise.
|
||||
:return: A serialised string of the settings.
|
||||
"""
|
||||
|
|
|
@ -18,14 +18,14 @@ from cura.ReaderWriters.ProfileReader import ProfileReader # The plug-in type t
|
|||
|
||||
class LegacyProfileReader(ProfileReader):
|
||||
"""A plugin that reads profile data from legacy Cura versions.
|
||||
|
||||
|
||||
It reads a profile from an .ini file, and performs some translations on it.
|
||||
Not all translations are correct, mind you, but it is a best effort.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialises the legacy profile reader.
|
||||
|
||||
|
||||
This does nothing since the only other function is basically stateless.
|
||||
"""
|
||||
|
||||
|
@ -33,9 +33,9 @@ class LegacyProfileReader(ProfileReader):
|
|||
|
||||
def prepareDefaults(self, json: Dict[str, Dict[str, str]]) -> Dict[str, str]:
|
||||
"""Prepares the default values of all legacy settings.
|
||||
|
||||
|
||||
These are loaded from the Dictionary of Doom.
|
||||
|
||||
|
||||
:param json: The JSON file to load the default setting values from. This
|
||||
should not be a URL but a pre-loaded JSON handle.
|
||||
:return: A dictionary of the default values of the legacy Cura version.
|
||||
|
@ -49,13 +49,13 @@ class LegacyProfileReader(ProfileReader):
|
|||
|
||||
def prepareLocals(self, config_parser, config_section, defaults):
|
||||
"""Prepares the local variables that can be used in evaluation of computing
|
||||
|
||||
|
||||
new setting values from the old ones.
|
||||
|
||||
|
||||
This fills a dictionary with all settings from the legacy Cura version
|
||||
and their values, so that they can be used in evaluating the new setting
|
||||
values as Python code.
|
||||
|
||||
|
||||
:param config_parser: The ConfigParser that finds the settings in the
|
||||
legacy profile.
|
||||
:param config_section: The section in the profile where the settings
|
||||
|
@ -71,7 +71,7 @@ class LegacyProfileReader(ProfileReader):
|
|||
|
||||
def read(self, file_name):
|
||||
"""Reads a legacy Cura profile from a file and returns it.
|
||||
|
||||
|
||||
:param file_name: The file to read the legacy Cura profile from.
|
||||
:return: The legacy Cura profile that was in the file, if any. If the
|
||||
file could not be read or didn't contain a valid profile, None is returned.
|
||||
|
|
|
@ -25,7 +25,7 @@ catalog = UM.i18n.i18nCatalog("cura")
|
|||
|
||||
class MachineSettingsAction(MachineAction):
|
||||
"""This action allows for certain settings that are "machine only") to be modified.
|
||||
|
||||
|
||||
It automatically detects machine definitions that it knows how to change and attaches itself to those.
|
||||
"""
|
||||
def __init__(self, parent: Optional["QObject"] = None) -> None:
|
||||
|
@ -60,7 +60,7 @@ class MachineSettingsAction(MachineAction):
|
|||
|
||||
def _updateHasMaterialsInContainerTree(self) -> None:
|
||||
"""Triggered when the global container stack changes or when the g-code
|
||||
|
||||
|
||||
flavour setting is changed.
|
||||
"""
|
||||
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
|
||||
|
|
|
@ -49,7 +49,7 @@ class ModelChecker(QObject, Extension):
|
|||
|
||||
def _pluginsInitialized(self):
|
||||
"""Called when plug-ins are initialized.
|
||||
|
||||
|
||||
This makes sure that we listen to changes of the material and that the
|
||||
button is created that indicates warnings with the current set-up.
|
||||
"""
|
||||
|
|
|
@ -17,7 +17,7 @@ from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
|
|||
|
||||
class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHandler.SettingVisibilityHandler):
|
||||
"""The per object setting visibility handler ensures that only setting
|
||||
|
||||
|
||||
definitions that have a matching instance Container are returned as visible.
|
||||
"""
|
||||
def __init__(self, parent = None, *args, **kwargs):
|
||||
|
|
|
@ -14,7 +14,7 @@ from UM.Event import Event
|
|||
|
||||
class PerObjectSettingsTool(Tool):
|
||||
"""This tool allows the user to add & change settings per node in the scene.
|
||||
|
||||
|
||||
The settings per object are kept in a ContainerStack, which is linked to a node by decorator.
|
||||
"""
|
||||
def __init__(self):
|
||||
|
@ -52,7 +52,7 @@ class PerObjectSettingsTool(Tool):
|
|||
|
||||
def getSelectedActiveExtruder(self):
|
||||
"""Gets the active extruder of the currently selected object.
|
||||
|
||||
|
||||
:return: The active extruder of the currently selected object.
|
||||
"""
|
||||
|
||||
|
@ -61,7 +61,7 @@ class PerObjectSettingsTool(Tool):
|
|||
|
||||
def setSelectedActiveExtruder(self, extruder_stack_id):
|
||||
"""Changes the active extruder of the currently selected object.
|
||||
|
||||
|
||||
:param extruder_stack_id: The ID of the extruder to print the currently
|
||||
selected object with.
|
||||
"""
|
||||
|
|
|
@ -132,7 +132,7 @@ class PostProcessingPlugin(QObject, Extension):
|
|||
|
||||
def loadAllScripts(self) -> None:
|
||||
"""Load all scripts from all paths where scripts can be found.
|
||||
|
||||
|
||||
This should probably only be done on init.
|
||||
"""
|
||||
|
||||
|
@ -157,7 +157,7 @@ class PostProcessingPlugin(QObject, Extension):
|
|||
|
||||
def loadScripts(self, path: str) -> None:
|
||||
"""Load all scripts from provided path.
|
||||
|
||||
|
||||
This should probably only be done on init.
|
||||
:param path: Path to check for scripts.
|
||||
"""
|
||||
|
@ -360,7 +360,7 @@ class PostProcessingPlugin(QObject, Extension):
|
|||
|
||||
def _propertyChanged(self) -> None:
|
||||
"""Property changed: trigger re-slice
|
||||
|
||||
|
||||
To do this we use the global container stack propertyChanged.
|
||||
Re-slicing is necessary for setting changes in this plugin, because the changes
|
||||
are applied only once per "fresh" gcode
|
||||
|
|
|
@ -81,7 +81,7 @@ class Script:
|
|||
|
||||
def getSettingData(self) -> Dict[str, Any]:
|
||||
"""Needs to return a dict that can be used to construct a settingcategory file.
|
||||
|
||||
|
||||
See the example script for an example.
|
||||
It follows the same style / guides as the Uranium settings.
|
||||
Scripts can either override getSettingData directly, or use getSettingDataString
|
||||
|
@ -116,7 +116,7 @@ class Script:
|
|||
|
||||
def getValue(self, line: str, key: str, default = None) -> Any:
|
||||
"""Convenience function that finds the value in a line of g-code.
|
||||
|
||||
|
||||
When requesting key = x from line "G1 X100" the value 100 is returned.
|
||||
"""
|
||||
if not key in line or (';' in line and line.find(key) > line.find(';')):
|
||||
|
@ -135,7 +135,7 @@ class Script:
|
|||
|
||||
def putValue(self, line: str = "", **kwargs) -> str:
|
||||
"""Convenience function to produce a line of g-code.
|
||||
|
||||
|
||||
You can put in an original g-code line and it'll re-use all the values
|
||||
in that line.
|
||||
All other keyword parameters are put in the result in g-code's format.
|
||||
|
@ -190,7 +190,7 @@ class Script:
|
|||
|
||||
def execute(self, data: List[str]) -> List[str]:
|
||||
"""This is called when the script is executed.
|
||||
|
||||
|
||||
It gets a list of g-code strings and needs to return a (modified) list.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
# Uses -
|
||||
# M163 - Set Mix Factor
|
||||
# M164 - Save Mix - saves to T2 as a unique mix
|
||||
|
||||
|
||||
import re #To perform the search and replace.
|
||||
from ..Script import Script
|
||||
|
||||
|
@ -127,7 +127,7 @@ class ColorMix(Script):
|
|||
firstMix = self.getSettingValueByKey("mix_start")
|
||||
secondMix = self.getSettingValueByKey("mix_finish")
|
||||
modelOfInterest = self.getSettingValueByKey("object_number")
|
||||
|
||||
|
||||
#get layer height
|
||||
layerHeight = 0
|
||||
for active_layer in data:
|
||||
|
@ -138,11 +138,11 @@ class ColorMix(Script):
|
|||
break
|
||||
if layerHeight != 0:
|
||||
break
|
||||
|
||||
|
||||
#default layerHeight if not found
|
||||
if layerHeight == 0:
|
||||
layerHeight = .2
|
||||
|
||||
|
||||
#get layers to use
|
||||
startLayer = 0
|
||||
endLayer = 0
|
||||
|
|
|
@ -56,7 +56,7 @@ class DisplayFilenameAndLayerOnLCD(Script):
|
|||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
|
||||
def execute(self, data):
|
||||
max_layer = 0
|
||||
if self.getSettingValueByKey("name") != "":
|
||||
|
@ -96,5 +96,5 @@ class DisplayFilenameAndLayerOnLCD(Script):
|
|||
i += 1
|
||||
final_lines = "\n".join(lines)
|
||||
data[layer_index] = final_lines
|
||||
|
||||
|
||||
return data
|
||||
|
|
|
@ -65,7 +65,7 @@ class FilamentChange(Script):
|
|||
|
||||
def execute(self, data: List[str]):
|
||||
"""Inserts the filament change g-code at specific layer numbers.
|
||||
|
||||
|
||||
:param data: A list of layers of g-code.
|
||||
:return: A similar list, with filament change commands inserted.
|
||||
"""
|
||||
|
|
|
@ -8,7 +8,7 @@ from ..Script import Script
|
|||
|
||||
class SearchAndReplace(Script):
|
||||
"""Performs a search-and-replace on all g-code.
|
||||
|
||||
|
||||
Due to technical limitations, the search can't cross the border between
|
||||
layers.
|
||||
"""
|
||||
|
|
|
@ -30,7 +30,7 @@ class UsePreviousProbeMeasurements(Script):
|
|||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
|
||||
def execute(self, data):
|
||||
text = "M501 ;load bed level data\nM420 S1 ;enable bed leveling"
|
||||
if self.getSettingValueByKey("use_previous_measurements"):
|
||||
|
|
|
@ -14,7 +14,7 @@ if TYPE_CHECKING:
|
|||
|
||||
class PreviewStage(CuraStage):
|
||||
"""Displays a preview of what you're about to print.
|
||||
|
||||
|
||||
The Python component of this stage just loads PreviewMain.qml for display
|
||||
when the stage is selected, and makes sure that it reverts to the previous
|
||||
view when the previous stage is activated.
|
||||
|
@ -28,14 +28,14 @@ class PreviewStage(CuraStage):
|
|||
|
||||
def onStageSelected(self) -> None:
|
||||
"""When selecting the stage, remember which was the previous view so that
|
||||
|
||||
|
||||
we can revert to that view when we go out of the stage later.
|
||||
"""
|
||||
self._previously_active_view = self._application.getController().getActiveView()
|
||||
|
||||
def onStageDeselected(self) -> None:
|
||||
"""Called when going to a different stage (away from the Preview Stage).
|
||||
|
||||
|
||||
When going to a different stage, the view should be reverted to what it
|
||||
was before. Normally, that just reverts it to solid view.
|
||||
"""
|
||||
|
@ -46,7 +46,7 @@ class PreviewStage(CuraStage):
|
|||
|
||||
def _engineCreated(self) -> None:
|
||||
"""Delayed load of the QML files.
|
||||
|
||||
|
||||
We need to make sure that the QML engine is running before we can load
|
||||
these.
|
||||
"""
|
||||
|
|
|
@ -13,7 +13,7 @@ import subprocess
|
|||
|
||||
class LinuxRemovableDrivePlugin(RemovableDrivePlugin.RemovableDrivePlugin):
|
||||
"""Support for removable devices on Linux.
|
||||
|
||||
|
||||
TODO: This code uses the most basic interfaces for handling this.
|
||||
We should instead use UDisks2 to handle mount/unmount and hotplugging events.
|
||||
"""
|
||||
|
|
|
@ -30,7 +30,7 @@ class RemovableDriveOutputDevice(OutputDevice):
|
|||
|
||||
def requestWrite(self, nodes, file_name = None, filter_by_machine = False, file_handler = None, **kwargs):
|
||||
"""Request the specified nodes to be written to the removable drive.
|
||||
|
||||
|
||||
:param nodes: A collection of scene nodes that should be written to the
|
||||
removable drive.
|
||||
:param file_name: :type{string} A suggestion for the file name to write to.
|
||||
|
@ -38,7 +38,7 @@ class RemovableDriveOutputDevice(OutputDevice):
|
|||
meshes.
|
||||
:param limit_mimetypes: Should we limit the available MIME types to the
|
||||
MIME types available to the currently active machine?
|
||||
|
||||
|
||||
"""
|
||||
|
||||
filter_by_machine = True # This plugin is intended to be used by machine (regardless of what it was told to do)
|
||||
|
@ -110,10 +110,10 @@ class RemovableDriveOutputDevice(OutputDevice):
|
|||
|
||||
def _automaticFileName(self, nodes):
|
||||
"""Generate a file name automatically for the specified nodes to be saved in.
|
||||
|
||||
|
||||
The name generated will be the name of one of the nodes. Which node that
|
||||
is can not be guaranteed.
|
||||
|
||||
|
||||
:param nodes: A collection of nodes for which to generate a file name.
|
||||
"""
|
||||
for root in nodes:
|
||||
|
|
|
@ -20,7 +20,7 @@ class SentryLogger(LogOutput):
|
|||
# processed and ready for sending.
|
||||
# Note that this only prepares them for sending. It only sends them when the user actually agrees to sending the
|
||||
# information.
|
||||
|
||||
|
||||
_levels = {
|
||||
"w": "warning",
|
||||
"i": "info",
|
||||
|
@ -32,10 +32,10 @@ class SentryLogger(LogOutput):
|
|||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._show_once = set() # type: Set[str]
|
||||
|
||||
|
||||
def log(self, log_type: str, message: str) -> None:
|
||||
"""Log the message to the sentry hub as a breadcrumb
|
||||
|
||||
|
||||
:param log_type: "e" (error), "i"(info), "d"(debug), "w"(warning) or "c"(critical) (can postfix with "_once")
|
||||
:param message: String containing message to be logged
|
||||
"""
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue