mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-05-06 23:48:59 +08:00
Merge branch 'main' into Makerbot-profiles-update
This commit is contained in:
commit
e1e443eadf
34
.github/workflows/linux.yml
vendored
34
.github/workflows/linux.yml
vendored
@ -147,7 +147,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 -c tools.build:skip_test=True
|
||||
|
||||
- name: Remove internal packages before uploading
|
||||
run: |
|
||||
@ -196,19 +196,12 @@ jobs:
|
||||
f.write(content)
|
||||
f.writelines(f"INSTALLER_FILENAME={installer_filename}\n")
|
||||
|
||||
- name: Summarize the used Conan dependencies
|
||||
- name: Summarize the used dependencies
|
||||
shell: python
|
||||
run: |
|
||||
import os
|
||||
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, PythonInstalls
|
||||
|
||||
summary_env = os.environ["GITHUB_STEP_SUMMARY"]
|
||||
content = ""
|
||||
@ -220,25 +213,12 @@ 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 ConanInstalls.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
|
||||
summary_env = os.environ["GITHUB_STEP_SUMMARY"]
|
||||
content = ""
|
||||
if os.path.exists(summary_env):
|
||||
with open(summary_env, "r") as f:
|
||||
content = f.read()
|
||||
|
||||
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 PythonInstalls.items():
|
||||
f.writelines(f"`{dep_name} {dep_info['version']}`\n")
|
||||
|
||||
- name: Create the Linux AppImage (Bash)
|
||||
run: |
|
||||
|
34
.github/workflows/macos.yml
vendored
34
.github/workflows/macos.yml
vendored
@ -156,7 +156,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 -c tools.build:skip_test=True
|
||||
|
||||
- name: Remove internal packages before uploading
|
||||
run: |
|
||||
@ -208,19 +208,12 @@ jobs:
|
||||
f.write(content)
|
||||
f.writelines(f"INSTALLER_FILENAME={installer_filename}\n")
|
||||
|
||||
- name: Summarize the used Conan dependencies
|
||||
- name: Summarize the used dependencies
|
||||
shell: python
|
||||
run: |
|
||||
import os
|
||||
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, PythonInstalls
|
||||
|
||||
summary_env = os.environ["GITHUB_STEP_SUMMARY"]
|
||||
content = ""
|
||||
@ -232,25 +225,12 @@ 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 ConanInstalls.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
|
||||
summary_env = os.environ["GITHUB_STEP_SUMMARY"]
|
||||
content = ""
|
||||
if os.path.exists(summary_env):
|
||||
with open(summary_env, "r") as f:
|
||||
content = f.read()
|
||||
|
||||
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 PythonInstalls.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"
|
||||
|
34
.github/workflows/windows.yml
vendored
34
.github/workflows/windows.yml
vendored
@ -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 -c tools.build:skip_test=True
|
||||
|
||||
- name: Remove internal packages before uploading
|
||||
run: |
|
||||
@ -167,19 +167,12 @@ jobs:
|
||||
f.write(content)
|
||||
f.writelines(f"INSTALLER_FILENAME={installer_filename}\n")
|
||||
|
||||
- name: Summarize the used Conan dependencies
|
||||
- name: Summarize the used dependencies
|
||||
shell: python
|
||||
run: |
|
||||
import os
|
||||
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, PythonInstalls
|
||||
|
||||
summary_env = os.environ["GITHUB_STEP_SUMMARY"]
|
||||
content = ""
|
||||
@ -191,25 +184,12 @@ 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 ConanInstalls.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
|
||||
summary_env = os.environ["GITHUB_STEP_SUMMARY"]
|
||||
content = ""
|
||||
if os.path.exists(summary_env):
|
||||
with open(summary_env, "r") as f:
|
||||
content = f.read()
|
||||
|
||||
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 PythonInstalls.items():
|
||||
f.writelines(f"`{dep_name} {dep_info['version']}`\n")
|
||||
|
||||
- name: Create PFX certificate from BASE64_PFX_CONTENT secret
|
||||
id: create-pfx
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
|
||||
|
@ -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] });
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
# Copyright (c) 2022 UltiMaker
|
||||
# Copyright (c) 2023 UltiMaker
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from pkg_resources import working_set
|
||||
|
||||
CuraAppName = "{{ cura_app_name }}"
|
||||
CuraAppDisplayName = "{{ cura_app_display_name }}"
|
||||
CuraVersion = "{{ cura_version }}"
|
||||
@ -12,3 +14,6 @@ CuraCloudAccountAPIRoot = "{{ cura_cloud_account_api_root }}"
|
||||
CuraMarketplaceRoot = "{{ cura_marketplace_root }}"
|
||||
CuraDigitalFactoryURL = "{{ cura_digital_factory_url }}"
|
||||
CuraLatestURL = "{{ cura_latest_url }}"
|
||||
|
||||
ConanInstalls = {{ conan_installs }}
|
||||
PythonInstalls = {package.key: {'version': package.version} for package in working_set}
|
@ -86,6 +86,7 @@ pyinstaller:
|
||||
hiddenimports:
|
||||
- "pySavitar"
|
||||
- "pyArcus"
|
||||
- "pyDulcificum"
|
||||
- "pynest2d"
|
||||
- "PyQt6"
|
||||
- "PyQt6.QtNetwork"
|
||||
|
97
conanfile.py
97
conanfile.py
@ -34,7 +34,8 @@ class CuraConan(ConanFile):
|
||||
"cloud_api_version": "ANY",
|
||||
"display_name": "ANY", # TODO: should this be an option??
|
||||
"cura_debug_mode": [True, False], # FIXME: Use profiles
|
||||
"internal": [True, False]
|
||||
"internal": [True, False],
|
||||
"enable_i18n": [True, False],
|
||||
}
|
||||
default_options = {
|
||||
"enterprise": "False",
|
||||
@ -44,6 +45,7 @@ class CuraConan(ConanFile):
|
||||
"display_name": "UltiMaker Cura",
|
||||
"cura_debug_mode": False, # Not yet implemented
|
||||
"internal": False,
|
||||
"enable_i18n": False,
|
||||
}
|
||||
|
||||
def set_version(self):
|
||||
@ -65,6 +67,8 @@ class CuraConan(ConanFile):
|
||||
self._cura_env = Environment()
|
||||
self._cura_env.define("QML2_IMPORT_PATH", str(self._site_packages.joinpath("PyQt6", "Qt6", "qml")))
|
||||
self._cura_env.define("QT_PLUGIN_PATH", str(self._site_packages.joinpath("PyQt6", "Qt6", "plugins")))
|
||||
if not self.in_local_cache:
|
||||
self._cura_env.define( "CURA_DATA_ROOT", str(self._share_dir.joinpath("cura")))
|
||||
|
||||
if self.settings.os == "Linux":
|
||||
self._cura_env.define("QT_QPA_FONTDIR", "/usr/share/fonts")
|
||||
@ -137,36 +141,16 @@ 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())
|
||||
|
||||
conan_installs = []
|
||||
python_installs = []
|
||||
|
||||
# list of conan installs
|
||||
for _, dependency in self.dependencies.host.items():
|
||||
conan_installs.append([dependency.ref.name,dependency.ref.version])
|
||||
|
||||
#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}"
|
||||
from six import StringIO
|
||||
buffer = StringIO()
|
||||
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
|
||||
))
|
||||
def _conan_installs(self):
|
||||
conan_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
|
||||
|
||||
def _generate_cura_version(self, location):
|
||||
with open(os.path.join(self.recipe_folder, "CuraVersion.py.jinja"), "r") as f:
|
||||
@ -192,11 +176,13 @@ 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"]))
|
||||
cura_latest_url=self.conan_data["urls"][self._urls]["cura_latest_url"],
|
||||
conan_installs=self._conan_installs(),
|
||||
))
|
||||
|
||||
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")), ".")]
|
||||
datas = []
|
||||
for data in pyinstaller_metadata["datas"].values():
|
||||
if not self.options.internal and data.get("internal", False):
|
||||
continue
|
||||
@ -289,10 +275,15 @@ class CuraConan(ConanFile):
|
||||
copy(self, "requirements-ultimaker.txt", self.recipe_folder, self.export_sources_folder)
|
||||
copy(self, "cura_app.py", self.recipe_folder, self.export_sources_folder)
|
||||
|
||||
def config_options(self):
|
||||
if self.settings.os == "Windows" and not self.conf.get("tools.microsoft.bash:path", check_type=str):
|
||||
del self.options.enable_i18n
|
||||
|
||||
def configure(self):
|
||||
self.options["pyarcus"].shared = True
|
||||
self.options["pysavitar"].shared = True
|
||||
self.options["pynest2d"].shared = True
|
||||
self.options["dulcificum"].shared = self.settings.os != "Windows"
|
||||
self.options["cpython"].shared = True
|
||||
self.options["boost"].header_only = True
|
||||
if self.settings.os == "Linux":
|
||||
@ -305,9 +296,11 @@ class CuraConan(ConanFile):
|
||||
|
||||
def requirements(self):
|
||||
self.requires("boost/1.82.0")
|
||||
self.requires("fmt/9.0.0")
|
||||
self.requires("curaengine_grpc_definitions/(latest)@ultimaker/testing")
|
||||
self.requires("zlib/1.2.13")
|
||||
self.requires("pyarcus/5.3.0")
|
||||
self.requires("dulcificum/(latest)@ultimaker/testing")
|
||||
self.requires("curaengine/(latest)@ultimaker/testing")
|
||||
self.requires("pysavitar/5.3.0")
|
||||
self.requires("pynest2d/5.3.0")
|
||||
@ -316,16 +309,14 @@ class CuraConan(ConanFile):
|
||||
self.requires("cura_binary_data/(latest)@ultimaker/testing")
|
||||
self.requires("cpython/3.10.4")
|
||||
if self.options.internal:
|
||||
self.requires("cura_private_data/(latest)@internal/testing")
|
||||
self.requires("cura_private_data/(latest)@internal/cura_10561")
|
||||
self.requires("fdm_materials/(latest)@internal/testing")
|
||||
else:
|
||||
self.requires("fdm_materials/(latest)@ultimaker/testing")
|
||||
|
||||
def build_requirements(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
|
||||
self.tool_requires("gettext/0.21@ultimaker/testing", force_host_context = True)
|
||||
if self.options.get_safe("enable_i18n", False):
|
||||
self.tool_requires("gettext/0.21@ultimaker/testing", force_host_context = True)
|
||||
|
||||
def layout(self):
|
||||
self.folders.source = "."
|
||||
@ -346,7 +337,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
|
||||
@ -393,26 +383,24 @@ class CuraConan(ConanFile):
|
||||
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")
|
||||
|
||||
if self.options.get_safe("enable_i18n", False):
|
||||
# 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)
|
||||
vb.generate()
|
||||
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
|
||||
# pot = self.python_requires["translationextractor"].module.ExtractTranslations(self, cpp_info.bindirs[0])
|
||||
# pot.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
|
||||
pot = self.python_requires["translationextractor"].module.ExtractTranslations(self, cpp_info.bindirs[0])
|
||||
pot.generate()
|
||||
|
||||
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
|
||||
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)
|
||||
if self.options.get_safe("enable_i18n", False):
|
||||
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 deploy(self):
|
||||
copy(self, "*", os.path.join(self.package_folder, self.cpp.package.resdirs[2]), os.path.join(self.install_folder, "packaging"), keep_path = True)
|
||||
@ -451,7 +439,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,
|
||||
|
@ -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 = {}
|
||||
|
@ -6,6 +6,7 @@ import sys
|
||||
import tempfile
|
||||
import time
|
||||
import platform
|
||||
from pathlib import Path
|
||||
from typing import cast, TYPE_CHECKING, Optional, Callable, List, Any, Dict
|
||||
|
||||
import numpy
|
||||
@ -269,6 +270,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
|
||||
@ -363,6 +367,10 @@ class CuraApplication(QtApplication):
|
||||
|
||||
Resources.addSecureSearchPath(os.path.join(self._app_install_dir, "share", "cura", "resources"))
|
||||
if not hasattr(sys, "frozen"):
|
||||
cura_data_root = os.environ.get('CURA_DATA_ROOT', None)
|
||||
if cura_data_root:
|
||||
Resources.addSearchPath(str(Path(cura_data_root).joinpath("resources")))
|
||||
|
||||
Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources"))
|
||||
|
||||
# local Conan cache
|
||||
@ -851,11 +859,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 +2135,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
|
||||
|
@ -1,7 +1,9 @@
|
||||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Copyright (c) 2023 UltiMaker
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
import numpy
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from PyQt6 import QtCore
|
||||
from PyQt6.QtCore import QCoreApplication
|
||||
from PyQt6.QtGui import QImage
|
||||
@ -10,11 +12,13 @@ from UM.Logger import Logger
|
||||
from cura.PreviewPass import PreviewPass
|
||||
|
||||
from UM.Application import Application
|
||||
from UM.Math.AxisAlignedBox import AxisAlignedBox
|
||||
from UM.Math.Matrix import Matrix
|
||||
from UM.Math.Vector import Vector
|
||||
from UM.Scene.Camera import Camera
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
from UM.Qt.QtRenderer import QtRenderer
|
||||
|
||||
class Snapshot:
|
||||
@staticmethod
|
||||
@ -32,6 +36,87 @@ class Snapshot:
|
||||
|
||||
return min_x, max_x, min_y, max_y
|
||||
|
||||
@staticmethod
|
||||
def isometricSnapshot(width: int = 300, height: int = 300) -> Optional[QImage]:
|
||||
"""Create an isometric snapshot of the scene."""
|
||||
|
||||
root = Application.getInstance().getController().getScene().getRoot()
|
||||
|
||||
# the direction the camera is looking at to create the isometric view
|
||||
iso_view_dir = Vector(-1, -1, -1).normalized()
|
||||
|
||||
bounds = Snapshot.nodeBounds(root)
|
||||
if bounds is None:
|
||||
Logger.log("w", "There appears to be nothing to render")
|
||||
return None
|
||||
|
||||
camera = Camera("snapshot")
|
||||
|
||||
# find local x and y directional vectors of the camera
|
||||
tangent_space_x_direction = iso_view_dir.cross(Vector.Unit_Y).normalized()
|
||||
tangent_space_y_direction = tangent_space_x_direction.cross(iso_view_dir).normalized()
|
||||
|
||||
# find extreme screen space coords of the scene
|
||||
x_points = [p.dot(tangent_space_x_direction) for p in bounds.points]
|
||||
y_points = [p.dot(tangent_space_y_direction) for p in bounds.points]
|
||||
min_x = min(x_points)
|
||||
max_x = max(x_points)
|
||||
min_y = min(y_points)
|
||||
max_y = max(y_points)
|
||||
camera_width = max_x - min_x
|
||||
camera_height = max_y - min_y
|
||||
|
||||
if camera_width == 0 or camera_height == 0:
|
||||
Logger.log("w", "There appears to be nothing to render")
|
||||
return None
|
||||
|
||||
# increase either width or height to match the aspect ratio of the image
|
||||
if camera_width / camera_height > width / height:
|
||||
camera_height = camera_width * height / width
|
||||
else:
|
||||
camera_width = camera_height * width / height
|
||||
|
||||
# Configure camera for isometric view
|
||||
ortho_matrix = Matrix()
|
||||
ortho_matrix.setOrtho(
|
||||
-camera_width / 2,
|
||||
camera_width / 2,
|
||||
-camera_height / 2,
|
||||
camera_height / 2,
|
||||
-10000,
|
||||
10000
|
||||
)
|
||||
camera.setPerspective(False)
|
||||
camera.setProjectionMatrix(ortho_matrix)
|
||||
camera.setPosition(bounds.center)
|
||||
camera.lookAt(bounds.center + iso_view_dir)
|
||||
|
||||
# Render the scene
|
||||
renderer = QtRenderer()
|
||||
render_pass = PreviewPass(width, height)
|
||||
renderer.setViewportSize(width, height)
|
||||
renderer.setWindowSize(width, height)
|
||||
render_pass.setCamera(camera)
|
||||
renderer.addRenderPass(render_pass)
|
||||
renderer.beginRendering()
|
||||
renderer.render()
|
||||
|
||||
return render_pass.getOutput()
|
||||
|
||||
@staticmethod
|
||||
def nodeBounds(root_node: SceneNode) -> Optional[AxisAlignedBox]:
|
||||
axis_aligned_box = None
|
||||
for node in DepthFirstIterator(root_node):
|
||||
if not getattr(node, "_outside_buildarea", False):
|
||||
if node.callDecoration(
|
||||
"isSliceable") and node.getMeshData() and node.isVisible() and not node.callDecoration(
|
||||
"isNonThumbnailVisibleMesh"):
|
||||
if axis_aligned_box is None:
|
||||
axis_aligned_box = node.getBoundingBox()
|
||||
else:
|
||||
axis_aligned_box = axis_aligned_box + node.getBoundingBox()
|
||||
return axis_aligned_box
|
||||
|
||||
@staticmethod
|
||||
def snapshot(width = 300, height = 300):
|
||||
"""Return a QImage of the scene
|
||||
@ -55,14 +140,7 @@ class Snapshot:
|
||||
camera = Camera("snapshot", root)
|
||||
|
||||
# determine zoom and look at
|
||||
bbox = None
|
||||
for node in DepthFirstIterator(root):
|
||||
if not getattr(node, "_outside_buildarea", False):
|
||||
if node.callDecoration("isSliceable") and node.getMeshData() and node.isVisible() and not node.callDecoration("isNonThumbnailVisibleMesh"):
|
||||
if bbox is None:
|
||||
bbox = node.getBoundingBox()
|
||||
else:
|
||||
bbox = bbox + node.getBoundingBox()
|
||||
bbox = Snapshot.nodeBounds(root)
|
||||
# If there is no bounding box, it means that there is no model in the buildplate
|
||||
if bbox is None:
|
||||
Logger.log("w", "Unable to create snapshot as we seem to have an empty buildplate")
|
||||
|
304
plugins/MakerbotWriter/MakerbotWriter.py
Normal file
304
plugins/MakerbotWriter/MakerbotWriter.py
Normal file
@ -0,0 +1,304 @@
|
||||
# Copyright (c) 2023 UltiMaker
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from io import StringIO, BufferedIOBase
|
||||
import json
|
||||
from typing import cast, List, Optional, Dict
|
||||
from zipfile import BadZipFile, ZipFile, ZIP_DEFLATED
|
||||
import pyDulcificum as du
|
||||
|
||||
from PyQt6.QtCore import QBuffer
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.Math.AxisAlignedBox import AxisAlignedBox
|
||||
from UM.Mesh.MeshWriter import MeshWriter
|
||||
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
from UM.i18n import i18nCatalog
|
||||
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.Snapshot import Snapshot
|
||||
from cura.Utils.Threading import call_on_qt_thread
|
||||
from cura.CuraVersion import ConanInstalls
|
||||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
class MakerbotWriter(MeshWriter):
|
||||
"""A file writer that writes '.makerbot' files."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__(add_to_recent_files=False)
|
||||
Logger.info(f"Using PyDulcificum: {du.__version__}")
|
||||
MimeTypeDatabase.addMimeType(
|
||||
MimeType(
|
||||
name="application/x-makerbot",
|
||||
comment="Makerbot Toolpath Package",
|
||||
suffixes=["makerbot"]
|
||||
)
|
||||
)
|
||||
|
||||
_PNG_FORMATS = [
|
||||
{"prefix": "isometric_thumbnail", "width": 120, "height": 120},
|
||||
{"prefix": "isometric_thumbnail", "width": 320, "height": 320},
|
||||
{"prefix": "isometric_thumbnail", "width": 640, "height": 640},
|
||||
{"prefix": "thumbnail", "width": 140, "height": 106},
|
||||
{"prefix": "thumbnail", "width": 212, "height": 300},
|
||||
{"prefix": "thumbnail", "width": 960, "height": 1460},
|
||||
{"prefix": "thumbnail", "width": 90, "height": 90},
|
||||
]
|
||||
_META_VERSION = "3.0.0"
|
||||
_PRINT_NAME_MAP = {
|
||||
"Makerbot Method": "fire_e",
|
||||
"Makerbot Method X": "lava_f",
|
||||
"Makerbot Method XL": "magma_10",
|
||||
}
|
||||
_EXTRUDER_NAME_MAP = {
|
||||
"1XA": "mk14_hot",
|
||||
"2XA": "mk14_hot_s",
|
||||
"1C": "mk14_c",
|
||||
"1A": "mk14",
|
||||
"2A": "mk14_s",
|
||||
}
|
||||
_MATERIAL_MAP = {"2780b345-577b-4a24-a2c5-12e6aad3e690": "abs",
|
||||
"88c8919c-6a09-471a-b7b6-e801263d862d": "abs-wss1",
|
||||
"416eead4-0d8e-4f0b-8bfc-a91a519befa5": "asa",
|
||||
"85bbae0e-938d-46fb-989f-c9b3689dc4f0": "nylon-cf",
|
||||
"283d439a-3490-4481-920c-c51d8cdecf9c": "nylon",
|
||||
"62414577-94d1-490d-b1e4-7ef3ec40db02": "pc",
|
||||
"69386c85-5b6c-421a-bec5-aeb1fb33f060": "petg",
|
||||
"0ff92885-617b-4144-a03c-9989872454bc": "pla",
|
||||
"a4255da2-cb2a-4042-be49-4a83957a2f9a": "pva",
|
||||
"a140ef8f-4f26-4e73-abe0-cfc29d6d1024": "wss1",
|
||||
"77873465-83a9-4283-bc44-4e542b8eb3eb": "sr30",
|
||||
"96fca5d9-0371-4516-9e96-8e8182677f3c": "im-pla",
|
||||
"9f52c514-bb53-46a6-8c0c-d507cd6ee742": "abs",
|
||||
"0f9a2a91-f9d6-4b6b-bd9b-a120a29391be": "abs",
|
||||
"d3e972f2-68c0-4d2f-8cfd-91028dfc3381": "abs",
|
||||
"495a0ce5-9daf-4a16-b7b2-06856d82394d": "abs-cf",
|
||||
"cb76bd6e-91fd-480c-a191-12301712ec77": "abs-wss1",
|
||||
"a017777e-3f37-4d89-a96c-dc71219aac77": "abs-wss1",
|
||||
"4d96000d-66de-4d54-a580-91827dcfd28f": "abs-wss1",
|
||||
"0ecb0e1a-6a66-49fb-b9ea-61a8924e0cf5": "asa",
|
||||
"efebc2ea-2381-4937-926f-e824524524a5": "asa",
|
||||
"b0199512-5714-4951-af85-be19693430f8": "asa",
|
||||
"b9f55a0a-a2b6-4b8d-8d48-07802c575bd1": "pla",
|
||||
"c439d884-9cdc-4296-a12c-1bacae01003f": "pla",
|
||||
"16a723e3-44df-49f4-82ec-2a1173c1e7d9": "pla",
|
||||
"74d0f5c2-fdfd-4c56-baf1-ff5fa92d177e": "pla",
|
||||
"64dcb783-470d-4400-91b1-7001652f20da": "pla",
|
||||
"3a1b479b-899c-46eb-a2ea-67050d1a4937": "pla",
|
||||
"4708ac49-5dde-4cc2-8c0a-87425a92c2b3": "pla",
|
||||
"4b560eda-1719-407f-b085-1c2c1fc8ffc1": "pla",
|
||||
"e10a287d-0067-4a58-9083-b7054f479991": "im-pla",
|
||||
"01a6b5b0-fab1-420c-a5d9-31713cbeb404": "im-pla",
|
||||
"f65df4ad-a027-4a48-a51d-975cc8b87041": "im-pla",
|
||||
"f48739f8-6d96-4a3d-9a2e-8505a47e2e35": "im-pla",
|
||||
"5c7d7672-e885-4452-9a78-8ba90ec79937": "petg",
|
||||
"91e05a6e-2f5b-4964-b973-d83b5afe6db4": "petg",
|
||||
"bdc7dd03-bf38-48ee-aeca-c3e11cee799e": "petg",
|
||||
"54f66c89-998d-4070-aa60-1cb0fd887518": "nylon",
|
||||
"002c84b3-84ac-4b5a-b57d-fe1f555a6351": "pva",
|
||||
"e4da5fcb-f62d-48a2-aaef-0b645aa6973b": "wss1",
|
||||
"77f06146-6569-437d-8380-9edb0d635a32": "sr30"}
|
||||
|
||||
# must be called from the main thread because of OpenGL
|
||||
@staticmethod
|
||||
@call_on_qt_thread
|
||||
def _createThumbnail(width: int, height: int) -> Optional[QBuffer]:
|
||||
if not CuraApplication.getInstance().isVisible:
|
||||
Logger.warning("Can't create snapshot when renderer not initialized.")
|
||||
return
|
||||
try:
|
||||
snapshot = Snapshot.isometricSnapshot(width, height)
|
||||
except:
|
||||
Logger.logException("w", "Failed to create snapshot image")
|
||||
return
|
||||
|
||||
thumbnail_buffer = QBuffer()
|
||||
thumbnail_buffer.open(QBuffer.OpenModeFlag.WriteOnly)
|
||||
|
||||
snapshot.save(thumbnail_buffer, "PNG")
|
||||
|
||||
return thumbnail_buffer
|
||||
|
||||
def write(self, stream: BufferedIOBase, nodes: List[SceneNode], mode=MeshWriter.OutputMode.BinaryMode) -> bool:
|
||||
if mode != MeshWriter.OutputMode.BinaryMode:
|
||||
Logger.log("e", "MakerbotWriter does not support text mode.")
|
||||
self.setInformation(catalog.i18nc("@error:not supported", "MakerbotWriter does not support text mode."))
|
||||
return False
|
||||
|
||||
# The GCodeWriter plugin is always available since it is in the "required" list of plugins.
|
||||
gcode_writer = PluginRegistry.getInstance().getPluginObject("GCodeWriter")
|
||||
|
||||
if gcode_writer is None:
|
||||
Logger.log("e", "Could not find the GCodeWriter plugin, is it disabled?.")
|
||||
self.setInformation(
|
||||
catalog.i18nc("@error:load", "Could not load GCodeWriter plugin. Try to re-enable the plugin."))
|
||||
return False
|
||||
|
||||
gcode_writer = cast(MeshWriter, gcode_writer)
|
||||
|
||||
gcode_text_io = StringIO()
|
||||
success = gcode_writer.write(gcode_text_io, None)
|
||||
|
||||
# Writing the g-code failed. Then I can also not write the gzipped g-code.
|
||||
if not success:
|
||||
self.setInformation(gcode_writer.getInformation())
|
||||
return False
|
||||
|
||||
json_toolpaths = du.gcode_2_miracle_jtp(gcode_text_io.getvalue())
|
||||
metadata = self._getMeta(nodes)
|
||||
|
||||
png_files = []
|
||||
for png_format in self._PNG_FORMATS:
|
||||
width, height, prefix = png_format["width"], png_format["height"], png_format["prefix"]
|
||||
thumbnail_buffer = self._createThumbnail(width, height)
|
||||
if thumbnail_buffer is None:
|
||||
Logger.warning(f"Could not create thumbnail of size {width}x{height}.")
|
||||
continue
|
||||
png_files.append({
|
||||
"file": f"{prefix}_{width}x{height}.png",
|
||||
"data": thumbnail_buffer.data(),
|
||||
})
|
||||
|
||||
try:
|
||||
with ZipFile(stream, "w", compression=ZIP_DEFLATED) as zip_stream:
|
||||
zip_stream.writestr("meta.json", json.dumps(metadata, indent=4))
|
||||
zip_stream.writestr("print.jsontoolpath", json_toolpaths)
|
||||
for png_file in png_files:
|
||||
file, data = png_file["file"], png_file["data"]
|
||||
zip_stream.writestr(file, data)
|
||||
except (IOError, OSError, BadZipFile) as ex:
|
||||
Logger.log("e", f"Could not write to (.makerbot) file because: '{ex}'.")
|
||||
self.setInformation(catalog.i18nc("@error", "MakerbotWriter could not save to the designated path."))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _getMeta(self, root_nodes: List[SceneNode]) -> Dict[str, any]:
|
||||
application = CuraApplication.getInstance()
|
||||
machine_manager = application.getMachineManager()
|
||||
global_stack = machine_manager.activeMachine
|
||||
extruders = global_stack.extruderList
|
||||
|
||||
nodes = []
|
||||
for root_node in root_nodes:
|
||||
for node in DepthFirstIterator(root_node):
|
||||
if not getattr(node, "_outside_buildarea", False):
|
||||
if node.callDecoration(
|
||||
"isSliceable") and node.getMeshData() and node.isVisible() and not node.callDecoration(
|
||||
"isNonThumbnailVisibleMesh"):
|
||||
nodes.append(node)
|
||||
|
||||
meta = dict()
|
||||
|
||||
meta["bot_type"] = MakerbotWriter._PRINT_NAME_MAP.get((name := global_stack.definition.name), name)
|
||||
|
||||
bounds: Optional[AxisAlignedBox] = None
|
||||
for node in nodes:
|
||||
node_bounds = node.getBoundingBox()
|
||||
if node_bounds is None:
|
||||
continue
|
||||
if bounds is None:
|
||||
bounds = node_bounds
|
||||
else:
|
||||
bounds = bounds + node_bounds
|
||||
|
||||
if bounds is not None:
|
||||
meta["bounding_box"] = {
|
||||
"x_min": bounds.left,
|
||||
"x_max": bounds.right,
|
||||
"y_min": bounds.back,
|
||||
"y_max": bounds.front,
|
||||
"z_min": bounds.bottom,
|
||||
"z_max": bounds.top,
|
||||
}
|
||||
|
||||
material_bed_temperature = global_stack.getProperty("material_bed_temperature", "value")
|
||||
meta["platform_temperature"] = material_bed_temperature
|
||||
|
||||
build_volume_temperature = global_stack.getProperty("build_volume_temperature", "value")
|
||||
meta["build_plane_temperature"] = build_volume_temperature
|
||||
|
||||
print_information = application.getPrintInformation()
|
||||
|
||||
meta["commanded_duration_s"] = int(print_information.currentPrintTime)
|
||||
meta["duration_s"] = int(print_information.currentPrintTime)
|
||||
|
||||
material_lengths = list(map(meterToMillimeter, print_information.materialLengths))
|
||||
meta["extrusion_distance_mm"] = material_lengths[0]
|
||||
meta["extrusion_distances_mm"] = material_lengths
|
||||
|
||||
meta["extrusion_mass_g"] = print_information.materialWeights[0]
|
||||
meta["extrusion_masses_g"] = print_information.materialWeights
|
||||
|
||||
meta["uuid"] = print_information.slice_uuid
|
||||
|
||||
materials = []
|
||||
for extruder in extruders:
|
||||
guid = extruder.material.getMetaData().get("GUID")
|
||||
material_name = extruder.material.getMetaData().get("material")
|
||||
material = self._MATERIAL_MAP.get(guid, material_name)
|
||||
materials.append(material)
|
||||
|
||||
meta["material"] = materials[0]
|
||||
meta["materials"] = materials
|
||||
|
||||
materials_temps = [extruder.getProperty("default_material_print_temperature", "value") for extruder in
|
||||
extruders]
|
||||
meta["extruder_temperature"] = materials_temps[0]
|
||||
meta["extruder_temperatures"] = materials_temps
|
||||
|
||||
meta["model_counts"] = [{"count": 1, "name": node.getName()} for node in nodes]
|
||||
|
||||
tool_types = [MakerbotWriter._EXTRUDER_NAME_MAP.get((name := extruder.variant.getName()), name) for extruder in
|
||||
extruders]
|
||||
meta["tool_type"] = tool_types[0]
|
||||
meta["tool_types"] = tool_types
|
||||
|
||||
meta["version"] = MakerbotWriter._META_VERSION
|
||||
|
||||
meta["preferences"] = dict()
|
||||
for node in nodes:
|
||||
bounds = node.getBoundingBox()
|
||||
meta["preferences"][str(node.getName())] = {
|
||||
"machineBounds": [bounds.right, bounds.back, bounds.left, bounds.front] if bounds is not None else None,
|
||||
"printMode": CuraApplication.getInstance().getIntentManager().currentIntentCategory,
|
||||
}
|
||||
|
||||
meta["miracle_config"] = {"gaggles": {str(node.getName()): {} for node in nodes}}
|
||||
|
||||
cura_engine_info = ConanInstalls.get("curaengine", {"version": "unknown", "revision": "unknown"})
|
||||
meta["curaengine_version"] = cura_engine_info["version"]
|
||||
meta["curaengine_commit_hash"] = cura_engine_info["revision"]
|
||||
|
||||
dulcificum_info = ConanInstalls.get("dulcificum", {"version": "unknown", "revision": "unknown"})
|
||||
meta["dulcificum_version"] = dulcificum_info["version"]
|
||||
meta["dulcificum_commit_hash"] = dulcificum_info["revision"]
|
||||
|
||||
meta["makerbot_writer_version"] = self.getVersion()
|
||||
meta["pyDulcificum_version"] = du.__version__
|
||||
|
||||
# Add engine plugin information to the metadata
|
||||
for name, package_info in ConanInstalls.items():
|
||||
if not name.startswith("curaengine_"):
|
||||
continue
|
||||
meta[f"{name}_version"] = package_info["version"]
|
||||
meta[f"{name}_commit_hash"] = package_info["revision"]
|
||||
|
||||
# TODO add the following instructions
|
||||
# num_tool_changes
|
||||
# num_z_layers
|
||||
# num_z_transitions
|
||||
# platform_temperature
|
||||
# total_commands
|
||||
|
||||
return meta
|
||||
|
||||
|
||||
def meterToMillimeter(value: float) -> float:
|
||||
"""Converts a value in meters to millimeters."""
|
||||
return value * 1000.0
|
28
plugins/MakerbotWriter/__init__.py
Normal file
28
plugins/MakerbotWriter/__init__.py
Normal file
@ -0,0 +1,28 @@
|
||||
# Copyright (c) 2023 UltiMaker
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.i18n import i18nCatalog
|
||||
|
||||
from . import MakerbotWriter
|
||||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
def getMetaData():
|
||||
file_extension = "makerbot"
|
||||
return {
|
||||
"mesh_writer": {
|
||||
"output": [{
|
||||
"extension": file_extension,
|
||||
"description": catalog.i18nc("@item:inlistbox", "Makerbot Printfile"),
|
||||
"mime_type": "application/x-makerbot",
|
||||
"mode": MakerbotWriter.MakerbotWriter.OutputMode.BinaryMode,
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def register(app):
|
||||
return {
|
||||
"mesh_writer": MakerbotWriter.MakerbotWriter(),
|
||||
}
|
13
plugins/MakerbotWriter/plugin.json
Normal file
13
plugins/MakerbotWriter/plugin.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "Makerbot Printfile Writer",
|
||||
"author": "UltiMaker",
|
||||
"version": "0.1.0",
|
||||
"description": "Provides support for writing MakerBot Format Packages.",
|
||||
"api": 8,
|
||||
"supported_sdk_versions": [
|
||||
"8.0.0",
|
||||
"8.1.0",
|
||||
"8.2.0"
|
||||
],
|
||||
"i18n-catalog": "cura"
|
||||
}
|
@ -305,6 +305,23 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"MakerbotWriter": {
|
||||
"package_info": {
|
||||
"package_id": "MakerbotWriter",
|
||||
"package_type": "plugin",
|
||||
"display_name": "Makerbot Printfile Writer",
|
||||
"description": "Provides support for writing MakerBot Format Packages.",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": "8.5.0",
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
"author_id": "UltimakerPackages",
|
||||
"display_name": "UltiMaker",
|
||||
"email": "plugins@ultimaker.com",
|
||||
"website": "https://ultimaker.com"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ModelChecker": {
|
||||
"package_info": {
|
||||
"package_id": "ModelChecker",
|
||||
|
@ -1,19 +1,24 @@
|
||||
// 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
|
||||
{
|
||||
readonly property UM.I18nCatalog catalog: UM.I18nCatalog { name: "cura" }
|
||||
|
||||
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,191 +26,255 @@ 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
|
||||
|
||||
UM.I18nCatalog{id: catalog; name: "cura"}
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
onClicked:
|
||||
{
|
||||
projectsList.visible = !projectsList.visible;
|
||||
projectBuildInfoList.visible = !projectBuildInfoList.visible;
|
||||
}
|
||||
}
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
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("default_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 (url !== "") {
|
||||
return `<a href="${url}">${name}</a>`;
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
visible: text !== ""
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
onLinkActivated: Qt.openUrlExternally(url)
|
||||
}
|
||||
|
||||
delegate: Row
|
||||
UM.Label
|
||||
{
|
||||
spacing: UM.Theme.getSize("narrow_margin").width
|
||||
text: description
|
||||
visible: text !== ""
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 2
|
||||
}
|
||||
|
||||
UM.Label
|
||||
{
|
||||
text: license
|
||||
visible: text !== ""
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
}
|
||||
|
||||
UM.Label
|
||||
{
|
||||
text: version
|
||||
visible: text !== ""
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 1
|
||||
}
|
||||
}
|
||||
|
||||
Flickable
|
||||
{
|
||||
anchors.fill: parent
|
||||
ScrollBar.vertical: UM.ScrollBar {
|
||||
visible: contentHeight > height
|
||||
}
|
||||
contentHeight: content.height
|
||||
clip: true
|
||||
|
||||
Column
|
||||
{
|
||||
id: content
|
||||
spacing: UM.Theme.getSize("default_margin").height
|
||||
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
|
||||
property string 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/" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(([name, { version }]) => ({ name, version }))
|
||||
delegate: Loader
|
||||
{
|
||||
sourceComponent: dependency_row
|
||||
width: parent.width
|
||||
property string name: modelData.name
|
||||
property string version: modelData.version
|
||||
property string license: ""
|
||||
property string url: ""
|
||||
property string description: ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
property string license: ""
|
||||
property string url: ""
|
||||
property string description: ""
|
||||
}
|
||||
width: parent.width
|
||||
model: Object
|
||||
.entries(CuraApplication.pythonInstalls)
|
||||
.map(([name, { version }]) => ({ name, 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
|
||||
{
|
||||
//: Close about dialog button
|
||||
id: closeButton
|
||||
text: catalog.i18nc("@action:button", "Close")
|
||||
onClicked: reject()
|
||||
|
Loading…
x
Reference in New Issue
Block a user