diff options
author | Jelle Spijker <j.spijker@ultimaker.com> | 2020-04-21 17:58:45 +0300 |
---|---|---|
committer | Jelle Spijker <spijker.jelle@gmail.com> | 2020-04-21 17:58:45 +0300 |
commit | 6aedab78dc2e8c55fe6323ff3647203d8b994509 (patch) | |
tree | 536bc25c1adc134bf4ce675fb0336f73974f1dff | |
parent | fb4aec96a86c8a13109997c52528ba84ba103e25 (diff) |
Converted comments in dir Cura/cura to rst style
Converted doxygen style comments to reStructuredText style in the files found in Cura/cura directory using the script dox_2_rst.py (provided in the Uranium repo). Comments were manually checked and changed if needed.
-rwxr-xr-x | cura/BuildVolume.py | 140 | ||||
-rw-r--r-- | cura/CrashHandler.py | 6 | ||||
-rw-r--r-- | cura/CuraActions.py | 25 | ||||
-rwxr-xr-x | cura/CuraApplication.py | 147 | ||||
-rw-r--r-- | cura/CuraPackageManager.py | 12 | ||||
-rw-r--r-- | cura/LayerData.py | 7 | ||||
-rwxr-xr-x | cura/LayerDataBuilder.py | 13 | ||||
-rw-r--r-- | cura/LayerDataDecorator.py | 3 | ||||
-rw-r--r-- | cura/LayerPolygon.py | 53 | ||||
-rw-r--r-- | cura/MachineAction.py | 50 | ||||
-rw-r--r-- | cura/OneAtATimeIterator.py | 51 | ||||
-rw-r--r-- | cura/PickingPass.py | 28 | ||||
-rw-r--r-- | cura/PreviewPass.py | 24 | ||||
-rw-r--r-- | cura/PrintJobPreviewImageProvider.py | 8 | ||||
-rw-r--r-- | cura/Snapshot.py | 12 |
15 files changed, 371 insertions, 208 deletions
diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 36edd427f7..76316f5e43 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -44,8 +44,9 @@ catalog = i18nCatalog("cura") PRIME_CLEARANCE = 6.5 -## Build volume is a special kind of node that is responsible for rendering the printable area & disallowed areas. class BuildVolume(SceneNode): + """Build volume is a special kind of node that is responsible for rendering the printable area & disallowed areas.""" + raftThicknessChanged = Signal() def __init__(self, application: "CuraApplication", parent: Optional[SceneNode] = None) -> None: @@ -113,7 +114,7 @@ class BuildVolume(SceneNode): self._has_errors = False self._application.getController().getScene().sceneChanged.connect(self._onSceneChanged) - #Objects loaded at the moment. We are connected to the property changed events of these objects. + # Objects loaded at the moment. We are connected to the property changed events of these objects. self._scene_objects = set() # type: Set[SceneNode] self._scene_change_timer = QTimer() @@ -163,10 +164,12 @@ class BuildVolume(SceneNode): self._scene_objects = new_scene_objects self._onSettingPropertyChanged("print_sequence", "value") # Create fake event, so right settings are triggered. - ## Updates the listeners that listen for changes in per-mesh stacks. - # - # \param node The node for which the decorators changed. 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. + """ + per_mesh_stack = node.callDecoration("getStack") if per_mesh_stack: per_mesh_stack.propertyChanged.connect(self._onSettingPropertyChanged) @@ -187,10 +190,14 @@ class BuildVolume(SceneNode): if shape: self._shape = shape - ## Get the length of the 3D diagonal through the build volume. - # - # This gives a sense of the scale of the build volume in general. def getDiagonalSize(self) -> float: + """Get the length of the 3D diagonal through the build volume. + + This gives a sense of the scale of the build volume in general. + + :return: length of the 3D diagonal through the build volume + """ + return math.sqrt(self._width * self._width + self._height * self._height + self._depth * self._depth) def getDisallowedAreas(self) -> List[Polygon]: @@ -226,9 +233,9 @@ class BuildVolume(SceneNode): return True - ## For every sliceable node, update node._outside_buildarea - # def updateNodeBoundaryCheck(self): + """For every sliceable node, update node._outside_buildarea""" + if not self._global_container_stack: return @@ -295,8 +302,13 @@ class BuildVolume(SceneNode): for child_node in children: child_node.setOutsideBuildArea(group_node.isOutsideBuildArea()) - ## Update the outsideBuildArea of a single node, given bounds or current build volume def checkBoundsAndUpdate(self, node: CuraSceneNode, bounds: Optional[AxisAlignedBox] = None) -> None: + """Update the outsideBuildArea of a single node, given bounds or current build volume + + :param node: single node + :param bounds: bounds or current build volume + """ + if not isinstance(node, CuraSceneNode) or self._global_container_stack is None: return @@ -484,8 +496,9 @@ class BuildVolume(SceneNode): self._disallowed_area_size = max(size, self._disallowed_area_size) return mb.build() - ## Recalculates the build volume & disallowed areas. def rebuild(self) -> None: + """Recalculates the build volume & disallowed areas.""" + if not self._width or not self._height or not self._depth: return @@ -586,8 +599,9 @@ class BuildVolume(SceneNode): def _onStackChanged(self): self._stack_change_timer.start() - ## Update the build volume visualization def _onStackChangeTimerFinished(self) -> None: + """Update the build volume visualization""" + if self._global_container_stack: self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged) extruders = ExtruderManager.getInstance().getActiveExtruderStacks() @@ -712,15 +726,15 @@ class BuildVolume(SceneNode): self._depth = self._global_container_stack.getProperty("machine_depth", "value") self._shape = self._global_container_stack.getProperty("machine_shape", "value") - ## Calls _updateDisallowedAreas and makes sure the changes appear in the - # scene. - # - # This is required for a signal to trigger the update in one go. The - # ``_updateDisallowedAreas`` method itself shouldn't call ``rebuild``, - # since there may be other changes before it needs to be rebuilt, which - # would hit performance. - 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, + which would hit performance. + """ + self._updateDisallowedAreas() self._updateRaftThickness() self._extra_z_clearance = self._calculateExtraZClearance(ExtruderManager.getInstance().getUsedExtruderStacks()) @@ -782,15 +796,14 @@ class BuildVolume(SceneNode): for extruder_id in result_areas_no_brim: self._disallowed_areas_no_brim.extend(result_areas_no_brim[extruder_id]) - ## 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. 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. + """ + result = {} adhesion_extruder = None #type: ExtruderStack for extruder in used_extruders: @@ -828,18 +841,18 @@ class BuildVolume(SceneNode): return result - ## 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. - # \return A dictionary with for each used extruder ID the prime areas. 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. + :return: A dictionary with for each used extruder ID the prime areas. + """ + result = {} # type: Dict[str, List[Polygon]] if not self._global_container_stack: return result @@ -867,19 +880,18 @@ class BuildVolume(SceneNode): return result - ## 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. - # - # \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. - # \return A dictionary with for each used extruder ID the disallowed areas - # where that extruder may not print. 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. + + :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. + :return: A dictionary with for each used extruder ID the disallowed areas where that extruder may not print. + """ + # Convert disallowed areas to polygons and dilate them. machine_disallowed_polygons = [] if self._global_container_stack is None: @@ -1010,13 +1022,14 @@ class BuildVolume(SceneNode): return result - ## 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. 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. + """ + all_values = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "value") all_types = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "type") for i, (setting_value, setting_type) in enumerate(zip(all_values, all_types)): @@ -1101,12 +1114,13 @@ class BuildVolume(SceneNode): return move_from_wall_radius - ## 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. 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. + """ + if not self._global_container_stack or not self._global_container_stack.extruderList: return 0 diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index ab7a7ebdd1..75fdd99798 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -150,8 +150,9 @@ class CrashHandler: self._sendCrashReport() os._exit(1) - ## Backup the current resource directories and create clean ones. def _backupAndStartClean(self): + """Backup the current resource directories and create clean ones.""" + Resources.factoryReset() self.early_crash_dialog.close() @@ -162,8 +163,9 @@ class CrashHandler: def _showDetailedReport(self): self.dialog.exec_() - ## Creates a modal dialog. def _createDialog(self): + """Creates a modal dialog.""" + self.dialog.setMinimumWidth(640) self.dialog.setMinimumHeight(640) self.dialog.setWindowTitle(catalog.i18nc("@title:window", "Crash Report")) diff --git a/cura/CuraActions.py b/cura/CuraActions.py index 20c44c7916..3b37c69adc 100644 --- a/cura/CuraActions.py +++ b/cura/CuraActions.py @@ -43,9 +43,10 @@ class CuraActions(QObject): event = CallFunctionEvent(self._openUrl, [QUrl("https://github.com/Ultimaker/Cura/issues")], {}) cura.CuraApplication.CuraApplication.getInstance().functionEvent(event) - ## Reset camera position and direction to default @pyqtSlot() def homeCamera(self) -> None: + """Reset camera position and direction to default""" + scene = cura.CuraApplication.CuraApplication.getInstance().getController().getScene() camera = scene.getActiveCamera() if camera: @@ -54,9 +55,10 @@ class CuraActions(QObject): camera.setPerspective(True) camera.lookAt(Vector(0, 0, 0)) - ## Center all objects in the selection @pyqtSlot() def centerSelection(self) -> None: + """Center all objects in the selection""" + operation = GroupedOperation() for node in Selection.getAllSelectedObjects(): current_node = node @@ -73,18 +75,21 @@ class CuraActions(QObject): operation.addOperation(center_operation) operation.push() - ## Multiply all objects in the selection - # - # \param count The number of times to multiply the selection. @pyqtSlot(int) def multiplySelection(self, count: int) -> None: + """Multiply all objects in the selection + + :param count: The number of times to multiply the selection. + """ + min_offset = cura.CuraApplication.CuraApplication.getInstance().getBuildVolume().getEdgeDisallowedSize() + 2 # Allow for some rounding errors job = MultiplyObjectsJob(Selection.getAllSelectedObjects(), count, min_offset = max(min_offset, 8)) job.start() - ## Delete all selected objects. @pyqtSlot() def deleteSelection(self) -> None: + """Delete all selected objects.""" + if not cura.CuraApplication.CuraApplication.getInstance().getController().getToolsEnabled(): return @@ -106,11 +111,13 @@ class CuraActions(QObject): op.push() - ## 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. @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. + """ + operation = GroupedOperation() nodes_to_change = [] diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 993bb15ae2..a588be3d5c 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -258,9 +258,12 @@ class CuraApplication(QtApplication): def ultimakerCloudAccountRootUrl(self) -> str: return UltimakerCloudAuthentication.CuraCloudAccountAPIRoot - # Adds command line options to the command line parser. This should be called after the application is created and - # before the pre-start. def addCommandLineOptions(self): + """Adds command line options to the command line parser. + + This should be called after the application is created and before the pre-start. + """ + super().addCommandLineOptions() self._cli_parser.add_argument("--help", "-h", action = "store_true", @@ -322,8 +325,9 @@ class CuraApplication(QtApplication): Logger.log("i", "Single instance commands were sent, exiting") sys.exit(0) - # Adds expected directory names and search paths for Resources. def __addExpectedResourceDirsAndSearchPaths(self): + """Adds expected directory names and search paths for Resources.""" + # this list of dir names will be used by UM to detect an old cura directory for dir_name in ["extruders", "machine_instances", "materials", "plugins", "quality", "quality_changes", "user", "variants", "intent"]: Resources.addExpectedDirNameInData(dir_name) @@ -365,9 +369,12 @@ class CuraApplication(QtApplication): SettingDefinition.addSettingType("[int]", None, str, None) - # Adds custom property types, settings types, and extra operators (functions) that need to be registered in - # SettingDefinition and SettingFunction. def _initializeSettingFunctions(self): + """Adds custom property types, settings types, and extra operators (functions). + + Whom need to be registered in SettingDefinition and SettingFunction. + """ + self._cura_formula_functions = CuraFormulaFunctions(self) SettingFunction.registerOperator("extruderValue", self._cura_formula_functions.getValueInExtruder) @@ -377,8 +384,9 @@ class CuraApplication(QtApplication): SettingFunction.registerOperator("valueFromContainer", self._cura_formula_functions.getValueFromContainerAtIndex) SettingFunction.registerOperator("extruderValueFromContainer", self._cura_formula_functions.getValueFromContainerAtIndexInExtruder) - # Adds all resources and container related resources. def __addAllResourcesAndContainerResources(self) -> None: + """Adds all resources and container related resources.""" + Resources.addStorageType(self.ResourceTypes.QualityInstanceContainer, "quality") Resources.addStorageType(self.ResourceTypes.QualityChangesInstanceContainer, "quality_changes") Resources.addStorageType(self.ResourceTypes.VariantInstanceContainer, "variants") @@ -403,8 +411,9 @@ class CuraApplication(QtApplication): Resources.addType(self.ResourceTypes.QmlFiles, "qml") Resources.addType(self.ResourceTypes.Firmware, "firmware") - # Adds all empty containers. def __addAllEmptyContainers(self) -> None: + """Adds all empty containers.""" + # Add empty variant, material and quality containers. # Since they are empty, they should never be serialized and instead just programmatically created. # We need them to simplify the switching between materials. @@ -429,9 +438,11 @@ class CuraApplication(QtApplication): self._container_registry.addContainer(cura.Settings.cura_empty_instance_containers.empty_quality_changes_container) self.empty_quality_changes_container = cura.Settings.cura_empty_instance_containers.empty_quality_changes_container - # Initializes the version upgrade manager with by providing the paths for each resource type and the latest - # versions. def __setLatestResouceVersionsForVersionUpgrade(self): + """Initializes the version upgrade manager with by providing the paths for each resource type and the latest + versions. + """ + self._version_upgrade_manager.setCurrentVersions( { ("quality", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"), @@ -446,8 +457,9 @@ class CuraApplication(QtApplication): } ) - # Runs preparations that needs to be done before the starting process. def startSplashWindowPhase(self) -> None: + """Runs preparations that needs to be done before the starting process.""" + super().startSplashWindowPhase() if not self.getIsHeadLess(): @@ -503,7 +515,7 @@ class CuraApplication(QtApplication): # Set the setting version for Preferences preferences = self.getPreferences() preferences.addPreference("metadata/setting_version", 0) - preferences.setValue("metadata/setting_version", self.SettingVersion) #Don't make it equal to the default so that the setting version always gets written to the file. + preferences.setValue("metadata/setting_version", self.SettingVersion) # Don't make it equal to the default so that the setting version always gets written to the file. preferences.addPreference("cura/active_mode", "simple") @@ -607,12 +619,13 @@ class CuraApplication(QtApplication): def callConfirmExitDialogCallback(self, yes_or_no: bool) -> None: self._confirm_exit_dialog_callback(yes_or_no) - ## Signal to connect preferences action in QML showPreferencesWindow = pyqtSignal() + """Signal to connect preferences action in QML""" - ## Show the preferences window @pyqtSlot() def showPreferences(self) -> None: + """Show the preferences window""" + self.showPreferencesWindow.emit() # This is called by drag-and-dropping curapackage files. @@ -630,10 +643,9 @@ class CuraApplication(QtApplication): self._setLoadingHint(self._i18n_catalog.i18nc("@info:progress", "Initializing Active Machine...")) super().setGlobalContainerStack(stack) - ## A reusable dialogbox - # showMessageBox = pyqtSignal(str,str, str, str, int, int, arguments = ["title", "text", "informativeText", "detailedText","buttons", "icon"]) + """ A reusable dialogbox""" def messageBox(self, title, text, informativeText = "", @@ -711,9 +723,12 @@ class CuraApplication(QtApplication): def setDefaultPath(self, key, default_path): self.getPreferences().setValue("local_file/%s" % key, QUrl(default_path).toLocalFile()) - ## Handle loading of all plugin types (and the backend explicitly) - # \sa PluginRegistry def _loadPlugins(self) -> None: + """Handle loading of all plugin types (and the backend explicitly) + + :py:class:`Uranium.UM.PluginRegistry` + """ + self._plugin_registry.setCheckIfTrusted(ApplicationMetadata.IsEnterpriseVersion) self._plugin_registry.addType("profile_reader", self._addProfileReader) @@ -737,9 +752,12 @@ class CuraApplication(QtApplication): self._plugins_loaded = True - ## Set a short, user-friendly hint about current loading status. - # The way this message is displayed depends on application state 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 + """ + if self.started: Logger.info(hint) else: @@ -824,12 +842,14 @@ class CuraApplication(QtApplication): initializationFinished = pyqtSignal() - ## Run Cura without GUI elements and interaction (server mode). def runWithoutGUI(self): + """Run Cura without GUI elements and interaction (server mode).""" + self.closeSplash() - ## Run Cura with GUI (desktop mode). def runWithGUI(self): + """Run Cura with GUI (desktop mode).""" + self._setLoadingHint(self._i18n_catalog.i18nc("@info:progress", "Setting up scene...")) controller = self.getController() @@ -979,10 +999,13 @@ class CuraApplication(QtApplication): self._setting_inheritance_manager = SettingInheritanceManager.createSettingInheritanceManager() return self._setting_inheritance_manager - ## 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. 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. + """ + return cast(MachineActionManager.MachineActionManager, self._machine_action_manager) @pyqtSlot(result = QObject) @@ -1002,8 +1025,9 @@ class CuraApplication(QtApplication): self._simple_mode_settings_manager = SimpleModeSettingsManager() return self._simple_mode_settings_manager - ## Handle Qt events def event(self, event): + """Handle Qt events""" + if event.type() == QEvent.FileOpen: if self._plugins_loaded: self._openFile(event.file()) @@ -1015,8 +1039,9 @@ class CuraApplication(QtApplication): def getAutoSave(self) -> Optional[AutoSave]: return self._auto_save - ## Get print information (duration / material used) def getPrintInformation(self): + """Get print information (duration / material used)""" + return self._print_information def getQualityProfilesDropDownMenuModel(self, *args, **kwargs): @@ -1032,10 +1057,12 @@ class CuraApplication(QtApplication): def getCuraAPI(self, *args, **kwargs) -> "CuraAPI": return self._cura_API - ## Registers objects for the QML engine to use. - # - # \param engine The QML engine. def registerObjects(self, engine): + """Registers objects for the QML engine to use. + + :param engine: The QML engine. + """ + super().registerObjects(engine) # global contexts @@ -1169,8 +1196,9 @@ class CuraApplication(QtApplication): if node is not None and (node.getMeshData() is not None or node.callDecoration("getLayerData")): self._update_platform_activity_timer.start() - ## Update scene bounding box for current build plate def updatePlatformActivity(self, node = None): + """Update scene bounding box for current build plate""" + count = 0 scene_bounding_box = None is_block_slicing_node = False @@ -1214,9 +1242,10 @@ class CuraApplication(QtApplication): self._platform_activity = True if count > 0 else False self.activityChanged.emit() - ## Select all nodes containing mesh data in the scene. @pyqtSlot() def selectAll(self): + """Select all nodes containing mesh data in the scene.""" + if not self.getController().getToolsEnabled(): return @@ -1235,9 +1264,10 @@ class CuraApplication(QtApplication): Selection.add(node) - ## Reset all translation on nodes with mesh data. @pyqtSlot() def resetAllTranslation(self): + """Reset all translation on nodes with mesh data.""" + Logger.log("i", "Resetting all scene translations") nodes = [] for node in DepthFirstIterator(self.getController().getScene().getRoot()): @@ -1263,9 +1293,10 @@ class CuraApplication(QtApplication): op.addOperation(SetTransformOperation(node, Vector(0, center_y, 0))) op.push() - ## Reset all transformations on nodes with mesh data. @pyqtSlot() def resetAll(self): + """Reset all transformations on nodes with mesh data.""" + Logger.log("i", "Resetting all scene transformations") nodes = [] for node in DepthFirstIterator(self.getController().getScene().getRoot()): @@ -1291,9 +1322,10 @@ class CuraApplication(QtApplication): op.addOperation(SetTransformOperation(node, Vector(0, center_y, 0), Quaternion(), Vector(1, 1, 1))) op.push() - ## Arrange all objects. @pyqtSlot() def arrangeObjectsToAllBuildPlates(self) -> None: + """Arrange all objects.""" + nodes_to_arrange = [] for node in DepthFirstIterator(self.getController().getScene().getRoot()): if not isinstance(node, SceneNode): @@ -1346,17 +1378,21 @@ class CuraApplication(QtApplication): nodes_to_arrange.append(node) self.arrange(nodes_to_arrange, fixed_nodes = []) - ## 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 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 + """ + min_offset = self.getBuildVolume().getEdgeDisallowedSize() + 2 # Allow for some rounding errors job = ArrangeObjectsJob(nodes, fixed_nodes, min_offset = max(min_offset, 8)) job.start() - ## Reload all mesh data on the screen from file. @pyqtSlot() def reloadAll(self) -> None: + """Reload all mesh data on the screen from file.""" + Logger.log("i", "Reloading all loaded mesh data.") nodes = [] has_merged_nodes = False @@ -1466,8 +1502,9 @@ class CuraApplication(QtApplication): group_node.setName("MergedMesh") # add a specific name to distinguish this node - ## Updates origin position of all merged meshes def updateOriginOfMergedMeshes(self, _): + """Updates origin position of all merged meshes""" + group_nodes = [] for node in DepthFirstIterator(self.getController().getScene().getRoot()): if isinstance(node, CuraSceneNode) and node.getName() == "MergedMesh": @@ -1585,9 +1622,10 @@ class CuraApplication(QtApplication): scene from its source file. The function gets all the nodes that exist in the file through the job result, and then finds the scene node that it wants to refresh by its object id. Each job refreshes only one node. - :param job: The ReadMeshJob running in the background that reads all the meshes in a file - :return: None + :param job: The :py:class:`Uranium.UM.ReadMeshJob.ReadMeshJob` running in the background that reads all the + meshes in a file """ + job_result = job.getResult() # nodes that exist inside the file read by this job if len(job_result) == 0: Logger.log("e", "Reloading the mesh failed.") @@ -1633,12 +1671,15 @@ class CuraApplication(QtApplication): def additionalComponents(self): return self._additional_components - ## 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 \type{str} Identifying name of the area to which the component should be reparented - # \param component \type{QQuickComponent} The component that should be reparented @pyqtSlot(str, "QVariant") - def addAdditionalComponent(self, area_id, component): + 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 + """ + if area_id not in self._additional_components: self._additional_components[area_id] = [] self._additional_components[area_id].append(component) @@ -1653,10 +1694,13 @@ class CuraApplication(QtApplication): @pyqtSlot(QUrl, str) @pyqtSlot(QUrl) - ## 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. 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. + """ + if not file.isValid(): return @@ -1829,9 +1873,8 @@ class CuraApplication(QtApplication): @pyqtSlot(str, result=bool) def checkIsValidProjectFile(self, file_url): - """ - Checks if the given file URL is a valid project file. - """ + """ Checks if the given file URL is a valid project file. """ + file_path = QUrl(file_url).toLocalFile() workspace_reader = self.getWorkspaceFileHandler().getReaderForFile(file_path) if workspace_reader is None: diff --git a/cura/CuraPackageManager.py b/cura/CuraPackageManager.py index a0d3a8d44a..fa862f3f9e 100644 --- a/cura/CuraPackageManager.py +++ b/cura/CuraPackageManager.py @@ -24,11 +24,15 @@ class CuraPackageManager(PackageManager): super().initialize() - ## Returns a list of where the package is used - # empty if it is never used. - # It loops through all the package contents and see if some of the ids are used. - # The list consists of 3-tuples: (global_stack, extruder_nr, container_id) def getMachinesUsingPackage(self, package_id: str) -> Tuple[List[Tuple[GlobalStack, str, str]], List[Tuple[GlobalStack, str, str]]]: + """Returns a list of where the package is used + + It loops through all the package contents and see if some of the ids are used. + + :param package_id: package id to search for + :return: empty if it is never used, otherwise a list consisting of 3-tuples + """ + ids = self.getPackageContainerIds(package_id) container_stacks = self._application.getContainerRegistry().findContainerStacks() global_stacks = [container_stack for container_stack in container_stacks if isinstance(container_stack, GlobalStack)] diff --git a/cura/LayerData.py b/cura/LayerData.py index 72824591ab..1b3f2a978e 100644 --- a/cura/LayerData.py +++ b/cura/LayerData.py @@ -3,9 +3,12 @@ from UM.Mesh.MeshData import MeshData -## Class to holds the layer mesh and information about the layers. -# Immutable, use LayerDataBuilder to create one of these. 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. + """ + def __init__(self, vertices = None, normals = None, indices = None, colors = None, uvs = None, file_name = None, center_position = None, layers=None, element_counts=None, attributes=None): super().__init__(vertices=vertices, normals=normals, indices=indices, colors=colors, uvs=uvs, diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index e8d1b8c59f..4650248780 100755 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -10,8 +10,9 @@ import numpy from typing import Dict, Optional -## Builder class for constructing a LayerData object class LayerDataBuilder(MeshBuilder): + """Builder class for constructing a :py:class:`cura.LayerData.LayerData` object""" + def __init__(self) -> None: super().__init__() self._layers = {} # type: Dict[int, Layer] @@ -42,11 +43,13 @@ class LayerDataBuilder(MeshBuilder): self._layers[layer].setThickness(thickness) - ## Return the layer data as 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 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 + """ + vertex_count = 0 index_count = 0 for layer, data in self._layers.items(): diff --git a/cura/LayerDataDecorator.py b/cura/LayerDataDecorator.py index 36466cac72..66924e8d2c 100644 --- a/cura/LayerDataDecorator.py +++ b/cura/LayerDataDecorator.py @@ -7,8 +7,9 @@ from UM.Scene.SceneNodeDecorator import SceneNodeDecorator from cura.LayerData import LayerData -## Simple decorator to indicate a scene node holds layer data. class LayerDataDecorator(SceneNodeDecorator): + """Simple decorator to indicate a scene node holds layer data.""" + def __init__(self) -> None: super().__init__() self._layer_data = None # type: Optional[LayerData] diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 70d818f1ca..38d4f756a4 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -26,14 +26,17 @@ class LayerPolygon: __jump_map = numpy.logical_or(numpy.logical_or(numpy.arange(__number_of_types) == NoneType, numpy.arange(__number_of_types) == MoveCombingType), numpy.arange(__number_of_types) == MoveRetractionType) - ## LayerPolygon, used in ProcessSlicedLayersJob - # \param extruder The position of the extruder - # \param line_types array with line_types - # \param data new_points - # \param line_widths array with line widths - # \param line_thicknesses: array with type as index and thickness as value - # \param line_feedrates array with line feedrates def __init__(self, extruder: int, line_types: numpy.ndarray, data: numpy.ndarray, line_widths: numpy.ndarray, line_thicknesses: numpy.ndarray, line_feedrates: numpy.ndarray) -> None: + """LayerPolygon, used in ProcessSlicedLayersJob + + :param extruder: The position of the extruder + :param line_types: array with line_types + :param data: new_points + :param line_widths: array with line widths + :param line_thicknesses: array with type as index and thickness as value + :param line_feedrates: array with line feedrates + """ + self._extruder = extruder self._types = line_types for i in range(len(self._types)): @@ -83,19 +86,22 @@ class LayerPolygon: self._vertex_begin = 0 self._vertex_end = numpy.sum( self._build_cache_needed_points ) - ## 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 - # \param colors : vertex numpy array to be filled - # \param line_dimensions : vertex numpy array to be filled - # \param feedrates : vertex numpy array to be filled - # \param extruders : vertex numpy array to be filled - # \param line_types : vertex numpy array to be filled - # \param indices : index numpy array to be filled 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 + :param colors: : vertex numpy array to be filled + :param line_dimensions: : vertex numpy array to be filled + :param feedrates: : vertex numpy array to be filled + :param extruders: : vertex numpy array to be filled + :param line_types: : vertex numpy array to be filled + :param indices: : index numpy array to be filled + """ + if self._build_cache_line_mesh_mask is None or self._build_cache_needed_points is None: self.buildCache() @@ -202,8 +208,12 @@ class LayerPolygon: def jumpCount(self): return self._jump_count - # Calculate normals for the entire polygon using numpy. def getNormals(self) -> numpy.ndarray: + """Calculate normals for the entire polygon using numpy. + + :return: normals for the entire polygon + """ + normals = numpy.copy(self._data) normals[:, 1] = 0.0 # We are only interested in 2D normals @@ -229,9 +239,10 @@ class LayerPolygon: __color_map = None # type: numpy.ndarray - ## Gets the instance of the VersionUpgradeManager, or creates one. @classmethod def getColorMap(cls) -> numpy.ndarray: + """Gets the instance of the VersionUpgradeManager, or creates one.""" + if cls.__color_map is None: theme = cast(Theme, QtApplication.getInstance().getTheme()) cls.__color_map = numpy.array([ diff --git a/cura/MachineAction.py b/cura/MachineAction.py index 0f05401c89..4c2b4e7aea 100644 --- a/cura/MachineAction.py +++ b/cura/MachineAction.py @@ -11,16 +11,22 @@ from UM.PluginObject import PluginObject from UM.PluginRegistry import PluginRegistry -## Machine actions are actions that are added to a specific machine type. Examples of such actions are -# updating the firmware, connecting with remote devices or doing bed leveling. A machine action can also have a -# qml, which should contain a "Cura.MachineAction" item. When activated, the item will be displayed in a dialog -# and this object will be added as "manager" (so all pyqtSlot() functions can be called by calling manager.func()) class MachineAction(QObject, PluginObject): + """Machine actions are actions that are added to a specific machine type. + + Examples of such actions are updating the firmware, connecting with remote devices or doing bed leveling. A + machine action can also have a qml, which should contain a :py:class:`cura.MachineAction.MachineAction` item. + When activated, the item will be displayed in a dialog and this object will be added as "manager" (so all + pyqtSlot() functions can be called by calling manager.func()) + """ - ## Create a new Machine action. - # \param key unique key of the machine action - # \param label Human readable label used to identify the machine action. def __init__(self, key: str, label: str = "") -> None: + """Create a new Machine action. + + :param key: unique key of the machine action + :param label: Human readable label used to identify the machine action. + """ + super().__init__() self._key = key self._label = label @@ -34,10 +40,14 @@ class MachineAction(QObject, PluginObject): def getKey(self) -> str: return self._key - ## Whether this action needs to ask the user anything. - # If not, we shouldn't present the user with certain screens which otherwise show up. - # Defaults to true to be in line with the old behaviour. def needsUserInteraction(self) -> bool: + """Whether this action needs to ask the user anything. + + If not, we shouldn't present the user with certain screens which otherwise show up. + + :return: Defaults to true to be in line with the old behaviour. + """ + return True @pyqtProperty(str, notify = labelChanged) @@ -49,17 +59,24 @@ class MachineAction(QObject, PluginObject): self._label = label self.labelChanged.emit() - ## Reset the action to it's default state. - # This should not be re-implemented by child classes, instead re-implement _reset. - # /sa _reset @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` + """ + self._finished = False self._reset() - ## Protected implementation of reset. - # /sa reset() def _reset(self) -> None: + """Protected implementation of reset. + + :py:meth:`cura.MachineAction.MachineAction.reset` + """ + pass @pyqtSlot() @@ -72,8 +89,9 @@ class MachineAction(QObject, PluginObject): def finished(self) -> bool: return self._finished - ## Protected helper to create a view object based on provided QML. def _createViewFromQML(self) -> Optional["QObject"]: + """Protected helper to create a view object based on provided QML.""" + plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId()) if plugin_path is None: Logger.log("e", "Cannot create QML view: cannot find plugin path for plugin [%s]", self.getPluginId()) diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py index 3373f2104f..4853cffcc1 100644 --- a/cura/OneAtATimeIterator.py +++ b/cura/OneAtATimeIterator.py @@ -7,18 +7,21 @@ from UM.Scene.Iterator import Iterator from UM.Scene.SceneNode import SceneNode from functools import cmp_to_key -## 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) 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) + """ + def __init__(self, scene_node) -> None: super().__init__(scene_node) # Call super to make multiple inheritance work. self._hit_map = [[]] # type: List[List[bool]] # For each node, which other nodes this hits. A grid of booleans on which nodes hit which. self._original_node_list = [] # type: List[SceneNode] # The nodes that need to be checked for collisions. - ## Fills the ``_node_stack`` with a list of scene nodes that need to be - # printed in order. def _fillStack(self) -> None: + """Fills the ``_node_stack`` with a list of scene nodes that need to be printed in order. """ + node_list = [] for node in self._scene_node.getChildren(): if not issubclass(type(node), SceneNode): @@ -75,10 +78,14 @@ class OneAtATimeIterator(Iterator.Iterator): return True return False - ## 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. 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 + """ + node_index = self._original_node_list.index(node) for other_node in other_nodes: other_node_index = self._original_node_list.index(other_node) @@ -86,14 +93,26 @@ class OneAtATimeIterator(Iterator.Iterator): return True return False - ## Calculate score simply sums the number of other objects it 'blocks' def _calculateScore(self, a: SceneNode, b: SceneNode) -> int: + """Calculate score simply sums the number of other objects it 'blocks' + + :param a: node + :param b: node + :return: sum of the number of other objects + """ + score_a = sum(self._hit_map[self._original_node_list.index(a)]) score_b = sum(self._hit_map[self._original_node_list.index(b)]) return score_a - score_b - ## Checks if A can be printed before B def _checkHit(self, a: SceneNode, b: SceneNode) -> bool: + """Checks if a can be printed before b + + :param a: node + :param b: node + :return: true if a can be printed before b + """ + if a == b: return False @@ -116,12 +135,14 @@ class OneAtATimeIterator(Iterator.Iterator): return False -## Internal object used to keep track of a possible order in which to print objects. class _ObjectOrder: - ## 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. + """Internal object used to keep track of a possible order in which to print objects.""" + 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. + """ self.order = order self.todo = todo diff --git a/cura/PickingPass.py b/cura/PickingPass.py index 75ee21ef41..f2dfbaaf1e 100644 --- a/cura/PickingPass.py +++ b/cura/PickingPass.py @@ -16,11 +16,15 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator if TYPE_CHECKING: from UM.View.GL.ShaderProgram import ShaderProgram -## A 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 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 + """ + def __init__(self, width: int, height: int) -> None: super().__init__("picking", width, height) @@ -50,8 +54,14 @@ class PickingPass(RenderPass): batch.render(self._scene.getActiveCamera()) self.release() - ## Get the distance in mm from the camera to at a certain pixel coordinate. def getPickedDepth(self, x: int, y: int) -> float: + """Get the distance in mm from the camera to at a certain pixel coordinate. + + :param x: x component of coordinate vector in pixels + :param y: y component of coordinate vector in pixels + :return: distance in mm from the camera to pixel coordinate + """ + output = self.getOutput() window_size = self._renderer.getWindowSize() @@ -66,8 +76,14 @@ class PickingPass(RenderPass): distance = (distance & 0x00ffffff) / 1000. # drop the alpha channel and covert to mm return distance - ## Get the world coordinates of a picked point def getPickedPosition(self, x: int, y: int) -> Vector: + """Get the world coordinates of a picked point + + :param x: x component of coordinate vector in pixels + :param y: y component of coordinate vector in pixels + :return: vector of the world coordinate + """ + distance = self.getPickedDepth(x, y) camera = self._scene.getActiveCamera() if camera: diff --git a/cura/PreviewPass.py b/cura/PreviewPass.py index da60db2d99..c3d38cb6c6 100644 --- a/cura/PreviewPass.py +++ b/cura/PreviewPass.py @@ -1,7 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Optional, TYPE_CHECKING, cast +from typing import Optional, TYPE_CHECKING, cast, List from UM.Application import Application @@ -20,9 +20,14 @@ if TYPE_CHECKING: from UM.Scene.Camera import Camera -# Make color brighter by normalizing it (maximum factor 2.5 brighter) -# color_list is a list of 4 elements: [r, g, b, a], each element is a float 0..1 -def prettier_color(color_list): +def prettier_color(color_list: List[float]) -> List[float]: + """Make color brighter by normalizing + + maximum factor 2.5 brighter + + :param color_list: a list of 4 elements: [r, g, b, a], each element is a float 0..1 + :return: a normalized list of 4 elements: [r, g, b, a], each element is a float 0..1 + """ maximum = max(color_list[:3]) if maximum > 0: factor = min(1 / maximum, 2.5) @@ -31,11 +36,14 @@ def prettier_color(color_list): return [min(i * factor, 1.0) for i in color_list] -## A render pass 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. 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. + """ + def __init__(self, width: int, height: int) -> None: super().__init__("preview", width, height, 0) diff --git a/cura/PrintJobPreviewImageProvider.py b/cura/PrintJobPreviewImageProvider.py index 8b46c6db37..321164adeb 100644 --- a/cura/PrintJobPreviewImageProvider.py +++ b/cura/PrintJobPreviewImageProvider.py @@ -10,8 +10,14 @@ class PrintJobPreviewImageProvider(QQuickImageProvider): def __init__(self): super().__init__(QQuickImageProvider.Image) - ## Request a new image. def requestImage(self, id: str, size: QSize) -> Tuple[QImage, QSize]: + """Request a new image. + + :param id: id of the requested image + :param size: is not used defaults to QSize(15, 15) + :return: an tuple containing the image and size + """ + # The id will have an uuid and an increment separated by a slash. As we don't care about the value of the # increment, we need to strip that first. uuid = id[id.find("/") + 1:] diff --git a/cura/Snapshot.py b/cura/Snapshot.py index 353b5ae17c..6f12aa88ba 100644 --- a/cura/Snapshot.py +++ b/cura/Snapshot.py @@ -30,11 +30,17 @@ class Snapshot: return min_x, max_x, min_y, max_y - ## Return a QImage of the scene - # Uses PreviewPass that leaves out some elements - # Aspect ratio assumes a square @staticmethod def snapshot(width = 300, height = 300): + """Return a QImage of the scene + + Uses PreviewPass that leaves out some elements Aspect ratio assumes a square + + :param width: width of the aspect ratio default 300 + :param height: height of the aspect ratio default 300 + :return: None when there is no model on the build plate otherwise it will return an image + """ + scene = Application.getInstance().getController().getScene() active_camera = scene.getActiveCamera() render_width, render_height = active_camera.getWindowSize() |