Browse Source

Merge branch 'replace_controls_1_for_controls_2' into CURA-8684_QtControls_replacement_Buttons,_Actions_&_'Exclusivity'

Conflicts:
	plugins/ImageReader/ConfigUI.qml
	plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml
	plugins/PerObjectSettingsTool/SettingPickDialog.qml
	resources/qml/Dialogs/DiscardOrKeepProfileChangesDialog.qml
	resources/qml/Menus/ConfigurationMenu/CustomConfiguration.qml
	resources/qml/Preferences/GeneralPage.qml
	resources/qml/Preferences/Materials/MaterialsPage.qml
	resources/qml/Preferences/Materials/MaterialsView.qml
	resources/qml/Preferences/ProfilesPage.qml

These conflicts are all arising from headers/includes being updated at the same time, or from the two branches marking the other one's components as needing OldControls.
This introduced more OldControls markers which don't get marked as merge conflicts by Git. This happens when an element could just be left as the original name but from the new import (e.g. a Button stays a Button in Controls 2, but should be marked as from OldControls on the branch that doesn't update the Button).
Ghostkeeper 3 years ago
parent
commit
6db4a55f6e

+ 3 - 0
.gitignore

@@ -10,6 +10,8 @@ resources/i18n/en_7S
 resources/i18n/x-test
 resources/i18n/x-test
 resources/firmware
 resources/firmware
 resources/materials
 resources/materials
+resources/images/whats_new
+resources/texts/whats_new
 CuraEngine.exe
 CuraEngine.exe
 LC_MESSAGES
 LC_MESSAGES
 .cache
 .cache
@@ -37,6 +39,7 @@ cura.desktop
 
 
 #Externally located plug-ins commonly installed by our devs.
 #Externally located plug-ins commonly installed by our devs.
 plugins/cura-big-flame-graph
 plugins/cura-big-flame-graph
+plugins/cura-camera-position
 plugins/cura-god-mode-plugin
 plugins/cura-god-mode-plugin
 plugins/cura-siemensnx-plugin
 plugins/cura-siemensnx-plugin
 plugins/CuraBlenderPlugin
 plugins/CuraBlenderPlugin

+ 1 - 1
cura/Arranging/Nest2DArrange.py

@@ -40,7 +40,7 @@ def findNodePlacement(nodes_to_arrange: List["SceneNode"], build_volume: "BuildV
 
 
     machine_width = build_volume.getWidth()
     machine_width = build_volume.getWidth()
     machine_depth = build_volume.getDepth()
     machine_depth = build_volume.getDepth()
-    build_plate_bounding_box = Box(machine_width * factor, machine_depth * factor)
+    build_plate_bounding_box = Box(int(machine_width * factor), int(machine_depth * factor))
 
 
     if fixed_nodes is None:
     if fixed_nodes is None:
         fixed_nodes = []
         fixed_nodes = []

+ 19 - 19
cura/BuildVolume.py

@@ -848,10 +848,10 @@ class BuildVolume(SceneNode):
         """
         """
 
 
         result = {}
         result = {}
-        adhesion_extruder = None #type: ExtruderStack
+        skirt_brim_extruder: ExtruderStack = None
         for extruder in used_extruders:
         for extruder in used_extruders:
-            if int(extruder.getProperty("extruder_nr", "value")) == int(self._global_container_stack.getProperty("adhesion_extruder_nr", "value")):
-                adhesion_extruder = extruder
+            if int(extruder.getProperty("extruder_nr", "value")) == int(self._global_container_stack.getProperty("skirt_brim_extruder_nr", "value")):
+                skirt_brim_extruder = extruder
             result[extruder.getId()] = []
             result[extruder.getId()] = []
 
 
         # Currently, the only normally printed object is the prime tower.
         # Currently, the only normally printed object is the prime tower.
@@ -865,11 +865,11 @@ class BuildVolume(SceneNode):
                 prime_tower_x = prime_tower_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left.
                 prime_tower_x = prime_tower_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left.
                 prime_tower_y = prime_tower_y + machine_depth / 2
                 prime_tower_y = prime_tower_y + machine_depth / 2
 
 
-            if adhesion_extruder is not None and self._global_container_stack.getProperty("prime_tower_brim_enable", "value") and self._global_container_stack.getProperty("adhesion_type", "value") != "raft":
+            if skirt_brim_extruder is not None and self._global_container_stack.getProperty("prime_tower_brim_enable", "value") and self._global_container_stack.getProperty("adhesion_type", "value") != "raft":
                 brim_size = (
                 brim_size = (
-                    adhesion_extruder.getProperty("brim_line_count", "value") *
-                    adhesion_extruder.getProperty("skirt_brim_line_width", "value") / 100.0 *
-                    adhesion_extruder.getProperty("initial_layer_line_width_factor", "value")
+                    skirt_brim_extruder.getProperty("brim_line_count", "value") *
+                    skirt_brim_extruder.getProperty("skirt_brim_line_width", "value") / 100.0 *
+                    skirt_brim_extruder.getProperty("initial_layer_line_width_factor", "value")
                 )
                 )
                 prime_tower_x -= brim_size
                 prime_tower_x -= brim_size
                 prime_tower_y += brim_size
                 prime_tower_y += brim_size
@@ -1100,18 +1100,18 @@ class BuildVolume(SceneNode):
         # with the adhesion extruder, but it also prints one extra line by all other extruders. As such, the
         # with the adhesion extruder, but it also prints one extra line by all other extruders. As such, the
         # setting does *not* have a limit_to_extruder setting (which means that we can't ask the global extruder what
         # setting does *not* have a limit_to_extruder setting (which means that we can't ask the global extruder what
         # the value is.
         # the value is.
-        adhesion_extruder = self._global_container_stack.getProperty("adhesion_extruder_nr", "value")
+        skirt_brim_extruder_nr = self._global_container_stack.getProperty("skirt_brim_extruder_nr", "value")
         try:
         try:
-            adhesion_stack = self._global_container_stack.extruderList[int(adhesion_extruder)]
+            skirt_brim_stack = self._global_container_stack.extruderList[int(skirt_brim_extruder_nr)]
         except IndexError:
         except IndexError:
-            Logger.warning(f"Couldn't find extruder with index '{adhesion_extruder}', defaulting to 0 instead.")
-            adhesion_stack = self._global_container_stack.extruderList[0]
-        skirt_brim_line_width = adhesion_stack.getProperty("skirt_brim_line_width", "value")
+            Logger.warning(f"Couldn't find extruder with index '{skirt_brim_extruder_nr}', defaulting to 0 instead.")
+            skirt_brim_stack = self._global_container_stack.extruderList[0]
+        skirt_brim_line_width = skirt_brim_stack.getProperty("skirt_brim_line_width", "value")
 
 
-        initial_layer_line_width_factor = adhesion_stack.getProperty("initial_layer_line_width_factor", "value")
+        initial_layer_line_width_factor = skirt_brim_stack.getProperty("initial_layer_line_width_factor", "value")
         # Use brim width if brim is enabled OR the prime tower has a brim.
         # Use brim width if brim is enabled OR the prime tower has a brim.
         if adhesion_type == "brim":
         if adhesion_type == "brim":
-            brim_line_count = self._global_container_stack.getProperty("brim_line_count", "value")
+            brim_line_count = skirt_brim_stack.getProperty("brim_line_count", "value")
             bed_adhesion_size = skirt_brim_line_width * brim_line_count * initial_layer_line_width_factor / 100.0
             bed_adhesion_size = skirt_brim_line_width * brim_line_count * initial_layer_line_width_factor / 100.0
 
 
             for extruder_stack in used_extruders:
             for extruder_stack in used_extruders:
@@ -1120,8 +1120,8 @@ class BuildVolume(SceneNode):
             # We don't create an additional line for the extruder we're printing the brim with.
             # We don't create an additional line for the extruder we're printing the brim with.
             bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0
             bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0
         elif adhesion_type == "skirt":
         elif adhesion_type == "skirt":
-            skirt_distance = self._global_container_stack.getProperty("skirt_gap", "value")
-            skirt_line_count = self._global_container_stack.getProperty("skirt_line_count", "value")
+            skirt_distance = skirt_brim_stack.getProperty("skirt_gap", "value")
+            skirt_line_count = skirt_brim_stack.getProperty("skirt_line_count", "value")
 
 
             bed_adhesion_size = skirt_distance + (
             bed_adhesion_size = skirt_distance + (
                         skirt_brim_line_width * skirt_line_count) * initial_layer_line_width_factor / 100.0
                         skirt_brim_line_width * skirt_line_count) * initial_layer_line_width_factor / 100.0
@@ -1132,7 +1132,7 @@ class BuildVolume(SceneNode):
             # We don't create an additional line for the extruder we're printing the skirt with.
             # We don't create an additional line for the extruder we're printing the skirt with.
             bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0
             bed_adhesion_size -= skirt_brim_line_width * initial_layer_line_width_factor / 100.0
         elif adhesion_type == "raft":
         elif adhesion_type == "raft":
-            bed_adhesion_size = self._global_container_stack.getProperty("raft_margin", "value")
+            bed_adhesion_size = self._global_container_stack.getProperty("raft_margin", "value")  # Should refer to the raft extruder if set.
         elif adhesion_type == "none":
         elif adhesion_type == "none":
             bed_adhesion_size = 0
             bed_adhesion_size = 0
         else:
         else:
@@ -1220,7 +1220,7 @@ class BuildVolume(SceneNode):
     _tower_settings = ["prime_tower_enable", "prime_tower_size", "prime_tower_position_x", "prime_tower_position_y", "prime_tower_brim_enable"]
     _tower_settings = ["prime_tower_enable", "prime_tower_size", "prime_tower_position_x", "prime_tower_position_y", "prime_tower_brim_enable"]
     _ooze_shield_settings = ["ooze_shield_enabled", "ooze_shield_dist"]
     _ooze_shield_settings = ["ooze_shield_enabled", "ooze_shield_dist"]
     _distance_settings = ["infill_wipe_dist", "travel_avoid_distance", "support_offset", "support_enable", "travel_avoid_other_parts", "travel_avoid_supports", "wall_line_count", "wall_line_width_0", "wall_line_width_x"]
     _distance_settings = ["infill_wipe_dist", "travel_avoid_distance", "support_offset", "support_enable", "travel_avoid_other_parts", "travel_avoid_supports", "wall_line_count", "wall_line_width_0", "wall_line_width_x"]
-    _extruder_settings = ["support_enable", "support_bottom_enable", "support_roof_enable", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "brim_line_count", "adhesion_extruder_nr", "adhesion_type"] #Settings that can affect which extruders are used.
-    _limit_to_extruder_settings = ["wall_extruder_nr", "wall_0_extruder_nr", "wall_x_extruder_nr", "top_bottom_extruder_nr", "infill_extruder_nr", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "adhesion_extruder_nr"]
+    _extruder_settings = ["support_enable", "support_bottom_enable", "support_roof_enable", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "brim_line_count", "skirt_brim_extruder_nr", "raft_base_extruder_nr", "raft_interface_extruder_nr", "raft_surface_extruder_nr", "adhesion_type"] #Settings that can affect which extruders are used.
+    _limit_to_extruder_settings = ["wall_extruder_nr", "wall_0_extruder_nr", "wall_x_extruder_nr", "top_bottom_extruder_nr", "infill_extruder_nr", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "skirt_brim_extruder_nr", "raft_base_extruder_nr", "raft_interface_extruder_nr", "raft_surface_extruder_nr"]
     _material_size_settings = ["material_shrinkage_percentage", "material_shrinkage_percentage_xy", "material_shrinkage_percentage_z"]
     _material_size_settings = ["material_shrinkage_percentage", "material_shrinkage_percentage_xy", "material_shrinkage_percentage_z"]
     _disallowed_area_settings = _skirt_settings + _prime_settings + _tower_settings + _ooze_shield_settings + _distance_settings + _extruder_settings + _material_size_settings
     _disallowed_area_settings = _skirt_settings + _prime_settings + _tower_settings + _ooze_shield_settings + _distance_settings + _extruder_settings + _material_size_settings

+ 8 - 1
cura/CrashHandler.py

@@ -15,7 +15,7 @@ from typing import cast, Any
 try:
 try:
     from sentry_sdk.hub import Hub
     from sentry_sdk.hub import Hub
     from sentry_sdk.utils import event_from_exception
     from sentry_sdk.utils import event_from_exception
-    from sentry_sdk import configure_scope
+    from sentry_sdk import configure_scope, add_breadcrumb
     with_sentry_sdk = True
     with_sentry_sdk = True
 except ImportError:
 except ImportError:
     with_sentry_sdk = False
     with_sentry_sdk = False
@@ -424,6 +424,13 @@ class CrashHandler:
         if with_sentry_sdk:
         if with_sentry_sdk:
             try:
             try:
                 hub = Hub.current
                 hub = Hub.current
+                if not Logger.getLoggers():
+                    # No loggers have been loaded yet, so we don't have any breadcrumbs :(
+                    # So add them manually so we at least have some info...
+                    add_breadcrumb(level = "info", message = "SentryLogging was not initialised yet")
+                    for log_type, line in Logger.getUnloggedLines():
+                        add_breadcrumb(message=line)
+
                 event, hint = event_from_exception((self.exception_type, self.value, self.traceback))
                 event, hint = event_from_exception((self.exception_type, self.value, self.traceback))
                 hub.capture_event(event, hint=hint)
                 hub.capture_event(event, hint=hint)
                 hub.flush()
                 hub.flush()

+ 4 - 0
cura/CuraApplication.py

@@ -777,10 +777,14 @@ class CuraApplication(QtApplication):
             lib_suffixes = {""}
             lib_suffixes = {""}
         for suffix in lib_suffixes:
         for suffix in lib_suffixes:
             self._plugin_registry.addPluginLocation(os.path.join(QtApplication.getInstallPrefix(), "lib" + suffix, "cura"))
             self._plugin_registry.addPluginLocation(os.path.join(QtApplication.getInstallPrefix(), "lib" + suffix, "cura"))
+
         if not hasattr(sys, "frozen"):
         if not hasattr(sys, "frozen"):
             self._plugin_registry.addPluginLocation(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "plugins"))
             self._plugin_registry.addPluginLocation(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "plugins"))
             self._plugin_registry.preloaded_plugins.append("ConsoleLogger")
             self._plugin_registry.preloaded_plugins.append("ConsoleLogger")
 
 
+        # Since it's possible to get crashes in code before the sentrylogger is loaded, we want to start this plugin
+        # as quickly as possible, as we might get unsolvable crash reports without it.
+        self._plugin_registry.preloaded_plugins.append("SentryLogger")
         self._plugin_registry.loadPlugins()
         self._plugin_registry.loadPlugins()
 
 
         if self.getBackend() is None:
         if self.getBackend() is None:

+ 1 - 1
cura/Machines/Models/MaterialManagementModel.py

@@ -60,7 +60,7 @@ class MaterialManagementModel(QObject):
 
 
         sync_materials_message.addAction(
         sync_materials_message.addAction(
                 "sync",
                 "sync",
-                name = catalog.i18nc("@action:button", "Sync materials with printers"),
+                name = catalog.i18nc("@action:button", "Sync materials"),
                 icon = "",
                 icon = "",
                 description = "Sync your newly installed materials with your printers.",
                 description = "Sync your newly installed materials with your printers.",
                 button_align = Message.ActionButtonAlignment.ALIGN_RIGHT
                 button_align = Message.ActionButtonAlignment.ALIGN_RIGHT

+ 10 - 2
cura/Machines/Models/QualitySettingsModel.py

@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Ultimaker B.V.
+# Copyright (c) 2022 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 # Cura is released under the terms of the LGPLv3 or higher.
 
 
 from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt
 from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt
@@ -9,6 +9,7 @@ from UM import i18nCatalog
 from UM.Logger import Logger
 from UM.Logger import Logger
 from UM.Qt.ListModel import ListModel
 from UM.Qt.ListModel import ListModel
 from UM.Settings.ContainerRegistry import ContainerRegistry
 from UM.Settings.ContainerRegistry import ContainerRegistry
+from UM.Settings.SettingFunction import SettingFunction  # To format setting functions differently.
 
 
 import os
 import os
 
 
@@ -173,12 +174,19 @@ class QualitySettingsModel(ListModel):
             label = definition.label
             label = definition.label
             if self._i18n_catalog:
             if self._i18n_catalog:
                 label = self._i18n_catalog.i18nc(definition.key + " label", label)
                 label = self._i18n_catalog.i18nc(definition.key + " label", label)
+            if profile_value_source == "quality_changes":
+                label = f"<i>{label}</i>"  # Make setting name italic if it's derived from the quality-changes profile.
+
+            if isinstance(profile_value, SettingFunction):
+                profile_value_display = self._i18n_catalog.i18nc("@info:status", "Calculated")
+            else:
+                profile_value_display = "" if profile_value is None else str(profile_value)
 
 
             items.append({
             items.append({
                 "key": definition.key,
                 "key": definition.key,
                 "label": label,
                 "label": label,
                 "unit": definition.unit,
                 "unit": definition.unit,
-                "profile_value": "" if profile_value is None else str(profile_value),  # it is for display only
+                "profile_value": profile_value_display,
                 "profile_value_source": profile_value_source,
                 "profile_value_source": profile_value_source,
                 "user_value": "" if user_value is None else str(user_value),
                 "user_value": "" if user_value is None else str(user_value),
                 "category": current_category
                 "category": current_category

+ 2 - 7
cura/PlatformPhysics.py

@@ -1,8 +1,7 @@
-# Copyright (c) 2020 Ultimaker B.V.
+# Copyright (c) 2021 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 # Cura is released under the terms of the LGPLv3 or higher.
 
 
 from PyQt5.QtCore import QTimer
 from PyQt5.QtCore import QTimer
-from shapely.errors import TopologicalError  # To capture errors if Shapely messes up.
 
 
 from UM.Application import Application
 from UM.Application import Application
 from UM.Logger import Logger
 from UM.Logger import Logger
@@ -138,11 +137,7 @@ class PlatformPhysics:
                             own_convex_hull = node.callDecoration("getConvexHull")
                             own_convex_hull = node.callDecoration("getConvexHull")
                             other_convex_hull = other_node.callDecoration("getConvexHull")
                             other_convex_hull = other_node.callDecoration("getConvexHull")
                             if own_convex_hull and other_convex_hull:
                             if own_convex_hull and other_convex_hull:
-                                try:
-                                    overlap = own_convex_hull.translate(move_vector.x, move_vector.z).intersectsPolygon(other_convex_hull)
-                                except TopologicalError as e:  # Can happen if the convex hull is degenerate?
-                                    Logger.warning("Got a topological error when calculating convex hull intersection: {err}".format(err = str(e)))
-                                    overlap = False
+                                overlap = own_convex_hull.translate(move_vector.x, move_vector.z).intersectsPolygon(other_convex_hull)
                                 if overlap:  # Moving ensured that overlap was still there. Try anew!
                                 if overlap:  # Moving ensured that overlap was still there. Try anew!
                                     temp_move_vector = move_vector.set(x = move_vector.x + overlap[0] * self._move_factor,
                                     temp_move_vector = move_vector.set(x = move_vector.x + overlap[0] * self._move_factor,
                                                                        z = move_vector.z + overlap[1] * self._move_factor)
                                                                        z = move_vector.z + overlap[1] * self._move_factor)

+ 23 - 8
cura/Settings/ExtruderManager.py

@@ -259,11 +259,20 @@ class ExtruderManager(QObject):
             if support_roof_enabled:
             if support_roof_enabled:
                 used_extruder_stack_ids.add(self.extruderIds[self.extruderValueWithDefault(str(global_stack.getProperty("support_roof_extruder_nr", "value")))])
                 used_extruder_stack_ids.add(self.extruderIds[self.extruderValueWithDefault(str(global_stack.getProperty("support_roof_extruder_nr", "value")))])
 
 
-        # The platform adhesion extruder. Not used if using none.
-        if global_stack.getProperty("adhesion_type", "value") != "none" or (
-                global_stack.getProperty("prime_tower_brim_enable", "value") and
-                global_stack.getProperty("adhesion_type", "value") != 'raft'):
-            extruder_str_nr = str(global_stack.getProperty("adhesion_extruder_nr", "value"))
+        # The platform adhesion extruders.
+        used_adhesion_extruders = set()
+        adhesion_type = global_stack.getProperty("adhesion_type", "value")
+        if adhesion_type == "skirt" and (global_stack.getProperty("skirt_line_count", "value") > 0 or global_stack.getProperty("skirt_brim_minimal_length", "value") > 0):
+            used_adhesion_extruders.add("skirt_brim_extruder_nr")  # There's a skirt.
+        if (adhesion_type == "brim" or global_stack.getProperty("prime_tower_brim_enable", "value")) and (global_stack.getProperty("brim_line_count", "value") > 0 or global_stack.getProperty("skirt_brim_minimal_length", "value") > 0):
+            used_adhesion_extruders.add("skirt_brim_extruder_nr")  # There's a brim or prime tower brim.
+        if adhesion_type == "raft":
+            used_adhesion_extruders.add("raft_base_extruder_nr")
+            used_adhesion_extruders.add("raft_interface_extruder_nr")
+            if global_stack.getProperty("raft_surface_layers", "value") > 0:
+                used_adhesion_extruders.add("raft_surface_extruder_nr")
+        for extruder_setting in used_adhesion_extruders:
+            extruder_str_nr = str(global_stack.getProperty(extruder_setting, "value"))
             if extruder_str_nr == "-1":
             if extruder_str_nr == "-1":
                 extruder_str_nr = self._application.getMachineManager().defaultExtruderPosition
                 extruder_str_nr = self._application.getMachineManager().defaultExtruderPosition
             if extruder_str_nr in self.extruderIds:
             if extruder_str_nr in self.extruderIds:
@@ -286,8 +295,11 @@ class ExtruderManager(QObject):
         global_stack = application.getGlobalContainerStack()
         global_stack = application.getGlobalContainerStack()
 
 
         # Starts with the adhesion extruder.
         # Starts with the adhesion extruder.
-        if global_stack.getProperty("adhesion_type", "value") != "none":
-            return global_stack.getProperty("adhesion_extruder_nr", "value")
+        adhesion_type = global_stack.getProperty("adhesion_type", "value")
+        if adhesion_type in {"skirt", "brim"}:
+            return global_stack.getProperty("skirt_brim_extruder_nr", "value")
+        if adhesion_type == "raft":
+            return global_stack.getProperty("raft_base_extruder_nr", "value")
 
 
         # No adhesion? Well maybe there is still support brim.
         # No adhesion? Well maybe there is still support brim.
         if (global_stack.getProperty("support_enable", "value") or global_stack.getProperty("support_structure", "value") == "tree") and global_stack.getProperty("support_brim_enable", "value"):
         if (global_stack.getProperty("support_enable", "value") or global_stack.getProperty("support_structure", "value") == "tree") and global_stack.getProperty("support_brim_enable", "value"):
@@ -422,7 +434,10 @@ class ExtruderManager(QObject):
             Logger.log("w", "Could not find the variant %s", active_variant_name)
             Logger.log("w", "Could not find the variant %s", active_variant_name)
             return True
             return True
         active_variant_node = machine_node.variants[active_variant_name]
         active_variant_node = machine_node.variants[active_variant_name]
-        active_material_node = active_variant_node.materials[extruder_stack.material.getMetaDataEntry("base_file")]
+        try:
+            active_material_node = active_variant_node.materials[extruder_stack.material.getMetaDataEntry("base_file")]
+        except KeyError:  # The material in this stack is not a supported material (e.g. wrong filament diameter, as loaded from a project file).
+            return False
 
 
         active_material_node_qualities = active_material_node.qualities
         active_material_node_qualities = active_material_node.qualities
         if not active_material_node_qualities:
         if not active_material_node_qualities:

+ 1 - 1
cura/UltimakerCloud/CloudMaterialSync.py

@@ -71,7 +71,7 @@ class CloudMaterialSync(QObject):
 
 
         sync_materials_message.addAction(
         sync_materials_message.addAction(
                 "sync",
                 "sync",
-                name = catalog.i18nc("@action:button", "Sync materials with printers"),
+                name = catalog.i18nc("@action:button", "Sync materials"),
                 icon = "",
                 icon = "",
                 description = "Sync your newly installed materials with your printers.",
                 description = "Sync your newly installed materials with your printers.",
                 button_align = Message.ActionButtonAlignment.ALIGN_RIGHT
                 button_align = Message.ActionButtonAlignment.ALIGN_RIGHT

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