Browse Source

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

Jaime van Kessel 7 years ago
parent
commit
561b97c255

+ 0 - 7
cura/Machines/MaterialManager.py

@@ -101,13 +101,6 @@ class MaterialManager(QObject):
         #    GUID -> material group list
         self._guid_material_groups_map = defaultdict(list)
         for root_material_id, material_group in self._material_group_map.items():
-            # This can happen when we are updating with incomplete data.
-            if material_group.root_material_node is None:
-                Logger.log("e", "Missing root material node for [%s]. Probably caused by update using incomplete data."
-                           " Check all related signals for further debugging.",
-                           material_group.name)
-                self._update_timer.start()
-                return
             guid = material_group.root_material_node.metadata["GUID"]
             self._guid_material_groups_map[guid].append(material_group)
 

+ 2 - 2
cura/Machines/Models/BrandMaterialsModel.py

@@ -53,8 +53,8 @@ class BrandMaterialsModel(ListModel):
         self._extruder_manager = CuraApplication.getInstance().getExtruderManager()
         self._material_manager = CuraApplication.getInstance().getMaterialManager()
 
-        self._machine_manager.globalContainerChanged.connect(self._update)
-        self._material_manager.materialsUpdated.connect(self._update)
+        self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines.
+        self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes.
         self._update()
 
     def setExtruderPosition(self, position: int):

+ 2 - 2
cura/Machines/Models/GenericMaterialsModel.py

@@ -15,8 +15,8 @@ class GenericMaterialsModel(BaseMaterialsModel):
         self._extruder_manager = CuraApplication.getInstance().getExtruderManager()
         self._material_manager = CuraApplication.getInstance().getMaterialManager()
 
-        self._machine_manager.globalContainerChanged.connect(self._update)
-        self._material_manager.materialsUpdated.connect(self._update)
+        self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines.
+        self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes.
         self._update()
 
     def _update(self):

+ 9 - 6
cura/PrinterOutput/NetworkedPrinterOutputDevice.py

@@ -56,12 +56,15 @@ class NetworkedPrinterOutputDevice(PrinterOutputDevice):
         self._connection_state_before_timeout = None    # type: Optional[ConnectionState]
 
         printer_type = self._properties.get(b"machine", b"").decode("utf-8")
-        if printer_type.startswith("9511"):
-            self._printer_type = "ultimaker3_extended"
-        elif printer_type.startswith("9066"):
-            self._printer_type = "ultimaker3"
-        else:
-            self._printer_type = "unknown"
+        printer_type_identifiers = {
+            "9066": "ultimaker3",
+            "9511": "ultimaker3_extended"
+        }
+        self._printer_type = "Unknown"
+        for key, value in printer_type_identifiers.items():
+            if printer_type.startswith(key):
+                self._printer_type = value
+                break
 
     def requestWrite(self, nodes, file_name=None, filter_by_machine=False, file_handler=None, **kwargs) -> None:
         raise NotImplementedError("requestWrite needs to be implemented")

+ 28 - 21
cura/Settings/MachineManager.py

@@ -50,7 +50,6 @@ class MachineManager(QObject):
         self._global_container_stack = None     # type: GlobalStack
 
         self._current_root_material_id = {}
-        self._current_root_material_name = {}
         self._current_quality_group = None
         self._current_quality_changes_group = None
 
@@ -129,6 +128,9 @@ class MachineManager(QObject):
         # When the materials lookup table gets updated, it can mean that a material has its name changed, which should
         # be reflected on the GUI. This signal emission makes sure that it happens.
         self._material_manager.materialsUpdated.connect(self.rootMaterialChanged)
+        # When the materials get updated, it can be that an activated material's diameter gets changed. In that case,
+        # a material update should be triggered to make sure that the machine still has compatible materials activated.
+        self._material_manager.materialsUpdated.connect(self._updateUponMaterialMetadataChange)
         self.rootMaterialChanged.connect(self._onRootMaterialChanged)
 
     activeQualityGroupChanged = pyqtSignal()
@@ -877,11 +879,13 @@ class MachineManager(QObject):
         return self._default_extruder_position
 
     ##  This will fire the propertiesChanged for all settings so they will be updated in the front-end
+    @pyqtSlot()
     def forceUpdateAllSettings(self):
         with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
             property_names = ["value", "resolve"]
-            for setting_key in self._global_container_stack.getAllKeys():
-                self._global_container_stack.propertiesChanged.emit(setting_key, property_names)
+            for container in [self._global_container_stack] + list(self._global_container_stack.extruders.values()):
+                for setting_key in container.getAllKeys():
+                    container.propertiesChanged.emit(setting_key, property_names)
 
     @pyqtSlot(int, bool)
     def setExtruderEnabled(self, position: int, enabled) -> None:
@@ -926,28 +930,18 @@ class MachineManager(QObject):
             return []
         return sorted(list(self._global_container_stack.extruders.keys()))
 
-    ##  Update _current_root_material_id and _current_root_material_name when
-    #   the current root material was changed.
+    ##  Update _current_root_material_id when the current root material was changed.
     def _onRootMaterialChanged(self):
         self._current_root_material_id = {}
 
         if self._global_container_stack:
             for position in self._global_container_stack.extruders:
                 self._current_root_material_id[position] = self._global_container_stack.extruders[position].material.getMetaDataEntry("base_file")
-            self._current_root_material_name = {}
-            for position in self._global_container_stack.extruders:
-                if position not in self._current_root_material_name:
-                    material = self._global_container_stack.extruders[position].material
-                    self._current_root_material_name[position] = material.getName()
 
     @pyqtProperty("QVariant", notify = rootMaterialChanged)
     def currentRootMaterialId(self):
         return self._current_root_material_id
 
-    @pyqtProperty("QVariant", notify = rootMaterialChanged)
-    def currentRootMaterialName(self):
-        return self._current_root_material_name
-
     ##  Return the variant names in the extruder stack(s).
     ##  For the variant in the global stack, use activeVariantBuildplateName
     @pyqtProperty("QVariant", notify = activeVariantChanged)
@@ -1044,15 +1038,12 @@ class MachineManager(QObject):
         if container_node:
             self._global_container_stack.extruders[position].material = container_node.getContainer()
             root_material_id = container_node.metadata["base_file"]
-            root_material_name = container_node.getContainer().getName()
         else:
             self._global_container_stack.extruders[position].material = self._empty_material_container
             root_material_id = None
-            root_material_name = None
         # The _current_root_material_id is used in the MaterialMenu to see which material is selected
         if root_material_id != self._current_root_material_id[position]:
             self._current_root_material_id[position] = root_material_id
-            self._current_root_material_name[position] = root_material_name
             self.rootMaterialChanged.emit()
 
     def activeMaterialsCompatible(self):
@@ -1066,7 +1057,7 @@ class MachineManager(QObject):
         return True
 
     ## Update current quality type and machine after setting material
-    def _updateQualityWithMaterial(self):
+    def _updateQualityWithMaterial(self, *args):
         Logger.log("i", "Updating quality/quality_changes due to material change")
         current_quality_type = None
         if self._current_quality_group:
@@ -1111,9 +1102,15 @@ class MachineManager(QObject):
             extruder = self._global_container_stack.extruders[position]
 
             current_material_base_name = extruder.material.getMetaDataEntry("base_file")
-            current_variant_name = extruder.variant.getMetaDataEntry("name")
-
-            material_diameter = self._global_container_stack.getProperty("material_diameter", "value")
+            current_variant_name = None
+            if extruder.variant.getId() != self._empty_variant_container.getId():
+                current_variant_name = extruder.variant.getMetaDataEntry("name")
+
+            from UM.Settings.Interfaces import PropertyEvaluationContext
+            from cura.Settings.CuraContainerStack import _ContainerIndexes
+            context = PropertyEvaluationContext(extruder)
+            context.context["evaluate_from_container_index"] = _ContainerIndexes.DefinitionChanges
+            material_diameter = self._global_container_stack.getProperty("material_diameter", "value", context)
             candidate_materials = self._material_manager.getAvailableMaterials(
                 self._global_container_stack.definition.getId(),
                 current_variant_name,
@@ -1128,6 +1125,11 @@ class MachineManager(QObject):
                 self._setMaterial(position, new_material)
                 continue
 
+            # The current material is not available, find the preferred one
+            material_node = self._material_manager.getDefaultMaterial(self._global_container_stack, current_variant_name)
+            if material_node is not None:
+                self._setMaterial(position, material_node)
+
     ##  Given a printer definition name, select the right machine instance. In case it doesn't exist, create a new
     #   instance with the same network key.
     @pyqtSlot(str)
@@ -1252,3 +1254,8 @@ class MachineManager(QObject):
         elif self._current_quality_group:
             name = self._current_quality_group.name
         return name
+
+    def _updateUponMaterialMetadataChange(self):
+        with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
+            self._updateMaterialWithVariant(None)
+            self._updateQualityWithMaterial()

+ 7 - 4
cura/Settings/SettingInheritanceManager.py

@@ -1,7 +1,7 @@
 # Copyright (c) 2017 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
-from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal
+from PyQt5.QtCore import QObject, QTimer, pyqtProperty, pyqtSignal
 from UM.FlameProfiler import pyqtSlot
 from UM.Application import Application
 from UM.Logger import Logger
@@ -30,6 +30,11 @@ class SettingInheritanceManager(QObject):
         ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
         self._onActiveExtruderChanged()
 
+        self._update_timer = QTimer()
+        self._update_timer.setInterval(500)
+        self._update_timer.setSingleShot(True)
+        self._update_timer.timeout.connect(self._update)
+
     settingsWithIntheritanceChanged = pyqtSignal()
 
     ##  Get the keys of all children settings with an override.
@@ -226,9 +231,7 @@ class SettingInheritanceManager(QObject):
         self._onActiveExtruderChanged()
 
     def _onContainersChanged(self, container):
-        # TODO: Multiple container changes in sequence now cause quite a few recalculations.
-        # This isn't that big of an issue, but it could be in the future.
-        self._update()
+        self._update_timer.start()
 
     @staticmethod
     def createSettingInheritanceManager(engine=None, script_engine=None):

+ 7 - 13
plugins/3MFReader/ThreeMFWorkspaceReader.py

@@ -265,13 +265,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
             for material_container_file in material_container_files:
                 container_id = self._stripFileToId(material_container_file)
 
-                from hashlib import sha1
-                hex_container_id = sha1(container_id.encode('utf-8')).hexdigest()
-
                 serialized = archive.open(material_container_file).read().decode("utf-8")
-                metadata_list = xml_material_profile.deserializeMetadata(serialized, hex_container_id)
-                reverse_map = {metadata["id"].replace(hex_container_id, container_id): container_id.replace(hex_container_id, container_id)
-                               for metadata in metadata_list}
+                metadata_list = xml_material_profile.deserializeMetadata(serialized, container_id)
+                reverse_map = {metadata["id"]: container_id for metadata in metadata_list}
                 reverse_material_id_dict.update(reverse_map)
 
                 material_labels.append(self._getMaterialLabelFromSerialized(serialized))
@@ -754,15 +750,13 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
                 quality_changes_containers = self._container_registry.findInstanceContainers(name = quality_changes_name,
                                                                                              type = "quality_changes")
                 for container in quality_changes_containers:
-                    extruder_definition_id = container.getMetaDataEntry("extruder")
-                    if not extruder_definition_id:
+                    extruder_position = container.getMetaDataEntry("position")
+                    if extruder_position is None:
                         quality_changes_info.global_info.container = container
                     else:
-                        extruder_definition_metadata = self._container_registry.findDefinitionContainersMetadata(id = extruder_definition_id)[0]
-                        position = extruder_definition_metadata["position"]
-                        if position not in quality_changes_info.extruder_info_dict:
-                            quality_changes_info.extruder_info_dict[position] = ContainerInfo(None, None, None)
-                        container_info = quality_changes_info.extruder_info_dict[position]
+                        if extruder_position not in quality_changes_info.extruder_info_dict:
+                            quality_changes_info.extruder_info_dict[extruder_position] = ContainerInfo(None, None, None)
+                        container_info = quality_changes_info.extruder_info_dict[extruder_position]
                         container_info.container = container
 
             # If there is no quality changes for any extruder, create one.

+ 1 - 1
plugins/CuraEngineBackend/StartSliceJob.py

@@ -281,7 +281,7 @@ class StartSliceJob(Job):
         default_extruder_position = int(Application.getInstance().getMachineManager().defaultExtruderPosition)
         result = {}
         for key in stack.getAllKeys():
-            setting_type = stack.getProperty(key, "type")
+            setting_type = stack.definition.getProperty(key, "type")
             value = stack.getProperty(key, "value")
             if setting_type == "extruder" and value == -1:
                 # replace with the default value

+ 6 - 1
plugins/MachineSettingsAction/MachineSettingsAction.qml

@@ -382,6 +382,11 @@ Cura.MachineAction
                             property string settingKey: "machine_nozzle_size"
                             property string label: catalog.i18nc("@label", "Nozzle size")
                             property string unit: catalog.i18nc("@label", "mm")
+                            function afterOnEditingFinished()
+                            {
+                                // Somehow the machine_nozzle_size dependent settings are not updated otherwise
+                                Cura.MachineManager.forceUpdateAllSettings()
+                            }
                             property bool isExtruderSetting: true
                         }
 
@@ -889,4 +894,4 @@ Cura.MachineAction
         watchedProperties: [ "value" ]
         storeIndex: manager.containerIndex
     }
-}
+}

+ 13 - 23
plugins/XmlMaterialProfile/XmlMaterialProfile.py

@@ -838,15 +838,11 @@ class XmlMaterialProfile(InstanceContainer):
                     if machine_compatibility:
                         new_material_id = container_id + "_" + machine_id
 
-                        # The child or derived material container may already exist. This can happen when a material in a
-                        # project file and the a material in Cura have the same ID.
-                        # In the case if a derived material already exists, override that material container because if
-                        # the data in the parent material has been changed, the derived ones should be updated too.
-                        found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_material_id)
-                        if found_materials:
-                            new_material_metadata = found_materials[0]
-                        else:
-                            new_material_metadata = {}
+                        # Do not look for existing container/container metadata with the same ID although they may exist.
+                        # In project loading and perhaps some other places, we only want to get information (metadata)
+                        # from a file without changing the current state of the system. If we overwrite the existing
+                        # metadata here, deserializeMetadata() will not be safe for retrieving information.
+                        new_material_metadata = {}
 
                         new_material_metadata.update(base_metadata)
                         new_material_metadata["id"] = new_material_id
@@ -854,8 +850,7 @@ class XmlMaterialProfile(InstanceContainer):
                         new_material_metadata["machine_manufacturer"] = machine_manufacturer
                         new_material_metadata["definition"] = machine_id
 
-                        if len(found_materials) == 0: #This is a new material.
-                            result_metadata.append(new_material_metadata)
+                        result_metadata.append(new_material_metadata)
 
                     buildplates = machine.iterfind("./um:buildplate", cls.__namespaces)
                     buildplate_map = {}
@@ -866,12 +861,12 @@ class XmlMaterialProfile(InstanceContainer):
                         if buildplate_id is None:
                             continue
 
-                        variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = buildplate_id)
-                        if not variant_containers:
+                        variant_metadata = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = buildplate_id)
+                        if not variant_metadata:
                             # It is not really properly defined what "ID" is so also search for variants by name.
-                            variant_containers = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = machine_id, name = buildplate_id)
+                            variant_metadata = ContainerRegistry.getInstance().findInstanceContainersMetadata(definition = machine_id, name = buildplate_id)
 
-                        if not variant_containers:
+                        if not variant_metadata:
                             continue
 
                         settings = buildplate.iterfind("./um:setting", cls.__namespaces)
@@ -900,12 +895,8 @@ class XmlMaterialProfile(InstanceContainer):
 
                         new_hotend_specific_material_id = container_id + "_" + machine_id + "_" + hotend_name.replace(" ", "_")
 
-                        # Same as machine compatibility, keep the derived material containers consistent with the parent material
-                        found_materials = ContainerRegistry.getInstance().findInstanceContainersMetadata(id = new_hotend_specific_material_id)
-                        if found_materials:
-                            new_hotend_material_metadata = found_materials[0]
-                        else:
-                            new_hotend_material_metadata = {}
+                        # Same as above, do not overwrite existing metadata.
+                        new_hotend_material_metadata = {}
 
                         new_hotend_material_metadata.update(base_metadata)
                         new_hotend_material_metadata["variant_name"] = hotend_name
@@ -917,8 +908,7 @@ class XmlMaterialProfile(InstanceContainer):
                             new_hotend_material_metadata["buildplate_compatible"] = buildplate_map["buildplate_compatible"]
                             new_hotend_material_metadata["buildplate_recommended"] = buildplate_map["buildplate_recommended"]
 
-                        if len(found_materials) == 0:
-                            result_metadata.append(new_hotend_material_metadata)
+                        result_metadata.append(new_hotend_material_metadata)
 
                     # there is only one ID for a machine. Once we have reached here, it means we have already found
                     # a workable ID for that machine, so there is no need to continue

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