diff options
author | Ghostkeeper <rubend@tutanota.com> | 2022-02-21 13:52:28 +0300 |
---|---|---|
committer | Ghostkeeper <rubend@tutanota.com> | 2022-02-21 13:52:28 +0300 |
commit | c7d7dd11d143c804d0c1b3ff67fc6f89ed5171e6 (patch) | |
tree | db5f78d4f88e85e01c408c03d3298c95cd14ebb9 /cura | |
parent | 28924a1c87032e29306d0fca067bb39abc2accf2 (diff) | |
parent | 614fe6fd4f0b6370b731c11d3cf5395f788b9ad4 (diff) |
Merge branch 'master' into PyQt6_upgrade
Conflicts:
cura/PlatformPhysics.py -> Removed shapely on master, while QTimer import got updated to Qt6.
plugins/Toolbox -> Entire folder is deleted in master, but it was updated to Qt6 here. This can all be removed.
Diffstat (limited to 'cura')
-rw-r--r-- | cura/Arranging/Nest2DArrange.py | 2 | ||||
-rwxr-xr-x | cura/BuildVolume.py | 43 | ||||
-rw-r--r-- | cura/CrashHandler.py | 9 | ||||
-rwxr-xr-x | cura/CuraApplication.py | 10 | ||||
-rw-r--r-- | cura/CuraPackageManager.py | 44 | ||||
-rw-r--r-- | cura/Machines/Models/MaterialManagementModel.py | 2 | ||||
-rwxr-xr-x | cura/PlatformPhysics.py | 9 | ||||
-rwxr-xr-x | cura/Settings/ExtruderManager.py | 32 | ||||
-rw-r--r-- | cura/UltimakerCloud/CloudMaterialSync.py | 2 |
9 files changed, 108 insertions, 45 deletions
diff --git a/cura/Arranging/Nest2DArrange.py b/cura/Arranging/Nest2DArrange.py index dad67ba161..43d4d7f8a8 100644 --- a/cura/Arranging/Nest2DArrange.py +++ b/cura/Arranging/Nest2DArrange.py @@ -40,7 +40,7 @@ def findNodePlacement(nodes_to_arrange: List["SceneNode"], build_volume: "BuildV machine_width = build_volume.getWidth() 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: fixed_nodes = [] diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 372d6152fc..dd798ac7e7 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -72,7 +72,7 @@ class BuildVolume(SceneNode): self._origin_mesh = None # type: Optional[MeshData] self._origin_line_length = 20 - self._origin_line_width = 1.5 + self._origin_line_width = 1 self._enabled = False self._grid_mesh = None # type: Optional[MeshData] @@ -601,6 +601,7 @@ class BuildVolume(SceneNode): if self._adhesion_type == "raft": self._raft_thickness = ( self._global_container_stack.getProperty("raft_base_thickness", "value") + + self._global_container_stack.getProperty("raft_interface_layers", "value") * self._global_container_stack.getProperty("raft_interface_thickness", "value") + self._global_container_stack.getProperty("raft_surface_layers", "value") * self._global_container_stack.getProperty("raft_surface_thickness", "value") + @@ -848,10 +849,10 @@ class BuildVolume(SceneNode): """ result = {} - adhesion_extruder = None #type: ExtruderStack + skirt_brim_extruder: ExtruderStack = None 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()] = [] # Currently, the only normally printed object is the prime tower. @@ -865,11 +866,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_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 = ( - 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_y += brim_size @@ -1100,18 +1101,18 @@ class BuildVolume(SceneNode): # 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 # 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: - 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: - 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. 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 for extruder_stack in used_extruders: @@ -1120,8 +1121,8 @@ class BuildVolume(SceneNode): # 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 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 + ( skirt_brim_line_width * skirt_line_count) * initial_layer_line_width_factor / 100.0 @@ -1132,7 +1133,7 @@ class BuildVolume(SceneNode): # 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 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": bed_adhesion_size = 0 else: @@ -1214,13 +1215,13 @@ class BuildVolume(SceneNode): _machine_settings = ["machine_width", "machine_depth", "machine_height", "machine_shape", "machine_center_is_zero"] _skirt_settings = ["adhesion_type", "skirt_gap", "skirt_line_count", "skirt_brim_line_width", "brim_width", "brim_line_count", "raft_margin", "draft_shield_enabled", "draft_shield_dist", "initial_layer_line_width_factor"] - _raft_settings = ["adhesion_type", "raft_base_thickness", "raft_interface_thickness", "raft_surface_layers", "raft_surface_thickness", "raft_airgap", "layer_0_z_overlap"] + _raft_settings = ["adhesion_type", "raft_base_thickness", "raft_interface_layers", "raft_interface_thickness", "raft_surface_layers", "raft_surface_thickness", "raft_airgap", "layer_0_z_overlap"] _extra_z_settings = ["retraction_hop_enabled", "retraction_hop"] _prime_settings = ["extruder_prime_pos_x", "extruder_prime_pos_y", "prime_blob_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"] _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"] _disallowed_area_settings = _skirt_settings + _prime_settings + _tower_settings + _ooze_shield_settings + _distance_settings + _extruder_settings + _material_size_settings diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index f5ce13e04b..bda9568666 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -15,7 +15,7 @@ from typing import cast, Any try: from sentry_sdk.hub import Hub 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 except ImportError: with_sentry_sdk = False @@ -424,6 +424,13 @@ class CrashHandler: if with_sentry_sdk: try: 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)) hub.capture_event(event, hint=hint) hub.flush() diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 6eea5eaefe..7183789de3 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -494,7 +494,7 @@ class CuraApplication(QtApplication): "CuraEngineBackend", #Cura is useless without this one since you can't slice. "FileLogger", #You want to be able to read the log if something goes wrong. "XmlMaterialProfile", #Cura crashes without this one. - "Toolbox", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back. + "Marketplace", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back. "PrepareStage", #Cura is useless without this one since you can't load models. "PreviewStage", #This shows the list of the plugin views that are installed in Cura. "MonitorStage", #Major part of Cura's functionality. @@ -573,6 +573,10 @@ class CuraApplication(QtApplication): preferences.addPreference("general/accepted_user_agreement", False) + preferences.addPreference("cura/market_place_show_plugin_banner", True) + preferences.addPreference("cura/market_place_show_material_banner", True) + preferences.addPreference("cura/market_place_show_manage_packages_banner", True) + for key in [ "dialog_load_path", # dialog_save_path is in LocalFileOutputDevicePlugin "dialog_profile_path", @@ -777,10 +781,14 @@ class CuraApplication(QtApplication): lib_suffixes = {""} for suffix in lib_suffixes: self._plugin_registry.addPluginLocation(os.path.join(QtApplication.getInstallPrefix(), "lib" + suffix, "cura")) + if not hasattr(sys, "frozen"): self._plugin_registry.addPluginLocation(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "plugins")) 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() if self.getBackend() is None: diff --git a/cura/CuraPackageManager.py b/cura/CuraPackageManager.py index 212993e19b..17d6832ac6 100644 --- a/cura/CuraPackageManager.py +++ b/cura/CuraPackageManager.py @@ -1,13 +1,15 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import List, Tuple, TYPE_CHECKING, Optional +from typing import Any, cast, Dict, List, Set, Tuple, TYPE_CHECKING, Optional -from cura.CuraApplication import CuraApplication #To find some resource types. +from cura.CuraApplication import CuraApplication # To find some resource types. from cura.Settings.GlobalStack import GlobalStack -from UM.PackageManager import PackageManager #The class we're extending. -from UM.Resources import Resources #To find storage paths for some resource types. +from UM.PackageManager import PackageManager # The class we're extending. +from UM.Resources import Resources # To find storage paths for some resource types. +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") if TYPE_CHECKING: from UM.Qt.QtApplication import QtApplication @@ -17,6 +19,31 @@ if TYPE_CHECKING: class CuraPackageManager(PackageManager): def __init__(self, application: "QtApplication", parent: Optional["QObject"] = None) -> None: super().__init__(application, parent) + self._local_packages: Optional[List[Dict[str, Any]]] = None + self._local_packages_ids: Optional[Set[str]] = None + self.installedPackagesChanged.connect(self._updateLocalPackages) + + def _updateLocalPackages(self) -> None: + self._local_packages = self.getAllLocalPackages() + self._local_packages_ids = set(pkg["package_id"] for pkg in self._local_packages) + + @property + def local_packages(self) -> List[Dict[str, Any]]: + """locally installed packages, lazy execution""" + if self._local_packages is None: + self._updateLocalPackages() + # _updateLocalPackages always results in a list of packages, not None. + # It's guaranteed to be a list now. + return cast(List[Dict[str, Any]], self._local_packages) + + @property + def local_packages_ids(self) -> Set[str]: + """locally installed packages, lazy execution""" + if self._local_packages_ids is None: + self._updateLocalPackages() + # _updateLocalPackages always results in a list of packages, not None. + # It's guaranteed to be a list now. + return cast(Set[str], self._local_packages_ids) def initialize(self) -> None: self._installation_dirs_dict["materials"] = Resources.getStoragePath(CuraApplication.ResourceTypes.MaterialInstanceContainer) @@ -47,3 +74,12 @@ class CuraPackageManager(PackageManager): machine_with_qualities.append((global_stack, str(extruder_nr), container_id)) return machine_with_materials, machine_with_qualities + + def getAllLocalPackages(self) -> List[Dict[str, Any]]: + """ Returns an unordered list of all the package_info of installed, to be installed, or bundled packages""" + packages: List[Dict[str, Any]] = [] + + for packages_to_add in self.getAllInstalledPackagesInfo().values(): + packages.extend(packages_to_add) + + return packages diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py index ab904573c2..53d0cca0a2 100644 --- a/cura/Machines/Models/MaterialManagementModel.py +++ b/cura/Machines/Models/MaterialManagementModel.py @@ -60,7 +60,7 @@ class MaterialManagementModel(QObject): sync_materials_message.addAction( "sync", - name = catalog.i18nc("@action:button", "Sync materials with printers"), + name = catalog.i18nc("@action:button", "Sync materials"), icon = "", description = "Sync your newly installed materials with your printers.", button_align = Message.ActionButtonAlignment.ALIGN_RIGHT diff --git a/cura/PlatformPhysics.py b/cura/PlatformPhysics.py index 1cd5c1844c..e054528c42 100755 --- a/cura/PlatformPhysics.py +++ b/cura/PlatformPhysics.py @@ -1,8 +1,7 @@ -# Copyright (c) 2020 Ultimaker B.V. +# Copyright (c) 2022 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. from PyQt6.QtCore import QTimer -from shapely.errors import TopologicalError # To capture errors if Shapely messes up. from UM.Application import Application from UM.Logger import Logger @@ -138,11 +137,7 @@ class PlatformPhysics: own_convex_hull = node.callDecoration("getConvexHull") other_convex_hull = other_node.callDecoration("getConvexHull") 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! temp_move_vector = move_vector.set(x = move_vector.x + overlap[0] * self._move_factor, z = move_vector.z + overlap[1] * self._move_factor) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 34ba96e280..07c074254f 100755 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -259,11 +259,21 @@ class ExtruderManager(QObject): if support_roof_enabled: 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") + if global_stack.getProperty("raft_interface_layers", "value") > 0: + 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": extruder_str_nr = self._application.getMachineManager().defaultExtruderPosition if extruder_str_nr in self.extruderIds: @@ -286,8 +296,11 @@ class ExtruderManager(QObject): global_stack = application.getGlobalContainerStack() # 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. 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 +435,10 @@ class ExtruderManager(QObject): Logger.log("w", "Could not find the variant %s", active_variant_name) return True 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 if not active_material_node_qualities: diff --git a/cura/UltimakerCloud/CloudMaterialSync.py b/cura/UltimakerCloud/CloudMaterialSync.py index 9b3af4a1b3..e2eb50f97e 100644 --- a/cura/UltimakerCloud/CloudMaterialSync.py +++ b/cura/UltimakerCloud/CloudMaterialSync.py @@ -71,7 +71,7 @@ class CloudMaterialSync(QObject): sync_materials_message.addAction( "sync", - name = catalog.i18nc("@action:button", "Sync materials with printers"), + name = catalog.i18nc("@action:button", "Sync materials"), icon = "", description = "Sync your newly installed materials with your printers.", button_align = Message.ActionButtonAlignment.ALIGN_RIGHT |