From 6f1adaad4345f1c3b4839d4a757e1a93ab2dd003 Mon Sep 17 00:00:00 2001
From: "c.lamboo" <casperlamboo@gmail.com>
Date: Thu, 19 Oct 2023 15:48:28 +0200
Subject: [PATCH] Make Conan/Python installs available for whole project and
 not just the AboutDialog

Generation of dependency list now happens in
Also cleaned up the AboutDialog.qml

CURA-10561
---
 .github/workflows/linux.yml           |  20 +-
 .github/workflows/macos.yml           |  20 +-
 .github/workflows/windows.yml         |  20 +-
 .gitignore                            |   1 -
 AboutDialogVersionsList.qml.jinja     |  61 -----
 CuraVersion.py.jinja                  |   5 +-
 conanfile.py                          | 135 ++--------
 cura/ApplicationMetadata.py           |  32 ++-
 cura/CuraApplication.py               |  18 +-
 resources/qml/Dialogs/AboutDialog.qml | 344 +++++++++++++++-----------
 10 files changed, 287 insertions(+), 369 deletions(-)
 delete mode 100644 AboutDialogVersionsList.qml.jinja

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 719a07250c..1830a023c4 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -155,7 +155,7 @@ jobs:
         run: conan config set storage.download_cache="$HOME/.conan/conan_download_cache"
 
       - name: Create the Packages (Bash)
-        run: conan install $CURA_CONAN_VERSION ${{ inputs.conan_args }} --build=missing --update -if cura_inst -g VirtualPythonEnv -o cura:enterprise=$ENTERPRISE -o cura:staging=$STAGING --json "cura_inst/conan_install_info.json"
+        run: conan install $CURA_CONAN_VERSION ${{ inputs.conan_args }} --build=missing --update -if cura_inst -g VirtualPythonEnv -o cura:enterprise=$ENTERPRISE -o cura:staging=$STAGING
 
       - name: Upload the Package(s)
         if: always()
@@ -206,12 +206,7 @@ jobs:
           import json
           from pathlib import Path
           
-          conan_install_info_path = Path("cura_inst/conan_install_info.json")
-          conan_info = {"installed": []}
-          if os.path.exists(conan_install_info_path):
-              with open(conan_install_info_path, "r") as f:
-                  conan_info = json.load(f)
-          sorted_deps = sorted([dep["recipe"]["id"].replace('#', r' rev: ') for dep in conan_info["installed"]])
+          from cura.CuraVersion import ConanInstalls
           
           summary_env = os.environ["GITHUB_STEP_SUMMARY"]
           content = ""
@@ -223,14 +218,17 @@ jobs:
               f.write(content)
               f.writelines("# ${{ steps.filename.outputs.INSTALLER_FILENAME }}\n")
               f.writelines("## Conan packages:\n")
-              for dep in sorted_deps:
-                  f.writelines(f"`{dep}`\n")
+              for dep_name, dep_info in ConanDependencies.items():
+                  f.writelines(f"`{dep_name} {dep_info["version"]} {dep_info["revision"]}`\n")
 
       - name: Summarize the used Python modules
         shell: python
         run: |
           import os
           import pkg_resources
+
+          from cura.CuraVersion import ConanDependencies
+
           summary_env = os.environ["GITHUB_STEP_SUMMARY"]
           content = ""
           if os.path.exists(summary_env):
@@ -240,8 +238,8 @@ jobs:
           with open(summary_env, "w") as f:
               f.write(content)
               f.writelines("## Python modules:\n")
-              for package in pkg_resources.working_set:
-                  f.writelines(f"`{package.key}/{package.version}`\n")
+              for dep_name, dep_info in ConanDependencies.items():
+                  f.writelines(f"`{dep_name} {dep_info["version"]}`\n")
 
       - name: Create the Linux AppImage (Bash)
         run: |
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 01a64f5180..b8ade8f4da 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -155,7 +155,7 @@ jobs:
         run: conan config set storage.download_cache="$HOME/.conan/conan_download_cache"
 
       - name: Create the Packages (Bash)
-        run: conan install $CURA_CONAN_VERSION ${{ inputs.conan_args }} --build=missing --update -if cura_inst -g VirtualPythonEnv -o cura:enterprise=$ENTERPRISE -o cura:staging=$STAGING --json "cura_inst/conan_install_info.json"
+        run: conan install $CURA_CONAN_VERSION ${{ inputs.conan_args }} --build=missing --update -if cura_inst -g VirtualPythonEnv -o cura:enterprise=$ENTERPRISE -o cura:staging=$STAGING"
 
       - name: Upload the Package(s)
         if: ${{ inputs.operating_system != 'self-hosted' }}
@@ -210,12 +210,7 @@ jobs:
           import json
           from pathlib import Path
           
-          conan_install_info_path = Path("cura_inst/conan_install_info.json")
-          conan_info = {"installed": []}
-          if os.path.exists(conan_install_info_path):
-              with open(conan_install_info_path, "r") as f:
-                  conan_info = json.load(f)
-          sorted_deps = sorted([dep["recipe"]["id"].replace('#', r' rev: ') for dep in conan_info["installed"]])
+          from cura.CuraVersion import ConanInstalls
           
           summary_env = os.environ["GITHUB_STEP_SUMMARY"]
           content = ""
@@ -227,14 +222,17 @@ jobs:
               f.write(content)
               f.writelines("# ${{ steps.filename.outputs.INSTALLER_FILENAME }}\n")
               f.writelines("## Conan packages:\n")
-              for dep in sorted_deps:
-                  f.writelines(f"`{dep}`\n")
+              for dep_name, dep_info in ConanDependencies.items():
+                  f.writelines(f"`{dep_name} {dep_info["version"]} {dep_info["revision"]}`\n")
 
       - name: Summarize the used Python modules
         shell: python
         run: |
           import os
           import pkg_resources
+
+          from cura.CuraVersion import PythonInstalls
+
           summary_env = os.environ["GITHUB_STEP_SUMMARY"]
           content = ""
           if os.path.exists(summary_env):
@@ -244,8 +242,8 @@ jobs:
           with open(summary_env, "w") as f:
               f.write(content)
               f.writelines("## Python modules:\n")
-              for package in pkg_resources.working_set:
-                  f.writelines(f"`{package.key}/{package.version}`\n")
+              for dep_name, dep_info in ConanDependencies.items():
+                  f.writelines(f"`{dep_name} {dep_info["version"]}`\n")
 
       - name: Create the Macos dmg (Bash)
         run: python ../cura_inst/packaging/MacOS/build_macos.py --source_path ../cura_inst --dist_path . --cura_conan_version $CURA_CONAN_VERSION --filename "${{ steps.filename.outputs.INSTALLER_FILENAME }}" --build_dmg --build_pkg --app_name "$CURA_APP_NAME"
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 9c9775cae7..067d811e9f 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -122,7 +122,7 @@ jobs:
         run: conan config set storage.download_cache="C:\Users\runneradmin\.conan\conan_download_cache"
 
       - name: Create the Packages (Powershell)
-        run: conan install $Env:CURA_CONAN_VERSION ${{ inputs.conan_args }} --build=missing --update -if cura_inst -g VirtualPythonEnv -o cura:enterprise=$Env:ENTERPRISE -o cura:staging=$Env:STAGING --json "cura_inst/conan_install_info.json"
+        run: conan install $Env:CURA_CONAN_VERSION ${{ inputs.conan_args }} --build=missing --update -if cura_inst -g VirtualPythonEnv -o cura:enterprise=$Env:ENTERPRISE -o cura:staging=$Env:STAGING
 
       - name: Upload the Package(s)
         if: always()
@@ -169,12 +169,7 @@ jobs:
           import json
           from pathlib import Path
           
-          conan_install_info_path = Path("cura_inst/conan_install_info.json")
-          conan_info = {"installed": []}
-          if os.path.exists(conan_install_info_path):
-              with open(conan_install_info_path, "r") as f:
-                  conan_info = json.load(f)
-          sorted_deps = sorted([dep["recipe"]["id"].replace('#', r' rev: ') for dep in conan_info["installed"]])
+          from cura.CuraVersion import ConanInstalls
           
           summary_env = os.environ["GITHUB_STEP_SUMMARY"]
           content = ""
@@ -186,14 +181,17 @@ jobs:
               f.write(content)
               f.writelines("# ${{ steps.filename.outputs.INSTALLER_FILENAME }}\n")
               f.writelines("## Conan packages:\n")
-              for dep in sorted_deps:
-                  f.writelines(f"`{dep}`\n")
+              for dep_name, dep_info in ConanDependencies.items():
+                  f.writelines(f"`{dep_name} {dep_info["version"]} {dep_info["revision"]}`\n")
 
       - name: Summarize the used Python modules
         shell: python
         run: |
           import os
           import pkg_resources
+
+          from cura.CuraVersion import PythonInstalls
+
           summary_env = os.environ["GITHUB_STEP_SUMMARY"]
           content = ""
           if os.path.exists(summary_env):
@@ -203,8 +201,8 @@ jobs:
           with open(summary_env, "w") as f:
               f.write(content)
               f.writelines("## Python modules:\n")
-              for package in pkg_resources.working_set:
-                  f.writelines(f"`{package.key}/{package.version}`\n")
+              for dep_name, dep_info in ConanDependencies.items():
+                  f.writelines(f"`{dep_name} {dep_info["version"]}`\n")
 
       - name: Create PFX certificate from BASE64_PFX_CONTENT secret
         id: create-pfx
diff --git a/.gitignore b/.gitignore
index f1a72d342e..0290869b41 100644
--- a/.gitignore
+++ b/.gitignore
@@ -101,7 +101,6 @@ graph_info.json
 Ultimaker-Cura.spec
 .run/
 /printer-linter/src/printerlinter.egg-info/
-/resources/qml/Dialogs/AboutDialogVersionsList.qml
 /plugins/CuraEngineGradualFlow
 /resources/bundled_packages/bundled_*.json
 curaengine_plugin_gradual_flow
diff --git a/AboutDialogVersionsList.qml.jinja b/AboutDialogVersionsList.qml.jinja
deleted file mode 100644
index 0503469660..0000000000
--- a/AboutDialogVersionsList.qml.jinja
+++ /dev/null
@@ -1,61 +0,0 @@
-import QtQuick 2.2
-import QtQuick.Controls 2.9
-
-import UM 1.6 as UM
-import Cura 1.5 as Cura
-
-
-ListView
-{
-    id: projectBuildInfoList
-    visible: false
-    anchors.top: creditsNotes.bottom
-    anchors.topMargin: UM.Theme.getSize("default_margin").height
-    width: parent.width
-    height: base.height - y - (2 * UM.Theme.getSize("default_margin").height + closeButton.height)
-
-    ScrollBar.vertical: UM.ScrollBar
-    {
-        id: projectBuildInfoListScrollBar
-    }
-
-    delegate: Row
-    {
-        spacing: UM.Theme.getSize("narrow_margin").width
-        UM.Label
-        {
-            text: (model.name)
-            width: (projectBuildInfoList.width* 0.4) | 0
-            elide: Text.ElideRight
-        }
-        UM.Label
-        {
-            text: (model.version)
-            width: (projectBuildInfoList.width *0.6) | 0
-            elide: Text.ElideRight
-        }
-
-    }
-    model: ListModel
-    {
-        id: developerInfo
-    }
-    Component.onCompleted:
-    {
-        var conan_installs = {{ conan_installs }};
-        var python_installs = {{ python_installs }};
-        developerInfo.append({ name : "<H1>Conan Installs</H1>", version : '' });
-        for (var n in conan_installs)
-        {
-            developerInfo.append({ name : conan_installs[n][0], version : conan_installs[n][1] });
-        }
-        developerInfo.append({ name : '', version : '' });
-        developerInfo.append({ name : "<H1>Python Installs</H1>", version : '' });
-        for (var n in python_installs)
-        {
-            developerInfo.append({ name : python_installs[n][0], version : python_installs[n][1] });
-        }
-
-    }
-}
-
diff --git a/CuraVersion.py.jinja b/CuraVersion.py.jinja
index 87ef7d205d..515293b8af 100644
--- a/CuraVersion.py.jinja
+++ b/CuraVersion.py.jinja
@@ -1,4 +1,4 @@
-# Copyright (c) 2022 UltiMaker
+# Copyright (c) 2023 UltiMaker
 # Cura is released under the terms of the LGPLv3 or higher.
 
 CuraAppName = "{{ cura_app_name }}"
@@ -12,3 +12,6 @@ CuraCloudAccountAPIRoot = "{{ cura_cloud_account_api_root }}"
 CuraMarketplaceRoot = "{{ cura_marketplace_root }}"
 CuraDigitalFactoryURL = "{{ cura_digital_factory_url }}"
 CuraLatestURL = "{{ cura_latest_url }}"
+
+ConanInstalls = {{ conan_installs }}
+PythonInstalls = {{ python_installs }}
diff --git a/conanfile.py b/conanfile.py
index 4c6138656b..fc56d5033c 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -137,18 +137,21 @@ class CuraConan(ConanFile):
             return "'x86_64'"
         return "None"
 
-    def _generate_about_versions(self, location):
-        with open(os.path.join(self.recipe_folder, "AboutDialogVersionsList.qml.jinja"), "r") as f:
-            cura_version_py = Template(f.read())
+    def _conan_installs(self):
+        conan_installs = {}
 
-        conan_installs = []
-        python_installs = []
+        # list of conan installs
+        for dependency in self.dependencies.host.values():
+            conan_installs[dependency.ref.name] = {
+                "version": dependency.ref.version,
+                "revision": dependency.ref.revision
+            }
+        return conan_installs
 
-        # list  of conan installs
-        for _, dependency in self.dependencies.host.items():
-            conan_installs.append([dependency.ref.name,dependency.ref.version])
+    def _python_installs(self):
+        python_installs = {}
 
-        #list of python installs
+        # list of python installs
         outer = '"' if self.settings.os == "Windows" else "'"
         inner = "'" if self.settings.os == "Windows" else '"'
         python_ins_cmd = f"python -c {outer}import pkg_resources; print({inner};{inner}.join([(s.key+{inner},{inner}+ s.version) for s in pkg_resources.working_set])){outer}"
@@ -157,16 +160,12 @@ class CuraConan(ConanFile):
         self.run(python_ins_cmd, run_environment= True, env = "conanrun",  output=buffer)
 
         packages = str(buffer.getvalue()).split("-----------------\n")
-        package = packages[1].strip('\r\n').split(";")
-        for pack in package:
-            python_installs.append(pack.split(","))
-
-        with open(os.path.join(location, "AboutDialogVersionsList.qml"), "w") as f:
-            f.write(cura_version_py.render(
-                conan_installs = conan_installs,
-                python_installs = python_installs
-            ))
+        packages = packages[1].strip('\r\n').split(";")
+        for package in packages:
+            name, version = package.split(",")
+            python_installs[name] = {"version": version}
 
+        return python_installs
 
     def _generate_cura_version(self, location):
         with open(os.path.join(self.recipe_folder, "CuraVersion.py.jinja"), "r") as f:
@@ -192,89 +191,9 @@ class CuraConan(ConanFile):
                 cura_cloud_account_api_root = self.conan_data["urls"][self._urls]["cloud_account_api_root"],
                 cura_marketplace_root = self.conan_data["urls"][self._urls]["marketplace_root"],
                 cura_digital_factory_url = self.conan_data["urls"][self._urls]["digital_factory_url"],
-                cura_latest_url = self.conan_data["urls"][self._urls]["cura_latest_url"]))
-
-    def _generate_pyinstaller_spec(self, location, entrypoint_location, icon_path, entitlements_file):
-        pyinstaller_metadata = self.conan_data["pyinstaller"]
-        datas = [(str(self._base_dir.joinpath("conan_install_info.json")), ".")]
-        for data in pyinstaller_metadata["datas"].values():
-            if not self.options.internal and data.get("internal", False):
-                continue
-
-            if "package" in data:  # get the paths from conan package
-                if data["package"] == self.name:
-                    if self.in_local_cache:
-                        src_path = os.path.join(self.package_folder, data["src"])
-                    else:
-                        src_path = os.path.join(self.source_folder, data["src"])
-                else:
-                    src_path = os.path.join(self.deps_cpp_info[data["package"]].rootpath, data["src"])
-            elif "root" in data:  # get the paths relative from the install folder
-                src_path = os.path.join(self.install_folder, data["root"], data["src"])
-            else:
-                continue
-            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 = 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 = str(self.source_path.joinpath(binary["root"], binary["src"]))
-                if self.settings.os == "Windows":
-                    src_path = src_path.replace("\\", "\\\\")
-            else:
-                continue
-            if not Path(src_path).exists():
-                self.output.warning(f"Source path for binary {binary['binary']} does not exist")
-                continue
-
-            for bin in Path(src_path).glob(binary["binary"] + "*[.exe|.dll|.so|.dylib|.so.]*"):
-                binaries.append((str(bin), binary["dst"]))
-            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
-        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")])
-            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("**/*.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")])
-
-        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(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,
-                entrypoint = entrypoint_location,
-                datas = datas,
-                binaries = binaries,
-                venv_script_path = str(self._script_dir),
-                hiddenimports = pyinstaller_metadata["hiddenimports"],
-                collect_all = pyinstaller_metadata["collect_all"],
-                icon = icon_path,
-                entitlements_file = entitlements_file,
-                osx_bundle_identifier = "'nl.ultimaker.cura'" if self.settings.os == "Macos" else "None",
-                upx = str(self.settings.os == "Windows"),
-                strip = False,  # This should be possible on Linux and MacOS but, it can also cause issues on some distributions. Safest is to disable it for now
-                target_arch = self._pyinstaller_spec_arch,
-                macos = self.settings.os == "Macos",
-                version = f"'{version}'",
-                short_version = f"'{cura_version.major}.{cura_version.minor}.{cura_version.patch}'",
+                cura_latest_url=self.conan_data["urls"][self._urls]["cura_latest_url"],
+                conan_installs=self._conan_installs(),
+                python_installs=self._python_installs(),
             ))
 
     def export_sources(self):
@@ -346,7 +265,6 @@ class CuraConan(ConanFile):
         vr.generate()
 
         self._generate_cura_version(os.path.join(self.source_folder, "cura"))
-        self._generate_about_versions(os.path.join(self.source_folder, "resources","qml", "Dialogs"))
 
         if not self.in_local_cache:
             # Copy CuraEngine.exe to bindirs of Virtual Python Environment
@@ -387,12 +305,6 @@ class CuraConan(ConanFile):
             copy(self, "*", cura_private_data.resdirs[0], str(self._share_dir.joinpath("cura")))
 
         if self.options.devtools:
-            entitlements_file = "'{}'".format(os.path.join(self.source_folder, "packaging", "MacOS", "cura.entitlements"))
-            self._generate_pyinstaller_spec(location = self.generators_folder,
-                                            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 and pot files
             if self.settings.os != "Windows" or self.conf.get("tools.microsoft.bash:path", check_type=str):
                 vb = VirtualBuildEnv(self)
@@ -451,13 +363,6 @@ echo "CURA_APP_NAME={{ cura_app_name }}" >> ${{ env_prefix }}GITHUB_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(os.path.join(self._site_packages, "cura"))
-        self._generate_about_versions(str(self._share_dir.joinpath("cura", "resources", "qml", "Dialogs")))
-
-        entitlements_file = "'{}'".format(Path(self.cpp_info.res_paths[2], "MacOS", "cura.entitlements"))
-        self._generate_pyinstaller_spec(location = self._base_dir,
-                                        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_folder, dst = os.path.join(self.package_folder, self.cpp.package.bindirs[0]))
diff --git a/cura/ApplicationMetadata.py b/cura/ApplicationMetadata.py
index 96cfa6c64d..9d399e7ad8 100644
--- a/cura/ApplicationMetadata.py
+++ b/cura/ApplicationMetadata.py
@@ -1,4 +1,4 @@
-#  Copyright (c) 2022 UltiMaker
+#  Copyright (c) 2023 UltiMaker
 #  Cura is released under the terms of the LGPLv3 or higher.
 
 # ---------
@@ -69,13 +69,25 @@ try:
 except ImportError:
     CuraAppDisplayName = DEFAULT_CURA_DISPLAY_NAME
 
-DEPENDENCY_INFO = {}
+
 try:
-    from pathlib import Path
-    conan_install_info = Path(__file__).parent.parent.joinpath("conan_install_info.json")
-    if conan_install_info.exists():
-        import json
-        with open(conan_install_info, "r") as f:
-            DEPENDENCY_INFO = json.loads(f.read())
-except:
-    pass
+    from cura.CuraVersion import ConanInstalls
+
+    if type(ConanInstalls) == dict:
+        CONAN_INSTALLS = ConanInstalls
+    else:
+        CONAN_INSTALLS = {}
+
+except ImportError:
+    CONAN_INSTALLS = {}
+
+try:
+    from cura.CuraVersion import PythonInstalls
+
+    if type(PythonInstalls) == dict:
+        PYTHON_INSTALLS = PythonInstalls
+    else:
+        PYTHON_INSTALLS = {}
+
+except ImportError:
+    PYTHON_INSTALLS = {}
diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py
index e075fe92f5..b51fbd9d82 100755
--- a/cura/CuraApplication.py
+++ b/cura/CuraApplication.py
@@ -269,6 +269,9 @@ class CuraApplication(QtApplication):
         CentralFileStorage.setIsEnterprise(ApplicationMetadata.IsEnterpriseVersion)
         Resources.setIsEnterprise(ApplicationMetadata.IsEnterpriseVersion)
 
+        self._conan_installs = ApplicationMetadata.CONAN_INSTALLS
+        self._python_installs = ApplicationMetadata.PYTHON_INSTALLS
+
     @pyqtProperty(str, constant=True)
     def ultimakerCloudApiRootUrl(self) -> str:
         return UltimakerCloudConstants.CuraCloudAPIRoot
@@ -851,11 +854,8 @@ class CuraApplication(QtApplication):
 
         self._log_hardware_info()
 
-        if len(ApplicationMetadata.DEPENDENCY_INFO) > 0:
-            Logger.debug("Using Conan managed dependencies: " + ", ".join(
-                [dep["recipe"]["id"] for dep in ApplicationMetadata.DEPENDENCY_INFO["installed"] if dep["recipe"]["version"] != "latest"]))
-        else:
-            Logger.warning("Could not find conan_install_info.json")
+        Logger.debug("Using conan dependencies: {}", str(self.conanInstalls))
+        Logger.debug("Using python dependencies: {}", str(self.pythonInstalls))
 
         Logger.log("i", "Initializing machine error checker")
         self._machine_error_checker = MachineErrorChecker(self)
@@ -2130,3 +2130,11 @@ class CuraApplication(QtApplication):
     @pyqtProperty(bool, constant=True)
     def isEnterprise(self) -> bool:
         return ApplicationMetadata.IsEnterpriseVersion
+
+    @pyqtProperty("QVariant", constant=True)
+    def conanInstalls(self) -> Dict[str, Dict[str, str]]:
+        return self._conan_installs
+
+    @pyqtProperty("QVariant", constant=True)
+    def pythonInstalls(self) -> Dict[str, Dict[str, str]]:
+        return self._python_installs
diff --git a/resources/qml/Dialogs/AboutDialog.qml b/resources/qml/Dialogs/AboutDialog.qml
index b0cd9d2ad3..bbd7c45b8d 100644
--- a/resources/qml/Dialogs/AboutDialog.qml
+++ b/resources/qml/Dialogs/AboutDialog.qml
@@ -1,19 +1,22 @@
-// Copyright (c) 2022 UltiMaker
+// Copyright (c) 2023 UltiMaker
 // Cura is released under the terms of the LGPLv3 or higher.
 
 import QtQuick 2.4
 import QtQuick.Controls 2.9
+import QtQuick.Layouts 1.3
 
 import UM 1.6 as UM
-import Cura 1.5 as Cura
+import Cura 1.6 as Cura
 
 UM.Dialog
 {
     id: base
 
-    //: About dialog title
     title: catalog.i18nc("@title:window The argument is the application name.", "About %1").arg(CuraApplication.applicationDisplayName)
 
+    // Flag to toggle between main dependencies information and extensive dependencies information
+    property bool showDefaultDependencies: true
+
     minimumWidth: 500 * screenScaleFactor
     minimumHeight: 700 * screenScaleFactor
     width: minimumWidth
@@ -21,186 +24,241 @@ UM.Dialog
 
     backgroundColor: UM.Theme.getColor("main_background")
 
-
-    Rectangle
+    headerComponent: Rectangle
     {
-        id: header
-        width: parent.width + 2 * margin // margin from Dialog.qml
-        height: childrenRect.height + topPadding
-
-        anchors.top: parent.top
-        anchors.topMargin: -margin
-        anchors.horizontalCenter: parent.horizontalCenter
-
-        property real topPadding: UM.Theme.getSize("wide_margin").height
-
+        width: parent.width
+        height: logo.height + 2 * UM.Theme.getSize("wide_margin").height
         color: UM.Theme.getColor("main_window_header_background")
 
         Image
         {
             id: logo
-            width: (base.minimumWidth * 0.85) | 0
-            height: (width * (UM.Theme.getSize("logo").height / UM.Theme.getSize("logo").width)) | 0
+            width: Math.floor(base.width * 0.85)
+            height: Math.floor(width * UM.Theme.getSize("logo").height / UM.Theme.getSize("logo").width)
             source: UM.Theme.getImage("logo")
-            sourceSize.width: width
-            sourceSize.height: height
             fillMode: Image.PreserveAspectFit
 
-            anchors.top: parent.top
-            anchors.topMargin: parent.topPadding
-            anchors.horizontalCenter: parent.horizontalCenter
+            anchors.centerIn: parent
 
-            UM.I18nCatalog{id: catalog; name: "cura"}
-            MouseArea
-            {
-                anchors.fill: parent
-                onClicked:
-                {
-                    projectsList.visible = !projectsList.visible;
-                    projectBuildInfoList.visible = !projectBuildInfoList.visible;
-                }
-            }
+            UM.I18nCatalog{ id: catalog; name: "cura" }
         }
 
         UM.Label
         {
             id: version
-
             text: catalog.i18nc("@label","version: %1").arg(UM.Application.version)
             font: UM.Theme.getFont("large_bold")
             color: UM.Theme.getColor("button_text")
             anchors.right : logo.right
             anchors.top: logo.bottom
-            anchors.topMargin: (UM.Theme.getSize("default_margin").height / 2) | 0
+        }
+
+        MouseArea
+        {
+            anchors.fill: parent
+            onDoubleClicked: showDefaultDependencies = !showDefaultDependencies
         }
     }
 
-    UM.Label
+    // Reusable component to display a dependency
+    readonly property Component dependency_row: RowLayout
     {
-        id: description
-        width: parent.width
+        spacing: UM.Theme.getSize("narrow_margin").width
 
-        //: About dialog application description
-        text: catalog.i18nc("@label","End-to-end solution for fused filament 3D printing.")
-        font: UM.Theme.getFont("system")
-        wrapMode: Text.WordWrap
-        anchors.top: header.bottom
-        anchors.topMargin: UM.Theme.getSize("default_margin").height
-    }
-
-    UM.Label
-    {
-        id: creditsNotes
-        width: parent.width
-
-        //: About dialog application author note
-        text: catalog.i18nc("@info:credit","Cura is developed by UltiMaker in cooperation with the community.\nCura proudly uses the following open source projects:")
-        font: UM.Theme.getFont("system")
-        wrapMode: Text.WordWrap
-        anchors.top: description.bottom
-        anchors.topMargin: UM.Theme.getSize("default_margin").height
-    }
-
-    ListView
-    {
-        id: projectsList
-        anchors.top: creditsNotes.bottom
-        anchors.topMargin: UM.Theme.getSize("default_margin").height
-        width: parent.width
-        height: base.height - y - (2 * UM.Theme.getSize("default_margin").height + closeButton.height)
-
-        ScrollBar.vertical: UM.ScrollBar
+        UM.Label
         {
-            id: projectsListScrollBar
+            text: {
+                if (typeof(url) !== "undefined" && url !== "") {
+                    return "<a href=\"" + url + "\">" + name + "</a>";
+                } else {
+                    return name;
+                }
+            }
+            visible: text !== ""
+            Layout.fillWidth: true
+            Layout.preferredWidth: 2
+            elide: Text.ElideRight
         }
 
-        delegate: Row
+        UM.Label
         {
+            text: description
+            visible: text !== ""
+            Layout.fillWidth: true
+            Layout.preferredWidth: 3
+            elide: Text.ElideRight
+        }
+
+        UM.Label
+        {
+            text: license
+            visible: text !== ""
+            Layout.fillWidth: true
+            Layout.preferredWidth: 2
+            elide: Text.ElideRight
+        }
+
+        UM.Label
+        {
+            text: version
+            visible: text !== ""
+            Layout.fillWidth: true
+            Layout.preferredWidth: 2
+            elide: Text.ElideRight
+        }
+    }
+
+    Flickable
+    {
+        anchors.fill: parent
+        ScrollBar.vertical: UM.ScrollBar {
+            visible: contentHeight > height
+        }
+        contentHeight: content.height
+        clip: true
+
+        Column
+        {
+            id: content
             spacing: UM.Theme.getSize("narrow_margin").width
+            width: parent.width
+
             UM.Label
             {
-                text: "<a href='%1' title='%2'>%2</a>".arg(model.url).arg(model.name)
-                width: (projectsList.width * 0.25) | 0
-                elide: Text.ElideRight
-                onLinkActivated: Qt.openUrlExternally(link)
+                text: catalog.i18nc("@label", "End-to-end solution for fused filament 3D printing.")
+                font: UM.Theme.getFont("system")
+                wrapMode: Text.WordWrap
             }
+
             UM.Label
             {
-                text: model.description
-                elide: Text.ElideRight
-                width: ((projectsList.width * 0.6) | 0) - parent.spacing * 2 - projectsListScrollBar.width
+                text: catalog.i18nc("@info:credit", "Cura is developed by UltiMaker in cooperation with the community.\nCura proudly uses the following open source projects:")
+                font: UM.Theme.getFont("system")
+                wrapMode: Text.WordWrap
             }
+
+            Column
+            {
+                visible: showDefaultDependencies
+                width: parent.width
+
+                Repeater
+                {
+                    width: parent.width
+
+                    delegate: Loader {
+                        sourceComponent: dependency_row
+                        width: parent.width
+                        property string name: model.name
+                        property string description: model.description
+                        property string license: model.license
+                        property string url: model.url
+                    }
+
+                    model: ListModel
+                    {
+                        id: projectsModel
+                    }
+                    Component.onCompleted:
+                    {
+                        //Do NOT add dependencies of our dependencies here, nor CI-dependencies!
+                        //UltiMaker's own projects and forks.
+                        projectsModel.append({ name: "Cura", description: catalog.i18nc("@label Description for application component", "Graphical user interface"), license: "LGPLv3", url: "https://github.com/Ultimaker/Cura" });
+                        projectsModel.append({ name: "Uranium", description: catalog.i18nc("@label Description for application component", "Application framework"), license: "LGPLv3", url: "https://github.com/Ultimaker/Uranium" });
+                        projectsModel.append({ name: "CuraEngine", description: catalog.i18nc("@label Description for application component", "G-code generator"), license: "AGPLv3", url: "https://github.com/Ultimaker/CuraEngine" });
+                        projectsModel.append({ name: "libArcus", description: catalog.i18nc("@label Description for application component", "Interprocess communication library"), license: "LGPLv3", url: "https://github.com/Ultimaker/libArcus" });
+                        projectsModel.append({ name: "pynest2d", description: catalog.i18nc("@label Description for application component", "Python bindings for libnest2d"), license: "LGPL", url: "https://github.com/Ultimaker/pynest2d" });
+                        projectsModel.append({ name: "libnest2d", description: catalog.i18nc("@label Description for application component", "Polygon packing library, developed by Prusa Research"), license: "LGPL", url: "https://github.com/tamasmeszaros/libnest2d" });
+                        projectsModel.append({ name: "libSavitar", description: catalog.i18nc("@label Description for application component", "Support library for handling 3MF files"), license: "LGPLv3", url: "https://github.com/ultimaker/libsavitar" });
+                        projectsModel.append({ name: "libCharon", description: catalog.i18nc("@label Description for application component", "Support library for file metadata and streaming"), license: "LGPLv3", url: "https://github.com/ultimaker/libcharon" });
+
+                        //Direct dependencies of the front-end.
+                        projectsModel.append({ name: "Python", description: catalog.i18nc("@label Description for application dependency", "Programming language"), license: "Python", url: "http://python.org/" });
+                        projectsModel.append({ name: "Qt6", description: catalog.i18nc("@label Description for application dependency", "GUI framework"), license: "LGPLv3", url: "https://www.qt.io/" });
+                        projectsModel.append({ name: "PyQt", description: catalog.i18nc("@label Description for application dependency", "GUI framework bindings"), license: "GPL", url: "https://riverbankcomputing.com/software/pyqt" });
+                        projectsModel.append({ name: "SIP", description: catalog.i18nc("@label Description for application dependency", "C/C++ Binding library"), license: "GPL", url: "https://riverbankcomputing.com/software/sip" });
+                        projectsModel.append({ name: "Protobuf", description: catalog.i18nc("@label Description for application dependency", "Data interchange format"), license: "BSD", url: "https://developers.google.com/protocol-buffers" });
+                        projectsModel.append({ name: "Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" });
+
+                        //CuraEngine's dependencies.
+                        projectsModel.append({ name: "Clipper", description: catalog.i18nc("@label Description for application dependency", "Polygon clipping library"), license: "Boost", url: "http://www.angusj.com/delphi/clipper.php" });
+                        projectsModel.append({ name: "RapidJSON", description: catalog.i18nc("@label Description for application dependency", "JSON parser"), license: "MIT", url: "https://rapidjson.org/" });
+                        projectsModel.append({ name: "STB", description: catalog.i18nc("@label Description for application dependency", "Utility functions, including an image loader"), license: "Public Domain", url: "https://github.com/nothings/stb" });
+                        projectsModel.append({ name: "Boost", description: catalog.i18nc("@label Description for application dependency", "Utility library, including Voronoi generation"), license: "Boost", url: "https://www.boost.org/" });
+
+                        //Python modules.
+                        projectsModel.append({ name: "Certifi", description: catalog.i18nc("@label Description for application dependency", "Root Certificates for validating SSL trustworthiness"), license: "MPL", url: "https://github.com/certifi/python-certifi" });
+                        projectsModel.append({ name: "Cryptography", description: catalog.i18nc("@label Description for application dependency", "Root Certificates for validating SSL trustworthiness"), license: "APACHE and BSD", url: "https://cryptography.io/" });
+                        projectsModel.append({ name: "Future", description: catalog.i18nc("@label Description for application dependency", "Compatibility between Python 2 and 3"), license: "MIT", url: "https://python-future.org/" });
+                        projectsModel.append({ name: "keyring", description: catalog.i18nc("@label Description for application dependency", "Support library for system keyring access"), license: "MIT", url: "https://github.com/jaraco/keyring" });
+                        projectsModel.append({ name: "NumPy", description: catalog.i18nc("@label Description for application dependency", "Support library for faster math"), license: "BSD", url: "http://www.numpy.org/" });
+                        projectsModel.append({ name: "NumPy-STL", description: catalog.i18nc("@label Description for application dependency", "Support library for handling STL files"), license: "BSD", url: "https://github.com/WoLpH/numpy-stl" });
+                        projectsModel.append({ name: "PyClipper", description: catalog.i18nc("@label Description for application dependency", "Python bindings for Clipper"), license: "MIT", url: "https://github.com/fonttools/pyclipper" });
+                        projectsModel.append({ name: "PySerial", description: catalog.i18nc("@label Description for application dependency", "Serial communication library"), license: "Python", url: "http://pyserial.sourceforge.net/" });
+                        projectsModel.append({ name: "SciPy", description: catalog.i18nc("@label Description for application dependency", "Support library for scientific computing"), license: "BSD-new", url: "https://www.scipy.org/" });
+                        projectsModel.append({ name: "Sentry", description: catalog.i18nc("@Label Description for application dependency", "Python Error tracking library"), license: "BSD 2-Clause 'Simplified'", url: "https://sentry.io/for/python/" });
+                        projectsModel.append({ name: "Trimesh", description: catalog.i18nc("@label Description for application dependency", "Support library for handling triangular meshes"), license: "MIT", url: "https://trimsh.org" });
+                        projectsModel.append({ name: "python-zeroconf", description: catalog.i18nc("@label Description for application dependency", "ZeroConf discovery library"), license: "LGPL", url: "https://github.com/jstasiak/python-zeroconf" });
+
+                        //Building/packaging.
+                        projectsModel.append({ name: "CMake", description: catalog.i18nc("@label Description for development tool", "Universal build system configuration"), license: "BSD 3-Clause", url: "https://cmake.org/" });
+                        projectsModel.append({ name: "Conan", description: catalog.i18nc("@label Description for development tool", "Dependency and package manager"), license: "MIT", url: "https://conan.io/" });
+                        projectsModel.append({ name: "Pyinstaller", description: catalog.i18nc("@label Description for development tool", "Packaging Python-applications"), license: "GPLv2", url: "https://pyinstaller.org/" });
+                        projectsModel.append({ name: "AppImageKit", description: catalog.i18nc("@label Description for development tool", "Linux cross-distribution application deployment"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" });
+                        projectsModel.append({ name: "NSIS", description: catalog.i18nc("@label Description for development tool", "Generating Windows installers"), license: "Zlib", url: "https://nsis.sourceforge.io/" });
+                    }
+                }
+            }
+
             UM.Label
             {
-                text: model.license
-                elide: Text.ElideRight
-                width: (projectsList.width * 0.15) | 0
+                visible: !showDefaultDependencies
+                text: "Conan Installs"
+                font: UM.Theme.getFont("large_bold")
+            }
+
+            Column
+            {
+                visible: !showDefaultDependencies
+                width: parent.width
+
+                Repeater
+                {
+                    width: parent.width
+                    model: Object.entries(CuraApplication.conanInstalls).map(function (item) { return { name: item[0], version: item[1].version } })
+                    delegate: Loader {
+                        sourceComponent: dependency_row
+                        width: parent.width
+                        property string name: modelData.name
+                        property string version: modelData.version
+                    }
+                }
+            }
+
+            UM.Label
+            {
+                visible: !showDefaultDependencies
+                text: "Python Installs"
+                font: UM.Theme.getFont("large_bold")
+            }
+
+            Column
+            {
+                width: parent.width
+                visible: !showDefaultDependencies
+                Repeater
+                {
+                    delegate: Loader {
+                        sourceComponent: dependency_row
+                        width: parent.width
+                        property string name: modelData.name
+                        property string version: modelData.version
+                    }
+                    width: parent.width
+                    model: Object.entries(CuraApplication.pythonInstalls).map(function (item) { return { name: item[0], version: item[1].version } })
+                }
             }
         }
-        model: ListModel
-        {
-            id: projectsModel
-        }
-        Component.onCompleted:
-        {
-            //Do NOT add dependencies of our dependencies here, nor CI-dependencies!
-            //UltiMaker's own projects and forks.
-            projectsModel.append({ name: "Cura", description: catalog.i18nc("@label Description for application component", "Graphical user interface"), license: "LGPLv3", url: "https://github.com/Ultimaker/Cura" });
-            projectsModel.append({ name: "Uranium", description: catalog.i18nc("@label Description for application component", "Application framework"), license: "LGPLv3", url: "https://github.com/Ultimaker/Uranium" });
-            projectsModel.append({ name: "CuraEngine", description: catalog.i18nc("@label Description for application component", "G-code generator"), license: "AGPLv3", url: "https://github.com/Ultimaker/CuraEngine" });
-            projectsModel.append({ name: "libArcus", description: catalog.i18nc("@label Description for application component", "Interprocess communication library"), license: "LGPLv3", url: "https://github.com/Ultimaker/libArcus" });
-            projectsModel.append({ name: "pynest2d", description: catalog.i18nc("@label Description for application component", "Python bindings for libnest2d"), license: "LGPL", url: "https://github.com/Ultimaker/pynest2d" });
-            projectsModel.append({ name: "libnest2d", description: catalog.i18nc("@label Description for application component", "Polygon packing library, developed by Prusa Research"), license: "LGPL", url: "https://github.com/tamasmeszaros/libnest2d" });
-            projectsModel.append({ name: "libSavitar", description: catalog.i18nc("@label Description for application component", "Support library for handling 3MF files"), license: "LGPLv3", url: "https://github.com/ultimaker/libsavitar" });
-            projectsModel.append({ name: "libCharon", description: catalog.i18nc("@label Description for application component", "Support library for file metadata and streaming"), license: "LGPLv3", url: "https://github.com/ultimaker/libcharon" });
-
-            //Direct dependencies of the front-end.
-            projectsModel.append({ name: "Python", description: catalog.i18nc("@label Description for application dependency", "Programming language"), license: "Python", url: "http://python.org/" });
-            projectsModel.append({ name: "Qt6", description: catalog.i18nc("@label Description for application dependency", "GUI framework"), license: "LGPLv3", url: "https://www.qt.io/" });
-            projectsModel.append({ name: "PyQt", description: catalog.i18nc("@label Description for application dependency", "GUI framework bindings"), license: "GPL", url: "https://riverbankcomputing.com/software/pyqt" });
-            projectsModel.append({ name: "SIP", description: catalog.i18nc("@label Description for application dependency", "C/C++ Binding library"), license: "GPL", url: "https://riverbankcomputing.com/software/sip" });
-            projectsModel.append({ name: "Protobuf", description: catalog.i18nc("@label Description for application dependency", "Data interchange format"), license: "BSD", url: "https://developers.google.com/protocol-buffers" });
-            projectsModel.append({ name: "Noto Sans", description: catalog.i18nc("@label", "Font"), license: "Apache 2.0", url: "https://www.google.com/get/noto/" });
-
-            //CuraEngine's dependencies.
-            projectsModel.append({ name: "Clipper", description: catalog.i18nc("@label Description for application dependency", "Polygon clipping library"), license: "Boost", url: "http://www.angusj.com/delphi/clipper.php" });
-            projectsModel.append({ name: "RapidJSON", description: catalog.i18nc("@label Description for application dependency", "JSON parser"), license: "MIT", url: "https://rapidjson.org/" });
-            projectsModel.append({ name: "STB", description: catalog.i18nc("@label Description for application dependency", "Utility functions, including an image loader"), license: "Public Domain", url: "https://github.com/nothings/stb" });
-            projectsModel.append({ name: "Boost", description: catalog.i18nc("@label Description for application dependency", "Utility library, including Voronoi generation"), license: "Boost", url: "https://www.boost.org/" });
-
-            //Python modules.
-            projectsModel.append({ name: "Certifi", description: catalog.i18nc("@label Description for application dependency", "Root Certificates for validating SSL trustworthiness"), license: "MPL", url: "https://github.com/certifi/python-certifi" });
-            projectsModel.append({ name: "Cryptography", description: catalog.i18nc("@label Description for application dependency", "Root Certificates for validating SSL trustworthiness"), license: "APACHE and BSD", url: "https://cryptography.io/" });
-            projectsModel.append({ name: "Future", description: catalog.i18nc("@label Description for application dependency", "Compatibility between Python 2 and 3"), license: "MIT", url: "https://python-future.org/" });
-            projectsModel.append({ name: "keyring", description: catalog.i18nc("@label Description for application dependency", "Support library for system keyring access"), license: "MIT", url: "https://github.com/jaraco/keyring" });
-            projectsModel.append({ name: "NumPy", description: catalog.i18nc("@label Description for application dependency", "Support library for faster math"), license: "BSD", url: "http://www.numpy.org/" });
-            projectsModel.append({ name: "NumPy-STL", description: catalog.i18nc("@label Description for application dependency", "Support library for handling STL files"), license: "BSD", url: "https://github.com/WoLpH/numpy-stl" });
-            projectsModel.append({ name: "PyClipper", description: catalog.i18nc("@label Description for application dependency", "Python bindings for Clipper"), license: "MIT", url: "https://github.com/fonttools/pyclipper" });
-            projectsModel.append({ name: "PySerial", description: catalog.i18nc("@label Description for application dependency", "Serial communication library"), license: "Python", url: "http://pyserial.sourceforge.net/" });
-            projectsModel.append({ name: "SciPy", description: catalog.i18nc("@label Description for application dependency", "Support library for scientific computing"), license: "BSD-new", url: "https://www.scipy.org/" });
-            projectsModel.append({ name: "Sentry", description: catalog.i18nc("@Label Description for application dependency", "Python Error tracking library"), license: "BSD 2-Clause 'Simplified'", url: "https://sentry.io/for/python/" });
-            projectsModel.append({ name: "Trimesh", description: catalog.i18nc("@label Description for application dependency", "Support library for handling triangular meshes"), license: "MIT", url: "https://trimsh.org" });
-            projectsModel.append({ name: "python-zeroconf", description: catalog.i18nc("@label Description for application dependency", "ZeroConf discovery library"), license: "LGPL", url: "https://github.com/jstasiak/python-zeroconf" });
-
-            //Building/packaging.
-            projectsModel.append({ name: "CMake", description: catalog.i18nc("@label Description for development tool", "Universal build system configuration"), license: "BSD 3-Clause", url: "https://cmake.org/" });
-            projectsModel.append({ name: "Conan", description: catalog.i18nc("@label Description for development tool", "Dependency and package manager"), license: "MIT", url: "https://conan.io/" });
-            projectsModel.append({ name: "Pyinstaller", description: catalog.i18nc("@label Description for development tool", "Packaging Python-applications"), license: "GPLv2", url: "https://pyinstaller.org/" });
-            projectsModel.append({ name: "AppImageKit", description: catalog.i18nc("@label Description for development tool", "Linux cross-distribution application deployment"), license: "MIT", url: "https://github.com/AppImage/AppImageKit" });
-            projectsModel.append({ name: "NSIS", description: catalog.i18nc("@label Description for development tool", "Generating Windows installers"), license: "Zlib", url: "https://nsis.sourceforge.io/" });
-        }
-    }
-
-    AboutDialogVersionsList{
-        id: projectBuildInfoList
-
-    }
-
-
-    onVisibleChanged:
-    {
-         projectsList.visible = true;
-         projectBuildInfoList.visible = false;
     }
 
     rightButtons: Cura.TertiaryButton