Browse Source

Merge branch 'master' of github.com:Ultimaker/Cura

Jaime van Kessel 4 years ago
parent
commit
82ecc95c22

+ 1 - 1
cura/PrinterOutput/Models/ExtruderOutputModel.py

@@ -99,7 +99,7 @@ class ExtruderOutputModel(QObject):
             self._is_preheating = pre_heating
             self.isPreheatingChanged.emit()
 
-    @pyqtProperty(bool, notify=isPreheatingChanged)
+    @pyqtProperty(bool, notify = isPreheatingChanged)
     def isPreheating(self) -> bool:
         return self._is_preheating
 

+ 2 - 2
cura_app.py

@@ -39,7 +39,7 @@ except ImportError:
 parser = argparse.ArgumentParser(prog = "cura",
                                  add_help = False)
 parser.add_argument("--debug",
-                    action="store_true",
+                    action = "store_true",
                     default = False,
                     help = "Turn on the debug mode by setting this option."
                     )
@@ -49,7 +49,7 @@ known_args = vars(parser.parse_known_args()[0])
 if with_sentry_sdk:
     sentry_env = "unknown"  # Start off with a "IDK"
     if hasattr(sys, "frozen"):
-        sentry_env = "production"  # A frozen build has the posibility to be a "real" distribution.
+        sentry_env = "production"  # A frozen build has the possibility to be a "real" distribution.
 
     if ApplicationMetadata.CuraVersion == "master":
         sentry_env = "development"  # Master is always a development version.

+ 13 - 9
plugins/3MFWriter/ThreeMFWorkspaceWriter.py

@@ -127,15 +127,19 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
 
         file_name = "Cura/%s.%s" % (container.getId(), file_suffix)
 
-        if file_name in archive.namelist():
-            return  # File was already saved, no need to do it again. Uranium guarantees unique ID's, so this should hold.
+        try:
+            if file_name in archive.namelist():
+                return  # File was already saved, no need to do it again. Uranium guarantees unique ID's, so this should hold.
 
-        file_in_archive = zipfile.ZipInfo(file_name)
-        # For some reason we have to set the compress type of each file as well (it doesn't keep the type of the entire archive)
-        file_in_archive.compress_type = zipfile.ZIP_DEFLATED
+            file_in_archive = zipfile.ZipInfo(file_name)
+            # For some reason we have to set the compress type of each file as well (it doesn't keep the type of the entire archive)
+            file_in_archive.compress_type = zipfile.ZIP_DEFLATED
 
-        # Do not include the network authentication keys
-        ignore_keys = {"network_authentication_id", "network_authentication_key", "octoprint_api_key"}
-        serialized_data = container.serialize(ignored_metadata_keys = ignore_keys)
+            # Do not include the network authentication keys
+            ignore_keys = {"network_authentication_id", "network_authentication_key", "octoprint_api_key"}
+            serialized_data = container.serialize(ignored_metadata_keys = ignore_keys)
 
-        archive.writestr(file_in_archive, serialized_data)
+            archive.writestr(file_in_archive, serialized_data)
+        except (FileNotFoundError, EnvironmentError):
+            Logger.error("File became inaccessible while writing to it: {archive_filename}".format(archive_filename = archive.fp.name))
+            return

+ 4 - 0
plugins/Toolbox/src/CloudSync/DownloadPresenter.py

@@ -120,6 +120,10 @@ class DownloadPresenter:
             received += item["received"]
             total += item["total"]
 
+        if total == 0:  # Total download size is 0, or unknown, or there are no progress items at all.
+            self._progress_message.setProgress(100.0)
+            return
+
         self._progress_message.setProgress(100.0 * (received / total))  # [0 .. 100] %
 
     def _onError(self, package_id: str) -> None:

+ 35 - 14
plugins/UFPWriter/UFPWriter.py

@@ -1,18 +1,20 @@
-#Copyright (c) 2020 Ultimaker B.V.
-#Cura is released under the terms of the LGPLv3 or higher.
+# Copyright (c) 2020 Ultimaker B.V.
+# Cura is released under the terms of the LGPLv3 or higher.
 
-from typing import cast
+from typing import cast, List, Dict
 
-from Charon.VirtualFile import VirtualFile #To open UFP files.
-from Charon.OpenMode import OpenMode #To indicate that we want to write to UFP files.
-from io import StringIO #For converting g-code to bytes.
+from Charon.VirtualFile import VirtualFile  # To open UFP files.
+from Charon.OpenMode import OpenMode  # To indicate that we want to write to UFP files.
+from io import StringIO  # For converting g-code to bytes.
 
 from UM.Logger import Logger
-from UM.Mesh.MeshWriter import MeshWriter #The writer we need to implement.
+from UM.Mesh.MeshWriter import MeshWriter  # The writer we need to implement.
 from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
-from UM.PluginRegistry import PluginRegistry #To get the g-code writer.
+from UM.PluginRegistry import PluginRegistry  # To get the g-code writer.
 from PyQt5.QtCore import QBuffer
 
+from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
+from UM.Scene.SceneNode import SceneNode
 from cura.CuraApplication import CuraApplication
 from cura.Snapshot import Snapshot
 from cura.Utils.Threading import call_on_qt_thread
@@ -58,12 +60,12 @@ class UFPWriter(MeshWriter):
 
         self._writeObjectList(archive)
 
-        #Store the g-code from the scene.
+        # Store the g-code from the scene.
         archive.addContentType(extension = "gcode", mime_type = "text/x-gcode")
-        gcode_textio = StringIO() #We have to convert the g-code into bytes.
+        gcode_textio = StringIO()  # We have to convert the g-code into bytes.
         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.
+        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
         gcode = archive.getStream("/3D/model.gcode")
@@ -72,7 +74,7 @@ class UFPWriter(MeshWriter):
 
         self._createSnapshot()
 
-        #Store the thumbnail.
+        # Store the thumbnail.
         if self._snapshot:
             archive.addContentType(extension = "png", mime_type = "image/png")
             thumbnail = archive.getStream("/Metadata/thumbnail.png")
@@ -83,7 +85,9 @@ class UFPWriter(MeshWriter):
             thumbnail_image.save(thumbnail_buffer, "PNG")
 
             thumbnail.write(thumbnail_buffer.data())
-            archive.addRelation(virtual_path = "/Metadata/thumbnail.png", relation_type = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail", origin = "/3D/model.gcode")
+            archive.addRelation(virtual_path = "/Metadata/thumbnail.png",
+                                relation_type = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail",
+                                origin = "/3D/model.gcode")
         else:
             Logger.log("d", "Thumbnail not created, cannot save it")
 
@@ -151,8 +155,25 @@ class UFPWriter(MeshWriter):
 
         To retrieve, use: `archive.getMetadata(METADATA_OBJECTS_PATH)`
         """
+
         objects_model = CuraApplication.getInstance().getObjectsModel()
-        object_metas = [{"name": item["name"]} for item in objects_model.items]
+        object_metas = []
+
+        for item in objects_model.items:
+            object_metas.extend(UFPWriter._getObjectMetadata(item["node"]))
 
         data = {METADATA_OBJECTS_PATH: object_metas}
         archive.setMetadata(data)
+
+    @staticmethod
+    def _getObjectMetadata(node: SceneNode) -> List[Dict[str, str]]:
+        """Get object metadata to write for a Node.
+
+        :return: List of object metadata dictionaries.
+                 Might contain > 1 element in case of a group node.
+                 Might be empty in case of nonPrintingMesh
+        """
+
+        return [{"name": item.getName()}
+                for item in DepthFirstIterator(node)
+                if item.getMeshData() is not None and not item.callDecoration("isNonPrintingMesh")]

+ 9 - 0
plugins/VersionUpgrade/VersionUpgrade462to47/VersionUpgrade462to47.py

@@ -4,6 +4,8 @@
 import configparser
 from typing import Tuple, List, Dict, Set
 import io
+
+from UM.Util import parseBool
 from UM.VersionUpgrade import VersionUpgrade
 
 
@@ -42,6 +44,13 @@ class VersionUpgrade462to47(VersionUpgrade):
             parser["general"]["visible_settings"] = ";".join(
                 set(parser["general"]["visible_settings"].split(";")).difference(_removed_settings))
 
+        if "cura" in parser and "jobname_prefix" in parser["cura"]:
+            if not parseBool(parser["cura"]["jobname_prefix"]):
+                parser["cura"]["job_name_template"] = "{project_name}"
+            del parser["cura"]["jobname_prefix"]
+        # else: When the jobname_prefix preference is True or not set,
+        # the default value for job_name_template ("{machine_name_short}_{project_name}") will be used
+
         result = io.StringIO()
         parser.write(result)
         return [filename], [result.getvalue()]