diff options
author | Nino van Hooff <ninovanhooff@gmail.com> | 2020-05-08 16:23:51 +0300 |
---|---|---|
committer | Nino van Hooff <ninovanhooff@gmail.com> | 2020-05-08 16:23:51 +0300 |
commit | 797d6ed4381f70fa91b623dbd7b9e1b61053e04d (patch) | |
tree | 6ce65c26b1b504d741b96498996edae55e0adcff /plugins/CuraEngineBackend/CuraEngineBackend.py | |
parent | 8f3827d5aef4c5a35c55bed8ec4ffc6eb7fb6c57 (diff) |
Convert doxygen to rst for CuraEngineBackend
Diffstat (limited to 'plugins/CuraEngineBackend/CuraEngineBackend.py')
-rwxr-xr-x | plugins/CuraEngineBackend/CuraEngineBackend.py | 256 |
1 files changed, 156 insertions, 100 deletions
diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 3dd0589865..4de10c5ed0 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -42,12 +42,14 @@ catalog = i18nCatalog("cura") class CuraEngineBackend(QObject, Backend): backendError = Signal() - ## Starts the back-end plug-in. - # - # This registers all the signal listeners and prepares for communication - # with the back-end in general. - # CuraEngineBackend is exposed to qml as well. def __init__(self) -> None: + """Starts the back-end plug-in. + + This registers all the signal listeners and prepares for communication + with the back-end in general. + CuraEngineBackend is exposed to qml as well. + """ + super().__init__() # Find out where the engine is located, and how it is called. # This depends on how Cura is packaged and which OS we are running on. @@ -177,18 +179,22 @@ class CuraEngineBackend(QObject, Backend): self._machine_error_checker = self._application.getMachineErrorChecker() self._machine_error_checker.errorCheckFinished.connect(self._onStackErrorCheckFinished) - ## Terminate the engine process. - # - # This function should terminate the engine process. - # Called when closing the application. def close(self) -> None: + """Terminate the engine process. + + This function should terminate the engine process. + Called when closing the application. + """ + # Terminate CuraEngine if it is still running at this point self._terminate() - ## Get the command that is used to call the engine. - # This is useful for debugging and used to actually start the engine. - # \return list of commands and args / parameters. def getEngineCommand(self) -> List[str]: + """Get the command that is used to call the engine. + + This is useful for debugging and used to actually start the engine. + :return: list of commands and args / parameters. + """ command = [self._application.getPreferences().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), ""] parser = argparse.ArgumentParser(prog = "cura", add_help = False) @@ -199,17 +205,18 @@ class CuraEngineBackend(QObject, Backend): return command - ## 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. printDurationMessage = Signal() - - ## Emitted when the slicing process starts. + """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. + """ slicingStarted = Signal() + """Emitted when the slicing process starts.""" - ## Emitted when the slicing process is aborted forcefully. slicingCancelled = Signal() + """Emitted when the slicing process is aborted forcefully.""" @pyqtSlot() def stopSlicing(self) -> None: @@ -226,14 +233,16 @@ class CuraEngineBackend(QObject, Backend): if self._error_message: self._error_message.hide() - ## Manually triggers a reslice @pyqtSlot() def forceSlice(self) -> None: + """Manually triggers a reslice""" + self.markSliceAll() self.slice() - ## Perform a slice of the scene. def slice(self) -> None: + """Perform a slice of the scene.""" + Logger.log("i", "Starting to slice...") self._slice_start_time = time() if not self._build_plates_to_be_sliced: @@ -289,9 +298,11 @@ class CuraEngineBackend(QObject, Backend): self._start_slice_job.start() self._start_slice_job.finished.connect(self._onStartSliceCompleted) - ## Terminate the engine process. - # Start the engine process by calling _createSocket() def _terminate(self) -> None: + """Terminate the engine process. + + Start the engine process by calling _createSocket() + """ self._slicing = False self._stored_layer_data = [] if self._start_slice_job_build_plate in self._stored_optimized_layer_data: @@ -316,15 +327,17 @@ class CuraEngineBackend(QObject, Backend): except Exception as e: # terminating a process that is already terminating causes an exception, silently ignore this. Logger.log("d", "Exception occurred while trying to kill the engine %s", str(e)) - ## Event handler to call when the job to initiate the slicing process is - # completed. - # - # When the start slice job is successfully completed, it will be happily - # slicing. This function handles any errors that may occur during the - # bootstrapping of a slice job. - # - # \param job The start slice job that was just finished. def _onStartSliceCompleted(self, job: StartSliceJob) -> None: + """Event handler to call when the job to initiate the slicing process is + + completed. + + When the start slice job is successfully completed, it will be happily + slicing. This function handles any errors that may occur during the + bootstrapping of a slice job. + + :param job: The start slice job that was just finished. + """ if self._error_message: self._error_message.hide() @@ -443,11 +456,13 @@ class CuraEngineBackend(QObject, Backend): if self._slice_start_time: Logger.log("d", "Sending slice message took %s seconds", time() - self._slice_start_time ) - ## Determine enable or disable auto slicing. Return True for enable timer and False otherwise. - # It disables when - # - preference auto slice is off - # - decorator isBlockSlicing is found (used in g-code reader) def determineAutoSlicing(self) -> bool: + """Determine enable or disable auto slicing. Return True for enable timer and False otherwise. + + It disables when: + - preference auto slice is off + - decorator isBlockSlicing is found (used in g-code reader) + """ enable_timer = True self._is_disabled = False @@ -472,8 +487,9 @@ class CuraEngineBackend(QObject, Backend): self.disableTimer() return False - ## Return a dict with number of objects per build plate def _numObjectsPerBuildPlate(self) -> Dict[int, int]: + """Return a dict with number of objects per build plate""" + num_objects = defaultdict(int) #type: Dict[int, int] for node in DepthFirstIterator(self._scene.getRoot()): # Only count sliceable objects @@ -483,12 +499,14 @@ class CuraEngineBackend(QObject, Backend): num_objects[build_plate_number] += 1 return num_objects - ## Listener for when the scene has changed. - # - # This should start a slice if the scene is now ready to slice. - # - # \param source The scene node that was changed. def _onSceneChanged(self, source: SceneNode) -> None: + """Listener for when the scene has changed. + + This should start a slice if the scene is now ready to slice. + + :param source: The scene node that was changed. + """ + if not source.callDecoration("isSliceable"): return @@ -536,10 +554,12 @@ class CuraEngineBackend(QObject, Backend): self._invokeSlice() - ## Called when an error occurs in the socket connection towards the engine. - # - # \param error The exception that occurred. def _onSocketError(self, error: Arcus.Error) -> None: + """Called when an error occurs in the socket connection towards the engine. + + :param error: The exception that occurred. + """ + if self._application.isShuttingDown(): return @@ -567,8 +587,9 @@ class CuraEngineBackend(QObject, Backend): break return has_slicable - ## Remove old layer data (if any) def _clearLayerData(self, build_plate_numbers: Set = None) -> None: + """Remove old layer data (if any)""" + # Clear out any old gcode self._scene.gcode_dict = {} # type: ignore @@ -583,8 +604,9 @@ class CuraEngineBackend(QObject, Backend): if build_plate_number not in self._build_plates_to_be_sliced: self._build_plates_to_be_sliced.append(build_plate_number) - ## Convenient function: mark everything to slice, emit state and clear layer data def needsSlicing(self) -> None: + """Convenient function: mark everything to slice, emit state and clear layer data""" + # CURA-6604: If there's no slicable object, do not (try to) trigger slice, which will clear all the current # gcode. This can break Gcode file loading if it tries to remove it afterwards. if not self.hasSlicableObject(): @@ -597,10 +619,12 @@ class CuraEngineBackend(QObject, Backend): # With manually having to slice, we want to clear the old invalid layer data. self._clearLayerData() - ## A setting has changed, so check if we must reslice. - # \param instance The setting instance that has changed. - # \param property The property of the setting instance that has changed. def _onSettingChanged(self, instance: SettingInstance, property: str) -> None: + """A setting has changed, so check if we must reslice. + + :param instance: The setting instance that has changed. + :param property: The property of the setting instance that has changed. + """ if property == "value": # Only reslice if the value has changed. self.needsSlicing() self._onChanged() @@ -618,25 +642,31 @@ class CuraEngineBackend(QObject, Backend): self.needsSlicing() self._onChanged() - ## Called when a sliced layer data message is received from the engine. - # - # \param message The protobuf message containing sliced layer data. def _onLayerMessage(self, message: Arcus.PythonMessage) -> None: + """Called when a sliced layer data message is received from the engine. + + :param message: The protobuf message containing sliced layer data. + """ + self._stored_layer_data.append(message) - ## Called when an optimized sliced layer data message is received from the engine. - # - # \param message The protobuf message containing sliced layer data. def _onOptimizedLayerMessage(self, message: Arcus.PythonMessage) -> None: + """Called when an optimized sliced layer data message is received from the engine. + + :param message: The protobuf message containing sliced layer data. + """ + if self._start_slice_job_build_plate is not None: if self._start_slice_job_build_plate not in self._stored_optimized_layer_data: self._stored_optimized_layer_data[self._start_slice_job_build_plate] = [] self._stored_optimized_layer_data[self._start_slice_job_build_plate].append(message) - ## Called when a progress message is received from the engine. - # - # \param message The protobuf message containing the slicing progress. def _onProgressMessage(self, message: Arcus.PythonMessage) -> None: + """Called when a progress message is received from the engine. + + :param message: The protobuf message containing the slicing progress. + """ + self.processingProgress.emit(message.amount) self.setState(BackendState.Processing) @@ -653,10 +683,12 @@ class CuraEngineBackend(QObject, Backend): else: self._change_timer.start() - ## Called when the engine sends a message that slicing is finished. - # - # \param message The protobuf message signalling that slicing is finished. def _onSlicingFinishedMessage(self, message: Arcus.PythonMessage) -> None: + """Called when the engine sends a message that slicing is finished. + + :param message: The protobuf message signalling that slicing is finished. + """ + self.setState(BackendState.Done) self.processingProgress.emit(1.0) @@ -698,27 +730,32 @@ class CuraEngineBackend(QObject, Backend): self.enableTimer() # manually enable timer to be able to invoke slice, also when in manual slice mode self._invokeSlice() - ## Called when a g-code message is received from the engine. - # - # \param message The protobuf message containing g-code, encoded as UTF-8. def _onGCodeLayerMessage(self, message: Arcus.PythonMessage) -> None: + """Called when a g-code message is received from the engine. + + :param message: The protobuf message containing g-code, encoded as UTF-8. + """ + try: self._scene.gcode_dict[self._start_slice_job_build_plate].append(message.data.decode("utf-8", "replace")) #type: ignore #Because we generate this attribute dynamically. except KeyError: # Can occur if the g-code has been cleared while a slice message is still arriving from the other end. pass # Throw the message away. - ## Called when a g-code prefix message is received from the engine. - # - # \param message The protobuf message containing the g-code prefix, - # encoded as UTF-8. def _onGCodePrefixMessage(self, message: Arcus.PythonMessage) -> None: + """Called when a g-code prefix message is received from the engine. + + :param message: The protobuf message containing the g-code prefix, + encoded as UTF-8. + """ + try: self._scene.gcode_dict[self._start_slice_job_build_plate].insert(0, message.data.decode("utf-8", "replace")) #type: ignore #Because we generate this attribute dynamically. except KeyError: # Can occur if the g-code has been cleared while a slice message is still arriving from the other end. pass # Throw the message away. - ## Creates a new socket connection. def _createSocket(self, protocol_file: str = None) -> None: + """Creates a new socket connection.""" + if not protocol_file: plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId()) if not plugin_path: @@ -728,10 +765,12 @@ class CuraEngineBackend(QObject, Backend): super()._createSocket(protocol_file) self._engine_is_fresh = True - ## Called when anything has changed to the stuff that needs to be sliced. - # - # This indicates that we should probably re-slice soon. def _onChanged(self, *args: Any, **kwargs: Any) -> None: + """Called when anything has changed to the stuff that needs to be sliced. + + This indicates that we should probably re-slice soon. + """ + self.needsSlicing() if self._use_timer: # if the error check is scheduled, wait for the error check finish signal to trigger auto-slice, @@ -745,11 +784,13 @@ class CuraEngineBackend(QObject, Backend): else: self._change_timer.start() - ## Called when a print time message is received from the engine. - # - # \param message The protobuf message containing the print time per feature and - # material amount per extruder def _onPrintTimeMaterialEstimates(self, message: Arcus.PythonMessage) -> None: + """Called when a print time message is received from the engine. + + :param message: The protobuf message containing the print time per feature and + material amount per extruder + """ + material_amounts = [] for index in range(message.repeatedMessageCount("materialEstimates")): material_amounts.append(message.getRepeatedMessage("materialEstimates", index).material_amount) @@ -757,10 +798,12 @@ class CuraEngineBackend(QObject, Backend): times = self._parseMessagePrintTimes(message) self.printDurationMessage.emit(self._start_slice_job_build_plate, times, material_amounts) - ## Called for parsing message to retrieve estimated time per feature - # - # \param message The protobuf message containing the print time per feature def _parseMessagePrintTimes(self, message: Arcus.PythonMessage) -> Dict[str, float]: + """Called for parsing message to retrieve estimated time per feature + + :param message: The protobuf message containing the print time per feature + """ + result = { "inset_0": message.time_inset_0, "inset_x": message.time_inset_x, @@ -777,19 +820,22 @@ class CuraEngineBackend(QObject, Backend): } return result - ## Called when the back-end connects to the front-end. def _onBackendConnected(self) -> None: + """Called when the back-end connects to the front-end.""" + if self._restart: self._restart = False self._onChanged() - ## Called when the user starts using some tool. - # - # When the user starts using a tool, we should pause slicing to prevent - # continuously slicing while the user is dragging some tool handle. - # - # \param tool The tool that the user is using. def _onToolOperationStarted(self, tool: Tool) -> None: + """Called when the user starts using some tool. + + When the user starts using a tool, we should pause slicing to prevent + continuously slicing while the user is dragging some tool handle. + + :param tool: The tool that the user is using. + """ + self._tool_active = True # Do not react on scene change self.disableTimer() # Restart engine as soon as possible, we know we want to slice afterwards @@ -797,12 +843,14 @@ class CuraEngineBackend(QObject, Backend): self._terminate() self._createSocket() - ## Called when the user stops using some tool. - # - # This indicates that we can safely start slicing again. - # - # \param tool The tool that the user was using. def _onToolOperationStopped(self, tool: Tool) -> None: + """Called when the user stops using some tool. + + This indicates that we can safely start slicing again. + + :param tool: The tool that the user was using. + """ + self._tool_active = False # React on scene change again self.determineAutoSlicing() # Switch timer on if appropriate # Process all the postponed scene changes @@ -816,8 +864,9 @@ class CuraEngineBackend(QObject, Backend): self._process_layers_job.finished.connect(self._onProcessLayersFinished) self._process_layers_job.start() - ## Called when the user changes the active view mode. def _onActiveViewChanged(self) -> None: + """Called when the user changes the active view mode.""" + view = self._application.getController().getActiveView() if view: active_build_plate = self._application.getMultiBuildPlateModel().activeBuildPlate @@ -835,17 +884,20 @@ class CuraEngineBackend(QObject, Backend): else: self._layer_view_active = False - ## Called when the back-end self-terminates. - # - # We should reset our state and start listening for new connections. def _onBackendQuit(self) -> None: + """Called when the back-end self-terminates. + + We should reset our state and start listening for new connections. + """ + if not self._restart: if self._process: # type: ignore Logger.log("d", "Backend quit with return code %s. Resetting process and socket.", self._process.wait()) # type: ignore self._process = None # type: ignore - ## Called when the global container stack changes def _onGlobalStackChanged(self) -> None: + """Called when the global container stack changes""" + if self._global_container_stack: self._global_container_stack.propertyChanged.disconnect(self._onSettingChanged) self._global_container_stack.containersChanged.disconnect(self._onChanged) @@ -874,15 +926,18 @@ class CuraEngineBackend(QObject, Backend): Logger.log("d", "See if there is more to slice(2)...") self._invokeSlice() - ## Connect slice function to timer. def enableTimer(self) -> None: + """Connect slice function to timer.""" + if not self._use_timer: self._change_timer.timeout.connect(self.slice) self._use_timer = True - ## Disconnect slice function from timer. - # This means that slicing will not be triggered automatically def disableTimer(self) -> None: + """Disconnect slice function from timer. + + This means that slicing will not be triggered automatically + """ if self._use_timer: self._use_timer = False self._change_timer.timeout.disconnect(self.slice) @@ -894,8 +949,9 @@ class CuraEngineBackend(QObject, Backend): if auto_slice: self._change_timer.start() - ## Tickle the backend so in case of auto slicing, it starts the timer. def tickle(self) -> None: + """Tickle the backend so in case of auto slicing, it starts the timer.""" + if self._use_timer: self._change_timer.start() |