Browse Source

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

fieldOfView 8 years ago
parent
commit
6334f74fc6

+ 2 - 1
cura/PrinterOutputDevice.py

@@ -2,6 +2,7 @@ from UM.i18n import i18nCatalog
 from UM.OutputDevice.OutputDevice import OutputDevice
 from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
 from PyQt5.QtWidgets import QMessageBox
+import UM.Settings.ContainerRegistry
 
 from enum import IntEnum  # For the connection state tracking.
 from UM.Logger import Logger
@@ -285,7 +286,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
                 result.append(i18n_catalog.i18nc("@item:material", "No material loaded"))
                 continue
 
-            containers = self._container_registry.findInstanceContainers(type = "material", guid = material_id)
+            containers = self._container_registry.findInstanceContainers(type = "material", GUID = material_id)
             if containers:
                 result.append(containers[0].getName())
             else:

+ 7 - 1
cura/Settings/ContainerManager.py

@@ -349,6 +349,9 @@ class ContainerManager(QObject):
         except NotImplementedError:
             return { "status": "error", "message": "Unable to serialize container"}
 
+        if contents is None:
+            return {"status": "error", "message": "Serialization returned None. Unable to write to file"}
+
         with UM.SaveFile(file_url, "w") as f:
             f.write(contents)
 
@@ -586,6 +589,7 @@ class ContainerManager(QObject):
                 new_container = container.duplicate(self._createUniqueId(stack_id, new_name), new_name)
                 self._container_registry.addContainer(new_container)
         else:
+            UM.Logger.log("w", "Unable to duplicate profile. It has the wrong type.")
             return ""
 
         return new_name
@@ -688,7 +692,9 @@ class ContainerManager(QObject):
         filter_by_material = False
 
         if global_stack.getMetaDataEntry("has_machine_quality"):
-            criteria["definition"] = global_stack.getBottom().getId()
+            definition = global_stack.getBottom()
+            definition_id = definition.getMetaDataEntry("quality_definition", definition.getId())
+            criteria["definition"] = definition_id
 
             filter_by_material = global_stack.getMetaDataEntry("has_materials")
 

+ 10 - 0
plugins/CuraEngineBackend/CuraEngineBackend.py

@@ -227,6 +227,16 @@ class CuraEngineBackend(Backend):
         if job.isCancelled() or job.getError() or job.getResult() == StartSliceJob.StartJobResult.Error:
             return
 
+        if job.getResult() == StartSliceJob.StartJobResult.MaterialIncompatible:
+            if Application.getInstance().getPlatformActivity:
+                self._error_message = Message(catalog.i18nc("@info:status",
+                                            "The selected material is imcompatible with the selected machine or configuration."))
+                self._error_message.show()
+                self.backendStateChange.emit(BackendState.Error)
+            else:
+                self.backendStateChange.emit(BackendState.NotStarted)
+            return
+
         if job.getResult() == StartSliceJob.StartJobResult.SettingError:
             if Application.getInstance().getPlatformActivity:
                 self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current settings. Please check your settings for errors."))

+ 2 - 1
plugins/CuraEngineBackend/StartSliceJob.py

@@ -24,6 +24,7 @@ class StartJobResult(IntEnum):
     Error = 2
     SettingError = 3
     NothingToSlice = 4
+    MaterialIncompatible = 5
 
 
 ##  Formatter class that handles token expansion in start/end gcod
@@ -86,7 +87,7 @@ class StartSliceJob(Job):
             material = extruder_stack.findContainer({"type": "material"})
             if material:
                 if material.getMetaDataEntry("compatible") == False:
-                    self.setResult(StartJobResult.SettingError)
+                    self.setResult(StartJobResult.MaterialIncompatible)
                     return
 
         # Don't slice if there is a per object setting with an error value.

+ 18 - 24
plugins/SliceInfoPlugin/SliceInfo.py

@@ -1,6 +1,8 @@
 # Copyright (c) 2015 Ultimaker B.V.
 # Cura is released under the terms of the AGPLv3 or higher.
 
+from cura.CuraApplication import CuraApplication
+
 from UM.Extension import Extension
 from UM.Application import Application
 from UM.Preferences import Preferences
@@ -18,6 +20,7 @@ import math
 import urllib.request
 import urllib.parse
 import ssl
+import hashlib
 
 catalog = i18nCatalog("cura")
 
@@ -43,9 +46,11 @@ class SliceInfoJob(Job):
         if Platform.isOSX():
             kwoptions["context"] = ssl._create_unverified_context()
 
+        Logger.log("d", "Sending anonymous slice info to [%s]...", self.url)
+
         try:
             f = urllib.request.urlopen(self.url, **kwoptions)
-            Logger.log("i", "Sent anonymous slice info to %s", self.url)
+            Logger.log("i", "Sent anonymous slice info.")
             f.close()
         except urllib.error.HTTPError as http_exception:
             Logger.log("e", "An HTTP error occurred while trying to send slice information: %s" % http_exception)
@@ -56,7 +61,7 @@ class SliceInfoJob(Job):
 #       The data is only sent when the user in question gave permission to do so. All data is anonymous and
 #       no model files are being sent (Just a SHA256 hash of the model).
 class SliceInfo(Extension):
-    info_url = "https://stats.youmagine.com/curastats/slice"
+    info_url = "http://stats.youmagine.com/curastats/slice"
 
     def __init__(self):
         super().__init__()
@@ -80,6 +85,16 @@ class SliceInfo(Extension):
                 Logger.log("d", "'info/send_slice_info' is turned off.")
                 return # Do nothing, user does not want to send data
 
+            # Listing all files placed on the buildplate
+            modelhashes = []
+            for node in DepthFirstIterator(CuraApplication.getInstance().getController().getScene().getRoot()):
+                if type(node) is not SceneNode or not node.getMeshData():
+                    continue
+                modelhashes.append(node.getMeshData().getHash())
+
+            # Creating md5sums and formatting them as discussed on JIRA
+            modelhash_formatted = ",".join(modelhashes)
+
             global_container_stack = Application.getInstance().getGlobalContainerStack()
 
             # Get total material used (in mm^3)
@@ -89,27 +104,6 @@ class SliceInfo(Extension):
             # TODO: Send material per extruder instead of mashing it on a pile
             material_used = math.pi * material_radius * material_radius * sum(print_information.materialLengths) #Volume of all materials used
 
-            # Get model information (bounding boxes, hashes and transformation matrix)
-            models_info = []
-            for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
-                if type(node) is SceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None:
-                    if not getattr(node, "_outside_buildarea", False):
-                        model_info = {}
-                        model_info["hash"] = node.getMeshData().getHash()
-                        model_info["bounding_box"] = {}
-                        model_info["bounding_box"]["minimum"] = {}
-                        model_info["bounding_box"]["minimum"]["x"] = node.getBoundingBox().minimum.x
-                        model_info["bounding_box"]["minimum"]["y"] = node.getBoundingBox().minimum.y
-                        model_info["bounding_box"]["minimum"]["z"] = node.getBoundingBox().minimum.z
-
-                        model_info["bounding_box"]["maximum"] = {}
-                        model_info["bounding_box"]["maximum"]["x"] = node.getBoundingBox().maximum.x
-                        model_info["bounding_box"]["maximum"]["y"] = node.getBoundingBox().maximum.y
-                        model_info["bounding_box"]["maximum"]["z"] = node.getBoundingBox().maximum.z
-                        model_info["transformation"] = str(node.getWorldTransformation().getData())
-
-                        models_info.append(model_info)
-
             # Bundle the collected data
             submitted_data = {
                 "processor": platform.processor(),
@@ -117,7 +111,7 @@ class SliceInfo(Extension):
                 "platform": platform.platform(),
                 "settings": global_container_stack.serialize(), # global_container with references on used containers
                 "version": Application.getInstance().getVersion(),
-                "modelhash": "None",
+                "modelhash": modelhash_formatted,
                 "printtime": print_information.currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601),
                 "filament": material_used,
                 "language": Preferences.getInstance().getValue("general/language"),

+ 1 - 4
plugins/VersionUpgrade/VersionUpgrade21to22/MachineInstance.py

@@ -91,12 +91,9 @@ class MachineInstance:
 
         if has_machine_qualities: #This machine now has machine-quality profiles.
             active_material += "_" + variant_materials #That means that the profile was split into multiple.
-            current_settings = "" #The profile didn't know the definition ID when it was upgraded, so it will have been invalid. Sorry, your current settings are lost now.
-        else:
-            current_settings = self._name + "_current_settings"
 
         containers = [
-            current_settings,
+            "", #The current profile doesn't know the definition ID when it was upgraded, only the instance ID, so it will be invalid. Sorry, your current settings are lost now.
             active_quality_changes,
             active_quality,
             active_material,

+ 1 - 1
plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py

@@ -80,7 +80,7 @@ class Profile:
         import VersionUpgrade21to22 # Import here to prevent circular dependencies.
 
         if self._name == "Current settings":
-            self._filename += "_current_settings" #This resolves a duplicate ID arising from how Cura 2.1 stores its current settings.
+            return None #Can't upgrade these, because the new current profile needs to specify the definition ID and the old file only had the machine instance, not the definition.
 
         config = configparser.ConfigParser(interpolation = None)
 

+ 0 - 3
plugins/XmlMaterialProfile/XmlMaterialProfile.py

@@ -85,9 +85,6 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
     # base file: global settings + supported machines
     # machine / variant combination: only changes for itself.
     def serialize(self):
-        if self._read_only:
-            return
-
         registry = UM.Settings.ContainerRegistry.getInstance()
 
         base_file = self.getMetaDataEntry("base_file", "")

+ 1 - 0
resources/definitions/bq_hephestos.def.json

@@ -14,6 +14,7 @@
     },
 
     "overrides": {
+        "machine_name": { "default_value": "BQ Prusa i3 Hephestos" },
         "machine_start_gcode": {
             "default_value": "; -- START GCODE --\nG21                     ;set units to millimetres\nG90                     ;set to absolute positioning\nM106 S0                 ;set fan speed to zero (turned off)\nG28 X0 Y0               ;move to the X/Y origin (Home)\nG28 Z0                  ;move to the Z origin (Home)\nG1 Z15.0 F1200          ;move Z to position 15.0 mm\nG92 E0                  ;zero the extruded length\nG1 E20 F200             ;extrude 20mm of feed stock\nG92 E0                  ;zero the extruded length again\nG1 F7200                ;set feedrate to 120 mm/s\n; -- end of START GCODE --"
         },

+ 1 - 0
resources/definitions/bq_hephestos_2.def.json

@@ -14,6 +14,7 @@
     },
 
     "overrides": {
+        "machine_name": { "default_value": "BQ Hephestos 2" },
         "machine_start_gcode": { "default_value": "; -- START GCODE --\nM104 S{material_print_temperature} ; Heat up extruder while leveling\nM800 ; Custom GCODE to fire start print procedure\nM109 S{material_print_temperature} ; Makes sure the temperature is correct before printing\n; -- end of START GCODE --" },
         "machine_end_gcode": { "default_value": "; -- END GCODE --\nM801        ; Custom GCODE to fire end print procedure\n; -- end of END GCODE --" },
         "machine_width": { "default_value": 210 },

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