Browse Source

Merge branch '5.3'

Remco Burema 2 years ago
parent
commit
5970524b3a

+ 4 - 0
.github/workflows/conan-package-create.yml

@@ -109,9 +109,13 @@ jobs:
                 if:  ${{ runner.os == 'Macos' }}
                 run: brew install autoconf automake ninja
 
+            # NOTE: Due to what are probably github issues, we have to remove the cache and reconfigure before the rest.
+            #       This is maybe because grub caches the disk it uses last time, which is recreated each time.
             -   name: Install Linux system requirements
                 if: ${{ runner.os == 'Linux' }}
                 run: |
+                    sudo rm /var/cache/debconf/config.dat
+                    sudo dpkg --configure -a
                     sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
                     sudo apt update
                     sudo apt upgrade

+ 135 - 96
.github/workflows/conan-package.yml

@@ -7,110 +7,149 @@ name: conan-package
 # It should run on pushes against main or CURA-* branches, but it will only create the binaries for main and release branches
 
 on:
-    workflow_dispatch:
-        inputs:
-            create_binaries_windows:
-                required: true
-                default: false
-                description: 'create binaries Windows'
-            create_binaries_linux:
-                required: true
-                default: false
-                description: 'create binaries Linux'
-            create_binaries_macos:
-                required: true
-                default: false
-                description: 'create binaries Macos'
-
-    push:
-        paths:
-            - 'plugins/**'
-            - 'resources/**'
-            - 'cura/**'
-            - 'icons/**'
-            - 'tests/**'
-            - 'packaging/**'
-            - '.github/workflows/conan-*.yml'
-            - '.github/workflows/notify.yml'
-            - '.github/workflows/requirements-conan-package.txt'
-            - 'requirements*.txt'
-            - 'conanfile.py'
-            - 'conandata.yml'
-            - 'GitVersion.yml'
-            - '*.jinja'
-        branches:
-            - main
-            - 'CURA-*'
-            - '[1-9].[0-9]'
-            - '[1-9].[0-9][0-9]'
-        tags:
-            - '[1-9].[0-9].[0-9]*'
-            - '[1-9].[0-9].[0-9]'
-            - '[1-9].[0-9][0-9].[0-9]*'
+  workflow_dispatch:
+    inputs:
+      create_binaries_windows:
+        required: true
+        default: false
+        description: 'create binaries Windows'
+      create_binaries_linux:
+        required: true
+        default: false
+        description: 'create binaries Linux'
+      create_binaries_macos:
+        required: true
+        default: false
+        description: 'create binaries Macos'
+
+  push:
+    paths:
+      - 'plugins/**'
+      - 'resources/**'
+      - 'cura/**'
+      - 'icons/**'
+      - 'tests/**'
+      - 'packaging/**'
+      - '.github/workflows/conan-*.yml'
+      - '.github/workflows/notify.yml'
+      - '.github/workflows/requirements-conan-package.txt'
+      - 'requirements*.txt'
+      - 'conanfile.py'
+      - 'conandata.yml'
+      - 'GitVersion.yml'
+      - '*.jinja'
+    branches:
+      - main
+      - 'CURA-*'
+      - '[1-9].[0-9]'
+      - '[1-9].[0-9][0-9]'
+    tags:
+      - '[1-9].[0-9].[0-9]*'
+      - '[1-9].[0-9].[0-9]'
+      - '[1-9].[0-9][0-9].[0-9]*'
+
+env:
+    CONAN_LOGIN_USERNAME_CURA: ${{ secrets.CONAN_USER }}
+    CONAN_PASSWORD_CURA: ${{ secrets.CONAN_PASS }}
+    CONAN_LOGIN_USERNAME_CURA_CE: ${{ secrets.CONAN_USER }}
+    CONAN_PASSWORD_CURA_CE: ${{ secrets.CONAN_PASS }}
+    CONAN_LOG_RUN_TO_OUTPUT: 1
+    CONAN_LOGGING_LEVEL: ${{ inputs.conan_logging_level }}
+    CONAN_NON_INTERACTIVE: 1
 
 permissions: {}
 jobs:
-    conan-recipe-version:
-        permissions:
-          contents: read
+  conan-recipe-version:
+    permissions:
+      contents: read
 
-        uses: ultimaker/cura/.github/workflows/conan-recipe-version.yml@main
-        with:
-            project_name: cura
+    uses: ultimaker/cura/.github/workflows/conan-recipe-version.yml@main
+    with:
+      project_name: cura
+
+  conan-package-create-linux:
+    needs: [ conan-recipe-version ]
+    runs-on: 'ubuntu-latest'
 
-    conan-package-export:
-        permissions:
-          contents: read
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
 
-        needs: [ conan-recipe-version ]
-        uses: ultimaker/cura/.github/workflows/conan-recipe-export.yml@main
+      - name: Setup Python and pip
+        uses: actions/setup-python@v4
         with:
-            recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
-            recipe_id_latest: ${{ needs.conan-recipe-version.outputs.recipe_id_latest }}
-            runs_on: 'ubuntu-20.04'
-            python_version: '3.10.x'
-            conan_logging_level: 'info'
-        secrets: inherit
+          python-version: '3.10.x'
+          cache: 'pip'
+          cache-dependency-path: .github/workflows/requirements-conan-package.txt
 
-    conan-package-create-linux:
-        permissions:
-          contents: read
+      - name: Install Python requirements for runner
+        run: pip install -r https://raw.githubusercontent.com/Ultimaker/Cura/main/.github/workflows/requirements-conan-package.txt
+        #  Note the runner requirements are always installed from the main branch in the Ultimaker/Cura repo
 
-        if: ${{ (github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || needs.conan-recipe-version.outputs.is_release_branch == 'true')) || (github.event_name == 'workflow_dispatch' && inputs.create_binaries_linux) }}
-        needs: [ conan-recipe-version, conan-package-export ]
+      - name: Use Conan download cache (Bash)
+        if: ${{ runner.os != 'Windows' }}
+        run: conan config set storage.download_cache="$HOME/.conan/conan_download_cache"
 
-        uses: ultimaker/cura/.github/workflows/conan-package-create.yml@main
+      - name: Cache Conan local repository packages (Bash)
+        uses: actions/cache@v3
         with:
-            project_name: ${{ needs.conan-recipe-version.outputs.project_name }}
-            recipe_id_full: ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
-            build_id: 1
-            runs_on: 'ubuntu-20.04'
-            python_version: '3.10.x'
-            conan_logging_level: 'info'
-        secrets: inherit
-
-    notify-export:
-        if: ${{ always() }}
-        needs: [ conan-recipe-version, conan-package-export ]
-
-        uses: ultimaker/cura/.github/workflows/notify.yml@main
-        with:
-            success: ${{ contains(join(needs.*.result, ','), 'success') }}
-            success_title: "New Conan recipe exported in ${{ github.repository }}"
-            success_body: "Exported ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
-            failure_title: "Failed to export Conan Export in ${{ github.repository }}"
-            failure_body: "Failed to exported ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
-        secrets: inherit
-
-    notify-create:
-        if: ${{ always() && ((github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || needs.conan-recipe-version.outputs.is_release_branch == 'true')) || (github.event_name == 'workflow_dispatch' && inputs.create_binaries_linux)) }}
-        needs: [ conan-recipe-version, conan-package-create-linux ]
-
-        uses: ultimaker/cura/.github/workflows/notify.yml@main
-        with:
-            success: ${{ contains(join(needs.*.result, ','), 'success') }}
-            success_title: "New binaries created in ${{ github.repository }}"
-            success_body: "Created binaries for ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
-            failure_title: "Failed to create binaries in ${{ github.repository }}"
-            failure_body: "Failed to created binaries for ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
-        secrets: inherit
+          path: |
+            $HOME/.conan/data
+            $HOME/.conan/conan_download_cache
+          key: conan-ubuntu-${{ runner.arch }}-create-cache
+
+      # NOTE: Due to what are probably github issues, we have to remove the cache and reconfigure before the rest.
+      #       This is maybe because grub caches the disk it uses last time, which is recreated each time.
+      - name: Install Linux system requirements
+        if: ${{ runner.os == 'Linux' }}
+        run: |
+          sudo rm /var/cache/debconf/config.dat
+          sudo dpkg --configure -a
+          sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
+          sudo apt update
+          sudo apt upgrade
+          sudo apt install efibootmgr build-essential checkinstall libegl-dev zlib1g-dev libssl-dev ninja-build autoconf libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxcomposite-dev libxcursor-dev libxdamage-dev libxdmcp-dev libxext-dev libxfixes-dev libxi-dev libxinerama-dev libxkbfile-dev libxmu-dev libxmuu-dev libxpm-dev libxrandr-dev libxrender-dev libxres-dev libxss-dev libxt-dev libxtst-dev libxv-dev libxvmc-dev libxxf86vm-dev xtrans-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev xkb-data libxcb-dri3-dev uuid-dev libxcb-util-dev libxkbcommon-x11-dev pkg-config flex bison -y
+
+      - name: Install GCC-12
+        run: |
+          sudo apt install g++-12 gcc-12 -y
+          sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 12
+          sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 12
+
+      - name: Create the default Conan profile
+        run: conan profile new default --detect
+
+      - name: Get Conan configuration
+        run: conan config install https://github.com/Ultimaker/conan-config.git
+
+      - name: Create the Packages using lockfile
+        run: conan create . ${{ needs.conan-recipe-version.outputs.recipe_id_full }} --build=missing --update -o ${{ needs.conan-recipe-version.outputs.project_name }}:devtools=True
+
+      - name: Remove the latest alias
+        if: ${{ needs.conan-recipe-version.outputs.recipe_id_latest != '' }}
+        run: |
+          conan remove ${{ needs.conan-recipe-version.outputs.recipe_id_latest }} -r cura -f || true
+          conan remove ${{ needs.conan-recipe-version.outputs.recipe_id_latest }} -r cura-ce -f || true
+
+      - name: Create the latest alias
+        if: ${{ needs.conan-recipe-version.outputs.recipe_id_latest != '' && always() }}
+        run: conan alias ${{ needs.conan-recipe-version.outputs.recipe_id_latest }} ${{ needs.conan-recipe-version.outputs.recipe_id_full }}
+
+      - name: Upload the Package(s)
+        if: always()
+        run: |
+          conan upload "*" -r cura --all -c
+          conan upload "*" -r cura-ce -c
+
+  notify-create:
+    if: ${{ always() && (github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || needs.conan-recipe-version.outputs.is_release_branch == 'true')) }}
+    needs: [ conan-recipe-version, conan-package-create-linux ]
+
+    uses: ultimaker/cura/.github/workflows/notify.yml@main
+    with:
+      success: ${{ contains(join(needs.*.result, ','), 'success') }}
+      success_title: "New binaries created in ${{ github.repository }}"
+      success_body: "Created binaries for ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
+      failure_title: "Failed to create binaries in ${{ github.repository }}"
+      failure_body: "Failed to created binaries for ${{ needs.conan-recipe-version.outputs.recipe_id_full }}"
+    secrets: inherit

+ 8 - 0
.github/workflows/cura-installer.yml

@@ -122,9 +122,17 @@ jobs:
                 if:  ${{ runner.os == 'Macos' }}
                 run: brew install autoconf automake ninja create-dmg # Delete create-dmg when deprecating dmg
 
+            -   name: Hack needed specifically for ubuntu-22.04 from mid-Feb 2023 onwards
+                if: ${{ runner.os == 'Linux' && startsWith(inputs.platform, 'ubuntu-22.04') }}
+                run: sudo apt remove libodbc2 libodbcinst2 unixodbc-common -y
+
+            # NOTE: Due to what are probably github issues, we have to remove the cache and reconfigure before the rest.
+            #       This is maybe because grub caches the disk it uses last time, which is recreated each time.
             -   name: Install Linux system requirements
                 if: ${{ runner.os == 'Linux' }}
                 run: |
+                    sudo rm /var/cache/debconf/config.dat
+                    sudo dpkg --configure -a
                     sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
                     sudo apt update
                     sudo apt upgrade

+ 4 - 0
.github/workflows/unit-test.yml

@@ -105,9 +105,13 @@ jobs:
                         $HOME/.conan/conan_download_cache
                     key: conan-${{ runner.os }}-${{ runner.arch }}-unit-cache
 
+            # NOTE: Due to what are probably github issues, we have to remove the cache and reconfigure before the rest.
+            #       This is maybe because grub caches the disk it uses last time, which is recreated each time.
             -   name: Install Linux system requirements
                 if: ${{ runner.os == 'Linux' }}
                 run: |
+                    sudo rm /var/cache/debconf/config.dat
+                    sudo dpkg --configure -a
                     sudo apt update
                     sudo apt upgrade
                     sudo apt install build-essential checkinstall libegl-dev zlib1g-dev libssl-dev ninja-build autoconf libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxcomposite-dev libxcursor-dev libxdamage-dev libxdmcp-dev libxext-dev libxfixes-dev libxi-dev libxinerama-dev libxkbfile-dev libxmu-dev libxmuu-dev libxpm-dev libxrandr-dev libxrender-dev libxres-dev libxss-dev libxt-dev libxtst-dev libxv-dev libxvmc-dev libxxf86vm-dev xtrans-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev xkb-data libxcb-dri3-dev uuid-dev libxcb-util-dev libxkbcommon-x11-dev pkg-config -y

+ 86 - 103
conandata.yml

@@ -1,107 +1,90 @@
----
-# Usage: defaults to the first entry in this conandata.yml file
-# If you're on a release branch create an entry for that **version**  e.q.: `5.1.0` update the requirements (use pinned versions, not latest)
-# also create a beta entry for that **version**  e.q.: `5.1.0-beta`, update the requirements (use the <dep_name>/(latest)@ultimaker/stable)
-#
-# If you're working on a feature/bugfix branch from a release branch, create an entry for that **channel**,  update the requirements (use
-# the <dep_name>/(latest)@ultimaker/stable)
-#
-# If you're working on a feature/bugfix branch from a main branch, it is optional to create an entry for that **channel**,  update the
-# requirements (use the <dep_name>/(latest)@ultimaker/testing)
-#
-# Subject to change in the future!
-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
-    cura_private_data_plugins:
-      package: "cura_private_data"
-      src: "plugins"
-      dst: "share/cura/plugins"
-      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"
-    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"
+    runinfo:
+        entrypoint: "cura_app.py"
+    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"
+        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"
 pycharm_targets:
   - jinja_path: .run_templates/pycharm_cura_run.run.xml.jinja
     module_name: Cura

+ 72 - 55
conanfile.py

@@ -6,7 +6,7 @@ from jinja2 import Template
 from conan import ConanFile
 from conan.tools.files import copy, rmdir, save, mkdir
 from conan.tools.microsoft import unix_path
-from conan.tools.env import VirtualRunEnv, Environment
+from conan.tools.env import VirtualRunEnv, Environment, VirtualBuildEnv
 from conan.tools.scm import Version
 from conan.errors import ConanInvalidConfiguration, ConanException
 
@@ -19,7 +19,7 @@ class CuraConan(ConanFile):
     author = "UltiMaker"
     url = "https://github.com/Ultimaker/cura"
     description = "3D printer / slicing GUI built on top of the Uranium framework"
-    topics = ("conan", "python", "pyqt5", "qt", "qml", "3d-printing", "slicer")
+    topics = ("conan", "python", "pyqt6", "qt", "qml", "3d-printing", "slicer")
     build_policy = "missing"
     exports = "LICENSE*", "UltiMaker-Cura.spec.jinja", "CuraVersion.py.jinja"
     settings = "os", "compiler", "build_type", "arch"
@@ -48,12 +48,6 @@ class CuraConan(ConanFile):
         "cura_debug_mode": False,  # Not yet implemented
         "internal": False,
     }
-    scm = {
-        "type": "git",
-        "subfolder": ".",
-        "url": "auto",
-        "revision": "auto"
-    }
 
     @property
     def _pycharm_targets(self):
@@ -161,7 +155,7 @@ class CuraConan(ConanFile):
         return "None"
 
     def _generate_cura_version(self, location):
-        with open(Path(__file__).parent.joinpath("CuraVersion.py.jinja"), "r") as f:
+        with open(os.path.join(self.recipe_folder, "CuraVersion.py.jinja"), "r") as f:
             cura_version_py = Template(f.read())
 
         # If you want a specific Cura version to show up on the splash screen add the user configuration `user.cura:version=VERSION`
@@ -172,7 +166,7 @@ class CuraConan(ConanFile):
         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:
+        with open(os.path.join(location, "CuraVersion.py"), "w") as f:
             f.write(cura_version_py.render(
                 cura_app_name = self.name,
                 cura_app_display_name = self._app_name,
@@ -196,33 +190,33 @@ class CuraConan(ConanFile):
             if "package" in data:  # get the paths from conan package
                 if data["package"] == self.name:
                     if self.in_local_cache:
-                        src_path = Path(self.package_folder, data["src"])
+                        src_path = os.path.join(self.package_folder, data["src"])
                     else:
-                        src_path = Path(self.source_folder, data["src"])
+                        src_path = os.path.join(self.source_folder, data["src"])
                 else:
-                    src_path = Path(self.deps_cpp_info[data["package"]].rootpath, data["src"])
+                    src_path = os.path.join(self.deps_cpp_info[data["package"]].rootpath, data["src"])
             elif "root" in data:  # get the paths relative from the sourcefolder
-                src_path = Path(self.source_folder, data["root"], data["src"])
+                src_path = os.path.join(self.source_folder, data["root"], data["src"])
             else:
                 continue
-            if src_path.exists():
+            if Path(src_path).exists():
                 datas.append((str(src_path), data["dst"]))
 
         binaries = []
         for binary in pyinstaller_metadata["binaries"].values():
             if "package" in binary:  # get the paths from conan package
-                src_path = Path(self.deps_cpp_info[binary["package"]].rootpath, binary["src"])
+                src_path = os.path.join(self.deps_cpp_info[binary["package"]].rootpath, binary["src"])
             elif "root" in binary:  # get the paths relative from the sourcefolder
-                src_path = Path(self.source_folder, binary["root"], binary["src"])
+                src_path = os.path.join(self.source_folder, binary["root"], binary["src"])
             else:
                 continue
-            if not src_path.exists():
+            if not Path(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|.so.]*"):
+            for bin in Path(src_path).glob(binary["binary"] + "*[.exe|.dll|.so|.dylib|.so.]*"):
                 binaries.append((str(bin), binary["dst"]))
-            for bin in src_path.glob(binary["binary"]):
+            for bin in Path(src_path).glob(binary["binary"]):
                 binaries.append((str(bin), binary["dst"]))
 
         # Make sure all Conan dependencies which are shared are added to the binary list for pyinstaller
@@ -240,13 +234,13 @@ class CuraConan(ConanFile):
         # 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")])
 
-        with open(Path(__file__).parent.joinpath("UltiMaker-Cura.spec.jinja"), "r") as f:
+        with open(os.path.join(self.recipe_folder, "UltiMaker-Cura.spec.jinja"), "r") as f:
             pyinstaller = Template(f.read())
 
         version = self.conf_info.get("user.cura:version", default = self.version, check_type = str)
         cura_version = Version(version)
 
-        with open(Path(location, "UltiMaker-Cura.spec"), "w") as f:
+        with open(os.path.join(location, "UltiMaker-Cura.spec"), "w") as f:
             f.write(pyinstaller.render(
                 name = str(self.options.display_name).replace(" ", "-"),
                 display_name = self._app_name,
@@ -267,6 +261,20 @@ class CuraConan(ConanFile):
                 short_version = f"'{cura_version.major}.{cura_version.minor}.{cura_version.patch}'",
             ))
 
+    def export_sources(self):
+        copy(self, "*", os.path.join(self.recipe_folder, "plugins"), os.path.join(self.export_sources_folder, "plugins"))
+        copy(self, "*", os.path.join(self.recipe_folder, "resources"), os.path.join(self.export_sources_folder, "resources"), excludes = "*.mo")
+        copy(self, "*", os.path.join(self.recipe_folder, "tests"), os.path.join(self.export_sources_folder, "tests"))
+        copy(self, "*", os.path.join(self.recipe_folder, "cura"), os.path.join(self.export_sources_folder, "cura"), excludes="CuraVersion.py")
+        copy(self, "*", os.path.join(self.recipe_folder, "packaging"), os.path.join(self.export_sources_folder, "packaging"))
+        copy(self, "*", os.path.join(self.recipe_folder, ".run_templates"), os.path.join(self.export_sources_folder, "run_templates"))
+        copy(self, "requirements.txt", self.recipe_folder, self.export_sources_folder)
+        copy(self, "requirements-dev.txt", self.recipe_folder, self.export_sources_folder)
+        copy(self, "requirements-ultimaker.txt", self.recipe_folder, self.export_sources_folder)
+        copy(self, "UltiMaker-Cura.spec.jinja", self.recipe_folder, self.export_sources_folder)
+        copy(self, "CuraVersion.py.jinja", self.recipe_folder, self.export_sources_folder)
+        copy(self, "cura_app.py", self.recipe_folder, self.export_sources_folder)
+
     def set_version(self):
         if self.version is None:
             self.version = self._umdefault_version()
@@ -303,45 +311,54 @@ class CuraConan(ConanFile):
     def layout(self):
         self.folders.source = "."
         self.folders.build = "venv"
-        self.folders.generators = Path(self.folders.build, "conan")
+        self.folders.generators = os.path.join(self.folders.build, "conan")
 
         self.cpp.package.libdirs = [os.path.join("site-packages", "cura")]
         self.cpp.package.bindirs = ["bin"]
         self.cpp.package.resdirs = ["resources", "plugins", "packaging", "pip_requirements"]  # pip_requirements should be the last item in the list
 
-    def build(self):
-        if self.options.devtools:
-            if self.settings.os != "Windows" or self.conf.get("tools.microsoft.bash:path", check_type = str):
-                # FIXME: once m4, autoconf, automake are Conan V2 ready use self.win_bash and add gettext as base tool_requirement
-                cpp_info = self.dependencies["gettext"].cpp_info
-                for po_file in self.source_path.joinpath("resources", "i18n").glob("**/*.po"):
-                    mo_file = self.build_path.joinpath(po_file.with_suffix('.mo').relative_to(self.source_path))
-                    mkdir(self, str(unix_path(self, mo_file.parent)))
-                    self.run(f"{cpp_info.bindirs[0]}/msgfmt {po_file} -o {mo_file} -f", env="conanbuild", ignore_errors=True)
-
     def generate(self):
+        copy(self, "cura_app.py", self.source_folder, str(self._script_dir))
         cura_run_envvars = self._cura_run_env.vars(self, scope = "run")
         ext = ".ps1" if self.settings.os == "Windows" else ".sh"
-        cura_run_envvars.save_script(self.folders.generators.joinpath(f"cura_run_environment{ext}"))
+        cura_run_envvars.save_script(os.path.join(self.folders.generators, f"cura_run_environment{ext}"))
 
         vr = VirtualRunEnv(self)
         vr.generate()
 
-        self._generate_cura_version(Path(self.source_folder, "cura"))
+        self._generate_cura_version(os.path.join(self.source_folder, "cura"))
 
         if self.options.devtools:
-            entitlements_file = "'{}'".format(Path(self.source_folder, "packaging", "MacOS", "cura.entitlements"))
+            entitlements_file = "'{}'".format(os.path.join(self.source_folder, "packaging", "MacOS", "cura.entitlements"))
             self._generate_pyinstaller_spec(location = self.generators_folder,
-                                            entrypoint_location = "'{}'".format(Path(self.source_folder, self.conan_data["runinfo"]["entrypoint"])).replace("\\", "\\\\"),
-                                            icon_path = "'{}'".format(Path(self.source_folder, "packaging", self.conan_data["pyinstaller"]["icon"][str(self.settings.os)])).replace("\\", "\\\\"),
+                                            entrypoint_location = "'{}'".format(os.path.join(self.source_folder, self.conan_data["pyinstaller"]["runinfo"]["entrypoint"])).replace("\\", "\\\\"),
+                                            icon_path = "'{}'".format(os.path.join(self.source_folder, "packaging", self.conan_data["pyinstaller"]["icon"][str(self.settings.os)])).replace("\\", "\\\\"),
                                             entitlements_file = entitlements_file if self.settings.os == "Macos" else "None")
 
             # Update the po files
+            if self.settings.os != "Windows" or self.conf.get("tools.microsoft.bash:path", check_type=str):
+                vb = VirtualBuildEnv(self)
+                vb.generate()
+
+                # FIXME: once m4, autoconf, automake are Conan V2 ready use self.win_bash and add gettext as base tool_requirement
+                cpp_info = self.dependencies["gettext"].cpp_info
+                for po_file in self.source_path.joinpath("resources", "i18n").glob("**/*.po"):
+                    pot_file = self.source_path.joinpath("resources", "i18n", po_file.with_suffix('.pot').name)
+                    mkdir(self, str(unix_path(self, pot_file.parent)))
+                    self.run(
+                        f"{cpp_info.bindirs[0]}/msgmerge --no-wrap --no-fuzzy-matching -width=140 -o {po_file} {po_file} {pot_file}",
+                        env="conanbuild", ignore_errors=True)
+
+    def build(self):
+        if self.options.devtools:
             if self.settings.os != "Windows" or self.conf.get("tools.microsoft.bash:path", check_type = str):
                 # FIXME: once m4, autoconf, automake are Conan V2 ready use self.win_bash and add gettext as base tool_requirement
-                # Extract all the new strings and update the existing po files
-                extractTool = self.python_requires["translationextractor"].module.ExtractTranslations(self, self.source_path.joinpath("resources", "i18n"), "cura.pot")
-                extractTool.generate()
+                for po_file in self.source_path.joinpath("resources", "i18n").glob("**/*.po"):
+                    mo_file = Path(self.build_folder, po_file.with_suffix('.mo').relative_to(self.source_path))
+                    mo_file = mo_file.parent.joinpath("LC_MESSAGES", mo_file.name)
+                    mkdir(self, str(unix_path(self, Path(mo_file).parent)))
+                    cpp_info = self.dependencies["gettext"].cpp_info
+                    self.run(f"{cpp_info.bindirs[0]}/msgfmt {po_file} -o {mo_file} -f", env="conanbuild", ignore_errors=True)
 
     def imports(self):
         self.copy("CuraEngine.exe", root_package = "curaengine", src = "@bindirs", dst = "", keep_path = False)
@@ -402,7 +419,7 @@ class CuraConan(ConanFile):
         self.copy_deps("*", root_package = "uranium", src = self.deps_cpp_info["uranium"].libdirs[0],
                        dst = self._site_packages.joinpath("UM"),
                        keep_path = True)
-        self.copy_deps("*", root_package = "uranium", src = str(Path(self.deps_cpp_info["uranium"].libdirs[0], "Qt", "qml", "UM")),
+        self.copy_deps("*", root_package = "uranium", src = str(os.path.join(self.deps_cpp_info["uranium"].libdirs[0], "Qt", "qml", "UM")),
                        dst = self._site_packages.joinpath("PyQt6", "Qt6", "qml", "UM"),
                        keep_path = True)
 
@@ -445,24 +462,24 @@ echo "CURA_APP_NAME={{ cura_app_name }}" >> ${{ env_prefix }}GITHUB_ENV
                     env_prefix = env_prefix)
 
         ext = ".sh" if self.settings.os != "Windows" else ".ps1"
-        save(self, self._script_dir.joinpath(f"activate_github_actions_version_env{ext}"), activate_github_actions_version_env)
+        save(self, os.path.join(self._script_dir, f"activate_github_actions_version_env{ext}"), activate_github_actions_version_env)
 
-        self._generate_cura_version(Path(self._site_packages, "cura"))
+        self._generate_cura_version(os.path.join(self._site_packages, "cura"))
 
         entitlements_file = "'{}'".format(Path(self.cpp_info.res_paths[2], "MacOS", "cura.entitlements"))
         self._generate_pyinstaller_spec(location = self._base_dir,
-                                        entrypoint_location = "'{}'".format(Path(self.cpp_info.bin_paths[0], self.conan_data["runinfo"]["entrypoint"])).replace("\\", "\\\\"),
-                                        icon_path = "'{}'".format(Path(self.cpp_info.res_paths[2], self.conan_data["pyinstaller"]["icon"][str(self.settings.os)])).replace("\\", "\\\\"),
+                                        entrypoint_location = "'{}'".format(os.path.join(self.package_folder, self.cpp_info.bindirs[0], self.conan_data["pyinstaller"]["runinfo"]["entrypoint"])).replace("\\", "\\\\"),
+                                        icon_path = "'{}'".format(os.path.join(self.package_folder, self.cpp_info.resdirs[2], self.conan_data["pyinstaller"]["icon"][str(self.settings.os)])).replace("\\", "\\\\"),
                                         entitlements_file = entitlements_file if self.settings.os == "Macos" else "None")
 
     def package(self):
-        copy(self, "cura_app.py", src = self.source_path, dst = self.package_path.joinpath(self.cpp.package.bindirs[0]))
-        copy(self, "*", src = self.source_path.joinpath("cura"), dst = self.package_path.joinpath(self.cpp.package.libdirs[0]))
-        copy(self, "*", src = self.source_path.joinpath("resources"), dst = self.package_path.joinpath(self.cpp.package.resdirs[0]), excludes="*.po")
-        copy(self, "*", src = self.build_path.joinpath("resources"), dst = self.package_path.joinpath(self.cpp.package.resdirs[0]))
-        copy(self, "*", src = self.source_path.joinpath("plugins"), dst = self.package_path.joinpath(self.cpp.package.resdirs[1]))
-        copy(self, "requirement*.txt", src = self.source_path, dst = self.package_path.joinpath(self.cpp.package.resdirs[-1]))
-        copy(self, "*", src = self.source_path.joinpath("packaging"), dst = self.package_path.joinpath(self.cpp.package.resdirs[2]))
+        copy(self, "cura_app.py", src = self.source_folder, dst = os.path.join(self.package_folder, self.cpp.package.bindirs[0]))
+        copy(self, "*", src = os.path.join(self.source_folder, "cura"), dst = os.path.join(self.package_folder, self.cpp.package.libdirs[0]))
+        copy(self, "*", src = os.path.join(self.source_folder, "resources"), dst = os.path.join(self.package_folder, self.cpp.package.resdirs[0]))
+        copy(self, "*.mo", os.path.join(self.build_folder, "resources"), os.path.join(self.package_folder, "resources"))
+        copy(self, "*", src = os.path.join(self.source_folder, "plugins"), dst = os.path.join(self.package_folder, self.cpp.package.resdirs[1]))
+        copy(self, "requirement*.txt", src = self.source_folder, dst = os.path.join(self.package_folder, self.cpp.package.resdirs[-1]))
+        copy(self, "*", src = os.path.join(self.source_folder, "packaging"), dst = os.path.join(self.package_folder, self.cpp.package.resdirs[2]))
 
     def package_info(self):
         self.user_info.pip_requirements = "requirements.txt"
@@ -470,8 +487,8 @@ echo "CURA_APP_NAME={{ cura_app_name }}" >> ${{ env_prefix }}GITHUB_ENV
         self.user_info.pip_requirements_build = "requirements-dev.txt"
 
         if self.in_local_cache:
-            self.runenv_info.append_path("PYTHONPATH", str(Path(self.cpp_info.lib_paths[0]).parent))
-            self.runenv_info.append_path("PYTHONPATH", self.cpp_info.res_paths[1])  # Add plugins to PYTHONPATH
+            self.runenv_info.append_path("PYTHONPATH", os.path.join(self.package_folder, "site-packages"))
+            self.runenv_info.append_path("PYTHONPATH", os.path.join(self.package_folder, "plugins"))
         else:
             self.runenv_info.append_path("PYTHONPATH", self.source_folder)
             self.runenv_info.append_path("PYTHONPATH", os.path.join(self.source_folder, "plugins"))

+ 13 - 4
plugins/GCodeReader/FlavorParser.py

@@ -32,6 +32,7 @@ class FlavorParser:
     """This parser is intended to interpret the common firmware codes among all the different flavors"""
 
     MAX_EXTRUDER_COUNT = 16
+    DEFAULT_FILAMENT_DIAMETER = 2.85
 
     def __init__(self) -> None:
         CuraApplication.getInstance().hideMessageSignal.connect(self._onHideMessage)
@@ -48,7 +49,7 @@ class FlavorParser:
         self._is_layers_in_file = False  # Does the Gcode have the layers comment?
         self._extruder_offsets = {}  # type: Dict[int, List[float]] # Offsets for multi extruders. key is index, value is [x-offset, y-offset]
         self._current_layer_thickness = 0.2  # default
-        self._filament_diameter = 2.85       # default
+        self._current_filament_diameter = 2.85       # default
         self._previous_extrusion_value = 0.0  # keep track of the filament retractions
 
         CuraApplication.getInstance().getPreferences().addPreference("gcodereader/show_caution", True)
@@ -152,7 +153,7 @@ class FlavorParser:
 
     def _calculateLineWidth(self, current_point: Position, previous_point: Position, current_extrusion: float, previous_extrusion: float, layer_thickness: float) -> float:
         # Area of the filament
-        Af = (self._filament_diameter / 2) ** 2 * numpy.pi
+        Af = (self._current_filament_diameter / 2) ** 2 * numpy.pi
         # Length of the extruded filament
         de = current_extrusion - previous_extrusion
         # Volume of the extruded filament
@@ -287,7 +288,11 @@ class FlavorParser:
 
     def processTCode(self, global_stack, T: int, line: str, position: Position, path: List[List[Union[float, int]]]) -> Position:
         self._extruder_number = T
-        self._filament_diameter = global_stack.extruderList[self._extruder_number].getProperty("material_diameter", "value")
+        try:
+            self._current_filament_diameter = global_stack.extruderList[self._extruder_number].getProperty("material_diameter", "value")
+        except IndexError:
+            self._current_filament_diameter = self.DEFAULT_FILAMENT_DIAMETER
+
         if self._extruder_number + 1 > len(position.e):
             self._extrusion_length_offset.extend([0] * (self._extruder_number - len(position.e) + 1))
             position.e.extend([0] * (self._extruder_number - len(position.e) + 1))
@@ -323,7 +328,11 @@ class FlavorParser:
         if not global_stack:
             return None
 
-        self._filament_diameter = global_stack.extruderList[self._extruder_number].getProperty("material_diameter", "value")
+        try:
+            self._current_filament_diameter = global_stack.extruderList[self._extruder_number].getProperty("material_diameter", "value")
+        except IndexError:
+            # There can be a mismatch between the number of extruders in the G-Code file and the number of extruders in the current machine.
+            self._current_filament_diameter = self.DEFAULT_FILAMENT_DIAMETER
 
         scene_node = CuraSceneNode()
 

+ 0 - 1
resources/definitions/Geeetech_Base_Dual_Extruder.def.json

@@ -133,7 +133,6 @@
         "support_interface_pattern": { "value": "zigzag" },
         "support_interface_skip_height": { "value": 0.2 },
         "support_pattern": { "value": "'zigzag'" },
-        "support_use_towers": { "value": false },
         "support_wall_count": { "value": 0 },
         "support_xy_distance": { "value": "wall_line_width_0 * 2" },
         "support_xy_distance_overhang": { "value": "wall_line_width_0" },

+ 0 - 1
resources/definitions/Geeetech_Base_Multi_Extruder.def.json

@@ -134,7 +134,6 @@
         "support_interface_pattern": { "value": "zigzag" },
         "support_interface_skip_height": { "value": 0.2 },
         "support_pattern": { "value": "'zigzag'" },
-        "support_use_towers": { "value": false },
         "support_wall_count": { "value": 0 },
         "support_xy_distance": { "value": "wall_line_width_0 * 2" },
         "support_xy_distance_overhang": { "value": "wall_line_width_0" },

+ 0 - 1
resources/definitions/Geeetech_Base_Single_Extruder.def.json

@@ -121,7 +121,6 @@
         "support_interface_pattern": { "value": "zigzag" },
         "support_interface_skip_height": { "value": 0.2 },
         "support_pattern": { "value": "'zigzag'" },
-        "support_use_towers": { "value": false },
         "support_wall_count": { "value": 0 },
         "support_xy_distance": { "value": "wall_line_width_0 * 2" },
         "support_xy_distance_overhang": { "value": "wall_line_width_0" },

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