Browse Source

Merge branch '5.2'

# Conflicts:
#	conanfile.py
Jelle Spijker 2 years ago
parent
commit
48ea4cee9f

+ 3 - 2
.github/workflows/conan-package.yml

@@ -44,8 +44,9 @@ on:
             - '[1-9].[0-9]'
             - '[1-9].[0-9][0-9]'
         tags:
-            - '[1-9].[0-9].[0-9]+'
-            - '[1-9].[0-9][0-9].[0-9]+'
+            - '[1-9].[0-9].[0-9]*'
+            - '[1-9].[0-9].[0-9]'
+            - '[1-9].[0-9][0-9].[0-9]*'
 
 permissions: {}
 jobs:

+ 9 - 1
.github/workflows/conan-recipe-version.yml

@@ -169,6 +169,14 @@ jobs:
                             # FIXME: for external PR's
                             actual_version = f"5.3.0-alpha+{buildmetadata}pr_{issue_number}"
                     
+                    if is_tag:
+                        print("THE TAG IS: ", ${{ github.ref_name }})
+                    if is_tag and ${{ github.ref_name }} == "5.2.0-beta:
+                        actual_version = "5.2.0-beta"
+                        is_release_branch = True
+                        user = "_"
+                        channel = "_"
+
                     # %% print to output
                     cmd_name = ["echo", f"::set-output name=name::{project_name}"]
                     subprocess.call(cmd_name)
@@ -190,7 +198,7 @@ jobs:
                     print(f"version = {actual_version}")
                     print(f"user = {user}")
                     print(f"channel = {channel}")
-                    print(f"recipe_id_full = {project_name}/{actual_version}@{user}/{channel}")
+                    print(f"= {project_name}/{actual_version}@{user}/{channel}")
                     print(f"recipe_id_latest = {project_name}/latest@{user}/{channel}")
                     print(f"semver_full = {actual_version}")
                     print(f"is_release_branch = {str(is_release_branch).lower()}")

+ 421 - 1
conandata.yml

@@ -10,7 +10,7 @@
 # requirements (use the <dep_name>/(latest)@ultimaker/testing)
 #
 # Subject to change in the future!
-"5.2.0-alpha":
+"5.3.0-alpha":
     requirements:
         - "pyarcus/(latest)@ultimaker/testing"
         - "curaengine/(latest)@ultimaker/testing"
@@ -115,6 +115,426 @@
             Windows: "./icons/Cura.ico"
             Macos: "./icons/cura.icns"
             Linux: "./icons/cura-128.png"
+"5.2.0-beta.2":
+    requirements:
+        - "pyarcus/(latest)@ultimaker/stable"
+        - "curaengine/(latest)@ultimaker/stable"
+        - "pysavitar/(latest)@ultimaker/stable"
+        - "pynest2d/(latest)@ultimaker/stable"
+        - "uranium/(latest)@ultimaker/stable"
+        - "fdm_materials/(latest)@ultimaker/stable"
+        - "cura_binary_data/(latest)@ultimaker/stable"
+        - "cpython/3.10.4"
+    internal_requirements:
+        - "fdm_materials_private/(latest)@ultimaker/testing"
+        - "cura_private_data/(latest)@ultimaker/testing"
+    runinfo:
+        entrypoint: "cura_app.py"
+    pyinstaller:
+        datas:
+            cura_plugins:
+                package: "cura"
+                src: "plugins"
+                dst: "share/cura/plugins"
+            cura_resources:
+                package: "cura"
+                src: "resources"
+                dst: "share/cura/resources"
+            cura_private_data:
+                package: "cura_private_data"
+                src: "resources"
+                dst: "share/cura/resources"
+                internal: true
+            uranium_plugins:
+                package: "uranium"
+                src: "plugins"
+                dst: "share/uranium/plugins"
+            uranium_resources:
+                package: "uranium"
+                src: "resources"
+                dst: "share/uranium/resources"
+            uranium_um_qt_qml_um:
+                package: "uranium"
+                src: "site-packages/UM/Qt/qml/UM"
+                dst: "PyQt6/Qt6/qml/UM"
+            cura_binary_data:
+                package: "cura_binary_data"
+                src: "resources/cura/resources"
+                dst: "share/cura/resources"
+            uranium_binary_data:
+                package: "cura_binary_data"
+                src: "resources/uranium/resources"
+                dst: "share/uranium/resources"
+            windows_binary_data:
+                package: "cura_binary_data"
+                src: "windows"
+                dst: "share/windows"
+            fdm_materials:
+                package: "fdm_materials"
+                src: "materials"
+                dst: "share/cura/resources/materials"
+            fdm_materials_private:
+                package: "fdm_materials_private"
+                src: "resources/materials"
+                dst: "share/cura/resources/materials"
+                internal: true
+            tcl:
+                package: "tcl"
+                src: "lib/tcl8.6"
+                dst: "tcl"
+            tk:
+                package: "tk"
+                src: "lib/tk8.6"
+                dst: "tk"
+        binaries:
+            curaengine:
+                package: "curaengine"
+                src: "bin"
+                dst: "."
+                binary: "CuraEngine"
+        hiddenimports:
+            - "pySavitar"
+            - "pyArcus"
+            - "pynest2d"
+            - "PyQt6"
+            - "PyQt6.QtNetwork"
+            - "PyQt6.sip"
+            - "logging.handlers"
+            - "zeroconf"
+            - "fcntl"
+            - "stl"
+            - "serial"
+        collect_all:
+            - "cura"
+            - "UM"
+            - "serial"
+            - "Charon"
+            - "sqlite3"
+            - "trimesh"
+            - "win32ctypes"
+            - "PyQt6"
+            - "PyQt6.QtNetwork"
+            - "PyQt6.sip"
+            - "stl"
+        icon:
+            Windows: "./icons/Cura.ico"
+            Macos: "./icons/cura.icns"
+            Linux: "./icons/cura-128.png"
+"5.2.0-beta.1":
+    requirements:
+        - "pyarcus/5.2.0-beta.1"
+        - "curaengine/5.2.0-beta.1"
+        - "pysavitar/5.2.0-beta.1"
+        - "pynest2d/5.2.0-beta.1"
+        - "uranium/5.2.0-beta.1"
+        - "fdm_materials/5.2.0-beta.1"
+        - "cura_binary_data/5.2.0-beta.1"
+        - "cpython/3.10.4"
+    internal_requirements:
+        - "fdm_materials_private/(latest)@ultimaker/testing"
+        - "cura_private_data/(latest)@ultimaker/testing"
+    runinfo:
+        entrypoint: "cura_app.py"
+    pyinstaller:
+        datas:
+            cura_plugins:
+                package: "cura"
+                src: "plugins"
+                dst: "share/cura/plugins"
+            cura_resources:
+                package: "cura"
+                src: "resources"
+                dst: "share/cura/resources"
+            cura_private_data:
+                package: "cura_private_data"
+                src: "resources"
+                dst: "share/cura/resources"
+                internal: true
+            uranium_plugins:
+                package: "uranium"
+                src: "plugins"
+                dst: "share/uranium/plugins"
+            uranium_resources:
+                package: "uranium"
+                src: "resources"
+                dst: "share/uranium/resources"
+            uranium_um_qt_qml_um:
+                package: "uranium"
+                src: "site-packages/UM/Qt/qml/UM"
+                dst: "PyQt6/Qt6/qml/UM"
+            cura_binary_data:
+                package: "cura_binary_data"
+                src: "resources/cura/resources"
+                dst: "share/cura/resources"
+            uranium_binary_data:
+                package: "cura_binary_data"
+                src: "resources/uranium/resources"
+                dst: "share/uranium/resources"
+            windows_binary_data:
+                package: "cura_binary_data"
+                src: "windows"
+                dst: "share/windows"
+            fdm_materials:
+                package: "fdm_materials"
+                src: "materials"
+                dst: "share/cura/resources/materials"
+            fdm_materials_private:
+                package: "fdm_materials_private"
+                src: "resources/materials"
+                dst: "share/cura/resources/materials"
+                internal: true
+            tcl:
+                package: "tcl"
+                src: "lib/tcl8.6"
+                dst: "tcl"
+            tk:
+                package: "tk"
+                src: "lib/tk8.6"
+                dst: "tk"
+        binaries:
+            curaengine:
+                package: "curaengine"
+                src: "bin"
+                dst: "."
+                binary: "CuraEngine"
+        hiddenimports:
+            - "pySavitar"
+            - "pyArcus"
+            - "pynest2d"
+            - "PyQt6"
+            - "PyQt6.QtNetwork"
+            - "PyQt6.sip"
+            - "logging.handlers"
+            - "zeroconf"
+            - "fcntl"
+            - "stl"
+            - "serial"
+        collect_all:
+            - "cura"
+            - "UM"
+            - "serial"
+            - "Charon"
+            - "sqlite3"
+            - "trimesh"
+            - "win32ctypes"
+            - "PyQt6"
+            - "PyQt6.QtNetwork"
+            - "PyQt6.sip"
+            - "stl"
+        icon:
+            Windows: "./icons/Cura.ico"
+            Macos: "./icons/cura.icns"
+            Linux: "./icons/cura-128.png"
+"5.2.0":
+    requirements:
+        - "pyarcus/5.2.0"
+        - "curaengine/5.2.0"
+        - "pysavitar/5.2.0"
+        - "pynest2d/5.2.0"
+        - "uranium/5.2.0"
+        - "fdm_materials/5.2.0"
+        - "cura_binary_data/5.2.0"
+        - "cpython/3.10.4"
+    internal_requirements:
+        - "fdm_materials_private/(latest)@ultimaker/testing"
+        - "cura_private_data/(latest)@ultimaker/testing"
+    runinfo:
+        entrypoint: "cura_app.py"
+    pyinstaller:
+        datas:
+            cura_plugins:
+                package: "cura"
+                src: "plugins"
+                dst: "share/cura/plugins"
+            cura_resources:
+                package: "cura"
+                src: "resources"
+                dst: "share/cura/resources"
+            cura_private_data:
+                package: "cura_private_data"
+                src: "resources"
+                dst: "share/cura/resources"
+                internal: true
+            uranium_plugins:
+                package: "uranium"
+                src: "plugins"
+                dst: "share/uranium/plugins"
+            uranium_resources:
+                package: "uranium"
+                src: "resources"
+                dst: "share/uranium/resources"
+            uranium_um_qt_qml_um:
+                package: "uranium"
+                src: "site-packages/UM/Qt/qml/UM"
+                dst: "PyQt6/Qt6/qml/UM"
+            cura_binary_data:
+                package: "cura_binary_data"
+                src: "resources/cura/resources"
+                dst: "share/cura/resources"
+            uranium_binary_data:
+                package: "cura_binary_data"
+                src: "resources/uranium/resources"
+                dst: "share/uranium/resources"
+            windows_binary_data:
+                package: "cura_binary_data"
+                src: "windows"
+                dst: "share/windows"
+            fdm_materials:
+                package: "fdm_materials"
+                src: "materials"
+                dst: "share/cura/resources/materials"
+            fdm_materials_private:
+                package: "fdm_materials_private"
+                src: "resources/materials"
+                dst: "share/cura/resources/materials"
+                internal: true
+            tcl:
+                package: "tcl"
+                src: "lib/tcl8.6"
+                dst: "tcl"
+            tk:
+                package: "tk"
+                src: "lib/tk8.6"
+                dst: "tk"
+        binaries:
+            curaengine:
+                package: "curaengine"
+                src: "bin"
+                dst: "."
+                binary: "CuraEngine"
+        hiddenimports:
+            - "pySavitar"
+            - "pyArcus"
+            - "pynest2d"
+            - "PyQt6"
+            - "PyQt6.QtNetwork"
+            - "PyQt6.sip"
+            - "logging.handlers"
+            - "zeroconf"
+            - "fcntl"
+            - "stl"
+            - "serial"
+        collect_all:
+            - "cura"
+            - "UM"
+            - "serial"
+            - "Charon"
+            - "sqlite3"
+            - "trimesh"
+            - "win32ctypes"
+            - "PyQt6"
+            - "PyQt6.QtNetwork"
+            - "PyQt6.sip"
+            - "stl"
+        icon:
+            Windows: "./icons/Cura.ico"
+            Macos: "./icons/cura.icns"
+            Linux: "./icons/cura-128.png"
+"5.2.0-alpha":
+    requirements:
+        - "pyarcus/5.2@ultimaker/testing"
+        - "curaengine/(latest)@ultimaker/testing"
+        - "pysavitar/(latest)@ultimaker/testing"
+        - "pynest2d/(latest)@ultimaker/testing"
+        - "uranium/(latest)@ultimaker/testing"
+        - "fdm_materials/(latest)@ultimaker/testing"
+        - "cura_binary_data/(latest)@ultimaker/testing"
+        - "cpython/3.10.4"
+    internal_requirements:
+        - "fdm_materials_private/(latest)@ultimaker/testing"
+        - "cura_private_data/(latest)@ultimaker/testing"
+    runinfo:
+        entrypoint: "cura_app.py"
+    pyinstaller:
+        datas:
+            cura_plugins:
+                package: "cura"
+                src: "plugins"
+                dst: "share/cura/plugins"
+            cura_resources:
+                package: "cura"
+                src: "resources"
+                dst: "share/cura/resources"
+            cura_private_data:
+                package: "cura_private_data"
+                src: "resources"
+                dst: "share/cura/resources"
+                internal: true
+            uranium_plugins:
+                package: "uranium"
+                src: "plugins"
+                dst: "share/uranium/plugins"
+            uranium_resources:
+                package: "uranium"
+                src: "resources"
+                dst: "share/uranium/resources"
+            uranium_um_qt_qml_um:
+                package: "uranium"
+                src: "site-packages/UM/Qt/qml/UM"
+                dst: "PyQt6/Qt6/qml/UM"
+            cura_binary_data:
+                package: "cura_binary_data"
+                src: "resources/cura/resources"
+                dst: "share/cura/resources"
+            uranium_binary_data:
+                package: "cura_binary_data"
+                src: "resources/uranium/resources"
+                dst: "share/uranium/resources"
+            windows_binary_data:
+                package: "cura_binary_data"
+                src: "windows"
+                dst: "share/windows"
+            fdm_materials:
+                package: "fdm_materials"
+                src: "materials"
+                dst: "share/cura/resources/materials"
+            fdm_materials_private:
+                package: "fdm_materials_private"
+                src: "resources/materials"
+                dst: "share/cura/resources/materials"
+                internal: true
+            tcl:
+                package: "tcl"
+                src: "lib/tcl8.6"
+                dst: "tcl"
+            tk:
+                package: "tk"
+                src: "lib/tk8.6"
+                dst: "tk"
+        binaries:
+            curaengine:
+                package: "curaengine"
+                src: "bin"
+                dst: "."
+                binary: "CuraEngine"
+        hiddenimports:
+            - "pySavitar"
+            - "pyArcus"
+            - "pynest2d"
+            - "PyQt6"
+            - "PyQt6.QtNetwork"
+            - "PyQt6.sip"
+            - "logging.handlers"
+            - "zeroconf"
+            - "fcntl"
+            - "stl"
+            - "serial"
+        collect_all:
+            - "cura"
+            - "UM"
+            - "serial"
+            - "Charon"
+            - "sqlite3"
+            - "trimesh"
+            - "win32ctypes"
+            - "PyQt6"
+            - "PyQt6.QtNetwork"
+            - "PyQt6.sip"
+            - "stl"
+        icon:
+            Windows: "./icons/Cura.ico"
+            Macos: "./icons/cura.icns"
+            Linux: "./icons/cura-128.png"
 "5.1.0":
     requirements:
         - "arcus/5.1.0"

+ 18 - 13
conanfile.py

@@ -7,7 +7,7 @@ from conan import ConanFile
 from conan.tools.files import copy, rmdir, save
 from conan.tools.env import VirtualRunEnv, Environment
 from conan.tools.scm import Version
-from conan.errors import ConanInvalidConfiguration
+from conan.errors import ConanInvalidConfiguration, ConanException
 
 required_conan_version = ">=1.50.0"
 
@@ -149,13 +149,13 @@ class CuraConan(ConanFile):
         with open(Path(__file__).parent.joinpath("CuraVersion.py.jinja"), "r") as f:
             cura_version_py = Template(f.read())
 
-        cura_version = self.conf_info.get("user.cura:version", default = self.version, check_type = str)
-        if self.options.internal:
-            version = Version(cura_version)
-            if version.pre:
-                cura_version = f"{version.major}.{version.minor}.{version.patch}-{version.pre}+internal_{version.build}"
-            else:
-                cura_version = f"{version.major}.{version.minor}.{version.patch}+internal_{version.build}"
+        # If you want a specific Cura version to show up on the splash screen add the user configuration `user.cura:version=VERSION`
+        # the global.conf, profile, package_info (of dependency) or via the cmd line `-c user.cura:version=VERSION`
+        cura_version = Version(self.conf.get("user.cura:version", default = self.version, check_type = str))
+        pre_tag = f"-{cura_version.pre}" if cura_version.pre else ""
+        build_tag = f"+{cura_version.build}" if cura_version.build else ""
+        internal_tag = f"+internal" if self.options.internal else ""
+        cura_version = f"{cura_version.major}.{cura_version.minor}.{cura_version.patch}{pre_tag}{build_tag}{internal_tag}"
 
         with open(Path(location, "CuraVersion.py"), "w") as f:
             f.write(cura_version_py.render(
@@ -202,20 +202,25 @@ class CuraConan(ConanFile):
             else:
                 continue
             if not src_path.exists():
+                self.output.warning(f"Source path for binary {binary['binary']} does not exist")
                 continue
-            for bin in src_path.glob(binary["binary"] + ".*[exe|dll|so|dylib]"):
+
+            for bin in src_path.glob(binary["binary"] + "*[.exe|.dll|.so|.dylib|.so.]*"):
                 binaries.append((str(bin), binary["dst"]))
             for bin in src_path.glob(binary["binary"]):
                 binaries.append((str(bin), binary["dst"]))
 
-        for _, dependency in self.dependencies.items():
+        # Make sure all Conan dependencies which are shared are added to the binary list for pyinstaller
+        for _, dependency in self.dependencies.host.items():
             for bin_paths in dependency.cpp_info.bindirs:
                 binaries.extend([(f"{p}", ".") for p in Path(bin_paths).glob("**/*.dll")])
-                binaries.extend([(f"{p}", ".") for p in Path(bin_paths).glob("**/*.dylib")])
-                binaries.extend([(f"{p}", ".") for p in Path(bin_paths).glob("**/*.so")])
+            for lib_paths in dependency.cpp_info.libdirs:
+                binaries.extend([(f"{p}", ".") for p in Path(lib_paths).glob("**/*.so*")])
+                binaries.extend([(f"{p}", ".") for p in Path(lib_paths).glob("**/*.dylib*")])
 
         # Copy dynamic libs from lib path
-        binaries.extend([(f"{p}", ".") for p in Path(self._base_dir.joinpath("lib")).glob("**/*.dylib")])
+        binaries.extend([(f"{p}", ".") for p in Path(self._base_dir.joinpath("lib")).glob("**/*.dylib*")])
+        binaries.extend([(f"{p}", ".") for p in Path(self._base_dir.joinpath("lib")).glob("**/*.so*")])
 
         # Collect all dll's from PyQt6 and place them in the root
         binaries.extend([(f"{p}", ".") for p in Path(self._site_packages, "PyQt6", "Qt6").glob("**/*.dll")])

+ 1 - 1
cura/ApplicationMetadata.py

@@ -14,7 +14,7 @@ DEFAULT_CURA_LATEST_URL = "https://software.ultimaker.com/latest.json"
 # Each release has a fixed SDK version coupled with it. It doesn't make sense to make it configurable because, for
 # example Cura 3.2 with SDK version 6.1 will not work. So the SDK version is hard-coded here and left out of the
 # CuraVersion.py.in template.
-CuraSDKVersion = "8.1.0"
+CuraSDKVersion = "8.2.0"
 
 try:
     from cura.CuraVersion import CuraLatestURL

+ 1 - 0
cura/Machines/Models/MachineListModel.py

@@ -86,6 +86,7 @@ class MachineListModel(ListModel):
         machines_manager = CuraApplication.getInstance().getMachineManager()
 
         other_machine_stacks = CuraContainerRegistry.getInstance().findContainerStacks(type="machine")
+        other_machine_stacks.sort(key = lambda machine: machine.getName().upper())
 
         abstract_machine_stacks = CuraContainerRegistry.getInstance().findContainerStacks(is_abstract_machine = "True")
         abstract_machine_stacks.sort(key = lambda machine: machine.getName(), reverse = True)

+ 1 - 0
cura/Settings/MachineManager.py

@@ -904,6 +904,7 @@ class MachineManager(QObject):
 
         if self._global_container_stack is None \
                 or self._global_container_stack.getProperty(setting_key, "value") == new_value \
+                or self._global_container_stack.definitionChanges.getProperty("extruders_enabled_count", "value") is None \
                 or self._global_container_stack.definitionChanges.getProperty("extruders_enabled_count", "value") < 2:
             return
 

+ 1 - 1
packaging/NSIS/Ultimaker-Cura.nsi.jinja

@@ -12,7 +12,7 @@
 !define INSTALLER_NAME "{{ destination }}"
 !define MAIN_APP_EXE "{{ main_app }}"
 !define INSTALL_TYPE "SetShellVarContext all"
-!define REG_ROOT "HKCR"
+!define REG_ROOT "HKLM"
 !define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\${APP_NAME}"
 !define UNINSTALL_PATH "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}"
 

+ 1 - 0
plugins/3MFReader/ThreeMFWorkspaceReader.py

@@ -53,6 +53,7 @@ _ignored_machine_network_metadata = {
     "connection_type",
     "capabilities",
     "octoprint_api_key",
+    "is_abstract_machine"
 }  # type: Set[str]
 
 

+ 21 - 5
plugins/UFPWriter/UFPWriter.py

@@ -12,6 +12,7 @@ from PyQt6.QtCore import QBuffer
 
 from UM.Application import Application
 from UM.Logger import Logger
+from UM.Settings.SettingFunction import SettingFunction
 from UM.Mesh.MeshWriter import MeshWriter  # The writer we need to implement.
 from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
 from UM.PluginRegistry import PluginRegistry  # To get the g-code writer.
@@ -213,6 +214,7 @@ class UFPWriter(MeshWriter):
     def _getSliceMetadata(self) -> Dict[str, Dict[str, Dict[str, str]]]:
         """Get all changed settings and all settings. For each extruder and the global stack"""
         print_information = CuraApplication.getInstance().getPrintInformation()
+        machine_manager = CuraApplication.getInstance().getMachineManager()
         settings = {
             "material": {
                 "length": print_information.materialLengths,
@@ -222,7 +224,9 @@ class UFPWriter(MeshWriter):
             "global": {
                 "changes": {},
                 "all_settings": {},
-            }
+            },
+            "intent": machine_manager.activeIntentCategory,
+            "quality": machine_manager.activeQualityOrQualityChangesName,
         }
 
         global_stack = cast(GlobalStack, Application.getInstance().getGlobalContainerStack())
@@ -230,11 +234,17 @@ class UFPWriter(MeshWriter):
         # Add global user or quality changes
         global_flattened_changes = InstanceContainer.createMergedInstanceContainer(global_stack.userChanges, global_stack.qualityChanges)
         for setting in global_flattened_changes.getAllKeys():
-            settings["global"]["changes"][setting] = global_flattened_changes.getProperty(setting, "value")
+            value = global_flattened_changes.getProperty(setting, "value")
+            if isinstance(value, SettingFunction):
+                value = value(global_flattened_changes)
+            settings["global"]["changes"][setting] = value
 
         # Get global all settings values without user or quality changes
         for setting in global_stack.getAllKeys():
-            settings["global"]["all_settings"][setting] = global_stack.getProperty(setting, "value")
+            value = global_stack.getProperty(setting, "value")
+            if isinstance(value, SettingFunction):
+                value = value(global_stack)
+            settings["global"]["all_settings"][setting] = value
 
         for i, extruder in enumerate(global_stack.extruderList):
             # Add extruder fields to settings dictionary
@@ -246,10 +256,16 @@ class UFPWriter(MeshWriter):
             # Add extruder user or quality changes
             extruder_flattened_changes = InstanceContainer.createMergedInstanceContainer(extruder.userChanges, extruder.qualityChanges)
             for setting in extruder_flattened_changes.getAllKeys():
-                settings[f"extruder_{i}"]["changes"][setting] = extruder_flattened_changes.getProperty(setting, "value")
+                value = extruder_flattened_changes.getProperty(setting, "value")
+                if isinstance(value, SettingFunction):
+                    value = value(extruder_flattened_changes)
+                settings[f"extruder_{i}"]["changes"][setting] = value
 
             # Get extruder all settings values without user or quality changes
             for setting in extruder.getAllKeys():
-                settings[f"extruder_{i}"]["all_settings"][setting] = extruder.getProperty(setting, "value")
+                value = extruder.getProperty(setting, "value")
+                if isinstance(value, SettingFunction):
+                    value = value(extruder)
+                settings[f"extruder_{i}"]["all_settings"][setting] = value
 
         return settings

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