Browse Source

Merge branch 'master' into CURA-5595_add_custom_button_to_menu

Aleksei S 6 years ago
parent
commit
a1bc2f3ebf

+ 8 - 3
cura/CameraImageProvider.py

@@ -4,15 +4,20 @@ from PyQt5.QtCore import QSize
 
 from UM.Application import Application
 
+
 class CameraImageProvider(QQuickImageProvider):
     def __init__(self):
-        QQuickImageProvider.__init__(self, QQuickImageProvider.Image)
+        super().__init__(QQuickImageProvider.Image)
 
     ##  Request a new image.
     def requestImage(self, id, size):
         for output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices():
             try:
-                return output_device.activePrinter.camera.getImage(), QSize(15, 15)
+                image = output_device.activePrinter.camera.getImage()
+                if image.isNull():
+                    image = QImage()
+
+                return image, QSize(15, 15)
             except AttributeError:
                 pass
-        return QImage(), QSize(15, 15)
+        return QImage(), QSize(15, 15)

+ 4 - 3
cura/CuraApplication.py

@@ -229,6 +229,8 @@ class CuraApplication(QtApplication):
 
         self._sidebar_custom_menu_items = []  # type: list # Keeps list of custom menu items for the side bar
 
+        self._plugins_loaded = False
+
         # Backups
         self._auto_save = None
         self._save_data_enabled = True
@@ -1609,8 +1611,7 @@ class CuraApplication(QtApplication):
         self._currently_loading_files.remove(file_name)
 
         self.fileLoaded.emit(file_name)
-        arrange_objects_on_load = not self.getPreferences().getValue("cura/use_multi_build_plate")
-        target_build_plate = self.getMultiBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1
+        target_build_plate = self.getMultiBuildPlateModel().activeBuildPlate
 
         root = self.getController().getScene().getRoot()
         fixed_nodes = []
@@ -1664,7 +1665,7 @@ class CuraApplication(QtApplication):
                 if not child.getDecorator(ConvexHullDecorator):
                     child.addDecorator(ConvexHullDecorator())
 
-            if file_extension != "3mf" and arrange_objects_on_load:
+            if file_extension != "3mf":
                 if node.callDecoration("isSliceable"):
                     # Only check position if it's not already blatantly obvious that it won't fit.
                     if node.getBoundingBox() is None or self._volume.getBoundingBox() is None or node.getBoundingBox().width < self._volume.getBoundingBox().width or node.getBoundingBox().depth < self._volume.getBoundingBox().depth:

+ 10 - 0
cura/PrintInformation.py

@@ -267,6 +267,7 @@ class PrintInformation(QObject):
         new_active_build_plate = self._multi_build_plate_model.activeBuildPlate
         if new_active_build_plate != self._active_build_plate:
             self._active_build_plate = new_active_build_plate
+            self._updateJobName()
 
             self._initVariablesWithBuildPlate(self._active_build_plate)
 
@@ -320,6 +321,15 @@ class PrintInformation(QObject):
             else:
                 self._job_name = base_name
 
+        # In case there are several buildplates, a suffix is attached
+        if self._multi_build_plate_model.maxBuildPlate > 0:
+            connector = "_#"
+            suffix = connector + str(self._active_build_plate + 1)
+            if connector in self._job_name:
+                self._job_name = self._job_name.split(connector)[0] # get the real name
+            if self._active_build_plate != 0:
+                self._job_name += suffix
+
         self.jobNameChanged.emit()
 
     @pyqtSlot(str)

+ 1 - 1
cura/PrinterOutput/PrinterOutputModel.py

@@ -120,7 +120,7 @@ class PrinterOutputModel(QObject):
 
     @pyqtProperty(QVariant, notify = headPositionChanged)
     def headPosition(self):
-        return {"x": self._head_position.x, "y": self._head_position.y, "z": self.head_position_z}
+        return {"x": self._head_position.x, "y": self._head_position.y, "z": self.head_position.z}
 
     def updateHeadPosition(self, x, y, z):
         if self._head_position.x != x or self._head_position.y != y or self._head_position.z != z:

+ 6 - 1
cura/Settings/MachineManager.py

@@ -1455,9 +1455,14 @@ class MachineManager(QObject):
             if quality_group.node_for_global is None:
                 Logger.log("e", "Could not set quality group [%s] because it has no node_for_global", str(quality_group))
                 return
+            # This is not changing the quality for the active machine !!!!!!!!
             global_stack.quality = quality_group.node_for_global.getContainer()
             for extruder_nr, extruder_stack in global_stack.extruders.items():
-                extruder_stack.quality = quality_group.nodes_for_extruders[extruder_nr].getContainer()
+                quality_container = self._empty_quality_container
+                if extruder_nr in quality_group.nodes_for_extruders:
+                    container = quality_group.nodes_for_extruders[extruder_nr].getContainer()
+                    quality_container = container if container is not None else quality_container
+                extruder_stack.quality = quality_container
             return
 
         self.blurSettings.emit()

+ 1 - 0
cura_app.py

@@ -131,6 +131,7 @@ faulthandler.enable(all_threads = True)
 # first seems to prevent Sip from going into a state where it
 # tries to create PyQt objects on a non-main thread.
 import Arcus #@UnusedImport
+import Savitar #@UnusedImport
 from cura.CuraApplication import CuraApplication
 
 app = CuraApplication()

+ 4 - 0
plugins/3MFWriter/ThreeMFWriter.py

@@ -25,6 +25,9 @@ except ImportError:
 import zipfile
 import UM.Application
 
+from UM.i18n import i18nCatalog
+catalog = i18nCatalog("cura")
+
 
 class ThreeMFWriter(MeshWriter):
     def __init__(self):
@@ -173,6 +176,7 @@ class ThreeMFWriter(MeshWriter):
             archive.writestr(relations_file, b'<?xml version="1.0" encoding="UTF-8"?> \n' + ET.tostring(relations_element))
         except Exception as e:
             Logger.logException("e", "Error writing zip file")
+            self.setInformation(catalog.i18nc("@error:zip", "Error writing 3mf file."))
             return False
         finally:
             if not self._store_archive:

+ 13 - 1
plugins/CuraEngineBackend/CuraEngineBackend.py

@@ -1,6 +1,7 @@
 # Copyright (c) 2018 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
+import argparse #To run the engine in debug mode if the front-end is in debug mode.
 from collections import defaultdict
 import os
 from PyQt5.QtCore import QObject, QTimer, pyqtSlot
@@ -179,7 +180,15 @@ class CuraEngineBackend(QObject, Backend):
     #   \return list of commands and args / parameters.
     def getEngineCommand(self) -> List[str]:
         json_path = Resources.getPath(Resources.DefinitionContainers, "fdmprinter.def.json")
-        return [self._application.getPreferences().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", json_path, ""]
+        command = [self._application.getPreferences().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", json_path, ""]
+
+        parser = argparse.ArgumentParser(prog = "cura", add_help = False)
+        parser.add_argument("--debug", action = "store_true", default = False, help = "Turn on the debug mode by setting this option.")
+        known_args = vars(parser.parse_known_args()[0])
+        if known_args["debug"]:
+            command.append("-vvv")
+
+        return command
 
     ##  Emitted when we get a message containing print duration and material amount.
     #   This also implies the slicing has finished.
@@ -541,6 +550,9 @@ class CuraEngineBackend(QObject, Backend):
 
     ##  Remove old layer data (if any)
     def _clearLayerData(self, build_plate_numbers: Set = None) -> None:
+        # Clear out any old gcode
+        self._scene.gcode_dict = {}  # type: ignore
+
         for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
             if node.callDecoration("getLayerData"):
                 if not build_plate_numbers or node.callDecoration("getBuildPlateNumber") in build_plate_numbers:

+ 1 - 1
plugins/CuraEngineBackend/StartSliceJob.py

@@ -41,7 +41,7 @@ class StartJobResult(IntEnum):
 
 ##  Formatter class that handles token expansion in start/end gcode
 class GcodeStartEndFormatter(Formatter):
-    def get_value(self, key: str, *args: str, default_extruder_nr: str = "-1", **kwargs) -> str: #type: ignore # [CodeStyle: get_value is an overridden function from the Formatter class]
+    def get_value(self, key: str, args: str, kwargs: dict, default_extruder_nr: str = "-1") -> str: #type: ignore # [CodeStyle: get_value is an overridden function from the Formatter class]
         # The kwargs dictionary contains a dictionary for each stack (with a string of the extruder_nr as their key),
         # and a default_extruder_nr to use when no extruder_nr is specified
 

+ 7 - 1
plugins/GCodeGzWriter/GCodeGzWriter.py

@@ -10,6 +10,9 @@ from UM.Mesh.MeshWriter import MeshWriter #The class we're extending/implementin
 from UM.PluginRegistry import PluginRegistry
 from UM.Scene.SceneNode import SceneNode #For typing.
 
+from UM.i18n import i18nCatalog
+catalog = i18nCatalog("cura")
+
 ##  A file writer that writes gzipped g-code.
 #
 #   If you're zipping g-code, you might as well use gzip!
@@ -28,12 +31,15 @@ class GCodeGzWriter(MeshWriter):
     def write(self, stream: BufferedIOBase, nodes: List[SceneNode], mode = MeshWriter.OutputMode.BinaryMode) -> bool:
         if mode != MeshWriter.OutputMode.BinaryMode:
             Logger.log("e", "GCodeGzWriter does not support text mode.")
+            self.setInformation(catalog.i18nc("@error:not supported", "GCodeGzWriter does not support text mode."))
             return False
 
         #Get the g-code from the g-code writer.
         gcode_textio = StringIO() #We have to convert the g-code into bytes.
-        success = cast(MeshWriter, PluginRegistry.getInstance().getPluginObject("GCodeWriter")).write(gcode_textio, None)
+        gcode_writer = cast(MeshWriter, PluginRegistry.getInstance().getPluginObject("GCodeWriter"))
+        success = gcode_writer.write(gcode_textio, None)
         if not success: #Writing the g-code failed. Then I can also not write the gzipped g-code.
+            self.setInformation(gcode_writer.getInformation())
             return False
 
         result = gzip.compress(gcode_textio.getvalue().encode("utf-8"))

Some files were not shown because too many files changed in this diff