Browse Source

Merge branch 'master' into CURA-5204_send_anonymous_data

Diego Prado Gesto 6 years ago
parent
commit
4e53f219f0

+ 2 - 7
cura/CuraApplication.py

@@ -501,11 +501,6 @@ class CuraApplication(QtApplication):
     def getStaticVersion(cls):
         return CuraVersion
 
-    ##  Handle removing the unneeded plugins
-    #   \sa PluginRegistry
-    def _removePlugins(self):
-        self._plugin_registry.removePlugins()
-
     ##  Handle loading of all plugin types (and the backend explicitly)
     #   \sa PluginRegistry
     def _loadPlugins(self):
@@ -705,7 +700,7 @@ class CuraApplication(QtApplication):
         self._post_start_timer.timeout.connect(self._onPostStart)
         self._post_start_timer.start()
 
-
+        Logger.log("d", "Booting Cura took %s seconds", time.time() - self._boot_loading_time)
         self.exec_()
 
     def _onPostStart(self):
@@ -991,7 +986,7 @@ class CuraApplication(QtApplication):
         return self._i18n_catalog.i18nc("@info 'width', 'depth' and 'height' are variable names that must NOT be translated; just translate the format of ##x##x## mm.", "%(width).1f x %(depth).1f x %(height).1f mm") % {'width' : self._scene_bounding_box.width.item(), 'depth': self._scene_bounding_box.depth.item(), 'height' : self._scene_bounding_box.height.item()}
 
     def updatePlatformActivityDelayed(self, node = None):
-        if node is not None and node.getMeshData() is not None:
+        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

+ 15 - 3
cura/Machines/MaterialManager.py

@@ -19,7 +19,10 @@ from .MaterialNode import MaterialNode
 from .MaterialGroup import MaterialGroup
 
 if TYPE_CHECKING:
+    from UM.Settings.DefinitionContainer import DefinitionContainer
+    from UM.Settings.InstanceContainer import InstanceContainer
     from cura.Settings.GlobalStack import GlobalStack
+    from cura.Settings.ExtruderStack import ExtruderStack
 
 
 #
@@ -243,7 +246,7 @@ class MaterialManager(QObject):
     #
     # Return a dict with all root material IDs (k) and ContainerNodes (v) that's suitable for the given setup.
     #
-    def getAvailableMaterials(self, machine_definition_id: str, extruder_variant_name: Optional[str],
+    def getAvailableMaterials(self, machine_definition: "DefinitionContainer", extruder_variant_name: Optional[str],
                               diameter: float) -> dict:
         # round the diameter to get the approximate diameter
         rounded_diameter = str(round(diameter))
@@ -251,6 +254,8 @@ class MaterialManager(QObject):
             Logger.log("i", "Cannot find materials with diameter [%s] (rounded to [%s])", diameter, rounded_diameter)
             return dict()
 
+        machine_definition_id = machine_definition.getId()
+
         # If there are variant materials, get the variant material
         machine_variant_material_map = self._diameter_machine_variant_material_map[rounded_diameter]
         machine_node = machine_variant_material_map.get(machine_definition_id)
@@ -265,10 +270,18 @@ class MaterialManager(QObject):
         #  1. variant-specific material
         #  2. machine-specific material
         #  3. generic material (for fdmprinter)
+        machine_exclude_materials = machine_definition.getMetaDataEntry("exclude_materials", [])
+
         material_id_metadata_dict = dict()
         for node in nodes_to_check:
             if node is not None:
                 for material_id, node in node.material_map.items():
+                    fallback_id = self.getFallbackMaterialIdByMaterialType(node.metadata["material"])
+                    if fallback_id in machine_exclude_materials:
+                        Logger.log("d", "Exclude material [%s] for machine [%s]",
+                                   material_id, machine_definition.getId())
+                        continue
+
                     if material_id not in material_id_metadata_dict:
                         material_id_metadata_dict[material_id] = node
 
@@ -279,14 +292,13 @@ class MaterialManager(QObject):
     #
     def getAvailableMaterialsForMachineExtruder(self, machine: "GlobalStack",
                                                 extruder_stack: "ExtruderStack") -> Optional[dict]:
-        machine_definition_id = machine.definition.getId()
         variant_name = None
         if extruder_stack.variant.getId() != "empty_variant":
             variant_name = extruder_stack.variant.getName()
         diameter = extruder_stack.approximateMaterialDiameter
 
         # Fetch the available materials (ContainerNode) for the current active machine and extruder setup.
-        return self.getAvailableMaterials(machine_definition_id, variant_name, diameter)
+        return self.getAvailableMaterials(machine.definition, variant_name, diameter)
 
     #
     # Gets MaterialNode for the given extruder and machine with the given material name.

+ 0 - 4
cura/Machines/Models/GenericMaterialsModel.py

@@ -31,7 +31,6 @@ class GenericMaterialsModel(BaseMaterialsModel):
             self.setItems([])
             return
         extruder_stack = global_stack.extruders[extruder_position]
-        exclude_materials = set(global_stack.definition.getMetaDataEntry("exclude_materials", []))
 
         available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack,
                                                                                                  extruder_stack)
@@ -42,9 +41,6 @@ class GenericMaterialsModel(BaseMaterialsModel):
         item_list = []
         for root_material_id, container_node in available_material_dict.items():
             metadata = container_node.metadata
-            # Skip excluded materials
-            if metadata["id"] in exclude_materials:
-                continue
             # Only add results for generic materials
             if metadata["brand"].lower() != "generic":
                 continue

+ 1 - 3
cura/Machines/Models/QualityManagementModel.py

@@ -69,9 +69,7 @@ class QualityManagementModel(ListModel):
         # Create quality_changes group items
         quality_changes_item_list = []
         for quality_changes_group in quality_changes_group_dict.values():
-            if quality_changes_group.quality_type not in available_quality_types:
-                continue
-            quality_group = quality_group_dict[quality_changes_group.quality_type]
+            quality_group = quality_group_dict.get(quality_changes_group.quality_type)
             item = {"name": quality_changes_group.name,
                     "is_read_only": False,
                     "quality_group": quality_group,

+ 8 - 5
cura/Machines/Models/QualitySettingsModel.py

@@ -84,11 +84,14 @@ class QualitySettingsModel(ListModel):
         quality_group = self._selected_quality_item["quality_group"]
         quality_changes_group = self._selected_quality_item["quality_changes_group"]
 
-        if self._selected_position == self.GLOBAL_STACK_POSITION:
-            quality_node = quality_group.node_for_global
-        else:
-            quality_node = quality_group.nodes_for_extruders.get(str(self._selected_position))
-        settings_keys = quality_group.getAllKeys()
+        quality_node = None
+        settings_keys = set()
+        if quality_group:
+            if self._selected_position == self.GLOBAL_STACK_POSITION:
+                quality_node = quality_group.node_for_global
+            else:
+                quality_node = quality_group.nodes_for_extruders.get(str(self._selected_position))
+            settings_keys = quality_group.getAllKeys()
         quality_containers = []
         if quality_node is not None and quality_node.getContainer() is not None:
             quality_containers.append(quality_node.getContainer())

+ 6 - 1
cura/MultiplyObjectsJob.py

@@ -32,14 +32,19 @@ class MultiplyObjectsJob(Job):
 
         root = scene.getRoot()
         arranger = Arrange.create(scene_root=root)
+        processed_nodes = []
         nodes = []
 
         for node in self._objects:
             # If object is part of a group, multiply group
             current_node = node
-            while current_node.getParent() and current_node.getParent().callDecoration("isGroup"):
+            while current_node.getParent() and (current_node.getParent().callDecoration("isGroup") or current_node.getParent().callDecoration("isSliceable")):
                 current_node = current_node.getParent()
 
+            if current_node in processed_nodes:
+                continue
+            processed_nodes.append(current_node)
+
             node_too_big = False
             if node.getBoundingBox().width < 300 or node.getBoundingBox().depth < 300:
                 offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(current_node, min_offset=self._min_offset)

+ 12 - 6
cura/PrintInformation.py

@@ -138,6 +138,7 @@ class PrintInformation(QObject):
 
     def setPreSliced(self, pre_sliced):
         self._pre_sliced = pre_sliced
+        self._updateJobName()
         self.preSlicedChanged.emit()
 
     @pyqtProperty(Duration, notify = currentPrintTimeChanged)
@@ -322,16 +323,21 @@ class PrintInformation(QObject):
         # when a file is opened using the terminal; the filename comes from _onFileLoaded and still contains its
         # extension. This cuts the extension off if necessary.
         name = os.path.splitext(name)[0]
+        filename_parts = os.path.basename(base_name).split(".")
+
+        # If it's a gcode, also always update the job name
+        is_gcode = False
+        if len(filename_parts) > 1:
+            # Only check the extension(s)
+            is_gcode = "gcode" in filename_parts[1:]
 
         # if this is a profile file, always update the job name
         # name is "" when I first had some meshes and afterwards I deleted them so the naming should start again
         is_empty = name == ""
-        if is_project_file or (is_empty or (self._base_name == "" and self._base_name != name)):
-            # remove ".curaproject" suffix from (imported) the file name
-            if name.endswith(".curaproject"):
-                name = name[:name.rfind(".curaproject")]
-            self._base_name = name
-            self._updateJobName()
+        if is_gcode or is_project_file or (is_empty or (self._base_name == "" and self._base_name != name)):
+            # Only take the file name part
+            self._base_name = filename_parts[0]
+        self._updateJobName()
 
     @pyqtProperty(str, fset = setBaseName, notify = baseNameChanged)
     def baseName(self):

+ 14 - 0
cura/PrinterOutput/GenericOutputController.py

@@ -152,3 +152,17 @@ class GenericOutputController(PrinterOutputController):
         for extruder in self._preheat_hotends:
             self.setTargetHotendTemperature(extruder.getPrinter(), extruder.getPosition(), 0)
         self._preheat_hotends = set()
+
+    # Cancel any ongoing preheating timers, without setting back the temperature to 0
+    # This can be used eg at the start of a print
+    def stopPreheatTimers(self):
+        if self._preheat_hotends_timer.isActive():
+            for extruder in self._preheat_hotends:
+                extruder.updateIsPreheating(False)
+            self._preheat_hotends = set()
+
+            self._preheat_hotends_timer.stop()
+
+        if self._preheat_bed_timer.isActive():
+            self._preheat_printer.updateIsPreheating(False)
+            self._preheat_bed_timer.stop()

+ 19 - 0
cura/Scene/CuraSceneNode.py

@@ -103,6 +103,25 @@ class CuraSceneNode(SceneNode):
                 return True
         return False
 
+    ##  Override of SceneNode._calculateAABB to exclude non-printing-meshes from bounding box
+    def _calculateAABB(self):
+        aabb = None
+        if self._mesh_data:
+            aabb = self._mesh_data.getExtents(self.getWorldTransformation())
+        else:  # If there is no mesh_data, use a boundingbox that encompasses the local (0,0,0)
+            position = self.getWorldPosition()
+            aabb = AxisAlignedBox(minimum = position, maximum = position)
+
+        for child in self._children:
+            if child.callDecoration("isNonPrintingMesh"):
+                # Non-printing-meshes inside a group should not affect push apart or drop to build plate
+                continue
+            if aabb is None:
+                aabb = child.getBoundingBox()
+            else:
+                aabb = aabb + child.getBoundingBox()
+        self._aabb = aabb
+
     ##  Taken from SceneNode, but replaced SceneNode with CuraSceneNode
     def __deepcopy__(self, memo):
         copy = CuraSceneNode(no_setting_override = True)  # Setting override will be added later

+ 6 - 6
cura/Settings/ContainerManager.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2017 Ultimaker B.V.
+# Copyright (c) 2018 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
 import os.path
@@ -22,12 +22,10 @@ from UM.Settings.DefinitionContainer import DefinitionContainer
 from UM.Settings.InstanceContainer import InstanceContainer
 
 from UM.MimeTypeDatabase import MimeTypeNotFoundError
+from UM.Settings.ContainerFormatError import ContainerFormatError
 from UM.Settings.ContainerRegistry import ContainerRegistry
-
-from UM.i18n import i18nCatalog
-
 from cura.Settings.ExtruderManager import ExtruderManager
-from cura.Settings.ExtruderStack import ExtruderStack
+from UM.i18n import i18nCatalog
 
 catalog = i18nCatalog("cura")
 
@@ -289,7 +287,9 @@ class ContainerManager(QObject):
             with open(file_url, "rt", encoding = "utf-8") as f:
                 container.deserialize(f.read())
         except PermissionError:
-            return {"status": "error", "message": "Permission denied when trying to read the file"}
+            return {"status": "error", "message": "Permission denied when trying to read the file."}
+        except ContainerFormatError:
+            return {"status": "error", "Message": "The material file appears to be corrupt."}
         except Exception as ex:
             return {"status": "error", "message": str(ex)}
 

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